Transformer原理科普

Transformer 是一种基于自注意力机制(Self-Attention) 的深度学习模型,由 Google 团队在 2017 年的论文《Attention Is All You Need》中首次提出,它革命性的改变了自然语言处理(NLP)领域,并取代了传统的 RNN 和 CNN,成为 BERT、GPT 等现代预训练模型的核心架构。
其文章链接如下:https://arxiv.org/pdf/1706.03762
其核心思想及原理如下:

1. 核心思想

  • 传统模型的缺陷
    • RNN 难以并行计算,且长距离依赖能力弱;
    • CNN 的局部感受野限制了全局信息捕获。
  • Transformer 的突破
    • 完全基于注意力机制,无需循环或卷积结构;
    • 支持并行计算,高效处理长序列;
    • 通过自注意力直接建模序列中任意两个位置的关联。

2. 整体架构

Transformer 由 编码器(Encoder)解码器(Decoder) 堆叠组成,每个编码器和解码器包含多个相同的层。

Transformer Architecture

编码器(Encoder)
  1. 输入嵌入层:将输入词转换为向量(Word Embedding)。
  2. 位置编码(Positional Encoding):为序列中的每个位置添加位置信息(如正弦/余弦函数)。
  3. 多头自注意力层:计算序列中每个词与其他词的关系权重。
  4. 前馈神经网络(FFN):对每个位置的向量进行非线性变换。
  5. 残差连接 & 层归一化:每个子层后使用残差连接和归一化,加速训练。
解码器(Decoder)
  1. 输入嵌入 & 位置编码:与编码器类似,但处理目标序列。
  2. 掩码多头自注意力层:防止解码时看到未来信息(通过掩码矩阵)。
  3. 编码器-解码器注意力层:将解码器的查询与编码器的键、值交互。
  4. 前馈神经网络 & 残差连接:同编码器。

3. 自注意力机制(Self-Attention)

自注意力是 Transformer 的核心,其计算分为四步:

步骤 1:生成 Q、K、V 矩阵
  • 输入序列的每个词向量通过线性变换生成:
    • 查询(Query):当前词需要关注哪些词?
    • 键(Key):其他词如何响应查询?
    • 值(Value):实际传递的信息。
步骤 2:计算注意力分数
  • 通过点积计算每个查询与所有键的相似度:
  • A t t e n t i o n S c o r e = Q ⋅ K T Attention Score = Q \cdot K^T AttentionScore=QKT
  • 缩放分数(防止梯度消失):
  •  Scaled Score = Q ⋅ K T d k ( d k 为键的维度 )   \ \text{Scaled Score} = \frac{Q \cdot K^T}{\sqrt{d_k}} \quad (d_k \text{为键的维度}) \  Scaled Score=dk QKT(dk为键的维度) 

为什么公式中需要除dk呢?
在Transformer的自注意力机制中,将查询(Q)和键(K)的点积结果除以根号下dk的主要原因是为了控制点积的数值范围,防止梯度消失,从而稳定模型训练。假设查询 Q 和键K的每个元素是独立随机变量,均值为0,方差为1,   Q ⋅ K T   \ Q \cdot K^T \  QKT 的每个元素是 d_k个独立乘积之和,当 d_k 较大时,点积结果的绝对值会显著增大,这会导致 Softmax 函数的输入过大,进入梯度饱和区(极端值区域),梯度趋近于0,模型难以更新参数除根号下dk缩放后的数值范围更稳定,Softmax 的输入分布在梯度敏感区域(非饱和区),梯度可以有效传播。
在这里插入图片描述

步骤 3:应用 Softmax
  • 对每一行分数进行 Softmax,得到注意力权重(和为 1)。
步骤 4:加权求和
  • 用注意力权重对 Value 加权求和,得到最终的注意力输出:
  •  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 
    具体示意图如下:
    在这里插入图片描述

4. 多头注意力(Multi-Head Attention)

多头注意力(Multi-Head Attention)是 Transformer 模型的核心组件之一,通过并行计算多个独立的注意力头,使模型能够同时关注输入序列中的不同特征模式,从而增强模型的表达能力和泛化性能。以下是其详细原理与实现步骤:


  • 单一注意力的局限性
    传统的自注意力机制可能仅捕捉到一种类型的关联(如局部依赖或语法结构),无法充分建模复杂的上下文关系。
  • 多头注意力的优势
    • 允许模型在不同子空间中学习多样化的特征表示。
    • 类似 CNN 中多通道卷积核的设计,提升模型的灵活性和鲁棒性。

实现步骤
多头注意力的计算流程可分为以下四步:

线性投影生成多组 Q、K、V
将输入的 Query(Q)、Key(K)、Value(V)通过 h 个独立的线性变换,拆分为多个头(Head):
  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 i Q , W i K , W i V   \ W_i^Q, W_i^K, W_i^V \  WiQ,WiK,WiV 是第 ( i ) 个头的可学习参数矩阵。

  • 每个头的维度为   d k = d model / h   \ d_k = d_{\text{model}} / h \  dk=dmodel/h ,其中   d model   \ d_{\text{model}} \  dmodel  是模型总维度(如 512), h 是头数。

每个头独立计算自注意力
每个头执行标准的缩放点积注意力(Scaled Dot-Product Attention):
 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 

  • 每个头输出的维度为   d v = d model / h   \ d_v = d_{\text{model}} / h \  dv=dmodel/h 

拼接所有头的输出
将 h 个头的输出按特征维度拼接:
 Concat ( Head 1 , Head 2 , . . . , Head h ) ∈ R n × d model   \ \text{Concat}(\text{Head}_1, \text{Head}_2, ..., \text{Head}_h) \in \mathbb{R}^{n \times d_{\text{model}}} \  Concat(Head1,Head2,...,Headh)Rn×dmodel 
n 为序列长度,   d model = h × d v   \ d_{\text{model}} = h \times d_v \  dmodel=h×dv 

线性变换合并结果
通过可学习矩阵 ( W^O ) 将拼接后的结果映射回原始维度:

 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 
多头注意力的作用

功能说明
多样化特征学习不同头关注不同模式(如局部依赖、全局语义、语法结构等)。
并行计算效率多个头可并行计算,充分利用 GPU 的并行能力,提升训练速度。
抗过拟合能力通过多组参数学习,降低对单一注意力模式的依赖,增强泛化性。
解耦复杂关系将复合关系分解为多个子问题(如“苹果”指水果或公司,不同头分别处理)。

机器翻译任务 为例:

  • Head 1:关注词语的位置关系(如动词与主语的远距离依赖)。
  • Head 2:捕捉词性搭配(如形容词修饰名词)。
  • Head 3:识别语义关联(如“银行”与“钱”或“河流”的不同上下文)。
  • Head 4:处理指代消解(如代词“它”指向的实体)。

代码实现示例(PyTorch)

import torch
import torch.nn as nn

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model=512, h=8):
        super().__init__()
        self.d_model = d_model
        self.h = h
        self.d_k = d_model // h
        
        # 定义线性投影矩阵
        self.W_Q = nn.Linear(d_model, d_model)
        self.W_K = nn.Linear(d_model, d_model)
        self.W_V = nn.Linear(d_model, d_model)
        self.W_O = nn.Linear(d_model, d_model)
        
    def forward(self, Q, K, V, mask=None):
        batch_size = Q.size(0)
        
        # 线性投影并分头 [batch_size, seq_len, h, d_k]
        Q = self.W_Q(Q).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
        K = self.W_K(K).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
        V = self.W_V(V).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
        
        # 计算缩放点积注意力
        scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.d_k))
        if mask is not None:
            scores = scores.masked_fill(mask == 0, -1e9)
        attn_weights = torch.softmax(scores, dim=-1)
        context = torch.matmul(attn_weights, V)
        
        # 拼接多头结果并输出
        context = context.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
        output = self.W_O(context)
        return output

5. 位置编码(Positional Encoding)

  • Transformer 模型通过自注意力机制捕捉序列中元素的全局依赖关系,但其本身不具备处理序列顺序的能力(因为自注意力是位置无关的),位置编码(Positional Encoding) 的作用是为模型注入序列的位置信息,使其能够区分不同位置的词。以下是其核心原理与实现方法:
  • 编码方式:位置编码需满足以下条件:
  1. 唯一性:每个位置有唯一的编码。
  2. 相对位置感知:编码能反映位置间的相对距离(如位置 5 和 6 的编码差异应与位置 10 和 11 的差异相似)。
  3. 泛化性:能处理比训练时更长的序列(如训练时最大长度 512,推理时处理 1000 长度的文本)。
  •   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) 
  • pos 为位置,i 为维度索引。

** 其他位置编码方法**

方法原理优点缺点
可学习位置编码随机初始化位置嵌入向量并通过训练更新灵活性高,适应任务特性无法泛化到超出训练长度的序列
相对位置编码直接建模词对之间的相对距离(如 Transformer-XL)更符合语言特性计算复杂度较高
旋转位置编码(RoPE)通过复数空间旋转操作融合位置信息(如 LLaMA 模型)理论优雅,支持任意长度外推实现复杂

位置编码的代码实现(PyTorch)

import torch
import torch.nn as nn

class PositionalEncoding(nn.Module):
    def __init__(self, d_model: int, max_len: int = 5000):
        super().__init__()
        position = torch.arange(max_len).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))
        pe = torch.zeros(max_len, d_model)
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        self.register_buffer('pe', pe)  # 不参与训练

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # x: [batch_size, seq_len, d_model]
        x = x + self.pe[:x.size(1)]
        return x

6. 前馈神经网络(Feed-Forward Network)

  • 每个位置的向量独立通过两层全连接网络:
  •  FFN ( x ) = ReLU ( W 1 x + b 1 ) W 2 + b 2   \ \text{FFN}(x) = \text{ReLU}(W_1x + b_1)W_2 + b_2 \  FFN(x)=ReLU(W1x+b1)W2+b2 
  • 作用:增强模型的非线性表达能力。

7. 残差连接与层归一化

  • 残差连接:将输入直接加到子层输出上 ( x + Sublayer ( x ) ) (x + \text{Sublayer}(x)) (x+Sublayer(x)),缓解梯度消失。
  • 层归一化:对每个位置的向量进行归一化,加速训练。

8. 解码器的掩码自注意力

  • 掩码机制:在解码时,通过掩码矩阵(上三角为负无穷)阻止模型看到未来信息,确保自回归生成。

在这里插入图片描述
在计算过程中,t时刻应该只能看到0到t-1时刻的数据,但是在实际训练过程中,网络能够看到全局信息,所以增加了MASK,本质上是使网络在计算时可以使用全局信息,但是在输出时不要输出t时刻之后的值,将t时刻及其以后的值替换为一个非常大的负数,经过softmax后,该部分将变为0,不会被输出计算进去。


9. 模型输出

  • 解码器最终输出通过线性层和 Softmax,生成目标序列的概率分布。

10. 为什么 Transformer 比 RNN/CNN 更好?

特性RNN/CNNTransformer
长距离依赖依赖短,易遗忘远距离信息直接建模任意位置关系
并行计算序列顺序处理,难以并行所有位置同时计算
计算复杂度RNN:O(n),CNN:O(n log n)自注意力:O(n²)
实际训练速度慢(受限于序列长度)快(充分利用 GPU 并行)

11. 应用与变体

  • 经典模型
    • BERT:仅用编码器的双向预训练模型。
    • GPT:仅用解码器的自回归生成模型。
    • T5:编码器-解码器结构的通用文本生成模型。
  • 优化方向
    • 稀疏注意力(如 Sparse Transformer):降低计算复杂度。
    • 位置编码改进(如 Rotary Position Embedding):更灵活的位置表示。

总结

Transformer 通过自注意力机制实现了全局信息的高效捕获,解决了传统模型的序列处理瓶颈。其并行计算能力和灵活性使其成为 NLP 领域的基石,并逐步扩展到计算机视觉(ViT)、语音处理等领域。理解其原理是掌握现代深度学习模型(如 ChatGPT)的关键基础。
感谢您阅读到最后!😊总结不易,希望多多支持~🌹 点赞👍收藏⭐评论✍️,您的三连是我持续更新的动力💖~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坏脾气的小十七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值