tensorflow - tf.keras.layers.LSTM 参数的含义
问题描述
我无法理解APILSTM
中的一些层参数。tf.keras.layers
我正在研究使用CuDNNLSTM
层而不是LSTM
层(以加快训练速度),但在我致力于CuDNN
层之前,我想全面了解使用 aCuDNNLSTM
而不是LSTM
层而丢失的参数。我已经阅读了文档,但他们似乎假设了一些LSTM
我没有的 s 的先验知识。
我列出了CuDNNLSTM
没有(LSTM
有)的参数,并分别穿插了我对它们的问题。
activation
recurrent_activation
activation
和 和有什么不一样recurrent_activation
?我假设它与单元格的激活与全LSTM
层的激活有关,但我不确定。
use_bias
- 如果
use_bias
为真,这种偏差在哪里应用?
- 如果
dropout
recurrent_dropout
dropout
同样,和 和有什么区别recurrent_dropout
?如果recurrent_dropout
是 LSTM 单元之间的 dropout,那对我来说没有意义,因为你会忽略之前的输出,我认为这会破坏拥有 RNN 的目的。- 这些 dropout 参数中的任何一个都可以在 LSTM 层之前/之后替换为 dropout 层(即
tf.keras.models.sequential([Input(...), LSTM(...), Dropout(0.5)])
或tf.keras.models.sequential([Input(...), Dropout(0.5), LSTM(...)])
代替tf.keras.models.sequential([Input(...), LSTM(..., dropout=0.5)])
)
implementation
- 我理解为什么这个参数不在
CuDNN
层中,因为它可能会使并行化变得更加困难。但是,在LSTM
s 中,这会影响结果吗(即使用相同的种子,会implementation=1
收敛到与 相同或不同的结果implementation=2
)?
- 我理解为什么这个参数不在
unroll
我已经阅读了很多关于LSTM
s 的内容,并且正处于我决定开始训练事物的地步,否则我不会吸收更多的假设性知识。我在建模方面也尝试了很多东西,但是我正在训练的网络非常简单,所以似乎没有任何影响结果。
解决方案
activation
对比recurrent_activation
如果你看一下LSTM 方程。activation
(默认为sigmoid
)指的是用于门的激活(即输入/忘记/输出),recurrent_activation
(默认为tanh
)指的是用于其他事物的激活(例如单元格输出 h)。
我可以直观地解释为什么需要两个。对于门,0-1 之间的范围听起来很直观,因为门可以打开或关闭或在中间,但不是负数(因此sigmoid
)。然而,单元格输出将更具表现力并导致较少的饱和度,因为它的范围在 -1 和 1 之间(因此tanh
)。它也可能有助于解决消失的梯度。但我对此并不完全确定。
use_bias
如果use_bias
为真,方程中将有一个+b
(例如i_t = sigma(x_t Ui + h_t-1 Wi + bi)
)。如果没有,就不会有偏见(例如i_t = sigma(x_t Ui + h_t-1 Wi)
)。就个人而言,我总是使用偏见。
dropout
对比recurrent_dropout
需要dropout
并且recurrent_dropout
是,在时间维度上应用 dropout 可能是非常灾难性的,因为您正在影响模型的内存。然而dropout
,应用输入数据几乎就是我们日常使用前馈模型所做的事情。所以,
dropout
: 对输入数据应用 dropout 掩码 (x
)recurrent_dropout
: 对先前的状态数据应用 dropout 掩码 (h_t-1
)
implementation
该实现提供了不同的方法来计算相同的事物。差异的需要可能是不同的内存要求。
implementation=1
- 在这里,计算就像您编写以下方程一样完成。换句话说,分四个步骤进行。
i_t = sigma(x_t Ui + h_t-1 Wi + bi)
f_t = sigma(x_t Uf + h_t-1 Wf + bf)
o_t = sigma(x_t Uo + h_t-1 Wo + bo)
tilde{c}_t = tanh(x_c Uc + h_t-1 Wc + bc)
- 在这里,计算就像您编写以下方程一样完成。换句话说,分四个步骤进行。
implementation=anything else
- 您可以一次性完成上述计算,
z = x_t concat(Ui, Uf, Uo, Uc)
z += h_t-1 concat(Wi, Wf, Wo, Wc)
z += concat(bi, bf, bo, bc)
- 应用激活
- 您可以一次性完成上述计算,
所以第二种实现非常有效,因为只发生了两次矩阵乘法。
unroll
如果为真,它将在时间维度上展开 RNN 并在没有循环的情况下进行计算(这将是内存密集型的)。如果为 false,这将通过一个for
循环来完成,这将花费更长的时间但更少的内存密集型。
我提到的源代码可以在这里找到。希望这可以澄清它。
推荐阅读
- javascript - 有没有办法只接受字母而不是数字?如果给出数字,它应该显示验证错误,因为它只需要字母
- nltk - 调整 NLTK 句子标记器在括号中保留句子
- firebase - 什么是授权重定向 URI?
- java - 如何使用 thymeleaf 在具有动态列的数据表中显示输入值
- amazon-web-services - 如何在云端应用 CDN - 路由器 53 => lightsail 实例
- java - getString() 导致应用程序崩溃。bundle.getArgument() 不为空
- php - 如何在网上商店隐藏某些产品,但它必须可供购买
- c - 声明无效
- python - 为什么选择 Python 熊猫?
- sql-server - 从 SQL Server 插入一些数据的表中读取数据的问题