尽管 SimpleRNN 层直观,但在学习跨越长序列的模式时表现不佳。这主要是由于梯度消失问题,其中早期输入的影响在反向传播过程中迅速减弱,使得网络难以根据长距离依赖关系调整权重。为克服这一重要局限,Sepp Hochreiter 和 Jürgen Schmidhuber 于 1997 年开发了一种更复杂的循环架构,称为长短期记忆(LSTM)网络。LSTM 专门设计用于长时间记忆信息,使其在多种序列建模任务中非常有效。LSTM 的核心改进在于其内部结构。与只有一个简单循环连接和变换的 SimpleRNN 单元不同,一个 LSTM 单元包含一个记忆单元(或称单元状态)和多个门。可以将单元状态(常用 $C_t$ 表示)看作网络的长期记忆。它可以使信息在多个时间步中相对不变地传递。这些门是特殊的神经网络组件,它们像控制器一样,调节信息进出此单元状态的流动。它们学习在每个时间步保留哪些信息、丢弃哪些信息以及输出哪些信息。让我们看看 LSTM 单元在时间步 $t$ 的主要组成部分:门LSTM 单元通常有三个主要的门来控制信息流动。这些门使用 sigmoid 激活函数,输出介于 0 和 1 之间的值。接近 0 的值表示“不让任何信息通过”,而接近 1 的值表示“让所有信息通过”。它们将当前输入 $x_t$ 和前一个隐藏状态 $h_{t-1}$ 作为输入。遗忘门 ($f_t$): 此门决定应从单元状态中移除哪些信息。它查看 $h_{t-1}$ 和 $x_t$,并为前一个单元状态 $C_{t-1}$ 中的每个数字输出一个介于 0 和 1 之间的值。1 表示“完全保留此信息”,而 0 表示“完全清除此信息”。输入门 ($i_t$): 此门决定应在单元状态中存储哪些新信息。它由两部分组成:一个 sigmoid 层决定更新哪些值(输出 $i_t$)。一个 tanh 层创建一个新的候选值向量 $\tilde{C}_t$,这些值可以被添加到状态中。tanh 函数输出介于 -1 和 1 之间的值。输出门 ($o_t$): 此门决定下一个隐藏状态 $h_t$ 应是什么。输出将基于过滤后的单元状态。首先,一个 sigmoid 层决定单元状态的哪些部分要输出。然后,当前单元状态 $C_t$ 通过 tanh(将值推到 -1 和 1 之间)并乘以 sigmoid 门 ($o_t$) 的输出。这个过滤后的版本成为隐藏状态 $h_t$,它被传递到下一个时间步,也可以用作当前时间步的输出。单元状态 ($C_t$)单元状态就像信息的传送带。它直接沿着整个时间步链条运行,只有门控制的少量线性交互。遗忘门选择性地移除前一个单元状态 $C_{t-1}$ 中的信息,而输入门选择性地添加新的候选信息 $\tilde{C}_t$。更新方式如下:$$ C_t = (f_t * C_{t-1}) + (i_t * \tilde{C}_t) $$这里, $*$ 表示元素级乘法。第一项 ($f_t * C_{t-1}$) 表示从前一个状态保留的信息,第二项 ($i_t * \tilde{C}_t$) 表示添加的新信息。与 SimpleRNN 中重复的矩阵乘法和非线性变换相比,这种结构使得信息更容易长时间保持。隐藏状态 ($h_t$)隐藏状态 $h_t$ 根据过滤后的单元状态 $C_t$ 计算得出,并由输出门 $o_t$ 控制。$$ h_t = o_t * \tanh(C_t) $$这个 $h_t$ 随后被传递给下一个时间步 ($t+1$) 的 LSTM 单元,也可以用作当前时间步 $t$ 的输出预测。digraph G { rankdir=TB; node [shape=box, style=rounded, fontname="sans-serif"]; splines=ortho; newrank=true; compound=true; bgcolor="transparent"; edge [fontname="sans-serif"]; subgraph cluster_lstm { label="LSTM 单元 (t)"; fontname="sans-serif"; color="#adb5bd"; bgcolor="#e9ecef"; node [style="rounded,filled"]; C_t [label="Ct", shape=cylinder, fillcolor="#96f2d7", color="#12b886"]; h_t [label="ht", shape=parallelogram, fillcolor="#ffd8a8", color="#f76707"]; subgraph cluster_gates { label="门"; color="#ced4da"; bgcolor="#f8f9fa"; node [fillcolor="#a5d8ff", color="#1c7ed6"]; forget_gate [label="遗忘门 (σ)"]; input_gate_sig [label="输入门 (σ)"]; input_gate_tanh [label="输入门 (tanh)"]; output_gate [label="输出门 (σ)"]; } x_t [label="xt", shape=parallelogram, style="filled", fillcolor="#ffc9c9", color="#f03e3e"]; h_prev [label="ht-1", shape=parallelogram, style="filled", fillcolor="#ffd8a8", color="#f76707"]; C_prev [label="Ct-1", shape=cylinder, style="filled", fillcolor="#96f2d7", color="#12b886"]; C_prev -> forget_gate [lhead=cluster_gates, style=dashed, color="#adb5bd"]; forget_gate -> C_t [label=" *ft", color="#1c7ed6"]; input_gate_sig -> C_t [label=" *it", color="#1c7ed6"]; input_gate_tanh -> C_t [label=" 加", style=dotted, color="#1c7ed6"]; C_t -> output_gate [lhead=cluster_gates, style=dashed, color="#12b886"]; output_gate -> h_t [label=" *ot", color="#1c7ed6"]; {x_t, h_prev} -> forget_gate [style=dashed, color="#adb5bd"]; {x_t, h_prev} -> input_gate_sig [style=dashed, color="#adb5bd"]; {x_t, h_prev} -> input_gate_tanh [style=dashed, color="#adb5bd"]; {x_t, h_prev} -> output_gate [style=dashed, color="#adb5bd"]; C_prev -> C_t [label=" 遗忘", style=dotted, color="#12b886"]; input_gate_tanh -> input_gate_sig [style=invis]; } C_t -> h_t [label=" tanh", style=dotted, color="#12b886"]; h_prev -> h_t [style=invis, weight=100]; C_prev -> C_t [style=invis, weight=100]; }单个 LSTM 单元内部信息流的图示。门(蓝色)控制单元状态(绿色圆柱体)的更新方式以及作为隐藏状态(橙色平行四边形)输出的内容。Sigmoid ($\sigma$) 和 tanh 激活函数用于门内和状态更新。借由这种门控机制和独立的单元状态路径,LSTM 可以有效地学习在长序列中存储、遗忘和输出哪些信息。这解决了梯度消失问题,并使它们能够捕获可能相隔数百个时间步的依赖关系,从而成为许多序列相关任务的常用选择。在下一节,我们将了解如何使用 Keras 提供的便捷 LSTM 层来实现 LSTM。