关键词:隐藏状态、门控机制、Self-Attention、位置编码、梯度消失


15天学习大模型打卡(2):从 RNN 到 Transformer 的跨越

一、RNN:循环神经网络(Recurrent Neural Network)

🧠 核心思想

在每个时间步 $ t $,模型接收输入 $ x_t $,并结合上一时刻的隐藏状态 $ h_{t-1} $,计算当前状态 $ h_t $。

✅ 数学公式

h t = tanh ⁡ ( W h h h t − 1 + W x h x t + b h ) y t = W h y h t + b y \begin{align*} h_t &= \tanh(W_{hh} h_{t-1} + W_{xh} x_t + b_h) \\ y_t &= W_{hy} h_t + b_y \end{align*} htyt=tanh(Whhht1+Wxhxt+bh)=Whyht+by

  • h t ∈ R h h_t \in \mathbb{R}^h htRh:隐藏状态(记忆)
  • x t ∈ R d x_t \in \mathbb{R}^d xtRd:输入词向量
  • y t ∈ R V y_t \in \mathbb{R}^V ytRV:输出(通常是词表上的概率分布)
  • W h h , W x h , W h y W_{hh}, W_{xh}, W_{hy} Whh,Wxh,Why:可学习权重矩阵
  • tanh ⁡ \tanh tanh:激活函数,压缩数值范围

📐 网络架构(时间展开)

       x₁      x₂      x₃          x_T
       ↓       ↓       ↓           ↓
     ┌─────┐ ┌─────┐ ┌─────┐     ┌─────┐
  →  │  h₁ │→│  h₂ │→│  h₃ │→ ... │ h_T │→ y_T
     └─────┘ └─────┘ └─────┘     └─────┘
       ↑       ↑       ↑           ↑
      h₀      h₁      h₂         h_{T-1}

每个 h t h_t ht 依赖 h t − 1 h_{t-1} ht1,形成链式结构。

⚠️ 问题:梯度消失/爆炸

反向传播时,梯度通过链式法则:
∂ L ∂ h 1 = ∂ L ∂ h T ⋅ ∏ t = 2 T ∂ h t ∂ h t − 1 \frac{\partial L}{\partial h_1} = \frac{\partial L}{\partial h_T} \cdot \prod_{t=2}^T \frac{\partial h_t}{\partial h_{t-1}} h1L=hTLt=2Tht1ht
∥ ∂ h t ∂ h t − 1 ∥ < 1 \left\| \frac{\partial h_t}{\partial h_{t-1}} \right\| < 1 ht1ht <1,梯度指数衰减 → 早期信息丢失


二、LSTM:长短期记忆网络

🎯 核心结构

LSTM 引入细胞状态 c t c_t ct 作为长期记忆通道,并通过三个门控制信息流动。

✅ 数学公式

f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) 遗忘门 i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) 输入门 c ~ t = tanh ⁡ ( W c ⋅ [ h t − 1 , x t ] + b c ) 候选记忆 c t = f t ⊙ c t − 1 + i t ⊙ c ~ t 更新细胞状态 o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) 输出门 h t = o t ⊙ tanh ⁡ ( c t ) 输出隐藏状态 \begin{align*} f_t &= \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) && \text{遗忘门} \\ i_t &= \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) && \text{输入门} \\ \tilde{c}_t &= \tanh(W_c \cdot [h_{t-1}, x_t] + b_c) && \text{候选记忆} \\ c_t &= f_t \odot c_{t-1} + i_t \odot \tilde{c}_t && \text{更新细胞状态} \\ o_t &= \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) && \text{输出门} \\ h_t &= o_t \odot \tanh(c_t) && \text{输出隐藏状态} \end{align*} ftitc~tctotht=σ(Wf[ht1,xt]+bf)=σ(Wi[ht1,xt]+bi)=tanh(Wc[ht1,xt]+bc)=ftct1+itc~t=σ(Wo[ht1,xt]+bo)=ottanh(ct)遗忘门输入门候选记忆更新细胞状态输出门输出隐藏状态

  • σ \sigma σ:Sigmoid 函数(输出 0~1,控制“通过多少”)
  • ⊙ \odot :逐元素相乘(Hadamard 积)
  • [ h t − 1 , x t ] [h_{t-1}, x_t] [ht1,xt]:拼接向量

📐 LSTM 单元结构(ASCII 图)

        x_t     h_{t-1}
         ↓       ↓
      +-----------------+
      |  Forget Gate f_t| → f_t ⊙ c_{t-1}
      |  Input Gate  i_t| → i_t ⊙ c̃_t
      |Candidate ĉ_t    |
      |  Output Gate o_t| → o_t ⊙ tanh(c_t)
      +-----------------+
               ↓
         c_{t-1} → ⊗ → c_t → tanh → ⊗ → h_t
               ↑         ↑           ↑
               └─────────┘           │
                                   h_t

细胞状态 c t c_t ct 像一条“信息高速公路”,贯穿整个序列,门控决定信息的增删。


GRU(Gated Recurrent Unit)

简化公式:

z t = σ ( W z ⋅ [ h t − 1 , x t ] ) 更新门 r t = σ ( W r ⋅ [ h t − 1 , x t ] ) 重置门 h ~ t = tanh ⁡ ( W h ⋅ [ r t ⊙ h t − 1 , x t ] ) 候选状态 h t = ( 1 − z t ) ⊙ h t − 1 + z t ⊙ h ~ t 最终状态 \begin{align*} z_t &= \sigma(W_z \cdot [h_{t-1}, x_t]) && \text{更新门} \\ r_t &= \sigma(W_r \cdot [h_{t-1}, x_t]) && \text{重置门} \\ \tilde{h}_t &= \tanh(W_h \cdot [r_t \odot h_{t-1}, x_t]) && \text{候选状态} \\ h_t &= (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t && \text{最终状态} \end{align*} ztrth~tht=σ(Wz[ht1,xt])=σ(Wr[ht1,xt])=tanh(Wh[rtht1,xt])=(1zt)ht1+zth~t更新门重置门候选状态最终状态

💡 GRU 将细胞状态和隐藏状态合并,用两个门完成 LSTM 三个门的功能,更轻量。


三、Transformer:自注意力机制详解

🏗 整体架构(Encoder 部分)

Input Sequence: [x₁, x₂, ..., x_T]
       ↓
   Embedding + Positional Encoding
       ↓
   ┌───────────────────────────────┐
   │        Transformer Block      │
   │                               │
   │  ┌─────────────────────────┐  │
   │  │   Multi-Head Attention  │←─── Query, Key, Value
   │  └─────────────────────────┘  │
   │             ↓                 │
   │       LayerNorm + Residual    │
   │             ↓                 │
   │  ┌─────────────────────────┐  │
   │  │   Feed-Forward Network  │  │
   │  └─────────────────────────┘  │
   │             ↓                 │
   │       LayerNorm + Residual    │
   │                               │
   └───────────────────────────────┘
       ↓
   [h₁, h₂, ..., h_T]  → 上下文感知表示

🔍 Self-Attention 详细计算

1. 输入表示

每个词 x i x_i xi 转为向量 x i ∈ R d \mathbf{x}_i \in \mathbb{R}^d xiRd

2. 线性变换(生成 Q, K, V)

Q = X W Q K = X W K V = X W V \begin{align*} \mathbf{Q} &= \mathbf{X} W_Q \\ \mathbf{K} &= \mathbf{X} W_K \\ \mathbf{V} &= \mathbf{X} W_V \\ \end{align*} QKV=XWQ=XWK=XWV

  • X ∈ R T × d \mathbf{X} \in \mathbb{R}^{T \times d} XRT×d:输入矩阵
  • W Q , W K , W V ∈ R d × d k W_Q, W_K, W_V \in \mathbb{R}^{d \times d_k} WQ,WK,WVRd×dk:可学习权重
3. 计算注意力分数

Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left( \frac{QK^T}{\sqrt{d_k}} \right) V Attention(Q,K,V)=softmax(dk QKT)V

  • Q K T ∈ R T × T QK^T \in \mathbb{R}^{T \times T} QKTRT×T:相似度矩阵
  • d k \sqrt{d_k} dk :缩放因子,防止梯度消失
  • softmax:归一化为概率分布
4. 多头注意力(Multi-Head)

MultiHead ( Q , K , V ) = Concat ( head 1 , . . . , head h ) W O \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, ..., \text{head}_h) W^O MultiHead(Q,K,V)=Concat(head1,...,headh)WO
其中:
head i = Attention ( Q W i Q , K W i K , V W i V ) \text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V) headi=Attention(QWiQ,KWiK,VWiV)

  • 每个“头”关注不同语义(如语法、指代、情感)
  • W O W^O WO:合并输出

📍 位置编码(Positional Encoding)

因为 Self-Attention 不关心顺序,必须加入位置信息。

常用正弦编码:
P E ( p o s , 2 i ) = sin ⁡ ( p o s 1000 0 2 i / d ) P E ( p o s , 2 i + 1 ) = cos ⁡ ( p o s 1000 0 2 i / d ) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right) \\ PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i)=sin(100002i/dpos)PE(pos,2i+1)=cos(100002i/dpos)

  • p o s pos pos:位置索引
  • i i i:维度索引
  • 偶数位用 sin,奇数位用 cos

最终输入:
z i = x i + p i \mathbf{z}_i = \mathbf{x}_i + \mathbf{p}_i zi=xi+pi


🧩 Feed-Forward Network(FFN)

每个位置独立处理:
FFN ( x ) = W 2 ⋅ ReLU ( W 1 x + b 1 ) + b 2 \text{FFN}(x) = W_2 \cdot \text{ReLU}(W_1 x + b_1) + b_2 FFN(x)=W2ReLU(W1x+b1)+b2

  • 通常是两层全连接网络
  • 增强非线性表达能力

🔁 残差连接与层归一化

每个子层都有:
LayerNorm ( x + Sublayer ( x ) ) \text{LayerNorm}(x + \text{Sublayer}(x)) LayerNorm(x+Sublayer(x))

  • 残差连接:防止梯度消失
  • LayerNorm:稳定训练

四、对比总结(含架构特性)

特性 RNN LSTM GRU Transformer
记忆机制 隐藏状态 $ h_t $ 细胞状态 $ c_t $ + 门控 更新门 + 重置门 Self-Attention 权重
并行性 ❌ 串行 ❌ 串行 ❌ 串行 ✅ 全并行
长期依赖 较好 较好 极好
参数量
训练速度 快(并行)
架构核心 时间递归 门控 + 细胞状态 双门简化 多头注意力 + FFN

五、代码风格伪代码(帮助理解)

# RNN Cell
def rnn_step(x_t, h_prev, W_hh, W_xh, b):
    h_t = tanh(W_hh @ h_prev + W_xh @ x_t + b)
    return h_t

# LSTM Cell
def lstm_step(x_t, h_prev, c_prev, W_f, W_i, W_c, W_o, b_f, b_i, b_c, b_o):
    concat = concat(h_prev, x_t)
    f = sigmoid(W_f @ concat + b_f)          # 遗忘门
    i = sigmoid(W_i @ concat + b_i)          # 输入门
    c_tilde = tanh(W_c @ concat + b_c)       # 候选记忆
    c_t = f * c_prev + i * c_tilde           # 更新细胞状态
    o = sigmoid(W_o @ concat + b_o)          # 输出门
    h_t = o * tanh(c_t)                      # 输出隐藏状态
    return h_t, c_t

六、学习建议


这里的也留下来一个测试,各位同学可以试试,两天后我会发布代码

🚀 下一讲预告:我们将用 PyTorch 实现一个迷你 Transformer,从数据预处理到训练,完整走一遍流程!

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐