1. 从Word2Vec到Transformer:预训练模型的进化之路
2017年Transformer架构的横空出世,彻底改变了自然语言处理领域的游戏规则。在此之前,NLP领域长期被RNN和LSTM统治,这些序列模型虽然能够处理变长文本,但存在梯度消失和并行计算困难等固有缺陷。Transformer通过自注意力机制(Self-Attention)完美解决了这些问题,为后续GPT、BERT等里程碑式模型奠定了基础。
在Transformer出现之前,Word2Vec和GloVe等静态词向量模型是主流解决方案。这些模型虽然能够学习单词的分布式表示,但存在明显的局限性——同一个词在不同上下文中的向量表示完全相同。例如"苹果"在"吃苹果"和"苹果手机"中的语义完全不同,但Word2Vec无法区分这种差异。
Transformer的自注意力机制通过计算输入序列中所有位置之间的关系权重,实现了真正的上下文感知。具体来说,对于序列中的每个词,自注意力机制会计算它与序列中所有词(包括它自己)的关联程度,然后根据这些关联程度加权求和得到新的表示。这个过程可以用以下公式表示:
Attention(Q,K,V) = softmax(QK^T/√d_k)V
其中Q、K、V分别代表查询(Query)、键(Key)和值(Value)矩阵,d_k是键向量的维度。这种机制使得模型能够动态地关注输入序列的不同部分,从而捕捉长距离依赖关系。
关键理解:Transformer的自注意力机制本质上是一种"可学习的记忆访问机制",它允许模型根据需要从输入序列的任何位置检索信息,而不受序列长度的限制。
2. GPT-1:单向语言模型的开拓者
2.1 模型架构与训练目标
GPT-1(Generative Pre-trained Transformer)是OpenAI于2018年提出的首个基于Transformer的解码器架构的语言模型。它采用了12层的Transformer解码器堆叠,每层包含掩码自注意力机制和前馈神经网络。与原始Transformer不同的是,GPT-1去掉了编码器部分,仅保留解码器,并使用单向注意力掩码确保每个位置只能关注前面的位置。
这种设计使得GPT-1非常适合生成式任务。在预训练阶段,模型通过最大化以下目标函数来学习语言表示:
L = Σ log P(x_i | x_{i-k},...,x_{i-1}; Θ)
其中k是上下文窗口大小,Θ是模型参数。这个目标函数实际上是在让模型预测给定上文情况下下一个词出现的概率。
2.2 预训练与微调策略
GPT-1采用了二阶段训练策略:
- 无监督预训练:在大规模文本语料(BookCorpus数据集,约7,000本书)上训练语言模型
- 有监督微调:在特定下游任务(如文本分类、问答等)上进一步调整模型参数
在微调阶段,GPT-1通过简单的线性变换将预训练模型适配到各种任务。例如对于分类任务,会在Transformer的输出上添加一个线性分类器。整个微调过程的目标函数是:
L = L_C + λ*L_LM
其中L_C是任务特定的损失(如交叉熵),L_LM是语言模型损失,λ是超参数(通常取0.5)。
2.3 实践应用与局限性
在实际应用中,GPT-1展现出了强大的零样本和小样本学习能力。例如在文本生成任务中,只需提供适当的提示(prompt),模型就能生成连贯的续写。然而,GPT-1也存在明显局限:
- 单向上下文:由于采用从左到右的建模方式,模型无法利用右侧的上下文信息
- 规模限制:1.17亿参数在当时虽算大,但远小于后续模型
- 微调需求:虽然预训练模型强大,但仍需针对特定任务进行微调
以下是一个使用GPT-1进行文本生成的示例代码框架:
python复制import torch
from transformers import GPT2Tokenizer, GPT2LMHeadModel
# 加载模型和分词器(HuggingFace提供了GPT-1的复现)
tokenizer = GPT2Tokenizer.from_pretrained('openai-gpt')
model = GPT2LMHeadModel.from_pretrained('openai-gpt')
# 生成文本
input_text = "人工智能的未来发展"
input_ids = tokenizer.encode(input_text, return_tensors='pt')
output = model.generate(input_ids, max_length=100, num_return_sequences=1)
print(tokenizer.decode(output[0], skip_special_tokens=True))
3. BERT:双向编码的里程碑
3.1 架构创新:双向Transformer编码器
BERT(Bidirectional Encoder Representations from Transformers)由Google于2018年提出,与GPT-1的单向建模不同,BERT采用了Transformer的编码器部分,并通过掩码语言模型(MLM)实现了真正的双向上下文理解。BERT-base模型包含12层Transformer编码器,每层有12个注意力头,共1.1亿参数。
BERT的核心创新在于其预训练任务设计:
- 掩码语言模型(MLM):随机遮盖输入序列中15%的token,让模型预测这些被遮盖的token
- 下一句预测(NSP):判断两个句子是否是原文中连续的句子
MLM任务的数学表示为:
P(w_m|w_{\m}) = softmax(W_2·GELU(W_1·h_m + b_1) + b_2)
其中w_m是被遮盖的token,w_{\m}是其余token,h_m是被遮盖位置的隐藏状态。
3.2 输入表示与位置编码
BERT的输入表示由三部分组成:
- Token Embeddings:WordPiece分词后的词向量
- Segment Embeddings:区分句子A和句子B(用于NSP任务)
- Position Embeddings:与原始Transformer类似的位置编码
这种丰富的输入表示使BERT能够处理各种复杂的语言理解任务。例如在处理问答任务时,问题和段落可以分别作为句子A和句子B输入模型。
3.3 微调范式与应用场景
与GPT-1不同,BERT开创了"预训练+特征提取/微调"的新范式。在实际应用中,BERT可以以多种方式使用:
- 特征提取:直接使用BERT最后一层的隐藏状态作为特征输入下游模型
- 微调:在特定任务上继续训练整个模型
- 适配器:在Transformer层间插入小的可训练模块
以下表格对比了BERT在不同NLP任务上的典型应用方式:
| 任务类型 | 输入处理 | 输出处理 | 示例应用 |
|---|---|---|---|
| 单句分类 | [CLS] + 句子 | [CLS]对应向量接分类器 | 情感分析 |
| 句子对分类 | [CLS] + 句子A + [SEP] + 句子B | [CLS]向量接分类器 | 自然语言推理 |
| 问答任务 | [CLS] + 问题 + [SEP] + 段落 | 预测答案起始和结束位置 | SQuAD |
| 序列标注 | 单句输入 | 每个token对应输出接分类器 | 命名实体识别 |
实践技巧:使用BERT时,学习率通常需要设置得很小(如2e-5到5e-5),因为预训练模型已经包含了丰富的语言知识,微调时只需要小幅调整。
4. ViT:视觉领域的Transformer革命
4.1 从CNN到视觉Transformer
Vision Transformer(ViT)将Transformer成功应用于计算机视觉领域,挑战了CNN长期以来在视觉任务中的统治地位。ViT的核心思想是将图像分割为固定大小的图块(patches),然后将这些图块线性嵌入后作为Transformer的输入序列。
具体来说,给定一张H×W×C的图像,ViT的处理流程如下:
- 将图像分割为N个P×P的图块(N = HW/P²)
- 将每个图块展平为P²C维向量
- 通过可学习的线性投影将每个向量映射到D维(隐藏大小)
- 添加位置编码和[class] token
- 输入标准Transformer编码器
这个过程可以用公式表示为:
z_0 = [x_class; x_p^1E; x_p^2E; ...; x_p^N E] + E_pos
E ∈ ℝ^(P²·C)×D, E_pos ∈ ℝ^(N+1)×D
其中E是图块嵌入矩阵,E_pos是位置编码。
4.2 模型变体与训练策略
ViT论文提出了几种不同规模的模型配置:
| 模型名称 | 层数 | 隐藏大小 | MLP大小 | 注意力头数 | 参数量 |
|---|---|---|---|---|---|
| ViT-Base | 12 | 768 | 3072 | 12 | 86M |
| ViT-Large | 24 | 1024 | 4096 | 16 | 307M |
| ViT-Huge | 32 | 1280 | 5120 | 16 | 632M |
ViT的训练需要大量数据才能发挥优势。论文显示:
- 在ImageNet-1k(1百万图像)上训练,ViT略逊于ResNet
- 在ImageNet-21k(14百万图像)上预训练后微调,ViT与ResNet相当
- 在JFT-300M(3亿图像)上预训练,ViT显著优于所有CNN模型
4.3 视觉Transformer的独特优势
ViT相比传统CNN具有几个显著优势:
- 全局感受野:从第一层开始就能捕捉图像全局关系
- 可扩展性:模型容量可以轻松增加而不受局部感受野限制
- 多模态统一:与NLP使用相同的架构,便于多模态建模
然而,ViT也存在一些挑战:
- 需要大量训练数据
- 计算复杂度与图像分辨率平方成正比
- 缺乏CNN固有的平移等变性
以下是一个使用PyTorch实现ViT关键组件的示例:
python复制import torch
import torch.nn as nn
class PatchEmbedding(nn.Module):
def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768):
super().__init__()
self.img_size = img_size
self.patch_size = patch_size
self.n_patches = (img_size // patch_size) ** 2
self.proj = nn.Conv2d(
in_chans, embed_dim,
kernel_size=patch_size,
stride=patch_size
)
def forward(self, x):
x = self.proj(x) # (B, E, H/P, W/P)
x = x.flatten(2) # (B, E, N)
x = x.transpose(1, 2) # (B, N, E)
return x
class VisionTransformer(nn.Module):
def __init__(self, img_size=224, patch_size=16, in_chans=3,
embed_dim=768, depth=12, num_heads=12):
super().__init__()
self.patch_embed = PatchEmbedding(img_size, patch_size, in_chans, embed_dim)
self.pos_embed = nn.Parameter(torch.zeros(1, self.patch_embed.n_patches + 1, embed_dim))
self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))
self.blocks = nn.ModuleList([
TransformerBlock(embed_dim, num_heads) for _ in range(depth)
])
def forward(self, x):
B = x.shape[0]
x = self.patch_embed(x)
cls_tokens = self.cls_token.expand(B, -1, -1)
x = torch.cat((cls_tokens, x), dim=1)
x = x + self.pos_embed
for blk in self.blocks:
x = blk(x)
return x
5. 三大模型对比与选型指南
5.1 架构差异全景对比
通过下表可以清晰看到GPT-1、BERT和ViT的核心差异:
| 特性 | GPT-1 | BERT | ViT |
|---|---|---|---|
| 基础架构 | Transformer解码器 | Transformer编码器 | Transformer编码器 |
| 注意力类型 | 掩码单向自注意力 | 完全双向自注意力 | 完全双向自注意力 |
| 预训练任务 | 语言建模 | MLM + NSP | 图像分类 |
| 位置处理 | 位置编码 | 位置编码 | 位置编码 |
| 典型输入 | 文本序列 | 文本序列/对 | 图像图块序列 |
| 输出特性 | 生成式 | 判别式 | 判别式 |
| 参数规模 | 1.17亿 | 1.1亿/3.4亿 | 86M/307M/632M |
5.2 任务适配决策树
在实际项目中如何选择合适的模型?可以参考以下决策流程:
-
任务类型判断:
- 生成任务(文本生成、图像生成)→ GPT类架构
- 理解任务(分类、问答)→ BERT类架构
- 视觉任务 → ViT或CNN+Transformer混合架构
-
数据规模评估:
- 小规模数据 → 使用预训练模型进行微调
- 中等规模数据 → 预训练+领域适应
- 超大规模数据 → 从头开始预训练
-
计算资源考量:
- 有限资源 → 选择较小模型(如BERT-base)
- 充足资源 → 大型模型(ViT-Huge)
- 特殊硬件 → 考虑模型并行性和优化(如Deepspeed)
5.3 实际应用中的经验法则
基于实际项目经验,总结出以下实用建议:
-
文本领域:
- 对于分类任务,BERT通常优于GPT
- 生成任务中,GPT-3等后续模型比GPT-1强大得多
- 长文本处理考虑Longformer或Reformer等变体
-
视觉领域:
- 数据不足时,CNN+Transformer混合架构(如BoTNet)更稳定
- 高分辨率图像考虑Swin Transformer等层次化设计
- 轻量化部署可选择MobileViT
-
多模态场景:
- CLIP(ViT+文本编码器)适合图文匹配
- DALL·E(GPT-3变体)适合文生图
- BEiT统一了视觉和语言的掩码建模
避坑指南:在实际部署时,要注意Transformer模型的内存占用问题。例如ViT处理高分辨率图像时,序列长度会急剧增加(224×224图像→196序列,384×384→576序列),导致内存消耗平方级增长。这时可以采用分块处理或下采样策略。
