Transformer概述#
背景#
Transformer 由Vaswani等人在2017年提出,彻底改变了NLP和CV领域。
核心创新#
- 自注意力机制:并行处理序列,无需循环
- 位置编码:替代RNN的位置信息
- 完全并行:训练速度大幅提升
优势#
- 并行计算:比RNN快得多
- 长距离依赖:直接建模任意距离的关系
- 可解释性:注意力权重可视化
注意力机制#
基本思想#
注意力(Attention):让模型关注输入的不同部分。
查询-键-值(QKV)机制#
Query (Q): 查询向量,表示"我想找什么"
Key (K): 键向量,表示"我是什么"
Value (V): 值向量,表示"我的内容"计算过程#
- 计算相似度:$\text{scores} = Q \cdot K^T$
- 归一化:$\text{attention\_weights} = \text{softmax}(\text{scores} / \sqrt{d_k})$
- 加权求和:$\text{output} = \text{attention\_weights} \cdot V$
数学公式#
$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \cdot V $$其中 $d_k$ 是键的维度,用于缩放。
多头注意力(Multi-Head Attention)#
并行使用多个注意力头:
$$ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) \cdot W^O $$其中 $\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$
优势:
- 捕获不同类型的关系
- 增强表达能力
Transformer结构#
整体架构#

编码器(Encoder)#
1. 自注意力层#
$$ \text{Self-Attention}(x) = \text{Attention}(x, x, x) $$每个位置关注序列中的所有位置(包括自己)。
2. 前馈网络(FFN)#
$$ \text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2 $$通常是两层全连接网络,中间使用ReLU。
3. 残差连接和层归一化#
$$ x = \text{LayerNorm}(x + \text{Sublayer}(x)) $$解码器(Decoder)#
1. 掩码自注意力#
防止看到未来信息:
$$ \text{mask}[i, j] = \begin{cases} 0 & \text{if } i \geq j \quad \text{(允许)} \\ -\infty & \text{if } i < j \quad \text{(掩码)} \end{cases} $$2. 编码器-解码器注意力#
解码器关注编码器的输出:
$$ \text{Attention}(Q_{\text{decoder}}, K_{\text{encoder}}, V_{\text{encoder}}) $$位置编码#
由于Transformer没有循环结构,需要显式编码位置信息:
正弦位置编码#
$$ \text{PE}(\text{pos}, 2i) = \sin\left(\frac{\text{pos}}{10000^{2i/d_{\text{model}}}}\right) $$ $$ \text{PE}(\text{pos}, 2i+1) = \cos\left(\frac{\text{pos}}{10000^{2i/d_{\text{model}}}}\right) $$可学习位置编码#
直接学习位置嵌入。
BERT和GPT#
BERT(Bidirectional Encoder Representations)#
特点#
- 双向编码器:同时利用前后文
- 预训练任务:
- MLM(Masked Language Model):预测被掩码的词
- NSP(Next Sentence Prediction):判断句子关系
架构#
[CLS] token₁ token₂ [MASK] token₄ [SEP] ...
↓
Transformer Encoder (12/24层)
↓
输出表示应用#
- 文本分类
- 命名实体识别
- 问答系统
GPT(Generative Pre-trained Transformer)#
特点#
- 自回归生成:从左到右生成文本
- 解码器架构:使用掩码自注意力
- 预训练:语言建模(预测下一个词)
架构#
token₁ token₂ token₃ ...
↓
Transformer Decoder (12/24/...层)
↓
下一个token的概率分布GPT系列#
- GPT-1:1.17亿参数
- GPT-2:15亿参数
- GPT-3:1750亿参数
- GPT-4:更大规模
Vision Transformer#
概述#
ViT(Vision Transformer) 将Transformer应用到图像分类。
方法#
- 图像分块:将图像分成 $16 \times 16$ 的patches
- 线性投影:将patches投影为向量
- 位置编码:添加位置信息
- Transformer编码器:处理序列
- 分类头:输出类别
结构#
图像($224 \times 224 \times 3$)
↓
分块($14 \times 14$ patches,每个 $16 \times 16$)
↓
展平 + 线性投影 (768维)
↓
添加[CLS] token + 位置编码
↓
Transformer Encoder (12层)
↓
[CLS] token → 分类头优势#
- 无需卷积
- 可扩展到大规模数据
- 在ImageNet上达到SOTA
代码实现#
多头注意力#
import torch
import torch.nn as nn
import math
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, num_heads):
super(MultiHeadAttention, self).__init__()
assert d_model % num_heads == 0
self.d_model = d_model
self.num_heads = num_heads
self.d_k = d_model // num_heads
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 scaled_dot_product_attention(self, Q, K, V, mask=None):
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attention_weights = torch.softmax(scores, dim=-1)
output = torch.matmul(attention_weights, V)
return output, attention_weights
def forward(self, query, key, value, mask=None):
batch_size = query.size(0)
# 线性变换并分头
Q = self.W_q(query).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
K = self.W_k(key).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
V = self.W_v(value).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
# 注意力计算
x, attention_weights = self.scaled_dot_product_attention(Q, K, V, mask)
# 拼接多头
x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
# 输出投影
output = self.W_o(x)
return outputTransformer编码器层#
class TransformerEncoderLayer(nn.Module):
def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
super(TransformerEncoderLayer, self).__init__()
self.self_attn = MultiHeadAttention(d_model, num_heads)
self.feed_forward = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.ReLU(),
nn.Linear(d_ff, d_model)
)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.dropout = nn.Dropout(dropout)
def forward(self, x, mask=None):
# 自注意力 + 残差连接
attn_output = self.self_attn(x, x, x, mask)
x = self.norm1(x + self.dropout(attn_output))
# 前馈网络 + 残差连接
ff_output = self.feed_forward(x)
x = self.norm2(x + self.dropout(ff_output))
return x位置编码#
class PositionalEncoding(nn.Module):
def __init__(self, d_model, max_len=5000):
super(PositionalEncoding, self).__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
pe = pe.unsqueeze(0)
self.register_buffer('pe', pe)
def forward(self, x):
return x + self.pe[:, :x.size(1)]完整Transformer#
class Transformer(nn.Module):
def __init__(self, vocab_size, d_model, num_heads, num_layers, d_ff, max_len, dropout=0.1):
super(Transformer, self).__init__()
self.embedding = nn.Embedding(vocab_size, d_model)
self.pos_encoding = PositionalEncoding(d_model, max_len)
self.encoder_layers = nn.ModuleList([
TransformerEncoderLayer(d_model, num_heads, d_ff, dropout)
for _ in range(num_layers)
])
self.dropout = nn.Dropout(dropout)
self.fc = nn.Linear(d_model, vocab_size)
def forward(self, x, mask=None):
x = self.embedding(x) * math.sqrt(self.d_model)
x = self.pos_encoding(x)
x = self.dropout(x)
for layer in self.encoder_layers:
x = layer(x, mask)
output = self.fc(x)
return output总结#
- Transformer:基于注意力机制的架构
- 自注意力:并行处理,直接建模长距离依赖
- BERT:双向编码器,适合理解任务
- GPT:自回归生成,适合生成任务
- ViT:将Transformer应用到图像
关键要点:
- 注意力机制是Transformer的核心
- 并行计算大幅提升训练速度
- BERT和GPT是重要的预训练模型
- Transformer统一了NLP和CV领域
下一步:学习生成模型,了解VAE、GAN等。