为什么我们在使用递归神经网络进行预测时进行采样

数据挖掘 lstm 统计数据 rnn 预言 可能性
2022-02-13 00:54:19

我训练了一个循环神经网络来预测句子中的下一个单词。

我训练过,现在我想预测,但有些事情我没有好起来。

我在许多教程中甚至在Keras 文档中都看到了它。

当我们想要预测时,我们从预测函数中获取概率,并将其传递给下面的示例函数。

def sample(preds, temperature=1.0):
    # helper function to sample an index from a probability array
    preds = np.asarray(preds).astype('float64')
    preds = np.log(preds) / temperature
    exp_preds = np.exp(preds)
    preds = exp_preds / np.sum(exp_preds)
    probas = np.random.multinomial(1, preds, 1)
    return np.argmax(probas)

我没有得到这个函数在做什么。

我知道 :

我的预测是一系列概率,因此,单词 indice 是概率最大的单词。

从函数中我可以看到他们正在做日志,然后是 exp,这就是我没有得到的。

他们为什么这样做?

我在很多教程中都看到了这一点,但没有人解释得很好。

也许我应该回到我的统计和概率课程。

请指出正确的方向。

2个回答

在我看来你有两个问题:

  • 为什么要使用采样从经过训练的 RNN 语言模型生成文本?
  • Keras 的这种特殊采样功能是如何工作的?

为什么使用采样从经过训练的 RNN 语言模型生成文本

训练语言模型后,您通常希望使用该模型生成新文本。对于单词级 RNN 语言模型,文本一次生成一个单词。在每一步中,模型都会输出整个词汇表的概率分布。使用玩具词汇,例如:

vocabulary=[catdogfrog]

模型在每个生成步骤的分布输出可能看起来像

predictions=[0.70.10.2]

向量中的每个条目对应于我们词汇表中的一个条目。

之后,由用户决定如何从这个分布中选择一个词作为生成文本中的下一个词。从分布中挑选单词的两种截然不同的方法是:

  1. 贪婪搜索:取概率最高的词(将选择“猫”)
  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)

最后,这将返回向量中最大元素的索引。该索引将对应于我们词汇表中的一个单词。


我希望这可以帮助您理解问题,或者更清楚地表达您需要额外解释的内容。

def sample(preds, temperature=1.0):
    # helper function to sample an index from a probability array
    # convert input to float64 array
    preds = np.asarray(preds).astype('float64') 
    #devide the logarythm of the predictions by temperature
    preds = np.log(preds) / temperature 
    # calculates e^preds for each pred in your list where e is Euler's number (approximately 2.718)
    exp_preds = np.exp(preds)
    # divide euler ^ xn / sum of euler ^xn
    preds = exp_preds / np.sum(exp_preds)
    # run random experiment eg: -> array([[4, 1, 7, 5, 2, 1]])
    probas = np.random.multinomial(1, preds, 1)
    # pull the highest value of array eg 7 (with the example above)
    return np.argmax(probas)