循环层一遍又一遍地执行相同的重复操作。
在每个时间步,它需要两个输入:
- 您的输入(序列的一个步骤)
- 内部输入(例如,可以是状态和上一步的输出)
请注意,输入和输出的维度可能不匹配,这意味着“您的输入”维度将不匹配“循环输入(之前的步骤/状态)”维度。
然后在每个循环时间步中,有两个具有两个不同内核的操作:
- 一个内核应用于“您的输入”以在兼容的维度上处理和转换它
- 另一个(keras 称为循环内核)应用于上一步的输入。
正因为如此,keras 在循环层中也使用了两个 dropout 操作。(将应用于每个步骤的辍学)
- 输入的第一次转换的辍学
- 循环内核应用的 dropout
所以,实际上在 RNN 层中有两个 dropout 参数:
dropout
, 应用于输入的第一个操作
recurrent_dropout
,应用于循环输入(先前的输出和/或状态)上的其他操作
您可以在源代码中看到此GRUCell
描述的LSTMCell
代码。
什么是正确的?
这对创造力是开放的。
你可以使用一个Dropout(...)
层,它没有“错误”,但它也可能会丢弃“时间步”!(除非您noise_shape
正确设置或使用SpatialDropout1D
,目前尚未记录)
也许你想要,也许你不想要。如果您使用循环层中的参数,您将仅将 dropouts 应用于其他维度,而不会删除一个步骤。这对于循环层来说似乎是健康的,除非您希望您的网络学习如何处理包含间隙的序列(最后一句话是一个假设)。
此外,使用 dropout 参数,您将真正删除内核的一部分,因为“在每一步”中都会删除操作,而使用单独的层将使您的 RNN 在内部执行未删除的操作,因为您的 dropout 只会影响最终输出。