Tensorflow LSTM return 是什么?

What does Tensorflow LSTM return?

我正在使用 encoder/decoder 模式编写德语->英语翻译器,其中编码器通过传递其最后一个 LSTM 层的状态输出连接到解码器 作为解码器LSTM的输入状态。

不过我卡住了,因为我不知道如何解释编码器的 LSTM 的输出。一个小例子:

tensor = tf.random.normal( shape = [ 2, 2, 2 ])
lstm = tf.keras.layers.LSTM(units=4, return_sequences=True, return_state=True )
result = lstm( ( tensor )
print( "result:\n", result )

在 Tensorflow 2.0.0 中执行此操作会产生:

result:
[
<tf.Tensor: id=6423, shape=(2, 2, 3), dtype=float32, numpy=
array([[[ 0.05060377, -0.00500009, -0.10052835],
        [ 0.01804499,  0.0022153 ,  0.01820258]],
       [[ 0.00813384, -0.08705016,  0.06510869],
        [-0.00241707, -0.05084776,  0.08321179]]], dtype=float32)>,
<tf.Tensor: id=6410, shape=(2, 3), dtype=float32, numpy=
array([[ 0.01804499,  0.0022153 ,  0.01820258],
       [-0.00241707, -0.05084776,  0.08321179]], dtype=float32)>,
<tf.Tensor: id=6407, shape=(2, 3), dtype=float32, numpy=
array([[ 0.04316794,  0.00382055,  0.04829971],
       [-0.00499733, -0.10105743,  0.1755833 ]], dtype=float32)>
]

结果是三个张量的列表。第一个似乎是所有的输出 return_sequences=True 选择的隐藏状态。我的问题是:result中第二个和第三个Tensor的解释是什么?

Keras 中的 LSTM 单元为您提供三个输出:

  • 一个输出状态o_t(第一个输出)
  • 隐藏状态h_t(第二个输出)
  • 一个细胞状态c_t(第三个输出)

你可以在这里看到一个 LSTM 单元:

输出状态通常传递给任何上层,但不会传递给右边的任何层。您将在预测最终输出时使用此状态。

单元状态是从先前的 LSTM 单元传输到当前 LSTM 单元的信息。当它到达 LSTM 单元时,单元决定是否应删除来自单元状态的信息,即我们将“忘记”某些状态。这是通过遗忘门完成的:该门将当前特征 x_t 作为输入,并将前一个单元格的隐藏状态 h_{t-1} 作为输入。它输出一个概率向量,我们将其与最后一个细胞状态 c_{t-1} 相乘。在确定了我们想要忘记的信息后,我们用输入门更新单元状态。该门将当前特征 x_t 和前一个单元格的隐藏状态 h_{t-1} 作为输入,并产生一个输入,该输入被添加到最后一个单元格状态(我们已经忘记了来自它的信息)。这个总和就是新的细胞状态c_t。 为了获得新的隐藏状态,我们将细胞状态与隐藏状态向量结合起来,它又是一个概率向量,它决定细胞状态中的哪些信息应该被保留,哪些应该被丢弃。

正如您正确解释的那样,第一个张量是所有隐藏状态的输出。

第二张量是隐藏输出,即$h_t$,作为神经网络的短期记忆 第三个张量是单元输出,即$c_t$,作为神经网络的长期记忆

keras-documentation中写着

whole_seq_output, final_memory_state, final_carry_state = lstm(inputs)

不幸的是,他们不使用术语隐藏和细胞状态。在他们的术语中,记忆状态是短期记忆,即隐藏状态。携带状态通过所有LSTM单元,即它是单元状态。

我们也可以使用 source code of the LSTM cell 来验证这一点,其中向前的一步由

给出
def step(cell_inputs, cell_states):
    """Step function that will be used by Keras RNN backend."""
    h_tm1 = cell_states[0]   #previous memory state
    c_tm1 = cell_states[2]   #previous carry state

    z = backend.dot(cell_inputs, kernel)
    z += backend.dot(h_tm1, recurrent_kernel)
    z = backend.bias_add(z, bias)

    z0, z1, z2, z3 = array_ops.split(z, 4, axis=1)

    i = nn.sigmoid(z0)
    f = nn.sigmoid(z1)
    c = f * c_tm1 + i * nn.tanh(z2)
    o = nn.sigmoid(z3)

    h = o * nn.tanh(c)
    return h, [h, c]

从公式中我们很容易看出,第一和第二个输出是output/hidden状态,第三个输出是细胞状态。它还指出,他们将隐藏状态命名为“记忆状态”,将细胞状态命名为“携带状态”