5. Transformer

介绍 Transformer 结构

Transformer 模型架构

  • 基本思想

    • Transformer 模型由 Vaswani 等人在 2017 年提出,是基于自注意力机制的序列到序列模型,彻底改变了自然语言处理领域

    • 它摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN),通过并行计算和全局依赖建模实现了高效的序列处理

    • Transformer 的核心创新在于 多头自注意力机制,允许模型在处理每个 token 时同时关注序列中的所有其他 token,从而捕捉长距离依赖

    • 模型由 Encoder 和 Decoder 两部分组成,支持并行训练,并通过位置编码引入序列顺序信息

  • Transformer 采用 Encoder-Decoder 架构:

    • Encoder:将输入序列编码为连续表示(向量序列)

    • Decoder:基于 Encoder 输出和自身历史生成输出序列

    • 整个模型由 $N$ 层堆叠组成(通常 $N=6$ 或 $12$),每层包含多头注意力、前馈网络、残差连接和层归一化

    • 输入输出均为向量序列,维度为 $d_{\text{model}}$(如 512 或 768)

transformer

变量符号说明

符号
含义

$n$

输入序列长度(token 数量)

$m$

输出序列长度(token 数量)

$d_{\text{model}}$

模型维度(嵌入向量和隐藏层维度,通常 512 或 768)

$H$

多头注意力头数(通常 8 或 12)

$d_k$

注意力 Key/Query 维度(通常 $d_{\text{model}} / H$)

$d_v$

注意力 Value 维度(通常 $d_{\text{model}} / H$)

$d_{\text{ff}}$

前馈网络中间维度(通常 2048 或 4096)

$V$ 或 $\vert\mathcal{V}\vert$

词表大小(vocabulary size,通常 30000 或更多)

$N$

Encoder/Decoder 层数(通常 6 或 12)

$X$

输入序列嵌入矩阵($n \times d_{\text{model}}$)

$Y$

输出序列嵌入矩阵($m \times d_{\text{model}}$)

$H_{\text{enc}}$

Encoder 输出($n \times d_{\text{model}}$)

$H_{\text{dec}}$

Decoder 输出($m \times d_{\text{model}}$)

$Z$

输出 logits($m \times V$)

$P$

输出概率分布($m \times V$)

$W_q, W_k, W_v$

注意力投影矩阵($d_{\text{model}} \times d_k$ 或 $d_{\text{model}} \times d_v$)

$W_1, W_2$

前馈网络权重矩阵($d_{\text{model}} \times d_{\text{ff}}$ 和 $d_{\text{ff}} \times d_{\text{model}}$)

$W_{\text{out}}$

输出线性层权重($d_{\text{model}} \times V$)

Encoder 结构

  • 在 Encoder 之前,存在嵌入层(Embedding Layer):

    • 输入 token 通过可学习嵌入矩阵映射为向量,维度 $d_{\text{model}}$

    • 嵌入矩阵大小:$V \times d_{\text{model}}$,$V$ 为词表大小

    • 与位置编码相加后输入第一层

  • Encoder 由 $N$ 个相同层堆叠而成,每层包括:

    • 多头自注意力子层:对输入序列进行自注意力计算,捕捉 token 间的依赖关系

    • 前馈网络子层:对每个 token 独立进行非线性变换

    • 残差连接和层归一化:围绕每个子层添加

  • Encoder 输入:token 嵌入 + 位置编码的序列 $X \in \mathbb{R}^{n \times d_{\text{model}}}$($n$​ 为序列长度)

  • 每个 Encoder Block(层):

    • 输入:上一层输出或初始 $X$,维度 $n \times d_{\text{model}}$

    • 多头自注意力子层:

      • 输入 $X_{\text{in}} \in \mathbb{R}^{n \times d_{\text{model}}}$

      • 生成 Q/K/V:对于每个头 $h$

        • $Q_h = X_{\text{in}} W_q^{(h)} \in \mathbb{R}^{n \times d_k}$

        • $K_h = X_{\text{in}} W_k^{(h)} \in \mathbb{R}^{n \times d_k}$

        • $V_h = X_{\text{in}} W_v^{(h)} \in \mathbb{R}^{n \times d_v}$

        • $d_k = d_v = \frac{d_{\text{model}}}{H}$

      • 单个注意力头计算:

        Attention(Qh,Kh,Vh)=softmax(QhKhTdk)VhRn×dv\mathrm{Attention}(Q_h, K_h, V_h) = \mathrm{softmax}\left(\frac{Q_h K_h^T}{\sqrt{d_k}}\right) V_h \in \mathbb{R}^{n \times d_v}
      • 多头拼接并投影:

        Oattn=Concat(head1,,headH)WoRn×dmodelO_{\text{attn}} = \mathrm{Concat}(\text{head}_1, \ldots, \text{head}_H) W_o \in \mathbb{R}^{n \times d_{\text{model}}}
      • 其中 $W_o \in \mathbb{R}^{H d_v \times d_{\text{model}}}$,可见多头注意力输出的维度和输入一致,可以进行残差连接

      • 残差 + LayerNorm

        Xout=LayerNorm(Xin+Oattn)Rn×dmodelX_{\text{out}} = \mathrm{LayerNorm}(X_{\text{in}} + O_{\text{attn}}) \in \mathbb{R}^{n \times d_{\text{model}}}
      • 残差连接可以让网络只关注当前差异的部分,Layer Normalization 会将每一层神经元的输入变为均值方差一样,可以加快收敛

    • 前馈网络子层:

      • 输入 $X_{\text{out}} \in \mathbb{R}^{n \times d_{\text{model}}}$

      • 输出

        Off=σ(XoutW1+b1)W2+b2Rn×dmodelO_{\text{ff}} = \sigma\left(X_{\text{out}} W_1 + b_1\right) W_2 + b_2 \in \mathbb{R}^{n \times d_{\text{model}}}
      • 残差 + LayerNorm

        Xfinal=LayerNorm(Xout+Off)Rn×dmodelX_{\text{final}} = \mathrm{LayerNorm}(X_{\text{out}} + O_{\text{ff}}) \in \mathbb{R}^{n \times d_{\text{model}}}
    • 层输出:$X_{\text{final}}$ 传递到下一层,维度始终保持 $n \times d_{\text{model}}$

  • Encoder 输出:经过 $N$ 层后输出最终表示 $H_{\text{enc}} \in \mathbb{R}^{n \times d_{\text{model}}}$,用于 Decoder 或下游任务

  • Encoder 的特点:

    • 双向注意力:每个 token 可以关注序列中所有其他 token(包括未来 token),适合理解完整上下文的任务,如分类或编码

    • 无掩码:注意力矩阵不使用 causal mask,因为 Encoder 不需要生成顺序依赖

Decoder 结构

  • Decoder 也由 $N$ 个相同层堆叠而成,每层包括:

    • 掩码多头自注意力子层:仅关注当前及之前位置的 token,防止信息泄露(causal mask)

    • 多头交叉注意力子层:Query 来自 Decoder,Key/Value 来自 Encoder 输出,实现条件生成

    • 前馈网络子层:与 Encoder 相同

    • 残差连接和层归一化:围绕每个子层添加

  • Decoder 输入为目标序列的 token 嵌入 + 位置编码 $Y \in \mathbb{R}^{m \times d_{\text{model}}}$($m$​ 为目标长度),在训练时使用 teacher forcing(真实目标序列),推理时自回归生成

  • 每个 Decoder Block(层)的详细流向:

    • 输入:上一层输出或初始 $Y$,维度 $m \times d_{\text{model}}$;Encoder 输出 $H_{\text{enc}} \in \mathbb{R}^{n \times d_{\text{model}}}$

    • 掩码多头自注意力子层:

      • 输入 $Y_{\text{in}} \in \mathbb{R}^{m \times d_{\text{model}}}$

      • 生成 Q/K/V:类似 Encoder,$Q_h = Y_{\text{in}} W_q^{(h)} \in \mathbb{R}^{m \times d_k}$ 等

      • 计算未掩码的注意力打分(逐头)

        Sh=QhKhdkRm×mS_h = \frac{Q_h K_h^\top}{\sqrt{d_k}} \in \mathbb{R}^{m \times m}
      • 构造 causal mask(上三角掩码)

        MRm×m,Mij={0,ji,j>iM \in \mathbb{R}^{m \times m}, \qquad M_{ij} = \begin{cases} 0, & j \le i \\ -\infty,& j > i \end{cases}
      • 在 softmax 之前施加掩码

        S~h=Sh+M\tilde{S}_h = S_h + M
      • 归一化得到注意力权重

        Ah=softmax(S~h)Rm×mA_h = \mathrm{softmax}(\tilde{S}_h) \in \mathbb{R}^{m \times m}
      • 加权求和得到单头输出

        Zh=AhVhRm×dvZ_h = A_h V_h \in \mathbb{R}^{m \times d_v}
      • 多头拼接并线性映射

        Z=Concat(Z1,,ZH)Rm×dmodelOself-attn=ZWO,WORdmodel×dmodelZ = \mathrm{Concat}(Z_1, \dots, Z_H) \in \mathbb{R}^{m \times d_{\text{model}}}\\ O_{\text{self-attn}} = Z W^O, \qquad W^O \in \mathbb{R}^{d_{\text{model}} \times d_{\text{model}}}
      • 残差 + LayerNorm

        Yout1=LayerNorm(Yin+Oself-attn)Rm×dmodelY_{\text{out1}} = \mathrm{LayerNorm}(Y_{\text{in}} + O_{\text{self-attn}}) \in \mathbb{R}^{m \times d_{\text{model}}}
    • 多头交叉注意力子层:

      • 输入 $Y_{\text{out1}} \in \mathbb{R}^{m \times d_{\text{model}}}$(作为 Query),$H_{\text{enc}}$(作为 Key/Value)

      • 生成 Q:$Q_h = Y_{\text{out1}} W_q^{(h)} \in \mathbb{R}^{m \times d_k}$

      • 生成K/V:$K_h = H_{\text{enc}} W_k^{(h)} \in \mathbb{R}^{n \times d_k}$,$V_h = H_{\text{enc}} W_v^{(h)} \in \mathbb{R}^{n \times d_v}$

      • 注意力计算:

        Sh=QhKhdkRm×nS_h = \frac{Q_h K_h^\top}{\sqrt{d_k}}\in \mathbb{R}^{m \times n}
      • (可选)施加 encoder padding mask

        MencRm×n,(Menc)ij={0,encoder 第 j 个 token 非 padding,encoder 第 j 个 token 为 paddingS~h=Sh+MencM_{\text{enc}} \in \mathbb{R}^{m \times n}, \quad (M_{\text{enc}})_{ij} = \begin{cases} 0, & \text{encoder 第 } j \text{ 个 token 非 padding} \\ -\infty,& \text{encoder 第 } j \text{ 个 token 为 padding} \end{cases}\\ \tilde{S}_h = S_h + M_{\text{enc}}
      • softmax 得到注意力权重

        Ah=softmax(S~h)Rm×nA_h = \mathrm{softmax}(\tilde{S}_h) \in \mathbb{R}^{m \times n}
      • 加权求和得到单头输出

        Zh=AhVhRm×dvZ_h = A_h V_h \in \mathbb{R}^{m \times d_v}
      • 多头拼接与线性映射

        Z=Concat(Z1,,ZH)Rm×dmodelOcross-attn=ZWORm×dmodelZ = \mathrm{Concat}(Z_1, \dots, Z_H) \in \mathbb{R}^{m \times d_{\text{model}}}\\ O_{\text{cross-attn}} = Z W^O \in \mathbb{R}^{m \times d_{\text{model}}}
      • 残差 + LayerNorm

        Yout2=LayerNorm(Yout1+Ocross-attn)Rm×dmodelY_{\text{out2}} = \mathrm{LayerNorm}(Y_{\text{out1}} + O_{\text{cross-attn}}) \in \mathbb{R}^{m \times d_{\text{model}}}
    • 前馈网络子层:

      • 输入 $Y_{\text{out2}} \in \mathbb{R}^{m \times d_{\text{model}}}$

      • 输出 $O_{\text{ff}} = \mathrm{FFN}(Y_{\text{out2}}) \in \mathbb{R}^{m \times d_{\text{model}}}$

      • 残差 + LayerNorm:$Y_{\text{final}} = \mathrm{LayerNorm}(Y_{\text{out2}} + O_{\text{ff}}) \in \mathbb{R}^{m \times d_{\text{model}}}$

    • 层输出:$Y_{\text{final}}$ 传递到下一层,维度始终保持 $m \times d_{\text{model}}$

  • Decoder 输出

    • 经过 $N$ 层后输出 $H_{\text{dec}} \in \mathbb{R}^{m \times d_{\text{model}}}$

    • 线性映射到词表空间(逐位置独立)

      Zlogits=HdecWout+boutRm×VZ_{\text{logits}} = H_{\text{dec}} W_{out} + b_{out} \in \mathbb{R}^{m \times \vert\mathcal{V}\vert}
    • 其中

      WoutRdmodel×V,boutRVW_{out} \in \mathbb{R}^{d_{\text{model}} \times \vert\mathcal{V}\vert}, \quad b_{out} \in \mathbb{R}^{\vert\mathcal{V}\vert}
    • 再应用 Softmax 生成概率分布

      P=Softmax(Z)Rm×V,Pij=exp(Zij)k=1Vexp(Zik)P(yty<t,x)=softmax(Zlogits)tP = \mathrm{Softmax}(Z) \in \mathbb{R}^{m \times \vert\mathcal{V}\vert},\quad P_{ij} = \frac{\exp(Z_{ij})}{\sum_{k=1}^V \exp(Z_{ik})}\\ P(y_t \mid y_{< t}, x) = \mathrm{softmax}(Z_{\text{logits}})_t
    • 由于 decoder 的 masked self-attention 在每一层都施加了 causal mask,第 $i$ 个位置的隐状态 $H_{\text{dec}}[i]$ 在计算过程中只能依赖于输入序列中第 $0 \sim i$ 个 token 以及 encoder 输出 $x$,从而保证模型满足自回归生成的因果性

    • 因此,在输出概率矩阵 $P \in \mathbb{R}^{m \times |\mathcal{V}|}$ 中,第 $i$ 行表示在已知上下文 $y_{< i}$ 和输入 $x$ 的条件下,第 $i$ 个位置生成词表中各词的条件概率分布

    • 训练阶段(Teacher Forcing):对第 $t$ 个位置,使用真实标签 $y_t^{\ast}$,最大化条件对数似然:

      L=t=1mlogP(yty<t,x)\mathcal{L} = - \sum_{t=1}^{m} \log P(y_t^{\ast} \mid y_{< t}^{\ast}, x)
    • 推理阶段(自回归生成):对每个时间步 $t$​:

      • 采样

        ytP(yty<t,x)y_t \sim P(y_t \mid y_{< t}, x)
      • 或贪心

        yt=argmaxvVP(yt=vy<t,x)y_t = \arg\max_{v \in \mathcal{V}} P(y_t = v \mid y_{< t}, x)
    • (可选)权重共享,投影矩阵与输入嵌入矩阵共享参数:

      Wout=WembedW_{out} = W_{\text{embed}}^\top
  • Decoder 的特点:

    • 单向注意力:自注意力使用 causal mask,确保生成时只能看到历史 token

    • 交叉注意力:依赖 Encoder 输出,实现序列到序列转换

    • 与 Encoder 的区别:

      特性
      Encoder
      Decoder

      注意力类型

      自注意力(无掩码)

      自注意力(causal mask) + 交叉注意力

      输入

      源序列

      目标序列 + Encoder 输出

      输出

      上下文表示

      生成序列

      并行性

      完全并行

      自注意力部分并行,生成时顺序

      适用场景

      编码理解任务

      生成任务

残差连接和层归一化

  • Transformer 中,每个子层(注意力或前馈)后都添加 残差连接(Residual Connection) 和 层归一化(Layer Normalization),这是训练深层网络的关键

  • 为什么使用残差连接?

    • 残差连接允许梯度直接传播,避免梯度消失或爆炸问题,使深层网络更容易训练

    • 公式:输出 = 子层输入 + 子层输出,即 $y = x + \mathrm{Sublayer}(x)$

    • 在 Transformer 中,如果没有残差,深层堆叠会导致信息丢失;残差确保低层特征能直接传递到高层

    • 实验证明,残差连接使 Transformer 能稳定训练到 12+ 层,而非残差版本难以收敛

  • 为什么使用层归一化?

    • 层归一化对每个样本的特征维度进行归一化,稳定训练并加速收敛

    • 公式(其中 $\mu$ 和 $\sigma$ 为均值和方差):

      LayerNorm(x)=γxμσ2+ϵ+β\mathrm{LayerNorm}(x) = \gamma \cdot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta
    • 相比批归一化(BatchNorm),LayerNorm 不依赖 batch size,更适合序列数据和变长输入

    • 在 Transformer 中,LayerNorm 放在残差连接后,确保每层输出分布稳定,避免内部协变量偏移(internal covariate shift)

    • 好处:提高训练稳定性,减少过拟合,支持更大学习率

前馈网络

  • 每个 Encoder/Decoder 层包含一个位置-wise 前馈网络(Position-wise Feed-Forward Network),对每个 token 独立进行变换

  • 结构:两层全连接网络,中间有 ReLU 激活

    • 输入维度:$d_{\text{model}}$

    • 中间维度:$d_{\text{ff}}$(通常 2048 或 4096)

    • 输出维度:$d_{\text{model}}$

  • 公式:

    FFN(x)=max(0,xW1+b1)W2+b2\mathrm{FFN}(x) = \max(0, x W_1 + b_1) W_2 + b_2
  • 作用:

    • 提供非线性变换,增强模型表达能力

    • 位置-wise 设计允许并行计算,提高效率

    • 与注意力互补:注意力捕捉依赖,前馈进行特征变换

参数量计算

  • Transformer 参数主要来自 Q/K/V 的线性投影和前馈网络,忽略偏置和 LayerNorm(通常小)

  • 多头注意力(每层):

    • Q/K/V 投影:$H \times (d_{\text{model}} \times d_k + d_{\text{model}} \times d_k + d_{\text{model}} \times d_v)$

    • 输出投影:$H d_v \times d_{\text{model}}$

    • 总:$H \times (2 d_{\text{model}} d_k + d_{\text{model}} d_v) + H d_v d_{\text{model}}$($d_k = d_v = d_{\text{model}}/H$ 时简化)

  • 前馈网络(每层):$d_{\text{model}} \times d_{\text{ff}} + d_{\text{ff}} \times d_{\text{model}}$

  • 嵌入层:$V \times d_{\text{model}}$(输入) + $V \times d_{\text{model}}$(输出,若共享则减半)

  • 总参数(Encoder + Decoder,$N$ 层):约 $2N \times (\text{注意力} + \text{前馈}) + \text{嵌入}$

  • 示例(Base Transformer:$d_{\text{model}}=512, H=8, d_{\text{ff}}=2048, V=30000, N=6$):

    • 注意力/层:$8 \times (512 \times 64 \times 3) + 512 \times 512 \approx 2.3M$

    • 前馈/层:$512 \times 2048 + 2048 \times 512 \approx 2.1M$

    • 每层总:$\approx 4.4M$,$N=6$ 层 Encoder/Decoder:$\approx 53M$,总 $\approx 110M$(含嵌入)

为什么适合并行

  • Transformer 摒弃 RNN 的顺序依赖,所有 token 的计算可以同时进行:

    • 注意力机制:Q/K/V 矩阵乘法(如 $QK^T$)可并行计算,无需循环

    • 前馈网络:位置-wise,每个 token 独立处理,可批量运算

    • 层间:每层独立,无跨层依赖

    • Encoder:完全并行,适合 GPU 矩阵运算

    • Decoder 训练:使用 teacher forcing,目标序列也并行;推理时仅生成部分顺序,但 KV cache 优化加速

    • 相比 RNN 的 $O(n)$ 顺序复杂度,Transformer $O(1)$​ 并行度,使长序列训练高效

  • 并行性强,适合 GPU/TPU,但长序列时注意力复杂度 $O(n^2)$​,变体如 Sparse Transformer 优化长序列效率

  • 原始 Transformer 对长序列效率低,后续如 Longformer、Performer 等改进

  • 缺乏显式递归,某些任务需额外机制(如记忆模块)

正则化

  • Dropout 是一种简单而有效的正则化技术,最初用于缓解前馈神经网络中的过拟合问题

  • 其核心思想是在每次训练更新时,随机将一部分神经元的输出置零,从而向网络注入噪声

  • 这种随机失活机制可以防止神经元对特定其他单元产生过度依赖,促使模型学习更加分散、鲁棒的表示

  • 在标准的 Transformer 架构中,Dropout 通常应用于以下位置:

    • 嵌入与位置编码相加之后

      • 作用于合并后的输入表示,在其进入编码器或解码器堆栈之前

    • 各子层内部

      • 应用于多头注意力输出之后(在残差连接和层归一化之前)

      • 应用于前馈网络输出之后(同样在残差连接和层归一化之前)

    • 可选地,应用于注意力权重

      • 即对 $softmax(QK^T/\sqrt{d_k})$ 的输出进行 Dropout,然后再与 $V$ 相乘

      • 这种做法有时被称为注意力 Dropout

  • 将单元输出置零的概率 $p_{drop}$ 是一个超参数

    • 典型取值范围为 0.1 到 0.3,具体最优值依赖于模型规模、数据集大小和任务特性

    • 在训练阶段,每个单元的输出以 $p_{drop}$ 的概率被随机置零

    • 其余未被置零的输出通常按 $1/(1-p_{drop})$ 进行缩放,以保持输出的期望不变

    • 这种缩放策略保证了训练阶段与推理阶段的输入分布一致

  • 在推理或评估阶段,Dropout 被禁用

    • 所有单元均参与计算

    • 不再进行随机置零或额外缩放,从而保证输出的确定性

  • 一个子层内部的简化示例如下:

  • 通过在训练过程中注入随机噪声,Dropout 促使模型形成冗余表示,抑制神经元之间复杂的共同适应,从而有效提升模型的泛化能力

Last updated

Was this helpful?