我想更好地理解Tensorflow的BasicLSTMCell中Kernel和Bias的形状。
@tf_export("nn.rnn_cell.BasicLSTMCell")class BasicLSTMCell(LayerRNNCell):input_depth = inputs_shape[1].valueh_depth = self._num_unitsself._kernel = self.add_variable( _WEIGHTS_VARIABLE_NAME, shape=[input_depth + h_depth, 4 * self._num_units])self._bias = self.add_variable( _BIAS_VARIABLE_NAME, shape=[4 * self._num_units], initializer=init_ops.zeros_initializer(dtype=self.dtype))
为什么kernel的形状是[input_depth + h_depth, 4 * self._num_units],而bias的形状是[4 * self._num_units]?可能是由于遗忘门、块输入、输入门和输出门这四个因素?为什么要将input_depth和h_depth相加呢?
关于我的LSTM网络的更多信息:
num_input = 12, timesteps = 820, num_hidden = 64, num_classes = 2.
使用tf.trainables_variables()我得到以下信息:
- 变量名:Variable:0 形状:(64, 2) 参数:128
- 变量名:Variable_1:0 形状:(2,) 参数:2
- 变量名:rnn/basic_lstm_cell/kernel:0 形状:(76, 256) 参数:19456
- 变量名:rnn/basic_lstm_cell/bias:0 形状:(256,) 参数:256
以下代码定义了我的LSTM网络。
def RNN(x, weights, biases): x = tf.unstack(x, timesteps, 1) lstm_cell = rnn.BasicLSTMCell(num_hidden) outputs, states = rnn.static_rnn(lstm_cell, x, dtype=tf.float32) return tf.matmul(outputs[-1], weights['out']) + biases['out']
回答:
首先,关于input_depth
和h_depth
的求和:RNN通常遵循类似于h_t = W*h_t-1 + V*x_t
的方程来计算时间t
的状态h
。也就是说,我们对上一个状态和当前输入进行矩阵乘法并将两者相加。这实际上相当于将h_t-1
和x_t
(我们称之为c
)拼接起来,将两个矩阵W
和V
(我们称之为S
)“堆叠”起来,并计算S*c
。
这样我们只需要一次矩阵乘法而不是两次;我认为这样可以更有效地进行并行化,因此出于性能考虑这样做。因为h_t-1
的大小是h_depth
,而x
的大小是input_depth
,我们需要将这两个维度相加以得到拼接后的向量c
的维度。
其次,你关于因子4来自于门的说法是正确的。这基本上与上述相同:我们不是为输入和每个门分别进行四次矩阵乘法,而是进行一次乘法,得到一个大的向量,这个向量是输入和所有四个门值的拼接。然后我们可以将这个向量分成四部分。在LSTM单元的源代码中,这在第627-633行发生。