代码之家  ›  专栏  ›  技术社区  ›  Janina Nuber

经常性NNs:参数共享有什么意义?填充难道不起作用吗?

  •  7
  • Janina Nuber  · 技术社区  · 7 年前

    以下是我如何理解RNN中的参数共享点:

    在常规前馈神经网络中,每个输入单元都被分配一个单独的参数,这意味着输入单元(特征)的数量对应于要学习的参数的数量。在处理例如图像数据时,输入单元的数量在所有训练示例中都是相同的(通常是恒定的像素大小*像素大小*rgb帧)。

    然而,像句子这样的顺序输入数据可能具有高度不同的长度,这意味着参数的数量将不同,这取决于处理的示例句子。这就是为什么参数共享对于有效地处理顺序数据是必要的:它确保模型始终具有相同的输入大小,而不管序列长度如何,因为它是根据从一个状态到另一个状态的转换来指定的。因此,可以在每个时间步对相同的权重(输入到隐藏权重、隐藏到输出权重、隐藏到隐藏权重)使用相同的转换函数。最大的优点是,它允许泛化到训练集中未出现的序列长度。

    我的问题是:

    1. 如上所述,我对RNN的理解是否正确?
    2. 在我为LSTM查看的Keras中的实际代码示例中,他们首先将句子填充到相等的长度。通过这样做,这难道不会冲走RNN中参数共享的全部目的吗?
    1 回复  |  直到 3 年前
        1
  •  5
  •   Kilian Obermeier    5 年前

    参数共享

    能够有效地处理不同长度的序列并不是参数共享的唯一优点。正如你所说,你可以通过填充来实现这一点。参数共享的主要目的是减少模型必须学习的参数。这就是使用RNN的全部目的。

    如果您将为每个时间步学习不同的网络,并将第一个模型的输出反馈给第二个模型等,那么您将得到一个常规的前馈网络。对于20个时间步,您需要学习20个模型。在卷积网络中,参数由卷积滤波器共享,因为当我们可以假设图片的不同区域(例如简单边缘)有相似的有趣图案时。这大大减少了我们必须学习的参数数量。类似地,在序列学习中,我们通常可以假设在不同的时间步有相似的模式。比较 'Yesterday I ate an apple' 'I ate an apple yesterday' . 这两句话的意思相同,但 'I ate an apple' 零件发生在不同的时间步。通过共享参数,您只需了解该部分的含义一次。否则,您必须在模型中可能出现的每个时间步骤中学习它。

    共享参数有一个缺点。因为我们的模型在每个时间步都对输入应用相同的转换,所以现在必须学习对所有时间步都有意义的转换。所以,它必须记住,哪个词出现在哪个时间步,即。 'chocolate milk' 不应导致与相同的隐藏和内存状态 'milk chocolate' . 但与使用大型前馈网络相比,这个缺点很小。

    衬料

    至于填充序列:主要目的不是让模型直接预测不同长度的序列。正如您所说,这可以通过使用参数共享来实现。填充用于有效的训练,特别是在训练期间保持较低的计算图。在没有填充的情况下,我们有两种培训选项:

    1. 我们展开每个训练样本的模型。因此,当我们有一个长度为7的序列时,我们将模型展开为7个时间步,输入序列,通过7个时间步进行反向传播,并更新参数。这在理论上似乎很直观。但在实践中,这是低效的,因为TensorFlow的计算图不允许重复出现,它们是前馈的。
    2. 另一种选择是在开始训练之前创建计算图。我们让它们共享相同的权重,并为训练数据中的每个序列长度创建一个计算图。但当我们的数据集有30个不同的序列长度时,这意味着在训练期间有30个不同的图,因此对于大型模型,这是不可行的。

    这就是为什么我们需要填充物。我们将所有序列填充到相同的长度,然后在开始训练之前只需要构造一个计算图。当序列长度很短和很长(例如5和100)时,可以使用 bucketing and padding . 这意味着,将序列填充到不同的桶长度,例如[5、20、50、100]。然后,为每个桶创建一个计算图。这样做的好处是,您不必填充长度为5到100的序列,因为您将浪费大量时间“学习”其中的95个填充标记。