TL;DR

Transformer是一种革命性的神经网络架构,通过自注意力机制实现并行处理序列数据,彻底改变了自然语言处理领域。本指南详细介绍Transformer的核心组件(自注意力、位置编码、编码器-解码器架构),解释其相对于RNN/LSTM的优势,并探讨GPT、BERT等现代大模型如何基于Transformer构建。

引言

2017年,Google发表的论文《Attention Is All You Need》提出了Transformer架构,这一创新彻底改变了人工智能的发展轨迹。从ChatGPT到BERT,从机器翻译到代码生成,几乎所有现代AI大模型都建立在Transformer的基础之上。

在本指南中,你将学到:

  • Transformer架构的核心设计理念
  • 自注意力机制的数学原理和直观理解
  • 位置编码如何让模型理解序列顺序
  • 编码器-解码器架构的工作方式
  • Transformer与RNN/LSTM的对比分析
  • GPT、BERT等模型与Transformer的关系

什么是Transformer

Transformer是一种基于注意力机制的序列到序列(Seq2Seq)模型架构。与传统的循环神经网络不同,Transformer完全摒弃了循环结构,仅依靠注意力机制来捕获输入和输出之间的全局依赖关系。

graph TB subgraph "Transformer架构概览" Input["输入序列"] --> Encoder["编码器 (N层堆叠)"] Encoder --> Context["上下文表示"] Context --> Decoder["解码器 (N层堆叠)"] Target["目标序列"] --> Decoder Decoder --> Output["输出序列"] end subgraph "编码器层" E1["自注意力层"] --> E2["前馈神经网络"] end subgraph "解码器层" D1["掩码自注意力"] --> D2["交叉注意力"] --> D3["前馈神经网络"] end

为什么Transformer如此重要

Transformer的出现解决了传统序列模型的几个关键问题:

  1. 并行计算:RNN必须按顺序处理,而Transformer可以并行处理整个序列
  2. 长距离依赖:通过注意力机制直接建立任意位置之间的联系
  3. 可扩展性:架构设计使其能够扩展到数十亿参数规模

自注意力机制详解

自注意力(Self-Attention)是Transformer的核心创新。它允许模型在处理每个位置时,同时关注序列中的所有其他位置。

Query、Key、Value的概念

自注意力机制使用三个向量来计算注意力:

  • Query(查询):当前位置想要查找什么信息
  • Key(键):每个位置包含什么信息
  • Value(值):每个位置实际要传递的信息
python
import numpy as np

def scaled_dot_product_attention(Q, K, V):
    """
    缩放点积注意力计算
    Q: 查询矩阵 (seq_len, d_k)
    K: 键矩阵 (seq_len, d_k)
    V: 值矩阵 (seq_len, d_v)
    """
    d_k = K.shape[-1]
    
    # 计算注意力分数
    scores = np.matmul(Q, K.T) / np.sqrt(d_k)
    
    # Softmax归一化
    attention_weights = softmax(scores, axis=-1)
    
    # 加权求和
    output = np.matmul(attention_weights, V)
    
    return output, attention_weights

def softmax(x, axis=-1):
    exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
    return exp_x / np.sum(exp_x, axis=axis, keepdims=True)

注意力计算公式

自注意力的数学表达式为:

code
Attention(Q, K, V) = softmax(QK^T / √d_k) V

其中 d_k 是键向量的维度,除以 √d_k 是为了防止点积值过大导致softmax梯度消失。

多头注意力

为了让模型能够关注不同类型的信息,Transformer使用多头注意力(Multi-Head Attention):

python
def multi_head_attention(Q, K, V, num_heads, d_model):
    """
    多头注意力机制
    """
    d_k = d_model // num_heads
    
    heads = []
    for i in range(num_heads):
        # 每个头使用不同的线性投影
        Q_i = linear_projection(Q, d_k)
        K_i = linear_projection(K, d_k)
        V_i = linear_projection(V, d_k)
        
        head_i, _ = scaled_dot_product_attention(Q_i, K_i, V_i)
        heads.append(head_i)
    
    # 拼接所有头的输出
    concat = np.concatenate(heads, axis=-1)
    
    # 最终线性投影
    output = linear_projection(concat, d_model)
    
    return output

多头注意力允许模型同时从不同的表示子空间学习信息,例如一个头关注语法结构,另一个头关注语义关系。

位置编码原理

由于Transformer没有循环结构,它无法自然地感知序列中元素的位置。位置编码(Positional Encoding)解决了这个问题。

正弦位置编码

原始Transformer使用正弦和余弦函数生成位置编码:

python
def positional_encoding(seq_len, d_model):
    """
    生成正弦位置编码
    """
    position = np.arange(seq_len)[:, np.newaxis]
    div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))
    
    pe = np.zeros((seq_len, d_model))
    pe[:, 0::2] = np.sin(position * div_term)  # 偶数维度
    pe[:, 1::2] = np.cos(position * div_term)  # 奇数维度
    
    return pe

这种设计的优点:

  • 每个位置有唯一的编码
  • 模型可以学习相对位置关系
  • 可以外推到训练时未见过的序列长度

可学习位置编码

现代模型如BERT和GPT使用可学习的位置嵌入:

python
class LearnablePositionalEncoding:
    def __init__(self, max_seq_len, d_model):
        # 位置嵌入作为可训练参数
        self.position_embeddings = np.random.randn(max_seq_len, d_model) * 0.02

编码器-解码器架构

Transformer采用编码器-解码器架构,这是处理序列到序列任务的经典设计。

graph LR subgraph "编码器 Encoder" I[输入嵌入] --> PE1[位置编码] PE1 --> SA1[自注意力] SA1 --> AN1["Add & Norm"] AN1 --> FF1[前馈网络] FF1 --> AN2["Add & Norm"] end subgraph "解码器 Decoder" O[输出嵌入] --> PE2[位置编码] PE2 --> MSA[掩码自注意力] MSA --> AN3["Add & Norm"] AN3 --> CA[交叉注意力] AN2 -.-> CA CA --> AN4["Add & Norm"] AN4 --> FF2[前馈网络] FF2 --> AN5["Add & Norm"] AN5 --> Linear[线性层] Linear --> Softmax[Softmax] end

编码器结构

编码器由N个相同的层堆叠而成,每层包含:

  1. 多头自注意力层:让每个位置关注输入序列的所有位置
  2. 前馈神经网络:对每个位置独立进行非线性变换
  3. 残差连接和层归一化:稳定训练过程

解码器结构

解码器同样由N层堆叠,但每层有三个子层:

  1. 掩码多头自注意力:只能关注已生成的位置,防止信息泄露
  2. 交叉注意力:关注编码器的输出,获取源序列信息
  3. 前馈神经网络:与编码器相同

残差连接与层归一化

python
def transformer_sublayer(x, sublayer_fn):
    """
    Transformer子层:残差连接 + 层归一化
    """
    # 子层计算
    sublayer_output = sublayer_fn(x)
    
    # 残差连接
    residual = x + sublayer_output
    
    # 层归一化
    output = layer_norm(residual)
    
    return output

Transformer vs RNN/LSTM对比

特性 Transformer RNN/LSTM
并行计算 完全并行 必须顺序处理
长距离依赖 O(1)路径长度 O(n)路径长度
计算复杂度 O(n²·d) O(n·d²)
训练速度 快(可并行) 慢(顺序依赖)
内存占用 较高(注意力矩阵) 较低
可解释性 注意力权重可视化 较难解释

为什么Transformer取代了RNN

  1. 训练效率:GPU擅长并行计算,Transformer充分利用这一优势
  2. 长序列处理:RNN的梯度消失问题限制了有效记忆长度
  3. 模型容量:Transformer更容易扩展到大规模参数

GPT、BERT等模型的关系

现代大语言模型都基于Transformer架构,但采用不同的设计选择:

graph TB T[Transformer] --> E[仅编码器] T --> D[仅解码器] T --> ED[编码器-解码器] E --> BERT[BERT] E --> RoBERTa[RoBERTa] D --> GPT[GPT系列] D --> LLaMA[LLaMA] D --> Claude[Claude] ED --> T5[T5] ED --> BART[BART]

GPT系列(仅解码器)

GPT使用Transformer的解码器部分,采用自回归方式生成文本:

  • 训练目标:预测下一个token
  • 特点:单向注意力,适合文本生成
  • 应用:对话、写作、代码生成

BERT(仅编码器)

BERT使用Transformer的编码器部分,采用双向注意力:

  • 训练目标:掩码语言模型(MLM)+ 下一句预测
  • 特点:双向上下文理解
  • 应用:文本分类、问答、命名实体识别

T5(编码器-解码器)

T5保留完整的Transformer架构:

  • 训练目标:文本到文本的统一框架
  • 特点:灵活处理各种NLP任务
  • 应用:翻译、摘要、问答

实践指南

使用预训练模型

对于大多数应用,建议使用预训练模型而非从头训练:

python
from transformers import AutoModel, AutoTokenizer

# 加载预训练模型
model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# 文本编码
text = "Transformer改变了自然语言处理"
inputs = tokenizer(text, return_tensors="pt")
outputs = model(**inputs)

微调技巧

  1. 学习率:使用较小的学习率(1e-5到5e-5)
  2. 批次大小:根据显存调整,通常16-32
  3. 训练轮数:2-4轮通常足够
  4. 梯度累积:显存不足时使用

工具推荐

在AI开发和学习过程中,以下工具可以提升效率:

总结

Transformer架构的核心要点:

  1. 自注意力机制:通过Query-Key-Value计算实现全局依赖建模
  2. 位置编码:为无循环结构的模型提供位置信息
  3. 编码器-解码器:灵活的架构支持多种任务类型
  4. 并行计算:相比RNN大幅提升训练效率
  5. 可扩展性:支持扩展到数千亿参数规模

理解Transformer架构是掌握现代AI技术的基础,无论是使用大语言模型还是开发AI应用,这些知识都至关重要。

常见问题

Transformer中的注意力机制与人类注意力有什么关系?

Transformer的注意力机制是一种数学抽象,灵感来源于人类选择性关注重要信息的能力。在模型中,注意力权重表示不同位置之间的相关性强度,类似于人类阅读时会重点关注关键词。但这是一种计算机制,与生物神经系统的注意力机制有本质区别。

为什么Transformer需要位置编码?

因为Transformer的自注意力机制是位置无关的——它只关注元素之间的关系,不考虑它们在序列中的位置。而语言理解需要位置信息("狗咬人"和"人咬狗"意思完全不同),所以必须通过位置编码显式地注入位置信息。

GPT和BERT哪个更好?

这取决于具体任务。GPT适合生成任务(写作、对话、代码生成),因为它的自回归设计天然适合逐步生成。BERT适合理解任务(分类、问答、信息抽取),因为它的双向注意力能更好地理解上下文。现代趋势是GPT类模型在规模扩大后也能很好地完成理解任务。

Transformer的计算复杂度为什么是O(n²)?

自注意力需要计算序列中每对位置之间的注意力分数,对于长度为n的序列,需要计算n×n个分数,因此复杂度是O(n²)。这也是处理超长文本时的主要瓶颈,许多研究致力于开发线性复杂度的注意力变体。

如何选择合适的预训练模型?

选择预训练模型时考虑:1)任务类型(生成选GPT类,理解选BERT类);2)语言(中文任务选中文预训练模型);3)模型大小(根据计算资源和延迟要求);4)领域(有领域特定预训练模型时优先选择)。