Keras 中 LSTM 的return_sequences和return_states之间的区别

在本教程中,您将发现 Keras 深度学习库中 LSTM 层的返回序列和返回状态的区别和结果。

完成本教程后,您将了解:

  • 该返回序列返回每个输入时间步的隐藏状态输出。
  • 该返回状态返回最后一个输入时间步的隐藏状态输出和单元状态。
  • 可以同时使用返回序列和返回状态。

本教程分为 4 个部分:

  1. 长短期记忆
  2. 返回序列
  3. 返回状态
  4. 返回状态和序列

长短期记忆

长短期记忆(LSTM)是一个由内门组成的循环神经网络。与其他循环神经网络不同,该网络的内部门允许模型通过时间反向传播或 BPTT 成功训练,并避免梯度消失问题。

在 Keras 深度学习库中,可以使用LSTM() 类创建 LSTM 层。创建 LSTM 内存单元层允许指定层内的内存单元数。

层内的每个单元或单元都有一个内部单元状态,通常缩写为“ c ”,并输出一个隐藏状态,通常缩写为“ h ”。

Keras API 允许您访问这些数据,这在开发复杂的循环神经网络架构(例如编码器-解码器模型)时可能很有用甚至是必需的。

返回序列

每个 LSTM 单元将为每个输入输出一个隐藏状态h

h = LSTM(X)

我们可以在 Keras 中使用一个非常小的模型来证明这一点,该模型具有一个 LSTM 层,该层本身包含一个 LSTM 单元。

在此示例中,我们将有一个具有 3 个时间步长的输入样本,并在每个时间步长观察到一个特征:

t1 = 0.1
t2 = 0.2
t3 = 0.3

下面列出了完整的示例。

from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1 = LSTM(1)(inputs1)
model = Model(inputs=inputs1, outputs=lstm1)
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))

运行该示例会为具有 3 个时间步长的输入序列输出单个隐藏状态。鉴于 LSTM 权重和单元状态的随机初始化,您的特定输出值会有所不同。

[[-0.0953151]]

可以访问每个输入时间步的隐藏状态输出。

这可以通过在定义 LSTM 层时将return_sequences属性设置为True来完成,如下所示:

LSTM(1, return_sequences=True)

我们可以用这个改变来更新前面的例子。下面提供了完整的代码清单。

from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1 = LSTM(1, return_sequences=True)(inputs1)
model = Model(inputs=inputs1, outputs=lstm1)
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))

运行该示例会返回一个包含 3 个值的序列,该层中单个 LSTM 单元的每个输入时间步都有一个隐藏状态输出。

[[[-0.02243521]
  [-0.06210149]
  [-0.11457888]]]

返回状态

LSTM 单元或单元层的输出称为隐藏状态。

这很令人困惑,因为每个 LSTM 单元都保留了一个不输出的内部状态,称为单元状态或c

通常,我们不需要访问单元状态,除非我们正在开发复杂的模型,其中后续层可能需要使用另一层的最终单元状态初始化其单元状态,例如在编码器-解码器模型中。

Keras 向 LSTM 层提供 return_state 参数,该层将提供对隐藏状态输出 ( state_h ) 和单元状态 ( state_c ) 的访问。例如:

lstm1, state_h, state_c = LSTM(1, return_state=True)

这可能看起来令人困惑,因为 lstm1 和state_h都引用相同的隐藏状态输出。这两个张量分开的原因将在下一节中变得清楚。

我们可以通过下面列出的工作示例演示对 LSTM 层中单元格的隐藏状态和单元格状态的访问。

from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1, state_h, state_c = LSTM(1, return_state=True)(inputs1)
model = Model(inputs=inputs1, outputs=[lstm1, state_h, state_c])
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))

运行示例返回 3 个数组:

  1. 最后一个时间步的 LSTM 隐藏状态输出。
  2. 最后一个时间步的 LSTM 隐藏状态输出(再次)。
  3. 最后一个时间步的 LSTM 单元状态。
[array([[ 0.10951342]], dtype=float32),
array([[ 0.10951342]], dtype=float32),
array([[ 0.24143776]], dtype=float32)]

隐藏状态和单元状态又可以用于初始化具有相同单元数的另一个 LSTM 层的状态。

返回状态和序列

我们可以同时访问隐藏状态序列和单元状态。这可以通过将 LSTM 层配置为返回序列和返回状态来完成。

lstm1, state_h, state_c = LSTM(1, return_sequences=True, return_state=True)

下面列出了完整的示例。

from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1, state_h, state_c = LSTM(1, return_sequences=True, return_state=True)(inputs1)
model = Model(inputs=inputs1, outputs=[lstm1, state_h, state_c])
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))

运行这个例子,我们现在可以看到为什么 LSTM 输出张量和隐藏状态输出张量是分开声明的。

该层返回每个输入时间步的隐藏状态,然后分别返回最后一个时间步的隐藏状态输出和最后一个输入时间步的单元状态。

这可以通过查看返回序列(第一个数组)中的最后一个值与隐藏状态(第二个数组)中的值匹配来确认。

[array([[[-0.02145359],
        [-0.0540871 ],
        [-0.09228823]]], dtype=float32),
array([[-0.09228823]], dtype=float32),
array([[-0.19803026]], dtype=float32)]

概括

在本教程中,您发现了 Keras 深度学习库中 LSTM 层的返回序列和返回状态的差异和结果。

具体来说,了解到:

  • 该返回序列返回每个输入时间步的隐藏状态输出。
  • 该返回状态返回最后一个输入时间步的隐藏状态输出和单元状态。
  • 可以同时使用返回序列和返回状态。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>