一个语言模型可以根据序列中已观察到的单词来预测序列中下一个单词的概率。
神经网络模型是开发统计语言模型的首选方法,因为它们可以使用分布式表示,其中具有相似含义的不同单词具有相似的表示,并且在进行预测时可以使用大量最近观察到的单词的上下文。
在本教程中,您将了解如何使用Python中的深度学习开发统计语言模型。
完成本教程后,您将了解:
- 如何为开发基于单词的语言模型准备文本。
- 如何设计和拟合带有学习到的嵌入层和LSTM隐藏层的神经网络语言模型。
- 如何使用学习到的语言模型生成具有与源文本相似统计特性的新文本。
立即开始您的项目,阅读我的新书《自然语言处理深度学习》,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。
- 更新于2018年4月:模型描述中的类型已修复
- 更新于2020年5月:模型期望中的拼写错误已修复。

如何开发词级神经语言模型并用它来生成文本
照片由Carlo Raso拍摄,部分权利保留。
教程概述
本教程分为4个部分,它们是:
- 柏拉图的《理想国》
- 数据准备
- 训练语言模型
- 使用语言模型
柏拉图的《理想国》
《理想国》是古希腊哲学家柏拉图最著名的著作。
它被组织成一次关于城邦秩序和正义的对话(例如,谈话)。
全书文本均可在公共领域免费获取。您可以在Project Gutenberg网站上以多种格式找到它。
您可以在此处下载整本书(或多本书)的ASCII文本版本
下载书籍文本并将其以文件名“republic.txt”保存在当前工作目录中。
在文本编辑器中打开文件,并删除开头和结尾的附加内容。这包括书本开头的信息、长篇分析和结尾的许可信息。
文本应以以下内容开头:
第一卷。
昨天我和阿里斯顿的儿子格劳康一起去了比雷埃夫斯,
…
并以以下内容结尾:
…
我们两人都将在这一生和我们所描述的一千年朝圣中一切安好。
这是干净数据文件的直接链接
将清理后的版本另存为当前工作目录中的“republic_clean.txt”。文件应包含约15,802行文本。
现在我们可以从这些文本中开发一个语言模型了。
需要深度学习处理文本数据的帮助吗?
立即参加我的免费7天电子邮件速成课程(附代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
数据准备
我们将从准备数据开始。
第一步是查看数据。
回顾文本
在编辑器中打开文本,然后查看文本数据。
例如,这是第一段对话:
第一卷。
昨天我和阿里斯顿的儿子格劳康一起去了比雷埃夫斯,
我可以向女神(色雷斯人
阿耳忒弥斯)祈祷;而且我还想看看他们将如何
庆祝这个新颖的节日。我对居民们的游行感到很高兴;
但色雷斯人的游行同样,
如果不是更美的话。当我们完成了祈祷并观看了
景观后,我们转向城市的方向;就在那一刻
塞法洛斯的儿子波勒马尔科斯碰巧从远处看见我们,
当时我们正要回家,并告诉他的仆人去
跑过来叫我们等他。那仆人抓住了我的斗篷
后面,说:波勒马尔科斯要你等一下。我转过身,问他他的主人在哪里。
他说,年轻人,如果你等着,他就在你身后。
当然我们会等,格劳康说;几分钟后波勒马尔科斯
出现了,还有格劳康的兄弟阿德曼托斯,尼基亚斯
的儿子尼塞拉图斯,以及其他一些参加了游行的人。波勒马尔科斯对我说:我看到,苏格拉底,你和你的
同伴已经要去城里了。我说,你没说错。
…
在准备数据时,我们看到什么需要处理?
快速浏览一下,我看到了这些:
- 书籍/章节标题(例如,“第一卷”)。
- 英式拼写(例如,“honoured”)。
- 大量标点符号(例如,“–”,“;–”,“?–”等等)。
- 奇怪的名字(例如,“Polemarchus”)。
- 一些持续数百行的长独白。
- 一些引用的对话(例如,“……”)。
这些观察以及更多内容,都为我们如何准备文本数据提供了一些思路。
我们准备数据的具体方式确实取决于我们打算如何建模,而这又取决于我们打算如何使用它。
语言模型设计
在本教程中,我们将开发一个文本模型,然后用它来生成新的文本序列。
该语言模型将是统计性的,并且将根据文本的输入序列预测每个单词的概率。预测的单词将作为输入,以生成下一个单词。
一个关键的设计决策是输入序列的长度。它们需要足够长,以便模型能够学习单词的上下文以进行预测。这个输入长度也将定义我们使用模型生成新序列时使用的种子文本的长度。
没有正确答案。如果有足够的时间和资源,我们可以探索模型使用不同大小输入序列学习的能力。
相反,我们将输入序列的长度任意选择为50个单词。
我们可以处理数据,以便模型仅处理独立的句子,并填充或截断文本以满足每个输入序列的要求。您可以将此作为本教程的扩展来探索。
相反,为了保持示例简短,我们将让所有文本连贯地流动,并训练模型来预测跨越句子、段落甚至书籍或章节的下一个单词。
现在我们有了模型设计,我们可以着手将原始文本转换为50个输入单词到1个输出单词的序列,准备好拟合模型。
加载文本
第一步是将文本加载到内存中。
我们可以开发一个小型函数,将整个文本文件加载到内存中并返回。该函数名为load_doc(),如下所示。给定一个文件名,它返回加载的文本序列。
1 2 3 4 5 6 7 8 9 |
# 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() 返回 文本 |
使用此函数,我们可以加载文件‘republic_clean.txt’中文档的清理版本,如下所示:
1 2 3 4 |
# 加载文档 in_filename = 'republic_clean.txt' doc = load_doc(in_filename) print(doc[:200]) |
运行此片段会加载文档,并打印前200个字符作为初步检查。
第一卷。
昨天我和阿里斯顿的儿子格劳康一起去了比雷埃夫斯,
我可以向女神(色雷斯人
阿耳忒弥斯);而且我还想看看如何
到目前为止,一切顺利。接下来,让我们清理文本。
清理文本
我们需要将原始文本转换为标记或单词序列,作为训练模型的来源。
根据对原始文本的审查(见上文),以下是我们为清理文本将执行的一些具体操作。您可能想作为扩展来探索更多清理操作。
- 将‘–’替换为空格,以便我们能更好地分割单词。
- 按空格分割单词。
- 删除单词中的所有标点符号以减小词汇量(例如,“What?”变为“What”)。
- 删除所有非字母单词,以移除独立的标点符号标记。
- 将所有单词标准化为小写,以减小词汇量。
词汇量大小对于语言模型来说很重要。更小的词汇量意味着模型更小,训练速度更快。
我们可以在函数中按此顺序实现这些清理操作。下面是clean_doc()函数,它以加载的文档作为参数,并返回一个清理过的标记数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import string # 将文档转换为干净的令牌 def clean_doc(doc): # 将'--'替换为空格' ' doc = doc.replace('--', ' ') # 按空格分割成标记 tokens = doc.split() # 从每个标记中删除标点符号 table = str.maketrans('', '', string.punctuation) tokens = [w.translate(table) for w in tokens] # 删除所有非字母字符的标记 tokens = [word for word in tokens if word.isalpha()] # 转为小写 tokens = [word.lower() for word in tokens] return tokens |
我们可以对加载的文档运行此清理操作,并打印一些标记和统计信息作为初步检查。
1 2 3 4 5 |
# 清理文档 tokens = clean_doc(doc) print(tokens[:200]) print('总标记数: %d' % len(tokens)) print('唯一标记数: %d' % len(set(tokens))) |
首先,我们可以看到一列不错的标记,它们看起来比原始文本更干净。我们可以删除“Book I”章节标记等内容,但这只是一个好的开始。
1 |
['book', 'i', 'i', 'went', 'down', 'yesterday', 'to', 'the', 'piraeus', 'with', 'glaucon', 'the', 'son', 'of', 'ariston', 'that', 'i', 'might', 'offer', 'up', 'my', 'prayers', 'to', 'the', 'goddess', 'bendis', 'the', 'thracian', 'artemis', 'and', 'also', 'because', 'i', 'wanted', 'to', 'see', 'in', 'what', 'manner', 'they', 'would', 'celebrate', 'the', 'festival', 'which', 'was', 'a', 'new', 'thing', 'i', 'was', 'delighted', 'with', 'the', 'procession', 'of', 'the', 'inhabitants', 'but', 'that', 'of', 'the', 'thracians', 'was', 'equally', 'if', 'not', 'more', 'beautiful', 'when', 'we', 'had', 'finished', 'our', 'prayers', 'and', 'viewed', 'the', 'spectacle', 'we', 'turned', 'in', 'the', 'direction', 'of', 'the', 'city', 'and', 'at', 'that', 'instant', 'polemarchus', 'the', 'son', 'of', 'cephalus', 'chanced', 'to', 'catch', 'sight', 'of', 'us', 'from', 'a', 'distance', 'as', 'we', 'were', 'starting', 'on', 'our', 'way', 'home', 'and', 'told', 'his', 'servant', 'to', 'run', 'and', 'bid', 'us', 'wait', 'for', 'him', 'the', 'servant', 'took', 'hold', 'of', 'me', 'by', 'the', 'cloak', 'behind', 'and', 'said', 'polemarchus', 'desires', 'you', 'to', 'wait', 'i', 'turned', 'round', 'and', 'asked', 'him', 'where', 'his', 'master', 'was', 'there', 'he', 'is', 'said', 'the', 'youth', 'coming', 'after', 'you', 'if', 'you', 'will', 'only', 'wait', 'certainly', 'we', 'will', 'said', 'glaucon', 'and', 'in', 'a', 'few', 'minutes', 'polemarchus', 'appeared', 'and', 'with', 'him', 'adeimantus', 'glaucons', 'brother', 'niceratus', 'the', 'son', 'of', 'nicias', 'and', 'several', 'others', 'who', 'had', 'been', 'at', 'the', 'procession', 'polemarchus', 'said'] |
我们还获得了一些关于清理后文档的统计数据。
我们可以看到,清理后的文本中有近12万个单词,词汇量不足7500个单词。这相对较小,在适度的硬件上,可以处理在这个数据上拟合的模型。
1 2 |
总标记数: 118684 唯一标记数: 7409 |
接下来,我们可以将标记整理成序列并保存到文件中。
保存清理后的文本
我们可以将长长的标记列表组织成50个输入单词和1个输出单词的序列。
也就是说,序列的长度为51个单词。
我们可以通过从第51个标记开始迭代标记列表,并将前面的50个标记作为序列来做到这一点,然后重复这个过程直到列表的末尾。
我们将把标记转换为空格分隔的字符串,以便稍后存储在文件中。
下面列出了将清理后的标记列表分割成长度为51个标记的序列的代码。
1 2 3 4 5 6 7 8 9 10 11 |
# 整理成序列标记 length = 50 + 1 sequences = list() for i in range(length, len(tokens)): # 选择标记序列 seq = tokens[i-length:i] # 转换为一行 line = ' '.join(seq) # 存储 sequences.append(line) print('总序列数: %d' % len(sequences)) |
运行这段代码会创建一个长长的行列表。
打印列表的统计信息,我们可以看到我们将有118,633个训练样本来拟合模型。
1 |
总序列数: 118633 |
接下来,我们可以将序列保存到新文件中以供以后加载。
我们可以定义一个新函数来将文本行保存到文件。这个新函数名为save_doc(),如下所示。它接受行列表和文件名作为输入。这些行以ASCII格式逐行写入。
1 2 3 4 5 6 |
# 将标记保存到文件,每行一个对话 def save_doc(lines, filename): data = '\n'.join(lines) file = open(filename, 'w') file = file.write(data) file.close() |
我们可以调用此函数并将我们的训练序列保存到文件‘republic_sequences.txt’。
1 2 3 |
# 保存序列到文件 out_filename = 'republic_sequences.txt' save_doc(sequences, out_filename) |
用文本编辑器查看文件。
您会发现,每一行都向前移动了一个单词,末尾添加了一个新单词来预测;例如,这里是截断后的前3行:
book i i … catch sight of
i i went … sight of us
i went down … of us from
…
完整示例
将所有这些结合起来,完整的代码清单如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
import string # 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() return text # 将文档转换为干净的令牌 def clean_doc(doc): # 将'--'替换为空格' ' doc = doc.replace('--', ' ') # 按空格分割成标记 tokens = doc.split() # 从每个标记中删除标点符号 table = str.maketrans('', '', string.punctuation) tokens = [w.translate(table) for w in tokens] # 删除所有非字母字符的标记 tokens = [word for word in tokens if word.isalpha()] # 转为小写 tokens = [word.lower() for word in tokens] return tokens # 将标记保存到文件,每行一个对话 def save_doc(lines, filename): data = '\n'.join(lines) file = open(filename, 'w') file = file.write(data) file.close() # 加载文档 in_filename = 'republic_clean.txt' doc = load_doc(in_filename) print(doc[:200]) # 清理文档 tokens = clean_doc(doc) print(tokens[:200]) print('总标记数: %d' % len(tokens)) print('唯一标记数: %d' % len(set(tokens))) # 整理成序列标记 length = 50 + 1 sequences = list() for i in range(length, len(tokens)): # 选择标记序列 seq = tokens[i-length:i] # 转换为一行 line = ' '.join(seq) # 存储 sequences.append(line) print('总序列数: %d' % len(sequences)) # 保存序列到文件 out_filename = 'republic_sequences.txt' save_doc(sequences, out_filename) |
现在,您的当前工作目录中应该已经有一个名为“republic_sequences.txt”的文件,其中存储了训练数据。
接下来,让我们看看如何拟合语言模型。
训练语言模型
我们现在可以从准备好的数据中训练一个统计语言模型。
我们将训练的模型是一个神经网络语言模型。它有几个独特的特征:
- 它为单词使用分布式表示,因此具有相似含义的不同单词将具有相似的表示。
- 它在学习模型的同时学习表示。
- 它学会利用最近100个单词的上下文来预测下一个单词的概率。
具体来说,我们将使用Embedding Layer来学习单词的表示,并使用长短期记忆(LSTM)循环神经网络来学习根据上下文预测单词。
让我们从加载训练数据开始。
加载序列
我们可以使用我们在上一节中开发的load_doc()函数来加载训练数据。
加载后,我们可以通过按换行符分割数据来将数据分成独立的训练序列。
下面的片段将从当前工作目录加载“republic_sequences.txt”数据文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() return text # 加载 in_filename = 'republic_sequences.txt' doc = load_doc(in_filename) lines = doc.split('\n') |
接下来,我们可以对训练数据进行编码。
编码序列
词嵌入层期望输入序列由整数组成。
我们可以将词汇表中的每个单词映射到一个唯一的整数,并对输入序列进行编码。稍后,当我们进行预测时,我们可以将预测转换为数字,并在相同的映射中查找其关联的单词。
为了实现这种编码,我们将使用Keras API中的Tokenizer类。
首先,必须在整个训练数据集上训练Tokenizer,这意味着它会找到数据中的所有唯一单词,并为每个单词分配一个唯一的整数。
然后,我们可以使用训练好的Tokenizer对所有训练序列进行编码,将每个序列从单词列表转换为整数列表。
1 2 3 4 |
# 将单词序列整数编码 tokenizer = Tokenizer() tokenizer.fit_on_texts(lines) sequences = tokenizer.texts_to_sequences(lines) |
我们可以将单词到整数的映射作为字典属性`word_index`访问,它在Tokenizer对象上。
我们需要知道词汇量的大小,以便稍后定义嵌入层。我们可以通过计算映射字典的大小来确定词汇量。
单词被分配从1到单词总数(例如,7,409)的值。嵌入层需要为这个词汇表中从索引1到最大索引的每个单词分配一个向量表示,并且因为数组的索引是零偏移的,所以词汇表中最后一个单词的索引将是7,409;这意味着数组的长度必须是7,409 + 1。
因此,在为嵌入层指定词汇量大小时,我们指定的值比实际词汇量大1。
1 2 |
# 词汇量大小 vocab_size = len(tokenizer.word_index) + 1 |
序列输入和输出
现在我们已经对输入序列进行了编码,我们需要将它们分离成输入(X)和输出(y)元素。
我们可以通过数组切片来实现这一点。
分离后,我们需要对输出单词进行独热编码。这意味着将其从一个整数转换为一个向量,其中包含词汇表中每个单词的0值,以及一个1来指示在单词整数值索引处出现的特定单词。
这样,模型就可以学习预测下一个单词的概率分布,并且可以从(除了实际下一个单词之外的所有单词为0的)目标值中学习。
Keras提供了to_categorical()函数,可以用来对每个输入-输出序列对的输出单词进行独热编码。
最后,我们需要向嵌入层指定输入序列的长度。我们知道长度是50个单词,因为我们设计了模型,但一个好的通用方法是使用输入数据形状的第二个维度(列数)。这样,如果您在准备数据时更改序列的长度,您就不需要更改此数据加载代码;它是通用的。
1 2 3 4 5 |
# 分离为输入和输出 sequences = array(sequences) X, y = sequences[:,:-1], sequences[:,-1] y = to_categorical(y, num_classes=vocab_size) seq_length = X.shape[1] |
拟合模型
现在我们可以定义我们的语言模型并在训练数据上进行拟合。
学习到的嵌入需要知道词汇量的大小和输入序列的长度,如前所述。它还有一个参数可以指定用于表示每个单词的维度数量。也就是说,嵌入向量空间的大小。
常见的值是50、100和300。我们将使用50,但可以考虑测试更小或更大的值。
我们将使用两个LSTM隐藏层,每个隐藏层有100个记忆单元。更多的记忆单元和更深的网络可能会获得更好的结果。
一个具有100个神经元的密集全连接层连接到LSTM隐藏层,以解释从序列中提取的特征。输出层将下一个单词预测为与词汇量大小相同的单个向量,其中包含词汇表中每个单词的概率。使用softmax激活函数来确保输出具有归一化概率的特性。
1 2 3 4 5 6 7 8 |
# 定义模型 model = Sequential() model.add(Embedding(vocab_size, 50, input_length=seq_length)) model.add(LSTM(100, return_sequences=True)) model.add(LSTM(100)) model.add(Dense(100, activation='relu')) model.add(Dense(vocab_size, activation='softmax')) print(model.summary()) |
网络定义的摘要被打印出来,作为初步检查,以确保我们构建了我们想要的东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
_________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= embedding_1 (Embedding) (None, 50, 50) 370500 _________________________________________________________________ lstm_1 (LSTM) (None, 50, 100) 60400 _________________________________________________________________ lstm_2 (LSTM) (None, 100) 80400 _________________________________________________________________ dense_1 (Dense) (None, 100) 10100 _________________________________________________________________ dense_2 (Dense) (None, 7410) 748410 ================================================================= 总参数: 1,269,810 可训练参数: 1,269,810 不可训练参数: 0 _________________________________________________________________ |
接下来,模型被编译,指定了拟合模型所需的分类交叉熵损失。从技术上讲,模型正在学习多类分类,这是此类问题的合适损失函数。使用了高效的Adam实现来最小批量梯度下降,并评估了模型的准确性。
最后,模型在数据上训练100个训练周期,并使用了适度的128个批次大小来加速。
使用现代硬件(无GPU)进行训练可能需要几个小时。您可以通过更大的批次大小和/或更少的训练周期来加速它。
1 2 3 4 |
# 编译模型 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 拟合模型 model.fit(X, y, batch_size=128, epochs=100) |
在训练过程中,您将看到性能摘要,包括每个批次更新结束时从训练数据中评估出的损失和准确率。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑运行几次示例并比较平均结果。
您会得到不同的结果,但预测下一个单词的准确率可能略高于50%,这也不算差。我们的目标不是100%的准确率(例如,一个记住了文本的模型),而是捕捉文本本质的模型。
1 2 3 4 5 6 7 8 9 10 11 |
... 第96/100个周期 118633/118633 [==============================] - 265s - loss: 2.0324 - acc: 0.5187 第97/100个周期 118633/118633 [==============================] - 265s - loss: 2.0136 - acc: 0.5247 第98/100个周期 118633/118633 [==============================] - 267s - loss: 1.9956 - acc: 0.5262 Epoch 99/100 118633/118633 [==============================] - 266s - loss: 1.9812 - acc: 0.5291 Epoch 100/100 118633/118633 [==============================] - 270s - loss: 1.9709 - acc: 0.5315 |
保存模型
运行结束时,训练好的模型将被保存到文件。
在这里,我们使用Keras模型API将模型保存到当前工作目录下的文件“model.h5”中。
稍后,当我们加载模型进行预测时,我们还需要单词到整数的映射。这在Tokenizer对象中,我们也可以使用Pickle将其保存。
1 2 3 4 |
# 将模型保存到文件 model.save('model.h5') # 保存分词器 dump(tokenizer, open('tokenizer.pkl', 'wb')) |
完整示例
我们可以将所有这些放在一起;用于拟合语言模型的完整示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
from numpy import array from pickle import dump from keras.preprocessing.text import Tokenizer from keras.utils import to_categorical from keras.models import Sequential from keras.layers import Dense 从 keras.layers 导入 LSTM from keras.layers import Embedding # 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() return text # 加载 in_filename = 'republic_sequences.txt' doc = load_doc(in_filename) lines = doc.split('\n') # 将单词序列整数编码 tokenizer = Tokenizer() tokenizer.fit_on_texts(lines) sequences = tokenizer.texts_to_sequences(lines) # 词汇量大小 vocab_size = len(tokenizer.word_index) + 1 # 分离为输入和输出 sequences = array(sequences) X, y = sequences[:,:-1], sequences[:,-1] y = to_categorical(y, num_classes=vocab_size) seq_length = X.shape[1] # 定义模型 model = Sequential() model.add(Embedding(vocab_size, 50, input_length=seq_length)) model.add(LSTM(100, return_sequences=True)) model.add(LSTM(100)) model.add(Dense(100, activation='relu')) model.add(Dense(vocab_size, activation='softmax')) print(model.summary()) # 编译模型 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 拟合模型 model.fit(X, y, batch_size=128, epochs=100) # 将模型保存到文件 model.save('model.h5') # 保存分词器 dump(tokenizer, open('tokenizer.pkl', 'wb')) |
使用语言模型
现在我们有了一个训练好的语言模型,我们可以使用它了。
在这种情况下,我们可以使用它来生成具有与源文本相同统计特性的新文本序列。
这并不实用,至少对于这个例子来说不是,但它提供了一个具体的例子来说明语言模型学到了什么。
我们将从再次加载训练序列开始。
加载数据
我们可以使用上一节中的相同代码来加载文本的训练数据序列。
具体来说,是load_doc()函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() return text # 加载清理后的文本序列 in_filename = 'republic_sequences.txt' doc = load_doc(in_filename) lines = doc.split('\n') |
我们需要文本,以便我们可以选择一个源序列作为模型输入来生成新的文本序列。
模型将需要50个单词作为输入。
稍后,我们将需要指定预期的输入长度。我们可以通过计算加载数据的一行长度并减去一行中也存在的预期输出单词数来确定此长度。
1 |
seq_length = len(lines[0].split()) - 1 |
加载模型
我们现在可以从文件加载模型了。
Keras提供了load_model()函数来加载模型,以便使用。
1 2 |
# 加载模型 model = load_model('model.h5') |
我们也可以使用Pickle API从文件加载分词器。
1 2 |
# 加载分词器 tokenizer = load(open('tokenizer.pkl', 'rb')) |
我们已准备好使用已加载的模型。
生成文本
生成文本的第一步是准备种子输入。
为此,我们将从输入文本中选择一个随机行。选定后,我们将打印它,以便我们对使用的内容有所了解。
1 2 3 |
# 选择一个种子文本 seed_text = lines[randint(0,len(lines))] print(seed_text + '\n') |
接下来,我们可以一次生成一个新单词。
首先,必须使用与训练模型时相同的分词器将种子文本编码为整数。
1 |
encoded = tokenizer.texts_to_sequences([seed_text])[0] |
模型可以直接通过调用model.predict_classes()来预测下一个单词,它将返回概率最高的单词的索引。
1 2 |
# 预测每个单词的概率 yhat = model.predict_classes(encoded, verbose=0) |
然后,我们可以查找分词器映射中的索引以获取关联的单词。
1 2 3 4 5 |
out_word = '' for word, index in tokenizer.word_index.items(): if index == yhat: out_word = word break |
然后,我们可以将此单词附加到种子文本并重复此过程。
重要的是,输入序列会变得太长。在将输入序列编码为整数之后,我们可以将其截断到所需的长度。Keras提供了pad_sequences()函数,我们可以使用它来进行截断。
1 |
encoded = pad_sequences([encoded], maxlen=seq_length, truncating='pre') |
我们可以将所有这些包装到一个名为generate_seq()的函数中,该函数以模型、分词器、输入序列长度、种子文本和要生成的单词数为输入。然后,它返回模型生成的单词序列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 从语言模型生成序列 def generate_seq(model, tokenizer, seq_length, seed_text, n_words): result = list() in_text = seed_text # 生成固定数量的单词 for _ in range(n_words): # 将文本编码为整数 encoded = tokenizer.texts_to_sequences([in_text])[0] # 将序列截断为固定长度 encoded = pad_sequences([encoded], maxlen=seq_length, truncating='pre') # 预测每个单词的概率 yhat = model.predict_classes(encoded, verbose=0) # 将预测的单词索引映射到单词 out_word = '' for word, index in tokenizer.word_index.items(): if index == yhat: out_word = word break # 附加到输入 in_text += ' ' + out_word result.append(out_word) return ' '.join(result) |
现在我们准备根据一些种子文本生成新单词序列。
1 2 3 |
# 生成新文本 generated = generate_seq(model, tokenizer, seq_length, seed_text, 50) print(generated) |
将所有这些放在一起,用于从学习的语言模型生成文本的完整代码列表如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
from random import randint from pickle import load from keras.models import load_model from keras.preprocessing.sequence import pad_sequences # 加载文档到内存 def load_doc(filename): # 以只读方式打开文件 file = open(filename, 'r') # 读取所有文本 text = file.read() # 关闭文件 file.close() return text # 从语言模型生成序列 def generate_seq(model, tokenizer, seq_length, seed_text, n_words): result = list() in_text = seed_text # 生成固定数量的单词 for _ in range(n_words): # 将文本编码为整数 encoded = tokenizer.texts_to_sequences([in_text])[0] # 将序列截断为固定长度 encoded = pad_sequences([encoded], maxlen=seq_length, truncating='pre') # 预测每个单词的概率 yhat = model.predict_classes(encoded, verbose=0) # 将预测的单词索引映射到单词 out_word = '' for word, index in tokenizer.word_index.items(): if index == yhat: out_word = word break # 附加到输入 in_text += ' ' + out_word result.append(out_word) return ' '.join(result) # 加载清理后的文本序列 in_filename = 'republic_sequences.txt' doc = load_doc(in_filename) lines = doc.split('\n') seq_length = len(lines[0].split()) - 1 # 加载模型 model = load_model('model.h5') # 加载分词器 tokenizer = load(open('tokenizer.pkl', 'rb')) # 选择一个种子文本 seed_text = lines[randint(0,len(lines))] print(seed_text + '\n') # 生成新文本 generated = generate_seq(model, tokenizer, seq_length, seed_text, 50) print(generated) |
运行示例首先打印种子文本。
when he said that a man when he grows old may learn many things for he can no more learn much than he can run much youth is the time for any extraordinary toil of course and therefore calculation and geometry and all the other elements of instruction which are a
然后打印50个生成的文本单词。
preparation for dialectic should be presented to the name of idle spendthrifts of whom the other is the manifold and the unjust and is the best and the other which delighted to be the opening of the soul of the soul and the embroiderer will have to be said at
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑运行几次示例并比较平均结果。
您可以看到文本看起来是合理的。事实上,连接的添加将有助于解释种子文本和生成的文本。尽管如此,生成的文本还是会得到正确类型的单词,并以正确的顺序排列。
尝试运行几次示例,看看其他生成的文本。如果您看到任何有趣的内容,请在下面的评论中告诉我。
扩展
本节列出了一些您可能希望探索的扩展本教程的想法。
- 逐句模型。根据句子分割原始数据,并将每个句子填充到固定长度(例如,最长句子的长度)。
- 简化词汇。探索一个更简单的词汇,也许去除词干或停用词。
- 调整模型。调整模型,例如嵌入的大小或隐藏层中的记忆单元数量,看看您是否能开发出更好的模型。
- 更深的模型。将模型扩展为具有多个LSTM隐藏层,可能带有dropout,看看您是否能开发出更好的模型。
- 预训练词嵌入。将模型扩展为使用预训练的word2vec或GloVe向量,看看它是否能产生更好的模型。
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
- Project Gutenberg
- The Republic by Plato on Project Gutenberg
- Republic (Plato) on Wikipedia
- Language model on Wikipedia
总结
在本教程中,您将了解如何使用词嵌入和循环神经网络开发一个基于单词的语言模型。
具体来说,你学到了:
- 如何为开发基于单词的语言模型准备文本。
- 如何设计和拟合带有学习到的嵌入层和LSTM隐藏层的神经网络语言模型。
- 如何使用学习到的语言模型生成具有与源文本相似统计特性的新文本。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
感谢您提供此博客,您是否使用RNN进行推荐?例如,使用用户消费电影序列来推荐电影。
抱歉,我没有将RNN用于推荐系统。
out_word = ”
for word, index in tokenizer.word_index.items()
if index == yhat
out_word = word
break
为什么要对字典进行顺序搜索?
这是反向查找,按值而不是按键查找。
我明白了。但是不是有一个tokenizer.index_word(:: index -> word)字典来做这个吗?
可能吧,很棒的建议!也许在我写这个的时候它还没有,或者我没注意到。
嘿Jason,我有一个问题。我不明白为什么Embedding(输入)层和输出层比我们词汇表中的单词数多1。
我很确定输出层(以及one-hot向量的输入层)必须与我们的词汇表大小完全相同,这样每个输出值才能与我们的词汇表单词一一对应。如果我们在这个大小上加1,额外的输出值会映射到哪个单词?
我们添加一个“无”的“单词”,索引为0。这是针对所有我们不知道的单词,或者我们想将其映射为“不知道”的单词。
出色的文章,谢谢!两个问题
1. 移除标点符号的好处有多大?几更多的标点符号标记是不是比几千个单词标记要微不足道的添加?
2. 根据您的经验,哪种方法在合理的时间内(几小时内)在适中的硬件(较便宜的GPU AWS选项)上生成有意义的文本更好:单词级别还是字符级别生成?
另外,如果您能包含您的硬件设置、python/keras版本以及生成示例文本输出了多长时间,那将是极好的。
好问题。
测试一下就知道,我估计词汇量会减少近一半。
AWS对于一次性模型来说物有所值。我强烈推荐它。
https://machinelearning.org.cn/develop-evaluate-large-deep-learning-models-keras-amazon-web-services/
我有一个大的i7 iMac用于本地开发,并在AWS上运行大型模型/实验。
您是什么意思“词汇量会减少近一半”?
抱歉,我的意思是,移除句号和逗号等标点符号会减少我们需要建模的标记数量。
问题的一部分是“Party”和“Party;”不会被评估为相同。
很棒的教程,感谢分享!
我是否可以假设,给定特定的种子文本,模型总是会输出相同的文本?
是的,一个训练好的模型会。但是模型每次训练时都会不同。
https://machinelearning.org.cn/randomness-in-machine-learning/
不总是这样,你可以通过拟合多项分布来生成新文本,其中你取一个字符出现的概率而不是字符的最大概率。这允许生成文本有更多的多样性,并且你可以结合“温度”参数来控制这种多样性。
好的,谢谢分享。
Jason,
感谢优秀的博客,您认为深度学习的未来如何?
您认为深度学习会持续10年吗?
是的。结果在广泛的领域中都非常有价值。
你好Jason,很棒的博客!
不过,我在运行“model.add(LSTM(100, return_sequences=True))”时有一个问题。
TypeError: Expected int32, got list containing Tensors of type '_Message' instead.
您能帮忙吗?谢谢。
顺便说一句,我正在使用os系统,py3.5。
你好Roger。我遇到了同样的问题,通过pip install –upgrade Tensorflow更新Tensorflow对我有效。
抱歉,我以前没见过这个错误。也许试试发布到stackoverflow?
可能是你的库版本问题?确保一切都是最新的。
嗨,Jason,
您能将上面的代码用作语言模型,而不是预测下一个单词吗?
我想判断“我正在吃一个苹果”比“我一个苹果正在吃”更常用。
对于短句子,我可能没有50个单词作为输入。
另外,Keras是否可以输出概率及其索引,例如下一个单词的最大概率是“republic”,而我想获得“republic”的索引,该索引可以在tokenizer.word_index中匹配。
谢谢!
如果您想用3个前置词作为输入来预测下一个词,您有什么建议吗?谢谢。
您可以构建您的问题,准备数据并训练模型。
3个单词作为输入可能不够。
这是一个马尔可夫假设。循环神经网络模型的要点是避免这种情况。如果您只使用3个单词来预测下一个词,那么可以使用n-gram或前馈模型(如Bengio的模型)。不需要循环模型。
抱歉,我不确定您的应用程序。
Keras可以预测词汇表中的概率,您可以使用argmax()来获取概率最大的单词的索引。
嗨,Jason,
感谢您的帖子。我注意到在扩展部分您提到了逐句建模。
我理解填充(padding)技术(在阅读了您的另一篇博文后)。但是它如何包含句号来生成文本呢?这是后处理文本的问题吗?在嵌入之前标记句号是否可能/更方便?
我通常建议移除标点符号。它会膨胀词汇量大小,进而减慢建模速度。
好的,谢谢您的建议,那么如何将句子结构纳入我的模型呢?
每个句子都可以是一个“样本”或作为输入的单词序列。
嗨 Jason,我尝试使用你的模型并用我自己的语料库进行训练,一切似乎都正常工作,但在最后出现了这个错误
34 sequences = array(sequences)
35 #print(sequences)
—> 36 X, y = sequences[:,:-1], sequences[:,-1]
37 # print(sequences[:,:-1])
38 # X, y = sequences[:-1], sequences[-1]
IndexError: 数组索引过多
关于序列的滑动。你知道如何解决吗?
非常感谢!
也许仔细检查一下加载的数据是否具有你期望的形状?
嗨 Jason 和 Maria。
我遇到了完全相同的问题。
我希望 Jason 能有更好的建议
这是错误
IndexError Traceback (最近一次调用)
in ()
1 # 分离输入和输出
2 sequences = array(sequences)
—-> 3 X, y = sequences[:,:-1], sequences[:,-1]
4 y = to_categorical(y, num_classes=vocab_size)
5 seq_length = X.shape[1]
IndexError: 数组索引过多
你能确认你的 Python 3 环境是最新的吗,包括 Keras 和 tensorflow?
例如,这是我目前运行的版本
这意味着你的输入不均匀,np.array 无法正确解析它(作者创建了每个 50 个 token 的段落),一个可能的修复方法是
original_sequences = tokenizer.texts_to_sequences(text_chunk)
vocab_size = len(tokenizer.word_index) + 1
aligned_sequneces = []
for sequence in original_sequences
aligned_sequence = np.zeros(max_len, dtype=np.int64)
aligned_sequence[:len(sequence)] = np.array(sequence, dtype=np.int64)
aligned_sequneces.append(aligned_sequence)
sequences = np.array(aligned_sequneces)
你使用 gensim 来生成这段代码吗?
如果你使用了 gensim,你在代码中使用的 gensim 命令在哪里?
本教程未使用 Gensim。
不知道回复是不是太晚了。问题出现的原因是你错误地输入了
tokenizer.fit_on_sequences 而不是 tokenizer.texts_to_sequences。
希望这能帮助以后访问此页面的其他人!
谢谢 Jason。
谢谢您的留言。
Basil,我尝试了你的建议,但仍然遇到同样的错误。
有人遇到过这个错误并解决了它吗?
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
主要问题是 `tokenizer.texts_to_sequences(lines)` 返回的是 List of List,而不是保证是矩形的二维列表,
这意味着 `sequences` 可能具有这种形式
[[1, 2, 3], [2, 3, 4, 5]]
但本文中的示例假设 `sequences` 应该是这种矩形形状的列表
[[1, 2, 3, 4], [2, 3, 4, 5]]
如果你使用了自定义的 `clean_doc` 函数,你可能需要为 Tokenizer() 使用自定义的过滤器参数,例如 `tokenizer = Tokenizer(filters='\n')`。
Tokenizer() 的构造函数有一个可选参数
filters: 一个字符串,其中每个元素都是一个将从文本中过滤掉的字符。默认值是所有标点符号、制表符和换行符,但不包括 ' 字符。
示例已移除了所有标点符号和空格,因此在示例中这不成问题。
但是,如果你使用了自定义的,那么这可能会成为一个问题。
先生,我的词汇量大小为 12000,当我使用 to_categorical 时,系统会抛出如下所示的内存错误
/usr/local/lib/python2.7/dist-packages/keras/utils/np_utils.pyc in to_categorical(y, num_classes)
22 num_classes = np.max(y) + 1
23 n = y.shape[0]
—> 24 categorical = np.zeros((n, num_classes))
25 categorical[np.arange(n), y] = 1
26 return categorical
内存错误
如何解决这个错误?
也许可以尝试在具有更多 RAM 的机器上运行代码,例如 S3?
也许可以尝试使用更节省内存的代码手动映射词汇到整数?
你能基于其他相关文章生成一篇可供人类阅读的文章吗?
是的,我认为可以。模型必须足够大并且经过精心训练。
嗨,Jason,
我刚刚用我自己的文本样本(来自一个 Tumblr 博客的博文)试用了你的代码并进行了训练,现在它已经到了文本不再被“生成”,而是被原样返回的阶段。
我使用的样本集相当小(每个单独的帖子都很小,所以我将每个序列设置为 10 个输入 1 个输出),大约有 25,000 个序列。其他所有代码都与你的教程相同 - 大约 150 个 epoch 后,准确率约为 0.99,所以我停止了它,试图进行生成。
当我将种子文本从样本中的内容更改为词汇表中的其他内容(即不是完整的行,而是“随机”的行)时,文本就变得相当随机,这正是我想要的。当种子文本更改为词汇表之外的内容时,每次都会生成相同的文本。
如果我想要更随机一些,我应该怎么做?我应该更改 LSTM 层中的内存单元吗?减少序列长度?在更高的损失/更低的准确率下停止训练?
非常感谢你的教程,我从中学到了很多。
也许模型过拟合了,可以减少训练量?
也许需要更大的数据集?
我认为可能是过拟合了。可惜,我能获取的数据不多了(至少目前我所知道的),所以我无法获取更多数据,这很糟糕——这就是为什么我将序列长度减少到 10。
我每个 epoch 都进行了检查点,这样我就可以尝试找出能产生最佳结果的设置。谢谢你的建议!
也许还可以尝试混合/集成一些检查点模型或来自多次运行的模型,看看是否能带来一点提升。
嗨,Jason,
我在 Tensorflow 上查看了准确率和损失的数量。我想知道 NLP 中的准确率到底是什么意思?
在计算机视觉中,如果我们想预测猫,并且模型的预测结果是猫,那么我们可以说模型的准确率大于 95%。
我想从物理上理解 NLP 模型中的准确率意味着什么。你能解释一下吗?
我建议使用 BLEU 而不是准确率。准确率没有任何有用的意义。
在此处了解更多关于 BLEU 的信息
https://machinelearning.org.cn/calculate-bleu-score-for-text-python/
你好,我有一个关于评估这个模型的问题。据我所知,困惑度是一个非常流行的方法。对于 BLEU 和困惑度,你认为哪个更好?你能举一个在 keras 中评估这个模型的例子吗?
两者都很好。我没有特别偏好。
我在这里介绍了如何计算 BLEU
https://machinelearning.org.cn/calculate-bleu-score-for-text-python/
嗨 Jason,我有点困惑,你告诉我们需要 100 个词作为输入,但你的 X_train 每行只有 50 个词。你能解释一下吗?
谢谢,那是个拼写错误。已修正。
Jason,
你的模型中有一个嵌入层。嵌入权重将与其它层一起被训练。为什么不单独分离并训练它呢?换句话说,先单独使用 Embedding 来训练词向量/嵌入权重。然后用嵌入权重初始化嵌入层并设置 trainable=false 来运行你的模型。我看到大多数人使用你的方法来训练模型。但这在某种程度上违背了嵌入的目的,因为输出不是词语上下文而是 0/1 标签。为什么不将嵌入替换为一个具有线性激活的普通层呢?
另一个 Jason
你可以分开训练它们。我在博客上提供了示例。
通常,我发现模型在嵌入与网络一起训练时具有更好的技能。
“我在博客上提供了示例。”我猜你指的是你的博客中有其他文章谈论“分开训练它们”。
是的,你可以在这里搜索
https://machinelearning.org.cn/site-search/
ValueError: Error when checking : expected embedding_1_input to have shape (50,) but got array with shape (1,) while predicting output
这个可能会有帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
你好。你是否找到了问题的解决方案?我遇到了同样的错误。
我通过遵循这篇帖子解决了它
https://stackoverflow.com/questions/39950311/keras-error-on-predict
谢谢您。
你好,我想在 keras 中开发图像字幕。它的先决条件是什么?我已经完成了你的关于使用 CNN 进行对象检测的教程。接下来我应该做什么?
你可以遵循本教程
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
或者我在这本书中列出了所有必需的先验知识
https://machinelearning.org.cn/deep-learning-for-nlp/
嗨,Jason,
1.) 我们能否使用这种方法来预测训练数据中的某个词在序列中的位置是否高度异常?即它在该序列位置的概率不高。
2.) 有没有办法在嵌入层中集成预训练的词嵌入(glove/word2vec)?
这更多是关于生成新序列,而不是预测词语。
以下是处理预训练词嵌入的示例
https://machinelearning.org.cn/use-word-embedding-layers-deep-learning-keras/
你好,这对于像我这样的 NLP 初学者来说是一篇非常棒的文章。
我已经生成了一个语言模型,它正在生成我想要的文本。
我的问题是,在生成之后,我如何过滤掉所有在语法或语义上没有意义的文本?
谢谢。
你可能需要另一个模型来对文本进行分类、纠正文本或在使用前过滤文本。
这是否也会使用 Keras?你建议使用 nltk 还是 SpaCy?
也许吧,我当时不想说得太具体。
嗨,Jason,
感谢您这篇精彩的文章。
我正在处理句子中的单词纠正。理想情况下,模型应该生成与输入单词数量相同的输出单词,并纠正句子中的错误单词。
语言模型对此有帮助吗?如果可以,请给我一些关于模型的提示。
听起来是一个有趣的工程。语言模型可能有用。抱歉,我没有可用的示例。我建议查阅文献。
嗨,Jason,
我正在处理一个高度不平衡的文本分类问题。
例如:基于电子邮件正文中的文本,将“真实电子邮件”与“垃圾邮件”进行分类。
真实电子邮件文本 = 30k 行
垃圾邮件文本 = 1k 行
我需要分类下一封电子邮件是真实邮件还是垃圾邮件。
我使用与上述相同的示例来训练模型。
我提供给模型的训练数据仅为“真实文本”。
我是否能够通过生成的文本和词语的概率来分类下一句输入的句子:“真实电子邮件” vs “垃圾邮件”?
(我假设模型从未见过垃圾邮件数据,因此生成的文本的概率会很低。)
你认为有没有办法用语言模型来实现这个目标?在 NLP 用例的稀有事件场景中,还有什么其他选择?
谢谢你!!
我推荐使用 CNN 模型进行文本分类,例如
https://machinelearning.org.cn/best-practices-document-classification-deep-learning/
谢谢你,Jason!!
不客气。
嗨,Jason,
你能评论一下语言模型训练中的过拟合问题吗?我构建了一个基于句子的 LSTM 语言模型,并将训练:验证集划分为了 80:20 的比例。我没有在验证数据中看到任何改进,而模型的准确率似乎在提高。
谢谢
语言模型的过拟合实际上只在你使用该模型的问题上下文中才重要。
单独使用的语言模型实际上没有多大用处,所以过拟合并不重要。它可能是一个描述性模型,而不是预测性模型。
通常,它们在另一个模型的输入或输出中使用,在这种情况下,过拟合可能会限制预测能力。
返回隐藏状态和单元状态在这里会有什么影响?
我想象如果输入序列足够长,这可能不会太重要,因为时间关系会得到捕捉,但如果我们有较短的序列或非常长的文档,我们会考虑这样做来提高模型的学习能力……我这么想对吗?
返回隐藏序列和单元状态并将其输入到下一个观察值有什么缺点?
我不明白,为什么你要把单元状态外部返回?它在网络外部没有意义。
希望你一切都好。我有一个关于嵌入向量理解的问题。
例如,如果我有这个句子“the weather is nice”,我的模型目标是预测“nice”,当我想要使用预训练的谷歌词嵌入模型时,我必须搜索谷歌嵌入矩阵,找到与单词“the”、“weather”、“is”、“nice”相关的嵌入向量并将它们作为输入输入到我的模型中?我说的对吗?
为什么你要这样做?
你好,感谢你的精彩描述。我想使用预训练的谷歌词嵌入向量,所以我认为我不需要进行序列编码,例如,如果我想创建长度为 10 的序列,我必须搜索嵌入矩阵并找到每个 10 个词的等效嵌入向量,对吗?
正确。在准备嵌入或编码时,你必须将每个词映射到其分布式表示。
谢谢,你的书中有这方面的示例代码吗?我购买了你的专业套餐。
所有示例代码都随 PDF 一起提供在 code/ 目录中。
谢谢。当我想使用 model.fit 时,我必须指定 X 和 y,我使用了预训练的谷歌嵌入矩阵。所以每个词都映射到一个向量,我的输入实际上是句子(长度为 4)。现在我不理解 X 的等效值。例如,假设第一个句子是“the weather is nice”,那么 X 是“the weather is”,y 是“nice”。当我将 X 转换为整数时,X 中的每个词都会被映射到一个向量吗?例如,如果句子中词语的等效向量在谷歌模型中是:“the”= 0.9,0.6,0.8 和 “weather”=0.6,0.5,0.2 和 “is”=0.3,0.1,0.5,以及“nice”=0.4,0.3,0.5,那么输入 X 将是:[[0.9,0.6,0.8],[0.6,0.5,0.2],[0.3,0.1,0.5]] 而输出 y 将是 [0.4,0.3,0.5]?
你可以指定或学习映射,但之后模型会将整数映射到它们的向量。
你好 Jason,为什么你没有将 X 输入转换为热向量格式?你只对 y 输出做了这个。
我们不需要,因为我们使用了词嵌入。
您好!首先,我想感谢您对这个概念的详细解释。为了更好地理解,我正在一步步执行这个模型,但在进行预测时遇到了问题。
yhat = model.predict_classes(encoded, verbose=0)
我遇到了以下错误:
ValueError: Error when checking input: expected embedding_1_input to have shape (50,) but got array with shape (1,)
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
我通过遵循这篇帖子解决了这个问题。
https://stackoverflow.com/questions/39950311/keras-error-on-predict
您好,教程很棒!
调用时
model.fit(X, y, batch_size=128, epochs=100)
此时 X.shape 和 y.shape 是什么?
我收到了错误:
Error when checking input: expected embedding_1_input to have shape (500,) but got array with shape (1,)
在我的例子中
X.shape = (500,) # 在我的例子中是 500 个样本
y.shape = (500, 200) # 这是在 y= to_categorical(y, num_classes=vocab_size) 之后
使用 Theano 后端。
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
谢谢。可能对其他人有用:X.shape 的形式应该是 (a, b),其中 a 是“sequences”的长度,b 是输入序列的长度,以便进行前向预测。请注意,如果使用 Python 2.x(而不是 Python 3.x),则很可能需要修改/省略 string.maketrans(),并且 Theanos 后端也可能缓解 TensorFlow 潜在的维度错误。
谢谢。
我不明白为什么每个序列的长度必须相同(即固定)?RNN 的意义不就是通过一次接收一个单词作为输入,并将其余单词保留在隐藏状态中来处理可变长度的输入吗?
这是为了优化,当我们碰巧使用所有相同的尺寸时,但实际上我们并非必须这样做?那样的话更有意义。
你说得对,动态 RNN 可以做到这一点。
我大多数实现都使用固定长度的输入/输出以提高效率,并使用零填充和掩码来忽略填充。
@NLP_enthusiast 你是如何解决这个错误的?
你只需将这些替换为
table = string.maketrans(string.punctuation, ‘ ‘)
tokens = [‘w.translate(table)’ for w in tokens]
改为
tokens = [‘ ‘ if w in string.punctuation else w for w in tokens]
非常好!
有人有使用用户提供的文本字符串而不是随机样本数据进行预测的示例吗?我对此还是新手,所以提前为如此简单的问题道歉。谢谢!
新的输入数据必须与模型的训练数据以相同的方式进行准备。
例如,相同的 数据预处理步骤和分词器。
我们能否在 Android 平台上实现这个功能,以运行训练好的模型,为用户提供给定的单词集?
也许可以,我没有 Android 上的示例,抱歉。
你好,
博客中建议的一个扩展是
逐句模型。按句子分割原始数据,并将每个句子填充到固定长度(例如,最长句子的长度)。
所以如果我进行逐句分割,是保留标点符号还是删除它?
听起来是个不错的开始。
# 分离为输入和输出
sequences = array(sequences)
X, y = sequences[:,:-1], sequences[:,-1]
这个模型是只使用前面的 50 个单词来预测最后一个单词吗?
上下文长度是固定的吗?
在此示例中,我们使用 50 个单词作为输入。
为什么输入和输出相同?输出必须向左移动一个位置。对吗?
输出不等于输入。
sequences = array(sequences)
X, y = sequences[:,:-1], sequences[:,-1]
那么这个是什么意思?
如果您对 Python 中的数组切片和索引不熟悉,这将帮助您入门。
https://machinelearning.org.cn/index-slice-reshape-numpy-arrays-machine-learning-python/
Jason您好,我也在用RNN进行词预测。但是我遇到了和很多人一样的 INDEXERROR : Too many Indices 的问题。
lines = training_set.split(‘\n’)
tokenizer = Tokenizer()
tokenizer.fit_on_sequences(lines)
tokenizer.fit_on_texts(lines)
sequences = tokenizer.texts_to_sequences(lines)
vocab_size = len(tokenizer.word_index) + 1
sequences = array(sequences)
X_train = sequences[:, :-1]
y_train = sequences[:,-1]
我已经阅读了所有与此错误相关的评论,但似乎没有一个解决了我的问题。我想知道是否是我导入的文本有问题,我导入的是古腾堡的《傲慢与偏见》一书。
请帮帮我:提前感谢!!!
我没见过这个错误,您能确认您的库是最新版本并且您复制了教程中的所有代码吗?
非常好的文章。
在 118633 个长度为 50 个符号的序列,来自 7410 个元素的词汇表中,训练模型需要多长时间?
您能否分享一下您在哪台机器上训练了模型?内存、CPU、操作系统?
普通工作站,没有 GPU。
如果您遇到机器问题,可以尝试使用 EC2 实例,我在这里展示了如何操作。
https://machinelearning.org.cn/develop-evaluate-large-deep-learning-models-keras-amazon-web-services/
好文!
2 个问题
1. 在您的“扩展”部分,您提到了尝试 dropout。由于没有验证/保留集,为什么我们应该使用 dropout?它不是一种正则化技术,对训练数据准确性没有帮助吗?
2. 谈到准确性——我将我的模型训练到了 99% 的准确率。当我生成文本并使用柏拉图的确切台词作为种子文本时,我应该得到柏拉图的几乎精确副本,对吗?因为我的模型有 99% 的概率在我的种子文本中获得下一个单词。我发现事实并非如此。我是否正确地解释了这 99% 的准确率?是什么阻止它制造出副本?
是的,它是一种正则化方法。是的,它可以提供帮助,因为模型是使用监督学习进行训练的。
准确性不是语言模型的有效衡量标准。
我们不希望模型记住柏拉图,我们希望模型学会如何生成类似柏拉图的文本。
您好,非常棒的文章!
我有一个问题——如何使用该模型来获得句子中某个单词的概率?
例如 P(Piraeus| went down yesterday to the?
我不认为该模型可以这样使用。
我是您教程的忠实粉丝,当我需要学习深度学习知识时,我总是先搜索您的教程。
我目前遇到了一个问题,如下所示。
我有一个庞大的非结构化文本语料库(我已经对其进行了清理和分词,如:word1, word2, word3, … wordN)。我还有一个目标单词列表,它应该通过分析这些清理过的文本来输出(例如,word88, word34, word 48, word10002, … , word8)。
我想构建一个语言模型,它能通过我的清理文本正确地输出这些目标单词。我想知道这是否可以使用深度学习技术来实现?请告诉我您的想法。
如果您有与上述场景相关的教程,请与我分享(因为我找不到)。
感谢您提供的精彩教程。
-Emi
听起来很像翻译或文本摘要任务?
也许用于这些问题的模型会是一个好的起点?
感谢您的回复。不,它不是翻译或摘要。我下面举了一个更详细的例子。
—————————————————————————————————————-
我目前的输入准备过程如下:
非结构化文本 -> 清理数据 -> 只保留信息性词语 -> 计算不同特征
示例(假设我们只有 5 个词)
信息性词语 = {“Deep Learning”, “SVM”, “LSTM”, “Data Mining”, ‘Python’}
对于每个单词,我还有特征(假设我们只有 3 个词)
特征 = {Frequency, TF-IDF, MI}
但是,我不确定在构建深度学习模型时是否需要这些特征。
——————————————————————————————————————–
我的输出是信息性词语的排名列表。
目标输出 = {‘SVM’, ‘Data Mining’, ‘Deep Learning’, ‘Python’, ‘LSTM’}
——————————————————————————————————————–
我只是想弄清楚是否有办法通过深度学习或机器学习模型来获得我的目标输出?请告诉我您的想法。
-Emi
听起来您想要一个模型来输出相同的输入,但以某种方式排序。
可以尝试编码器-解码器吗?
嗨,Jason,
非常感谢您的建议。我今天遵循了您关于编码器-解码器的教程:https://machinelearning.org.cn/develop-encoder-decoder-model-sequence-sequence-prediction-keras/
它解释得很好,我想将其用于我的任务。但是,我遇到一个小问题。
在您的示例中,您使用了 100000 个训练示例,如下所示。
X=[22, 17, 23, 5, 29, 11] y=[23, 17, 22]
X=[28, 2, 46, 12, 21, 6] y=[46, 2, 28]
X=[12, 20, 45, 28, 18, 42] y=[45, 20, 12]
X=[3, 43, 45, 4, 33, 27] y=[45, 43, 3]
…
X=[34, 50, 21, 20, 11, 6] y=[21, 50, 34]
但是在我的任务中,我只有一个输入序列和目标序列,如下所示(输入相同,但顺序不同)。
信息性词语 = {“Deep Learning”, “SVM”, “LSTM”, “Data Mining”, ‘Python’}
目标输出 = {‘SVM’, ‘Data Mining’, ‘Deep Learning’, ‘Python’, ‘LSTM’}
这会是个问题吗?
PS:但是,在我的真实数据集中,我的输入和目标序列都非常长(大约 10000 个单词)。
您需要根据您的问题调整模型并进行测试,以便_发现_模型是否合适。
非常感谢您宝贵的建议。我真的很感激🙂
我遵循了您关于“编码器-解码器 LSTM”用于时间序列分析的教程。您是否有接近我任务的“编码器-解码器”教程?如果有,请提供链接。
Jason您好,我有一个关于预训练词向量的问题。我知道应该用 weights=[pre_embedding] 来设置嵌入层,但是如何决定预训练的顺序呢?比如,某一行中的向量代表哪个词?第一行是否总是全零?
每个向量的索引必须与词汇表中每个词的整数编码相匹配。
这就是为什么我们逐步收集词汇表中所需的向量。
我正在运行这里和书中描述的模型,但损失经常变为 NaN。我的计算机(18 核 + Vega 64 显卡)运行一个 epoch 的时间也比这里显示的长得多。所有 CPU 需要 1 小时才能完成。编码为 int8 并通过 PlaidML 使用 GPU 可以将其加速到约 376 秒,但会出现 NaN。
有什么建议吗?代码与这里和书中的完全一样,但我就是无法让它完成一次运行。
我有两个想法。
您是否尝试运行书中提供的代码文件?
您能否确认您的库是最新的?
Jason,非常棒的入门教程!谢谢!
谢谢,很高兴对您有帮助。
我在 Google Colab 中运行此程序(尽管使用了不同的、更大的数据集),Colab 系统崩溃,我的运行时基本上被重置。
我像您在此示例中一样分解了每个部分,发现它在以下代码处崩溃:
# 分离为输入和输出
sequences = array(sequences)
X, y = sequences[:,:-1], sequences[:,-1]
y = to_categorical(y, num_classes=vocab_size)
seq_length = X.shape[1]
我认为问题在于我的数据集可能太大了,但我不确定。
这是 Colab 笔记本的链接。
https://colab.research.google.com/drive/1iTXV_iC-aBTSlQ8BtiwM7zSszmIrlB3k
抱歉,我没有该环境的经验。
我建议在您自己的工作站上运行所有代码。
同样的问题((((google colab 没有足够的内存来处理如此大的矩阵。
可以尝试在您自己的工作站或 AWS EC2 上运行吗?
嗨,Jason,
我有两个问题,
1. 当我们用新的序列测试时,而不是尝试训练数据中已有的相同序列,会发生什么?
2. 为什么您可以使用 voc_size-1?
好问题,不确定。模型是针对特定数据集量身定制的,它可能会生成垃圾数据或回到它已知的模式。
不确定您的第二个问题,您具体指的是什么?
Jason 您好,希望您能帮助我解除困惑。
所以当我们把数据输入 LSTM 时,一个关于特征,另一个关于时间戳。
如果我对保持上下文为一段话感兴趣,而我拥有的最长段落是 200 个单词,那么我应该将时间戳设置为 200。
但是特征会怎样呢?
输入到模型的特征会是什么?
这里的特征是单词吗?还是段落?
抱歉,这让我非常困惑,我不确定如何准备我的文本数据。
如果这里的特征是单词,那么为什么我需要按段落分割?在这种情况下,我可以按单词分割并设置时间戳为 200,这样我的上下文就可以保持 200 个单词。
我这样做对吗?
感谢您的时间和耐心:)
如果您输入的是单词,那么一个特征就是一个单词,无论是独热编码还是使用词嵌入编码。
感谢您提供另一个信息丰富的网站。我还能在哪里
找到像这样写得如此完美的信息?我
有一个项目我正在处理,我一直在
寻找这类信息。
很高兴能帮到你。
您能帮我提供语法检查器的代码和好文章吗?
抱歉,我没有语法检查器的示例。
我是 NLP 领域的新手。如果您有一个输入文本“The price of orange has increased”(橙子的价格上涨了),输出文本“Increase the production of orange”(增加橙子的产量)。我们能否让我们的 RNN 模型预测输出文本?或者我应该使用什么算法?您能告诉我使用什么算法来映射输入句子到输出句子吗?
是的,也许可以从文本翻译模型开始。
https://machinelearning.org.cn/?s=translation&post_type=post&submit=Search
对于那些想使用神经语言模型来计算句子概率的人,请看这里。
https://stackoverflow.com/questions/51123481/how-to-build-a-language-model-using-lstm-that-assigns-probability-of-occurence-f
感谢分享。
而不是写一个循环
为什么不使用分词器的其他字典呢
我是新来的。你们如何标记评论中的代码块?你们如何添加个人资料图片?
您可以使用 `
听起来不错,它有效吗?
谢谢。我确实尝试了另一个字典,它似乎既有效又运行得更快。
嘿
首先,感谢您完成如此出色的项目。
我曾致力于此项目,但在预测值时遇到了困难。
错误显示:
ValueError: Error when checking input: expected embedding_1_input to have shape (50,) but got array with shape (1,)
你能帮忙吗?
该错误表明您的数据与模型的期望之间存在不匹配。
您可以更改您的数据或更改模型的期望。
你好!谢谢你的代码
有没有办法将 Keras 模型转换为 TFLite 或 TensorFlow 模型,因为官方文档显示 TFLite 不支持 LSTM 层?
谢谢!
我不知道,抱歉。
先生,请务必帮帮我。我正在做文本摘要。我能用语言模型来做吗,因为我对神经网络了解不多,或者如果您有任何建议,想法,请告诉我。我还有大约 20 天时间完成项目。
非常感谢!
这会有帮助
https://machinelearning.org.cn/best-practices-document-classification-deep-learning/
还有这个。
https://machinelearning.org.cn/develop-word-embedding-model-predicting-movie-review-sentiment/
先生,语言模型如何处理像金钱、日期之类的数字数据?
如果存在问题,该如何解决这个问题?我正在做文本摘要,而这些数字数据对于摘要可能很重要。我该如何处理它们?
非常感谢您的博文!非常喜欢您的帖子。说真的,非常有帮助!
对于小型数据集,最好将它们归一化为单个形式,例如单词。
再次感谢您发布了这篇精彩的博文。
我尝试了此处关于《爱丽丝梦游仙境》的词级别建模,该书来自 Project Gutenberg。但损失值太大了,从 6.39 开始,并没有怎么降低。前 10 个 epoch 损失在 6.18-6.19 之间。有什么建议吗?
是的,我在这里为诊断和改进深度学习模型性能提供了一些建议。
https://machinelearning.org.cn/start-here/#better
我修改了 clean_doc,使其生成独立的标点符号标记,但单引号用作撇号时除外,例如 "don't"、"Tom's"。
在第一次运行模型制作时,我将 batch_size 和 epochs 参数更改为 512 和 25,认为这可能会加快进程。在 MacBook Pro 上耗时 2 小时,但运行序列生成程序生成的文本大部分重复了“and the same, ”,如下所示:
to be the best , and the same , and the same , and the same , and the same , and the same , and the same , and the same , and the same , and the same , and the same , and
我将 batch_size 和 epochs 改回了原始值(125,100),然后通宵运行了模型构建程序。然后生成的序列看起来更合理。例如:
be a fortress to be justice and not yours , as we were saying that the just man will be enough to support the laws and loves among nature which we have been describing , and the disregard which he saw the concupiscent and be the truest pleasures , and
对我第一次尝试的糟糕结果是否有直观的解释?第一次尝试的最后一个 epoch 的损失值为 4.125,第二次尝试(结果良好)的损失值为 2.2130。我忘了记录准确率。
嗯,凭经验来看,增加更多的 token 可能需要增加数量级的数据、训练和一个更大的模型。
我正尝试将这些程序应用于某个流派的歌曲歌词集。一首歌通常由 50 到 200 个单词组成。由于它们属于同一流派,词汇量相对较小(谈论失去的爱、灵魂等)。在这种情况下,将序列大小从 50 减少到 20 是否有意义?
我的实验目标是通过给出前 5-10 个单词来生成歌词,纯粹为了好玩。
听起来很有趣。
也许可以尝试一下,看看什么最适合您的特定数据集。
我很想看看您的发现。
我正在针对阿拉伯语文本语料库实现这一点,但每次运行时,我都会在整个文本生成过程中得到重复相同的单词。我正在训练约 50,000 个单词,约 16,000 个唯一单词。我尝试了层数、更多数据(但这是一个问题,因为唯一单词的数量也会增加,这是一个有趣的发现,感觉像 Tokenizer 和非英语之间的错误)和 epoch。
有什么办法可以解决这个问题吗?
很遗憾听到这个消息,您可能需要为您的新数据集调整模型的容量和训练参数。
也许这里的一些教程会有帮助。
https://machinelearning.org.cn/start-here/#better
有没有办法从单个种子生成 2 或 3 个不同的样本文本?
例如,我们输入“Hello I’m”,模型会给我们:
Hello I’m interested in
Hello I’m a bit confused
Hello I’m not sure
而不是只生成一个输出,而是给出 2 到 3 个最佳输出。
实际上,我训练了您的模型,将序列长度从 50 改为 3,现在我希望当我输入一个三个单词的种子时,不是只生成一个三个单词的序列,而是生成 2 到 3 个与该种子相关的序列。这可能吗?请告诉我,我将非常感谢您!
是的,您可以获取预测的概率并运行束搜索以获得多个可能的序列。
您能给我多一点解释,说明我该如何实现它,或者给我一个例子吗?那就太好了!
试试搜索框。
也许这会有帮助。
https://machinelearning.org.cn/beam-search-decoder-natural-language-processing/
你好,
X 和 y 会是怎样的?
是否可以通过将 X 和 y 分割成训练集和测试集来完成?
另外,当模型创建后,嵌入层的输入会是什么?
然后将模型拟合到 X_train 上?
抱歉,我不明白。您具体指的是什么?
在拟合模型时,我似乎得到了一个错误。
ValueError: Error when checking input: expected embedding_input to have 2 dimensions, but got array with shape (264, 5, 1)
但输入应该是 3D 的,对吧?
所以我想,也许我在嵌入层中给出的输入有问题?
如果是这样,嵌入层应该给出哪些输入?
嵌入层的输入是 2D 的,每个样本都是一个映射到单词的整数向量。
好的,那么在模型形成后,我们将在拟合时将 X_train 设置为 3D 吗?
不。嵌入的输入是 2D 的。
您知道如何使用 RNN 进行神经网络旋律创作吗?
根据一份已发表的论文,其中使用了两个编码器并将其输入到一个解码器。
我想知道您是否能提供一些见解?
这是论文。
https://arxiv.org/pdf/1809.04318.pdf
抱歉,我对那篇论文不熟悉,也许可以尝试联系作者?
好的.. 谢谢..
您知道如何将两个序列作为输入提供给单个解码器吗?编码器和解码器都是 RNN 结构。那么如何将两个编码器用于一个解码器呢?
您可以尝试一个多输入模型。
https://machinelearning.org.cn/keras-functional-api-deep-learning/
它并没有完全解决我的疑问,但即使如此,谢谢你的帮助。
您好,如果我有两个输入序列,并且对这两个序列输入都有训练和测试。
我设法将两个输入连接起来并创建一个模型。
但是当涉及到拟合模型时,如何为两个序列提供 X 和 y?
如果您有一个多输入模型,那么 `fit()` 函数将接受一个包含每个样本数组的列表。
例如
X1 = …
X2 = …
X = [X1, X2]
model.fit(X, y, ….)
那么在训练 RNN 时,我们也应该有相同数量的输出吗?
ValueError: Error when checking model target: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 1 array(s), but instead got the following list of 2 arrays.
当我将多个输入传递给 fit 时,我得到了这个错误。
也许这篇教程能帮助您开始使用多输入模型。
https://machinelearning.org.cn/keras-functional-api-deep-learning/
抱歉,我不明白?
在什么意义上相等?
相等是指输入数量必须等于输出数量吗?
通常,输入和输出的时间步长必须相同。
它们可以不同,但要么必须固定,要么可以使用替代架构,例如编码器-解码器。
https://machinelearning.org.cn/encoder-decoder-long-short-term-memory-networks/
如果我们有两个不同的输入,并且需要一个同时包含这两个输入的模型,该怎么办?
我们是否可以将这两个输入都放入一个模型中,或者创建两个具有相应输入的模型,然后在最后将这两个模型合并?
当然,有许多不同的方法可以解决问题。也许可以探索几种不同的方法,看看哪种最适合您的数据集?
好的..
谢谢您..
我们如何知道两个输入是否已对齐?
我们可以通过合并两个模型来做到这一点吗?
无论哪种方式,我们都只能在测试之后才能知道结果,对吧?
是的。
我们的想法是通过验证来建立对模型的信任。
验证是什么意思?
使用测试集确认模型能产生合理的结果。
嗨,Jason,
我一直在做一个文本生成问题。
似乎在拟合 X_train 和 y_train 时遇到了问题。
这与形状不兼容有关。但我将 batch size 设置为 1 后,它就能运行了。
但是当它进行评估部分时,它显示了之前的错误。
InvalidArgumentError: 找到 2 个根错误。
(0) Invalid argument: Incompatible shapes: [32,5,5] vs. [32,5]
[[{{node metrics/mean_absolute_error/sub}}]]
(1) Invalid argument: Incompatible shapes: [32,5,5] vs. [32,5]
[[{{node metrics/mean_absolute_error/sub}}]]
[[metrics/mean_absolute_error/Identity/_153]]
0 次成功操作。
0 个派生错误被忽略。
这可能是什么原因?
很抱歉听到这个消息,我在这里有一些建议。
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
我也没完全照搬您的代码。我尝试自己做,只取了片段。即便如此,这也是我以前从未见过的错误。
我只是很困惑,为什么它在拟合时运行,但在评估时不运行?
我的意思是,我们无法在评估中对参数做太多调整?
抱歉,我不明白您的问题,也许您可以详细说明?
哦,抱歉,我的回复是基于之前的评论。
InvalidArgumentError: 找到 2 个根错误。
(0) Invalid argument: Incompatible shapes: [32,5,5] vs. [32,5]
[[{{node metrics/mean_absolute_error/sub}}]]
(1) Invalid argument: Incompatible shapes: [32,5,5] vs. [32,5]
[[{{node metrics/mean_absolute_error/sub}}]]
[[metrics/mean_absolute_error/Identity/_153]]
0 次成功操作。
0 个派生错误被忽略。
这个错误是在我拟合模型时发现的。但是当我把 batch size 设为 1 时,模型拟合得没有问题。
但是当我尝试评估它时,出现了同样的错误。
您知道为什么它在拟合时工作,但在评估时不工作吗?
抱歉,我没有见过这个错误。
也许尝试将您的代码和错误发布到stackoverflow?
好的,没问题..
谢谢你
你好 jason,
您能否就 Keras 中的注意力机制提供一些见解?
Keras 目前不支持注意力机制。
还有其他实现注意力机制的方法吗?
是的
- 手动实现
- 使用第三方实现
- 直接使用 TensorFlow
- 使用 PyTorch
训练准确率增加而验证准确率下降的原因是什么?
这是过拟合的情况吗?
准确率是会波动的。
请查看训练和验证损失。
甚至验证损失似乎也在波动。
那么这可能是过拟合的情况,对吧?
如果是这样,我们该如何解决这个问题?
或者验证数据集太小和/或不能代表训练数据集。
我正在为情感分析训练 IMDB 数据集。我正在训练 100,000 个单词。
一切似乎都进展顺利,直到训练部分,此时损失和准确率不断波动。
验证数据集是从整个数据集中分割出来的,所以我认为这不是问题。
也许尝试替代模型?
也许可以尝试一种替代的数据准备方法?
也许可以尝试一种替代的配置?
…
我们如何知道 IMDB 数据集中的总词数?
不是词汇量,而是数据集的大小?
对所有样本的长度求和。
此数据集中,一个样本是一条评论。每条评论包含不同数量的单词。我们考虑数据集包含10000或100000个单词,并将其分为训练集和测试集。所以,我需要获取总单词数。
嗨,Jason,
我完成了你帖子“使用Keras的Python LSTM循环神经网络进行文本生成”中的练习,但你在此处描述的使用语言模型的方法产生的文本更连贯,那么你能否详细说明何时使用一种技术而不是另一种?
提前感谢,
好问题。
没有好的启发式方法。也许可以遵循偏好,或者在特定数据集和指标上的模型技能。
你好!我正在尝试转换此示例,以制作一个简单的概念验证模型来进行单词预测,该模型可以使用相同的训练模型向后和向前进行推理。(不重复数据)
我想将文本行在中间分割,并将目标单词放在那里。像这样
X1 y X2
1. [yesterday to the piraeus with glaucon the son of ariston]
2. [yesterday to the piraeus with glaucon the son of ariston that]
3. [to the piraeus with glaucon the son of ariston that i]
等等
(X1 和 X2 实际上是各 20 个单词)
我一直遇到各种数据格式错误,感觉自己尝试了很多方法,但显然正确的方法仍然难以捉摸。
这大致是我的代码,
X1 = X1.reshape((n_lines+1, 20))
X2 = X2.reshape((n_lines+1, 20))
y = y.reshape((n_lines+1, vocab_size))
model = Sequential()
model.add(Embedding(vocab_size, 40, input_length=seq_length))
model.add(LSTM(100, return_sequences=True, input_shape=(20, 1)))
model.add(LSTM(100))
model.add(Dense(100, activation=’relu’))
model.add(Dense(vocab_size, activation=’softmax’))
model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
model.fit(np.array([X1, X2]), np.array(y), batch_size=128, epochs=10)
您认为这应该接近成功,而且您知道为什么我似乎无法输入两个“X”特征吗?
谢谢,Fred
我不确定这是否可行。
Google Groups 上有人建议我尝试函数式 API,所以我现在正在研究如何做。
这个可能会有帮助
https://machinelearning.org.cn/keras-functional-api-deep-learning/
我想考虑所有因素,包括标点符号,所以我在下面注释掉了这一行
tokens = [word for word in tokens if word.isalpha()]
但是当我运行时,我遇到了以下错误
回溯(最近一次调用)
File “lm2.py”, line 34, in
X, y = sequences[:,:-1], sequences[:,-1]
IndexError: 数组索引过多
有什么想法吗?
也许在您的更改后,确认数据的形状和类型是否符合我们的预期?
我不确定。您可以从以下 OneDrive 链接下载我创建/使用的文件
https://1drv.ms/u/s!AqMx36ZH6wJMhINbfIy1INrq5onhzg?e=UmUe4V
抱歉,我没有能力为您调试代码。
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
老师,当我们要考虑句子的上下文来将其分类到某个类别时,我应该使用哪种神经网络架构。
例如:我想像这样分类,
他们杀了很多人:无毒
我要杀了他们:有毒
好问题,请看这个
https://machinelearning.org.cn/best-practices-document-classification-deep-learning/
有没有人明确解决了“数组的索引太多”这个问题?
IndexError Traceback (最近一次调用)
in ()
1 sequences = np.array(sequences)
—-> 2 X, y = sequences[:,:-1], sequences[:,-1]
3 y = to_categorical(y, num_classes=vocab_size)
4 seq_length = X.shape[1]
IndexError: 数组索引过多
这会有帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
我有一个问题,你将 50 个单词输入到你的神经网络中,然后得到一个输出单词,如果我没记错的话,但当你只输入 50 个单词时,你怎么能得到一个 50 个单词的文本呢?
你可以递归地使用相同的模型,将输出作为输入,或者可以使用使用编码器-解码器模型实现的 seq2seq 模型。
你可以在这个博客上找到很多用于 NLP 的编码器-解码器示例,也许从这里开始
https://machinelearning.org.cn/start-here/#nlp
你能做一个关于使用 GANs 进行文本生成的教程吗?
感谢您的建议。
语言模型用于文本生成,GANs 用于生成图像。
嗨,Jason,
两个问题
“该模型需要 100 个单词作为输入。”
我认为是 50 个。
另外
“简化词汇。探索更简单的词汇,也许可以去除词干处理或去除停用词。”
这通常用于文本分类。在语言模型中这样做并用于文本生成会导致糟糕的结果。停用词对于捕捉基本单词组很重要,例如:“I went to the”。
谢谢你发现这个印刷错误。
当然,随意更改!
我需要一个深度神经网络来从预定义的候选中选择一个单词。请给我一些解决方案。
也许可以将其建模为文本分类。
https://machinelearning.org.cn/best-practices-document-classification-deep-learning/
对于句子级别的训练,下面帖子中的模型 2 是否基本上展示了这一点?
https://machinelearning.org.cn/develop-word-based-neural-language-models-python-keras/
你好 Jason!感谢你的帖子。
我需要构建一个神经网络来检测系统调用执行中的异常,以及这些系统调用接收的参数。哪种解决方案适合这个问题?
提前感谢!
也许可以从文本输入和类别标签输出开始,例如文本分类模型。测试词袋模型和嵌入表示,看看哪个效果最好。
嗨,Jason!
感谢您的帖子!
我需要构建一个神经网络来检测系统调用执行中的异常以及它们接收的参数中的异常。您对此有什么建议?
提前感谢!
我建议原型化并系统地评估一系列不同的模型,并发现什么最适合您的数据集。
你好 sir,感谢如此精彩的帖子,但是 sir,如何处理 csv 文件,如何加载、保存它们?我是一名深度学习新手,您能给我一些语法的思路吗?
这将向您展示如何加载 CSV 文件。
https://machinelearning.org.cn/load-machine-learning-data-python/
嗨,Jason,
感谢您提供有用的分步教程和相关解释。我正尝试将此技术用于为特定恶意软件家族/类型生成 snort 规则(某种程度上类似于防火墙规则 / 入侵检测规则)。您认为这可行吗?您能给我一些提示吗?这样做是否可行,因为此类规则需要遵循特定的格式或关键字序列。
这是规则示例。
“alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:”MALWARE-BACKDOOR Win.Backdoor.Demtranc variant outbound connection”; flow:to_server,established; content:”GET”; nocase; http_method; content:”/AES”; fast_pattern; nocase; http_uri; pcre:”/\/AES\d+O\d+\.jsp\?[a-z0-9=\x2b\x2f]{20}/iU”; metadata:policy balanced-ips drop, policy max-detect-ips drop, policy security-ips drop, service http; reference:url,www.virustotal.com/file/b3a97be4160fb261e138888df276f9076ed76fe2efca3c71b3ebf7aa8713f4a4/analysis/; classtype:trojan-activity; sid:24115; rev:3;)
您的建议将不胜感激。
“
不客气。
或许可以试试看?
我最好的建议是回顾文献,看看其他人如何解决相同类型的问题。这将节省大量时间,并可能很快获得良好的结果。
嗨,Jason,
非常感谢。可惜我没有找到任何文献让他们有类似的东西🙁。这就是我联系你的原因。
我会继续搜索。
坚持下去,也许可以搜索另一个“足够接近”的项目,并从中挖掘想法。
谢谢
嗨,Jason,
感谢这篇精彩的帖子。我使用了您的代码来进行词素预测。起初我实现了固定序列长度,但后来我必须使其可变序列长度。所以,我使用了 stateful LSTM,batch size 为 1,并将序列长度设置为 None。
我尝试一次拟合一个样本。但是,我遇到了“ValueError: Input arrays should have the same number of samples as target arrays. Found 1 input samples and 113 target samples。”
输入和输出样本的大小实际上是相等的,“113”是输出的 one-hot 向量大小。在我的第一个固定序列实现中,目标输出实现与您的代码完全相同,并且运行正确。
您知道为什么模型不识别 one-hot 编码吗?
提前感谢。
不客气。
如果您使用的是 stateful LSTM,您可能需要将目标设置为 3D 而不是 2D,例如 [samples, timesteps, features]。我可能错了,但我记得这可能是一个需要考虑的问题。
感谢您的回复。当我将其设置为 2D 时,它运行成功了。它本来是 1D 的。
不客气。
如果您想了解更多信息,还可以查看 Keras Team 在 GitHub 上的文本生成实现:https://github.com/keras-team/keras/blob/master/examples/lstm_text_generation.py。
看看这段代码……它展示得很好。
感谢分享。
嗨,Jason,
我使用了一个类似的 RNN 架构来开发一个语言模型。我现在想做的是,当向模型提供一个完整的句子时,能够生成它的概率。
注意:我指的是整个句子的概率,而不仅仅是下一个单词。
您是否知道如何做到这一点?
根据我所了解的,这种机制用于语音识别软件的实现。
好问题,我没有示例。
也许手动计算一下如何做到这一点,然后实现它?
也许查阅文献,看看是否有人以前做过,以及是如何做的?
也许查看开源库,看看它们是否提供此功能,并了解它们是如何做到的?
我一直在查找,但仍然找不到答案。
你好 Jason Sir,
感谢您提供如此精彩且信息丰富的博客,关于文本生成。刚看到标题时,我以为会很难,但解释和代码都很简洁易懂。期待阅读您更多博客!!
谢谢!
我遵循了这些步骤,几乎完成了,但在这一错误上卡住了
回溯(最近一次调用)
File “C:/Users/andya/PycharmProjects/finalfinalFINALCHAIN/venv/Scripts/Monster.py”, line 45, in
yhat = model.predict_classes(encoded)
File “C:\Users\andya\PycharmProjects\finalfinalFINALCHAIN\venv\lib\site-packages\keras\models.py”, line 1138, in predict_classes
steps=steps)
File “C:\Users\andya\PycharmProjects\finalfinalFINALCHAIN\venv\lib\site-packages\keras\models.py”, line 1025, in predict
steps=steps)
File “C:\Users\andya\PycharmProjects\finalfinalFINALCHAIN\venv\lib\site-packages\keras\engine\training.py”, line 1830, in predict
check_batch_axis=False)
File “C:\Users\andya\PycharmProjects\finalfinalFINALCHAIN\venv\lib\site-packages\keras\engine\training.py”, line 129, in _standardize_input_data
str(data_shape))
ValueError: Error when checking : expected embedding_1_input to have shape (50,) but got array with shape (51, 1)
供参考,我明确使用了几乎与您相同版本的库。除了第一个状态语句之外,其他一切都正常。
yhat = model.predict_classes(encoded, verbose=0)
我尝试过修改代码,但遗憾的是,我的数学和软件技能还不足以找到一个合适的解决方案。您可能需要记住,我已经修改了文本清理器,以保留数字和标点符号,即使在将其恢复正常时,它似乎也没有修复任何问题。还值得注意的是,为了测试目的,我已经将 epoch 数量设置为 1,但我怀疑这应该有任何影响。除此之外,应该没有重要的偏差。
很抱歉听到这个消息,我可以确认该示例在最新版本的库中有效,例如 Keras 2.4 和 TensorFlow 2.3,请确保您的库是最新的。
另外,看起来您是从 IDE 运行的,也许可以尝试从命令行运行。
https://machinelearning.org.cn/faq/single-faq/how-do-i-run-a-script-from-the-command-line
更多建议在这里
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason,
您将如何处理在多个不同文本源上训练模型?例如,如果我想在演讲稿上训练一个模型,以便能够生成特定发言者风格的文本,我是否应该将所有演讲稿存储在一个 .txt 文件中?我担心如果这样做,我会得到一些误导性的序列,例如序列以一个演讲稿的词开头,然后以下一个演讲稿的开头词结尾。将模型训练成一次一个演讲稿,而不是在一个包含所有演讲稿的大文件中训练,会不会更好?
也许为每个源训练一个单独的模型,然后使用模型的集成/堆叠来组合。
我现在不确定您的信息来源,但这是一个好话题。
我必须花一些时间学习更多或了解更多。
感谢您提供我一直在寻找的精彩信息,这对我现在的任务很有帮助。
谢谢。
感谢 Jason 的精彩教程。我如何为这个语言模型添加简单的控制?例如,正面-负面文本生成。
不客气。
也许分别为每种类型开发一个模型?
嗨,Jason,
在这个步骤中,我收到了这些代码。
# 定义模型
model = Sequential()
model.add(Embedding(vocab_size, 50, input_length=seq_length))
model.add(LSTM(100, return_sequences=True))
model.add(LSTM(100))
model.add(Dense(100, activation=’relu’))
model.add(Dense(vocab_size, activation=’softmax’))
打印(model.summary())
————————————————
总序列数: 118633
2021-04-27 06:24:25.190966: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cudart64_110.dll’; dlerror: cudart64_110.dll not found
2021-04-27 06:24:25.191304: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
2021-04-27 06:24:33.866815: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library nvcuda.dll
2021-04-27 06:24:34.937609: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties
pciBusID: 0000:01:00.0 name: GeForce GTX 1050 Ti computeCapability: 6.1
coreClock: 1.62GHz coreCount: 6 deviceMemorySize: 4.00GiB deviceMemoryBandwidth: 104.43GiB/s
2021-04-27 06:24:34.940037: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cudart64_110.dll’; dlerror: cudart64_110.dll not found
2021-04-27 06:24:34.941955: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cublas64_11.dll’; dlerror: cublas64_11.dll not found
2021-04-27 06:24:34.943931: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cublasLt64_11.dll’; dlerror: cublasLt64_11.dll not found
2021-04-27 06:24:34.945872: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cufft64_10.dll’; dlerror: cufft64_10.dll not found
2021-04-27 06:24:34.947770: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘curand64_10.dll’; dlerror: curand64_10.dll not found
2021-04-27 06:24:34.949522: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cusolver64_11.dll’; dlerror: cusolver64_11.dll not found
2021-04-27 06:24:34.951167: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cusparse64_11.dll’; dlerror: cusparse64_11.dll not found
2021-04-27 06:24:34.952449: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library ‘cudnn64_8.dll’; dlerror: cudnn64_8.dll not found
2021-04-27 06:24:34.952766: W tensorflow/core/common_runtime/gpu/gpu_device.cc:1766] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://tensorflowcn.cn/install/gpu for how to download and setup the required libraries for your platform.
Skipping registering GPU devices…
2021-04-27 06:24:34.954395: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-04-27 06:24:34.955743: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1258] Device interconnect StreamExecutor with strength 1 edge matrix
2021-04-27 06:24:34.956035: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1264]
回溯(最近一次调用)
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\LANGUAGE MODEL BUILDING\LANGUAGE MODEL TEST.py”, line 105, in
model.add(LSTM(100, return_sequences=True))
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\training\tracking\base.py”, line 522, in _method_wrapper
result = method(self, *args, **kwargs)
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\engine\sequential.py”, line 223, in add
output_tensor = layer(self.outputs[0])
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”, line 660, in __call__
return super(RNN, self).__call__(inputs, **kwargs)
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\engine\base_layer.py”, line 945, in __call__
return self._functional_construction_call(inputs, args, kwargs,
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\engine\base_layer.py”, line 1083, in _functional_construction_call
outputs = self._keras_tensor_symbolic_call(
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\engine\base_layer.py”, line 816, in _keras_tensor_symbolic_call
return self._infer_output_signature(inputs, args, kwargs, input_masks)
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\engine\base_layer.py”, line 856, in _infer_output_signature
outputs = call_fn(inputs, *args, **kwargs)
File “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent_v2.py”, line 1139, in call
inputs, initial_state, _ = self._process_inputs(inputs, initial_state, None)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 860 行,在 _process_inputs 中
initial_state = self.get_initial_state(inputs)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 642 行,在 get_initial_state 中
init_state = get_initial_state_fn(
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 2508 行,在 get_initial_state 中
return list(_generate_zero_filled_state_for_cell(
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 2990 行,在 _generate_zero_filled_state_for_cell 中
return _generate_zero_filled_state(batch_size, cell.state_size, dtype)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 3006 行,在 _generate_zero_filled_state 中
return tf.nest.map_structure(create_zeros, state_size)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\util\nest.py”,第 867 行,在 map_structure 中
structure[0], [func(*x) for x in entries],
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\util\nest.py”,第 867 行,在 中
structure[0], [func(*x) for x in entries],
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\keras\layers\recurrent.py”,第 3003 行,在 create_zeros 中
return tf.zeros(init_state_size, dtype=dtype)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\util\dispatch.py”,第 206 行,在 wrapper 中
return target(*args, **kwargs)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\ops\array_ops.py”,第 2911 行,在 wrapped 中
tensor = fun(*args, **kwargs)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\ops\array_ops.py”,第 2960 行,在 zeros 中
output = _constant_if_small(zero, shape, dtype, name)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\ops\array_ops.py”,第 2896 行,在 _constant_if_small 中
if np.prod(shape) < 1000
文件 " ", 第 5 行,在 prod 中
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\numpy\core\fromnumeric.py”,第 3030 行,在 prod 中
return _wrapreduction(a, np.multiply, ‘prod’, axis, dtype, out,
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\numpy\core\fromnumeric.py”,第 87 行,在 _wrapreduction 中
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
文件 “D:\PYTHON SOFTWARE\Doc\LEARN PYTHON\venv\lib\site-packages\tensorflow\python\framework\ops.py”,第 867 行,在 __array__ 中
raise NotImplementedError(
NotImplementedError: Cannot convert a symbolic Tensor (lstm/strided_slice:0) to a numpy array. This error may indicate that you’re trying to pass a Tensor to a NumPy call, which is not supported
我的库是:
Python 3.9
Theano 1.0.5
Numpy 1.20.2
pip 21.1
keras 2.4.3
tensorflow 2.4.1
matplotlib 3.4.1
pandas 1.2.4
我正在使用 PyCharm。看到这么多错误信息后,我想在从 PyCharm 外部运行脚本之前等待一下。
我的电脑有一个 GPU,是一台配备 NVIDIA 独立显卡的 DELL G3,但我没有为它进行任何设置或配置,以为运行这个教程不需要它。
非常感谢您的帮助!
听到这个消息很遗憾,也许这些提示会有帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
感谢教程,如果能提供 TF2 版本 的解码器会很好,predict_classes() 已弃用
谢谢!
谢谢你的建议。应该是用 np.argmax(model.predict_class(encoded)) 代替。
尝试替换但代码不起作用。
model.predict_classes(encoded, verbose=0) -> np.argmax(model.predict_class(encoded))
对此有什么解决方案吗?谢谢。。
你好 Amrit…你收到什么错误了?这将有助于我们更好地帮助你。
在“普通”笔记本电脑上运行此示例需要多长时间,CPU 1.10 GHz?可行吗?
我相信可以。除非你的内存真的很小。
你好 Jason,我有一个问题。希望你能花时间回答。关于这个例子,在训练的每个周期中,每行文本的第 51 个单词被预测出来,最终如何预测出有意义的连续单词字符串?
你好 John…请重述或阐述你的问题,以便我能更好地帮助你。
感谢你的及时回复,James。
让我重新表述我的问题如下:
1. 在训练阶段,我们将每行 50 个单词的文本字符串输入到 LSTM 中,并将输出(一个单词)与目标(该 50 个单词字符串的实际第 51 个单词)进行比较,然后反复回溯,直到权重和偏差设置为最优。简而言之,一个单词字符串被输入到模型,一个单词被预测出来。
2. 但是在“使用语言模型”阶段,我们给出一个种子文本,生成一个 50 个单词的文本。
3. 所以在训练时:文本 -> 单词,在使用模型时:文本 -> 文本。我的问题是:从 1 到 2,如何实现?我不是英语母语者。希望我的问题清楚。非常感谢您的时间和耐心。
嗨,Jason,
我尝试探索使用预训练词嵌入(GloVe 向量)来提高您在此处讨论的文本生成任务(柏拉图的《理想国》数据集)的准确性。但是,当我下载 zip 文件(glove.6B.zip)时,我发现上述数据集中有 90 多个单词在任何可用的文本文件中(glove.6B.50d.txt、glove.6B.100d.txt、glove.6B.200d.txt 和 glove.6B.300d.txt)都没有学习到的嵌入向量。
解决此问题的一个方法是完全从数据集中删除所有这些 90 个单词,然后通过冻结嵌入层来训练模型,但这似乎没有解决核心问题。由于预训练的 GloVe 向量 zip 文件没有预学习的嵌入向量来表示这 90 个单词,我不知道如何扩展模型以将这些预训练的 GloVe 向量用于整个柏拉图的《理想国》数据集。
您能否建议一种在这种数据集上执行迁移学习以提高准确性(正如您在博客的扩展部分中建议的那样)的方法,以防万一可以实现?
此致
Aniket Saxena
你好 Aniket…以下内容可能有所帮助。
https://machinelearning.org.cn/transfer-learning-for-deep-learning/
你好,你认为 flatten 层会有用或能提高模型的准确性吗?我有一个人总是提醒我使用 flatten 层放在每个模型的最后一层之后。
你好 Feron…你可能会对以下内容感兴趣:
https://machinelearning.org.cn/using-normalization-layers-to-improve-deep-learning-models/
嗨
感谢您出色的教程。我都很喜欢。
我在 Keras 中为波斯数据集实现了模型,效果很好。然后尝试实现 PyTorch 版本。模型什么也没学到。我没能找出问题所在,但我认为可能是 LSTM 层。我只想说,我用字典结构和列表为 Keras 和 PyTorch 制作了自己的分词器和整数词典。我将非常感谢任何帮助。
非常感谢。
这是我的模型…
class seqModel(nn.Module)
def __init__(self, vocab_size1=vocab_size, embedding_dim=50, hidden_size=100)
super(seqModel, self).__init__()
self.encoder = nn.Embedding(vocab_size1, embedding_dim)
self.lstm1 = nn.LSTM(embedding_dim, hidden_size)
self.lstm2 = nn.LSTM(hidden_size, hidden_size)
self.linear1 = nn.Linear(hidden_size, hidden_size)
self.linear2 = nn.Linear(hidden_size, vocab_size1)
self.act1 = nn.ReLU()
self.act2 = nn.Softmax(dim=1)
def forward(self, x)
output = self.encoder(x)
output, _ = self.lstm1(output)
output = output[:,-1,:]
output, _ = self.lstm2(output)
output = self.linear1(output)
output = self.act1(output)
output = self.linear2(output)
output = self.act2(output)
return output
你好 Fati…不客气!请提供有关您的模型性能遇到问题的更多详细信息,以便我们能更好地帮助您。也许您的模型可以受益于超参数优化。
谢谢回复。这是我的训练循环:
def train3(train_loader, sModel, optimizer, criterion, epochs)
loss_track = []
leastLoss = 100.000
sModel.train()
for epoch in range(epochs)
epoch_loss = []
sModel.train()
for x_batch, y_batch in train_loader
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
x_batch = x_batch.to(torch.long)
pred = model(x_batch)
y_batch = y_batch.to(torch.float32)
optimizer.zero_grad()
loss = criterion(pred,y_batch)
# 反向传播
loss.backward()
optimizer.step()
epoch_loss.append(loss.item())
print(” Epoch {} | Train Cross Entropy Loss: “.format(epoch),np.mean(epoch_loss))
loss_track.append(np.mean(epoch_loss))
print(“\n\n*********************************************”)
if ((np.mean(epoch_loss)) < leastLoss)
torch.save(sModel.state_dict(), ‘/path/Model/best_model2.pt’)
训练模型将如下所示,并且在 20 个 epoch 中没有任何改进(仅在很小的范围内徘徊):
Epoch 0 | Train Cross Entropy Loss: 9.027385948332194
*********************************************
Epoch 1 | Train Cross Entropy Loss: 9.027385958870033
*********************************************
Epoch 2 | Train Cross Entropy Loss: 9.027385963260798
*********************************************
Epoch 3 | Train Cross Entropy Loss: 9.027385970944637
*********************************************
Epoch 4 | Train Cross Entropy Loss: 9.027385972481406
*********************************************
Epoch 5 | Train Cross Entropy Loss: 9.027385962821722
*********************************************
Epoch 6 | Train Cross Entropy Loss: 9.027385953381575
*********************************************
Epoch 7 | Train Cross Entropy Loss: 9.027385970944637
*********************************************
*********************************************
我的损失函数有问题吗?我的意思是,打印层的尺寸,我发现输出必须从 (16,7,100) 重塑为 (16,100),其中 16 是批次大小,7 是序列长度,100 是 lstm 层的输出,在 lstm 层之后。在模型的末尾,输出的形状是 (16,vocab_size),与 y_batch 的形状匹配。从矩阵中消除一个维度是否会导致此问题?
我还尝试使用一个 lstm 层,并在每个批次中分离其状态,并在每个 epoch 开始时初始化状态,如下所示:
for epoch in range(epochs)
states = (torch.zeros(num_layers = 1, batch_size, hidden_size).to(device),
torch.zeros(num_layers, batch_size, hidden_size).to(device))
epoch_loss = []
sModel.train()
for x_batch, y_batch in train_loader
if (x_batch.size(0) < 16)
break
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
x_batch = x_batch.to(torch.long)
states = detach(states)
# 状态作为参数传递给 lstm 层,如下所示:
#output , (h,c) = self.lstm(output,states)
pred, states = model(x_batch, states)
y_batch = y_batch.to(torch.float32)
model.zero_grad()
loss = criterion(pred,y_batch)
# 反向传播
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), 0.5)
optimizer.step()
这在我训练的 epoch 数量上也有相同的损失。
* 还有一件事,我的 lstm 层中 batch_first = true。
再次感谢。
你好,非常感谢这个教程。
我尝试复制相同的步骤,但是模型每次都预测相同的单词,我不知道问题可能是什么。您能给点提示吗??
谢谢
你好 Nada…你可能想尝试一个更大的数据集来学习。另外,以下内容也可能让你感兴趣:
https://towardsdatascience.com/a-deep-learning-approach-in-predicting-the-next-word-s-7b0ee9341bfe