使用TensorFlow语言模型示例预测下一个单词

12

语言模型的TensorFlow教程可以计算句子的概率:

probabilities = tf.nn.softmax(logits)

在下面的评论中,它还指定了一种预测下一个单词而不是概率的方法,但没有说明如何实现。那么如何使用此示例输出单词而不是概率?

lstm = rnn_cell.BasicLSTMCell(lstm_size)
# Initial state of the LSTM memory.
state = tf.zeros([batch_size, lstm.state_size])

loss = 0.0
for current_batch_of_words in words_in_dataset:
    # The value of state is updated after processing each batch of words.
    output, state = lstm(current_batch_of_words, state)

    # The LSTM output can be used to make next word predictions
    logits = tf.matmul(output, softmax_w) + softmax_b
    probabilities = tf.nn.softmax(logits)
    loss += loss_function(probabilities, target_words)
3个回答

2
您的输出是一个 TensorFlow 列表,可以使用 TensorFlow 函数获取其最大参数(预测最可能的类)。通常这是包含下一个单词概率的列表。
page 的“评估模型”中,您的输出列表如下面的示例中的 y
“首先,我们将找出我们预测正确标签的位置。tf.argmax 是一个极其有用的函数,它给出张量沿某个轴上最高条目的索引。例如,tf.argmax(y,1) 是我们的模型认为每个输入最有可能的标签,而 tf.argmax(y_,1) 是真实标签。我们可以使用 tf.equal 检查我们的预测是否与真相匹配。correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))”。
另一种不同的方法是使用预先向量化(嵌入/编码)的单词。您可以使用Word2vec将单词向量化(因此嵌入它们)以加速学习,您可能会对此感兴趣。每个单词可以表示为一个300维意义空间中的点,您可以自动找到网络输出处预测点最接近的“N个单词”。在这种情况下,“argmax”处理方式不再适用,您可能需要使用余弦相似度与您真正想要进行比较的单词进行比较,但我不确定这是否会导致数值不稳定性。在这种情况下,y将不再代表单词作为特征,而是表示不同模型中大小为100到2000的单词嵌入。您可以搜索类似于“man woman queen word addition word2vec”的内容以了解更多关于嵌入的主题。
注意:当我在这里谈论word2vec时,指的是使用外部预训练的word2vec模型来帮助您的训练仅具有预先嵌入的输入并创建嵌入输出。这些输出对应的单词可以通过word2vec重新计算出来,以找到相应的相似顶部预测单词。
请注意,我建议的方法并不是完全准确的,因为它只有在我们准确预测出想要预测的单词时才有用。如果您使用句子或比单词更长的内容,则可以使用 ROUGE 或 BLEU 指标来评估您的模型,以获得更柔和的方法。

这不是正确的函数,因为需要找到现有序列中下一个最可能的单词。 - stackit
1
也许你的问题不够精确?在我的看法中,tf.argmax(probabilities,1)会在训练后给出答案。给出最可能的单词是模型训练的目标,因此它将是模型的输出。您可能需要微调我刚刚给您的函数调用所给出的索引,以从字典中获取单词。 - Guillaume Chevalier
1
如果您的模型是训练用于预测单词嵌入(以向量表示的单词),则需要有一种工具来反向嵌入您的单词。Word2vec和GloVe是有趣的预训练模型,因此可以使用它们。如果您的整个单词字典被嵌入为每个单词的独热向量,则从我的函数输出的数字是该单词在字典中的索引。 - Guillaume Chevalier
@GuillaumeChevalier @stackit 抱歉,只是为了澄清一下,你是说只要调用命令:correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)),就能预测出最有可能的值?y将是你想要进行预测的句子吗?抱歉,我仍然在从一个字符串转换成一个有效的单词列表并给出一些概率的过程中遇到困难。 - jlarks32
你似乎想要预测句子而不仅仅是单个单词。我建议你看一下Udacity的深度学习课程,其中有一个作业需要编写word2vec模型本身:https://classroom.udacity.com/courses/ud730/ 这可以帮助你弄清楚如何编写seq2seq模型以更好地预测句子,并使用动态解码器。这里也有更多信息:https://www.youtube.com/watch?v=RIR_-Xlbp7s - Guillaume Chevalier
如果您使用外部的word2vec来处理嵌入式预测,而不是自己编写单词概率列表,可能会简化事情[但我不太确定 - 在开始编码之前,我会多读一些资料]。 - Guillaume Chevalier

1
你需要找到概率的argmax,并通过反转word_to_id映射将索引翻译回单词。为使其工作,必须在模型中保存概率,然后从run_epoch函数中获取它们(也可以仅保存argmax本身)。以下是代码片段:
inverseDictionary = dict(zip(word_to_id.values(), word_to_id.keys()))

def run_epoch(...):
  decodedWordId = int(np.argmax(logits))
  print (" ".join([inverseDictionary[int(x1)] for x1 in np.nditer(x)])  
    + " got" + inverseDictionary[decodedWordId] + 
    + " expected:" + inverseDictionary[int(y)])

查看完整实现,请访问https://github.com/nelken/tf


以上代码不适用于当前版本的 TensorFlow。 - pr338

-1

函数返回概率而不是单词本身实际上是一个优势。因为它使用了一个包含相关概率的单词列表,你可以进行进一步处理,提高结果的准确性。

回答你的问题: 你可以遍历单词列表,并让程序显示具有最高概率的单词。


是的,我理解了。你能为此编写一个示例代码吗?另外,词汇量可能非常大,对于词汇表中的每个单词进行迭代实际上是不可行的。 - stackit
机器学习本质上是一种高计算方法来解决问题。根据您如何训练模型,您可能已经多次迭代词汇表。在典型的机器上,您可以在几秒钟内迭代几百万个字符串,因此这可能不是无法实现的。如果您想缩短计算时间(并随之提高性能),可以实现一种方法,仅在找到具有足够大概率的结果时停止迭代。 - Cristian F
在训练时没问题,但在生产使用中不行。 - stackit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接