使用Keras和LSTM/GRU单元进行Dropout

22

在Keras中,您可以像这样指定一个dropout层:

model.add(Dropout(0.5))

但是使用GRU单元,你可以在构造函数中指定dropout参数:

model.add(GRU(units=512,
        return_sequences=True,
        dropout=0.5,
        input_shape=(None, features_size,)))

有什么区别?一个比另一个更好吗?

Keras的文档中,它将其作为单独的dropout层添加(参见“使用LSTM进行序列分类”)

1个回答

27

循环层一遍又一遍地执行相同的重复操作。

在每个时间步中,它有两个输入:

  • 您的输入(序列的一个步骤)
  • 内部输入(可以是状态和上一步的输出)

请注意,输入和输出的维度可能不匹配,这意味着“您的输入”维度将不匹配“循环输入(上一步/状态)”维度。

然后,在每个循环时间步中,有两个具有两个不同内核的操作:

  • 一个内核应用于“您的输入”以处理并转换为兼容维度
  • 另一个(由keras称为循环内核)应用于上一步的输入。

因此,keras在循环层中还使用了两个丢失操作。 (将应用于每个步骤的丢失)

  • 第一个用于处理您的输入的转换
  • 另一个用于应用循环内核

因此,实际上RNN层中有两个丢失参数:

  • dropout,应用于对输入的第一次操作
  • recurrent_dropout,应用于对循环输入(先前的输出和/或状态)的其他操作

您可以在源代码中看到这个描述已编码为GRUCellLSTMCell


什么是正确的?

这取决于创造力。

你可以使用一个Dropout(...)层,这并不是“错误”的,但它可能会丢弃“时间步”!(除非你正确设置noise_shape或使用SpatialDropout1D,目前还没有文档说明)

也许你想要它,也许你不想要。如果你在循环层中使用参数,则只会对其他维度应用dropout,而不会丢失任何一步。这对于循环层似乎是健康的,除非你希望你的网络学习如何处理包含间隙的序列(这最后一句话是一种推测)。

此外,使用dropout参数,你将真正地丢弃核的部分,因为操作在每个步骤中都被丢弃了,而使用单独的层将使你的RNN在内部执行非丢弃操作,因为你的dropout仅影响最终输出。


谢谢Daniel,你对dropout的解释与这里给出的答案相符:https://dev59.com/zFcP5IYBdhLWcg3wDmUh显然,在单元格构造函数中设置意味着我也可以指定循环丢失,所以我想我会将其设置为构造函数的一部分。另外一个问题是,当我进行.evaluate和.predict时,我假设Keras会自动将dropout概率设置为零?我之前编写过TensorFlow代码,需要自己指定,但我认为Keras会为我完成...? - BigBadMe
1
是的,Keras 在其代码中使用条件 K.in_training_phase(expression_for_training,express_for_non_training)。而且,Dropout 只在训练阶段应用。 - Daniel Möller
@DanielMöller - 抱歉我是一个完全的初学者。根据我从上面理解的,您建议在lstm中使用dropout,并删除其外部的dropouts,如下所述:model = Sequential() model.add(LSTM(256, input_shape=(trainX.shape[1], trainX.shape[2]), Dropout=0.1, return_sequences=True)) model.add(LSTM(128, Dropout=0.1, return_sequences=True)) model.add(LSTM(32, return_sequences=True)) # model.add(Dropout(0.1)) model.add(Dense(14)) model.add(Dense(trainY.shape[1])) model.compile(optimizer='adam', loss='mean_squared_error') - SamV
@SamirVinchurkar,神经网络没有绝对的答案。这是一个你必须通过实验来做出选择并看看哪种方法能给你最好的结果的过程。 - Daniel Möller
@DanielMöller 谢谢!--我理解了,我只是想根据您的经验寻求建议。我曾经使用 ReLu,并尝试除去 0、裁剪、lr、改变训练数据大小等方法,但 tanh 真的对我有帮助。让我更具体地说明问题:您是否建议在 LSTM 中使用循环丢失,因为在外部使用会导致训练数据丢失(因此可能会降低性能)?或者我理解错了? - SamV
显示剩余5条评论

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