门控循环单元 (GRU),由 Cho 等人于 2014 年提出,提供了一种门控循环架构中的替代方案。这些单元与长短期记忆 (LSTM) 网络类似,旨在缓解简单循环神经网络 (RNN) 中固有的梯度问题。GRU 的目标是实现类似的效果,即控制信息随时间流动,但与 LSTM 相比,它通过一种略微简化的结构来实现。这种简化通常会减少参数,并可能加快计算速度,同时其性能常与 LSTM 相当。GRU 门和状态更新GRU 单元不使用独立的细胞状态,而是直接通过两个主要门控机制来修改其隐藏状态 $h_t$:重置门和更新门。我们来分析它们的作用和计算方式。重置门 ($r_t$)重置门决定了在提出新的候选隐藏状态时,前一个隐藏状态 $h_{t-1}$ 有多少应该被有效地“遗忘”或忽略。如果重置门输出接近 0 的值,它允许单元丢弃过去被认为与当前计算无关的信息。反之,接近 1 的值则保留了前一状态的大部分信息。计算涉及当前输入 $x_t$ 和前一个隐藏状态 $h_{t-1}$。一个 Sigmoid 函数 $\sigma$ 将输出压缩到 [0, 1] 范围:$$ r_t = \sigma(W_r x_t + U_r h_{t-1} + b_r) $$这里,$W_r$、$U_r$ 和 $b_r$ 是针对重置门学习到的权重矩阵和偏置向量。更新门 ($z_t$)更新门的作用类似于 LSTM 中遗忘门和输入门的组合。它决定了前一个隐藏状态 $h_{t-1}$ 有多少信息应该传递到新的隐藏状态 $h_t$。同时,它也控制着新计算出的候选隐藏状态 $\tilde{h}_t$ 有多少应该被纳入。它的计算结构与重置门相似:$$ z_t = \sigma(W_z x_t + U_z h_{t-1} + b_z) $$$W_z$、$U_z$ 和 $b_z$ 是用于更新门学习到的参数。候选隐藏状态 ($\tilde{h}_t$)候选隐藏状态表示在时间步 $t$ 新隐藏状态的一个提议。它的计算受重置门 $r_t$ 的影响。具体来说,前一个隐藏状态 $h_{t-1}$ 的贡献通过重置门的输出进行调节(按元素相乘,表示为 $\odot$),然后与处理后的输入 $x_t$ 结合。通常使用双曲正切函数 ($\tanh$) 作为激活函数:$$ \tilde{h}t = \tanh(W_h x_t + U_h (r_t \odot h{t-1}) + b_h) $$$W_h$、$U_h$ 和 $b_h$ 是用于计算候选状态的学习参数。按元素相乘 $r_t \odot h_{t-1}$ 是允许 GRU 根据 $r_t$ 选择性地丢弃前一状态部分内容的机制。最终隐藏状态 ($h_t$)当前时间步的最终隐藏状态 $h_t$ 通过对前一个隐藏状态 $h_{t-1}$ 和候选隐藏状态 $\tilde{h}_t$ 进行线性插值计算得出。更新门 $z_t$ 决定了这种插值的平衡。$$ h_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t $$当 $z_t$ 接近 1 时,候选状态 $\tilde{h}t$ 贡献更多,有效地用新信息更新隐藏状态。当 $z_t$ 接近 0 时,前一状态 $h{t-1}$ 大部分被保留,允许信息远距离传递。digraph GRU { rankdir=LR; node [shape=box, style=rounded, fontname="Arial"]; edge [fontname="Arial"]; subgraph cluster_t { label = "时间步 t"; bgcolor = "#e9ecef"; xt [label="x_t", shape=ellipse, style=filled, fillcolor="#a5d8ff"]; ht_prev [label="h_{t-1}", shape=ellipse, style=filled, fillcolor="#ffec99"]; // 门 rt_gate [label="重置门 (r_t)\nσ(...)"]; zt_gate [label="更新门 (z_t)\nσ(...)"]; // 候选状态 ht_tilde_calc [label="候选状态 (h̃_t)\ntanh(...)", shape=box]; reset_mult [label="⊙", shape=circle, width=0.3, height=0.3, fixedsize=true]; // 最终状态 ht_calc [label="最终状态 (h_t)", shape=box]; zt_mult1 [label="⊙", shape=circle, width=0.3, height=0.3, fixedsize=true]; zt_mult2 [label="⊙", shape=circle, width=0.3, height=0.3, fixedsize=true]; one_minus_zt [label="1 - z_t", shape=plaintext]; sum_ht [label="+", shape=circle, width=0.3, height=0.3, fixedsize=true]; ht_out [label="h_t", shape=ellipse, style=filled, fillcolor="#ffec99"]; // 连接 xt -> rt_gate [style=dashed]; ht_prev -> rt_gate [style=dashed]; xt -> zt_gate [style=dashed]; ht_prev -> zt_gate [style=dashed]; ht_prev -> reset_mult [style=dashed]; rt_gate -> reset_mult; reset_mult -> ht_tilde_calc [style=dashed]; xt -> ht_tilde_calc [style=dashed]; ht_tilde_calc -> zt_mult2; zt_gate -> zt_mult2; zt_mult2 -> sum_ht; ht_prev -> zt_mult1 [style=dashed]; zt_gate -> one_minus_zt; one_minus_zt -> zt_mult1; zt_mult1 -> sum_ht; sum_ht -> ht_out; sum_ht -> ht_calc [style=invis]; // 用于布局定位 ht_calc -> ht_out [style=invis]; // 用于布局定位 } // 集群外的输入/输出占位符 xt_in [label="输入 x_t", shape=none, style=invis]; ht_prev_in [label="前一状态 h_{t-1}", shape=none, style=invis]; ht_next_out [label="输出 h_t", shape=none, style=invis]; xt_in -> xt; ht_prev_in -> ht_prev; ht_out -> ht_next_out; } 门控循环单元 (GRU) 单元在时间步 $t$ 内的数据流。$x_t$ 是输入,$h_{t-1}$ 是前一个隐藏状态。重置门 ($r_t$) 和更新门 ($z_t$) 控制着候选状态 ($ ilde{h}_t$) 和最终隐藏状态 ($h_t$) 的计算。虚线表示某个值在计算中的使用。GRU 与 LSTM 对比GRU 架构可被视为 LSTM 的一种简化:门: GRU 使用两个门(重置、更新),而 LSTM 使用三个(输入、遗忘、输出)。细胞状态: GRU 没有 LSTM 中独立的细胞状态 ($c_t$)。隐藏状态 $h_t$ 直接包含了控制长期依赖的机制。参数数量: 由于门的数量减少且没有细胞状态路径,GRU 通常比具有相同隐藏状态维度的 LSTM 具有更少的训练参数。这使得它们在计算上可能略便宜,并且在较小数据集上可能更不容易过拟合。从经验来看,两种架构在所有任务上都没有哪一个持续表现更优。LSTM 和 GRU 之间的选择通常取决于特定问题的实验结果,尽管当计算资源或参数效率是主要考量时,GRU 可能更受青睐。依然存在的局限性尽管有精密的门控,GRU 仍保留了循环模型的基本特点:顺序计算。信息必须按序列长度一步步传播。这种固有的顺序性限制了训练时的并行化,使得它们在处理非常长的序列时,与 Transformer 等架构相比训练速度明显更慢。此外,尽管它们在捕捉更长距离的依赖关系方面远优于简单的 RNN,但依赖于将过去信息总结到一个固定大小的隐藏状态中,对于复杂依赖关系跨越很长的距离的极长序列,这仍然可能成为瓶颈。这些尚存的挑战促使了基于注意力的机制出现,我们接下来将讨论这些机制。