20

在 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 进行序列分类”)

4

1 回答 1

26

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

在每个时间步,它需要两个输入:

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

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

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

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

正因为如此,keras 在循环层中也使用了两个 dropout 操作。(将应用于每个步骤的辍学)

  • 输入的第一次转换的辍学
  • 循环内核应用的 dropout

所以,实际上在 RNN 层中有两个 dropout 参数:

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

您可以在源代码中看到此GRUCell描述LSTMCell代码。


什么是正确的?

这对创造力是开放的。

你可以使用一个Dropout(...)层,它没有“错误”,但它也可能会丢弃“时间步”!(除非您noise_shape正确设置或使用SpatialDropout1D,目前尚未记录)

也许你想要,也许你不想要。如果您使用循环层中的参数,您将仅将 dropouts 应用于其他维度,而不会删除一个步骤。这对于循环层来说似乎是健康的,除非您希望您的网络学习如何处理包含间隙的序列(最后一句话是一个假设)。

此外,使用 dropout 参数,您将真正删除内核的一部分,因为“在每一步”中都会删除操作,而使用单独的层将使您的 RNN 在内部执行未删除的操作,因为您的 dropout 只会影响最终输出。

于 2018-06-06T13:23:26.957 回答