代码之家  ›  专栏  ›  技术社区  ›  harish2704

将Pytorch LSTM的状态参数转换为Keras LSTM

  •  11
  • harish2704  · 技术社区  · 7 年前

    我试图将一个现有的经过训练的PyTorch模型移植到Keras中。

    在移植过程中,我被困在LSTM层。

    LSTM网络的Keras实现似乎有三种状态类型的状态矩阵,而Pytorch实现有四种。

    例如,对于隐藏层为64的双向LSTM,输入大小为512&输出大小=128个状态参数,其中如下所示

    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组状态参数吗

    1 回复  |  直到 7 年前
        1
  •  12
  •   Yu-Yang    7 年前

    他们真的没什么不同。如果将Pytork中的两个偏差向量求和,则方程将与Keras中实现的方程相同。

    这是上的LSTM公式 PyTorch documentation :

    enter image description here

    PyTorch使用两个单独的偏移向量进行输入变换(下标以开头 i )和循环变换(下标以 h ).

    在科拉斯 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 ). 我真的不太熟悉Pytork,但我想这就是为什么他们使用两个偏差参数。在凯拉斯 CuDNNLSTM 层还具有两个偏移权重向量。