将 Pytorch LSTM 的状态参数转换为 Keras LSTM
Posted
技术标签:
【中文标题】将 Pytorch LSTM 的状态参数转换为 Keras LSTM【英文标题】:Converting state-parameters of Pytorch LSTM to Keras LSTM 【发布时间】:2018-06-29 21:23:45 【问题描述】:我试图将现有的经过训练的 PyTorch 模型移植到 Keras。
在移植过程中,我卡在了 LSTM 层。
LSTM 网络的 Keras 实现似乎有三种状态类型的状态矩阵,而 Pytorch 实现有四种。
例如,对于具有 hidden_layers=64、input_size=512 & output size=128 状态参数的双向 LSTM,如下所示
Keras LSTM 的状态参数
[<tf.Variable 'bidirectional_1/forward_lstm_1/kernel:0' shape=(512, 256) dtype=float32_ref>,
<tf.Variable 'bidirectional_1/forward_lstm_1/recurrent_kernel:0' shape=(64, 256) dtype=float32_ref>,
<tf.Variable 'bidirectional_1/forward_lstm_1/bias:0' shape=(256,) dtype=float32_ref>,
<tf.Variable 'bidirectional_1/backward_lstm_1/kernel:0' shape=(512, 256) dtype=float32_ref>,
<tf.Variable 'bidirectional_1/backward_lstm_1/recurrent_kernel:0' shape=(64, 256) dtype=float32_ref>,
<tf.Variable 'bidirectional_1/backward_lstm_1/bias:0' shape=(256,) dtype=float32_ref>]
PyTorch LSTM 的状态参数
['rnn.0.rnn.weight_ih_l0', torch.Size([256, 512])],
['rnn.0.rnn.weight_hh_l0', torch.Size([256, 64])],
['rnn.0.rnn.bias_ih_l0', torch.Size([256])],
['rnn.0.rnn.bias_hh_l0', torch.Size([256])],
['rnn.0.rnn.weight_ih_l0_reverse', torch.Size([256, 512])],
['rnn.0.rnn.weight_hh_l0_reverse', torch.Size([256, 64])],
['rnn.0.rnn.bias_ih_l0_reverse', torch.Size([256])],
['rnn.0.rnn.bias_hh_l0_reverse', torch.Size([256])],
我试图查看这两种实现的代码,但不能理解太多。
有人可以帮我将 PyTorch 中的 4 组状态参数转换为 Keras 中的 3 组状态参数
【问题讨论】:
奇怪的是 Torch 在 LSTM 中有 4 个状态矩阵,考虑到模型应该有 3 个设计。 是的,LSTM 的 PyTorch 实现略有不同:pytorch.org/docs/0.3.0/nn.html?highlight=lstm#torch.nn.LSTM。有两组偏置参数。如果你想将 PyTorch 参数转换为 Keras,我的建议是关闭偏置参数。 【参考方案1】:他们真的没有什么不同。如果将 PyTorch 中的两个偏置向量相加,则方程将与 Keras 中实现的相同。
这是PyTorch documentation上的LSTM公式:
PyTorch 对输入转换(下标以 i
开头)和循环转换(下标以 h
开头)使用两个单独的偏置向量。
在 Keras LSTMCell
:
x_i = K.dot(inputs_i, self.kernel_i)
x_f = K.dot(inputs_f, self.kernel_f)
x_c = K.dot(inputs_c, self.kernel_c)
x_o = K.dot(inputs_o, self.kernel_o)
if self.use_bias:
x_i = K.bias_add(x_i, self.bias_i)
x_f = K.bias_add(x_f, self.bias_f)
x_c = K.bias_add(x_c, self.bias_c)
x_o = K.bias_add(x_o, self.bias_o)
if 0 < self.recurrent_dropout < 1.:
h_tm1_i = h_tm1 * rec_dp_mask[0]
h_tm1_f = h_tm1 * rec_dp_mask[1]
h_tm1_c = h_tm1 * rec_dp_mask[2]
h_tm1_o = h_tm1 * rec_dp_mask[3]
else:
h_tm1_i = h_tm1
h_tm1_f = h_tm1
h_tm1_c = h_tm1
h_tm1_o = h_tm1
i = self.recurrent_activation(x_i + K.dot(h_tm1_i,
self.recurrent_kernel_i))
f = self.recurrent_activation(x_f + K.dot(h_tm1_f,
self.recurrent_kernel_f))
c = f * c_tm1 + i * self.activation(x_c + K.dot(h_tm1_c,
self.recurrent_kernel_c))
o = self.recurrent_activation(x_o + K.dot(h_tm1_o,
self.recurrent_kernel_o))
输入转换中只添加了一个偏差。但是,如果我们将 PyTorch 中的两个偏差相加,这些方程将是等价的。
二偏 LSTM 是在 cuDNN 中实现的(参见 developer guide)。我真的对 PyTorch 不太熟悉,但我想这就是他们使用两个偏置参数的原因。在 Keras 中,CuDNNLSTM
层也有两个偏置权重向量。
【讨论】:
谢谢。我验证了它,你是对的。两个输出之间只有很小的差异(按 1E-7 的顺序)。另外在检查时我发现,Pytorch 使用 sigmoid 作为激活函数,而 Keras 默认使用 hard_sigmoid @harish2704 如果这个答案对您有所帮助(似乎是这样),您应该考虑接受它。 更新:我将我的 OCR 引擎的 Pytorch Model 移植到 Keras 并使用 Keras-js 成功地 run the trained model inside web-browser以上是关于将 Pytorch LSTM 的状态参数转换为 Keras LSTM的主要内容,如果未能解决你的问题,请参考以下文章
[Pytorch系列-53]:循环神经网络 - torch.nn.LSTM()参数详解
RuntimeError: Expected hidden[0] size (1, 1, 512), got (1, 128, 512) for LSTM pytorch