正如我们在上一章讨论的,标准前馈神经网络在处理序列数据时有一个基本局限:它们没有记忆功能。每个输入都被独立处理,不考虑之前输入提供的顺序或语境。想象一下阅读这个句子。为了理解“句子”这个词的含义,你的大脑会使用前面词语“阅读这个”提供的语境。前馈网络无法自然地做到这一点。它们是为固定大小的输入设计的,在这些输入中,顺序本身不以同样的方式带有含义。循环神经网络(RNNs)的主要思想是,它不一次性处理整个序列,也不单独处理每个元素,而是一次处理一个元素,迭代地处理序列。设想处理一个序列 $x = (x_1, x_2, ..., x_T)$。RNN接收第一个元素 $x_1$,对其进行处理,并生成一个内部状态(通常称为隐藏状态),我们称之为 $h_1$。当处理第二个元素 $x_2$ 时,RNN不仅仅查看 $x_2$。它还会考虑从第一步获得的信息,这些信息归纳在隐藏状态 $h_1$ 中。它将新的输入 $x_2$ 与先前的状态 $h_1$ 结合,以计算下一个隐藏状态 $h_2$。这个过程对序列中的每个元素都重复:在第 $t=1$ 步:使用 $x_1$ 计算 $h_1$(通常还会使用初始状态 $h_0$,通常设为零)。在第 $t=2$ 步:使用 $x_2$ 和 $h_1$ 计算 $h_2$。在第 $t=3$ 步:使用 $x_3$ 和 $h_2$ 计算 $h_3$。...在第 $t=T$ 步:使用 $x_T$ 和 $h_{T-1}$ 计算 $h_T$。隐藏状态 $h_t$ 充当网络的记忆。它捕获了网络认为与处理当前元素 $x_t$ 和未来元素相关的所有先前元素 ($x_1, ..., x_{t-1}$) 的信息。这个状态从一个时间步传递到下一个时间步,从而在网络连接中形成一个循环或递归。digraph G { rankdir=LR; node [shape=box, style=rounded, fontname="helvetica", fontsize=10]; edge [fontname="helvetica", fontsize=10]; subgraph cluster_rnn { label = "时间 t 的 RNN 单元"; style=dashed; bgcolor="#e9ecef"; // gray rnn_cell [label="RNN\n操作\n(结合输入和先前的状态)", shape=ellipse, style=filled, fillcolor="#a5d8ff"]; // blue } xt [label="输入\nx_t", shape=rect, style=filled, fillcolor="#ffd8a8"]; // orange ht_minus_1 [label="先前的状态\nh_{t-1}", shape=rect, style=filled, fillcolor="#b2f2bb"]; // green ht [label="当前状态\nh_t", shape=rect, style=filled, fillcolor="#b2f2bb"]; // green yt [label="输出\ny_t", shape=rect, style=filled, fillcolor="#ffd8a8"]; // orange loop_label [label="状态向前传递", shape=none, fontcolor="#495057", fontsize=9]; xt -> rnn_cell; ht_minus_1 -> rnn_cell; rnn_cell -> ht; rnn_cell -> yt [style=dashed]; // 输出是可选的,取决于任务 // Represent the loop ht -> loop_label [ arrowhead="none", style=dashed, color="#868e96"]; loop_label -> ht_minus_1 [label=" 成为\n t+1 步的输入", style=dashed, color="#868e96"]; }RNN 处理一步的示意图。输入 $x_t$ 和先前的隐藏状态 $h_{t-1}$ 通过 RNN 操作结合,生成当前的隐藏状态 $h_t$。这个状态 $h_t$ 随后被传递到下一个时间步(处理 $x_{t+1}$)使用,并且可以在这一步生成一个可选输出 $y_t$。这种带有持久状态的迭代处理与前馈网络本质上不同。前馈网络对每个输入独立应用相同的转换,而RNN在每一步应用相同的转换规则(RNN单元内相同的权重集合),但其结果(隐藏状态 $h_t$ 和输出 $y_t$)既取决于当前输入 $x_t$,也取决于归纳在 $h_{t-1}$ 中的历史信息。这种维持语境的能力使RNN天生适合处理顺序很重要且信息需要随时间累积的任务,例如理解语言、预测时间序列或分析音频信号。图中“RNN操作”框内使用的具体数学函数规定了先前的状态和当前输入如何结合,我们将在接下来的章节中查看这些细节。