在我看来你有两个问题:
- 为什么要使用采样从经过训练的 RNN 语言模型生成文本?
- Keras 的这种特殊采样功能是如何工作的?
为什么使用采样从经过训练的 RNN 语言模型生成文本
训练语言模型后,您通常希望使用该模型生成新文本。对于单词级 RNN 语言模型,文本一次生成一个单词。在每一步中,模型都会输出整个词汇表的概率分布。使用玩具词汇,例如:
vocabulary=⎡⎣⎢catdogfrog⎤⎦⎥
模型在每个生成步骤的分布输出可能看起来像
predictions=⎡⎣⎢0.70.10.2⎤⎦⎥
向量中的每个条目对应于我们词汇表中的一个条目。
之后,由用户决定如何从这个分布中选择一个词作为生成文本中的下一个词。从分布中挑选单词的两种截然不同的方法是:
- 贪婪搜索:取概率最高的词(将选择“猫”)
- 抽样:从分布中抽样,考虑概率(会随机选择一个词,但“猫”被选中的机会最高)
因此,搜索将返回一个非常可能的字符串(并且每次我们尝试时都返回相同的字符串),而采样将返回一些可能但更多样的文本。通常,这意味着采样会导致更“有趣”的文本。
这个特定的采样功能是如何工作的?
据我所知,这个采样函数的输入是softmax之后的归一化概率向量,例如
np.array([0.7, 0.1, 0.2])
以下是关于每一行的一些解释:
preds = np.asarray(preds).astype('float64')
这只是确保其他类似数组的对象,例如 Python 列表,作为输入工作,但被转换为正确的 numpy 数组类型。
preds = np.log(preds) / temperature
preds是通过将 softmax 函数应用于模型网络的最终输出(这些最终值称为logits)而创建的概率分布。Logits 被假定为非归一化的对数概率,应用 softmax 对其进行归一化。
这是 softmax with temperature 的问题,因为它是非归一化的 logits 应该除以 temperature:
qi=exp(zi/T)∑jexp(zj/T)
因此,np.log(preds)只需将值移回日志空间即可。如果没有这个,我们就不会缩放实际的网络输出,而是取幂值。
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
这两行只是应用了 softmax 函数,不管之前或之后发生了什么。
probas = np.random.multinomial(1, preds, 1)
这个具有这些特定参数的函数正在对一个单热向量进行采样,例如
predictions=⎡⎣⎢100⎤⎦⎥
其中每个索引为 1 的概率由preds.
return np.argmax(probas)
最后,这将返回向量中最大元素的索引。该索引将对应于我们词汇表中的一个单词。
我希望这可以帮助您理解问题,或者更清楚地表达您需要额外解释的内容。