2

最近一直在尝试基于这篇文章实现RNNLM 。有一个带有一些 LSTM 分解技巧的实现,但类似于作者的原始实现。

序言

1)数据集被分割成文件,然后文件的行在训练时被打乱,在测试时被顺序输入。(链接):

# deterministic at test time, non deterministic at train time
if not self._deterministic:
    random.shuffle(lines)

2)批次连续成型

* 符号代表句子的开始\结尾。每个矩阵代表一个巴赫。代码链接。所以:

  1. 如果句子长于 num_steps,则在同一行的下一批继续。

  2. 如果句子较短,则批处理行正在填充另一个句子。

3)他们计算批量平均损失。num_steps - LSTM 的内存。代码

# loss_shape = [batch_size * num_steps]
# 1D tensor, reshaped 2d tensor with dims of [batch_size, num_steps]
loss = tf.reduce_mean(loss)

4) LSTM 单元在每次训练迭代后更新,并在评估时归零。

他们将其声明为局部变量声明

然后它会在火车时间更新。并在评估时归零

5)在评估时间,作者以这种方式计算困惑度(链接):

for i, (x, y) in enumerate(data_iterator):
    # get a batch
    loss = sess.run(model.loss, {model.x: x, model.y: y})
    loss_nom += loss
    loss_den += 1
    loss = loss_nom / loss_den
    sys.stdout.write("%d: %.3f (%.3f) ... " % (i, loss, np.exp(loss)))
    sys.stdout.flush()
    sys.stdout.write("\n")

这意味着他们测量批量平均困惑度。

话虽如此,我有两个主要问题。

问题

  1. 考虑序言 1)、2) 和 4)。

为什么批次是这样形成的?

LSTM 单元不会在每个句子之后归零,因此它会保留前一个句子的记忆。

在顶部的示例中,当神经网络处理第 №1 批次时,第 2 行表示单词“Half”,它会记住单词 Music 和 start\end 标记的上下文。如果句子没有被打乱并且是真实的文本,这可能是有意义的,但是它们打乱并且没有相互连接。

我实现了这两种方法,无限批次提供更好的性能。

  1. 考虑序言 3) 和 5)。

为什么我们要估计批平均困惑度?

考虑到第一个问题,我不清楚当我们以这种方式测量困惑度时,我们真的可以估计我们的模型有多好。但是句子平均困惑似乎更有效。

如果我的逻辑有缺陷,如果您指出这一点,我将不胜感激。

4

0 回答 0