1. 预训练语言模型概述
在自然语言处理领域,预训练语言模型已经成为现代NLP系统的核心组件。这些模型通过在大规模文本数据上进行预训练,学习语言的通用表示,然后可以针对特定任务进行微调。这种"预训练+微调"的范式彻底改变了NLP领域的研究和应用方式。
Transformer架构是当前主流预训练语言模型的基础,其原始结构包含encoder和decoder两部分。基于这一架构,衍生出了三种主要类型的预训练模型:
- Encoder-based模型:如BERT,专注于理解输入文本的双向表示
- Decoder-based模型:如GPT系列,专注于自回归文本生成
- Encoder-Decoder模型:如T5,结合了理解和生成能力
提示:理解这三种架构的区别是掌握现代NLP系统的关键。选择哪种模型取决于具体任务需求——理解任务通常使用encoder模型,生成任务使用decoder模型,而需要同时理解和生成的任务则适合encoder-decoder架构。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. BERT:双向编码器表示
2.1 BERT的核心设计理念
BERT(Bidirectional Encoder Representations from Transformers)的核心创新在于其双向上下文理解能力。与传统语言模型不同,BERT可以同时考虑单词左右两侧的上下文信息,这使得它在语言理解任务上表现出色。
BERT的工作范式遵循"预训练+微调"的两阶段模式:
- 预训练阶段:在大规模无标注数据上训练,学习通用语言表示
- 微调阶段:在特定任务的小规模标注数据上调整模型参数
2.2 BERT的预训练任务
2.2.1 掩码语言建模(MLM)
MLM是BERT的核心预训练任务,其流程如下:
- 随机选择输入序列中15%的token进行掩码处理
- 其中80%替换为[MASK]标记
- 10%替换为随机token
- 10%保持不变
- 模型需要预测这些被掩码的原始token
这种设计迫使模型学习深层次的上下文表示,因为要准确预测被掩码的词,必须理解整个句子的语义和语法结构。
python复制# 伪代码展示MLM的实现逻辑
def masked_language_model(input_text):
tokens = tokenize(input_text)
masked_indices = randomly_select_15_percent(tokens)
for idx in masked_indices:
rand = random()
if rand < 0.8:
tokens[idx] = "[MASK]"
elif rand < 0.9:
tokens[idx] = random_token()
# else 10%保持原样
model_output = bert_model(tokens)
loss = cross_entropy(model_output[masked_indices], original_tokens[masked_indices])
return loss
2.2.2 下一句预测(NSP)
NSP任务要求模型判断两个句子是否是连续的文本:
- 50%的样本中,第二个句子是原文中第一个句子的下一句
- 50%的样本中,第二个句子是从语料库中随机选取的
- 模型需要预测这两个句子是否是连续的
这个任务帮助模型学习句子间的关系理解,对问答、自然语言推理等任务尤为重要。
2.3 BERT的微调应用
预训练后的BERT可以通过微调适应各种下游任务。常见的微调任务包括:
-
文本分类:输入完整句子,输出类别标签
- 情感分析(正面/负面)
- 主题分类
-
命名实体识别(NER):标记文本中的实体及其类型
- 使用BIO(Begin, Inside, Outside)标注体系
-
问答系统:给定问题和参考文本,定位答案位置
- 输出答案在文本中的起始和结束位置
注意:微调阶段的学习率通常需要设置得比预训练时小1-2个数量级,以避免破坏预训练获得的通用语言表示。
3. GPT:生成式预训练模型
3.1 GPT的核心架构
GPT(Generative Pretrained Transformer)采用纯decoder架构,专注于自回归文本生成。与BERT不同,GPT是单向的——每个token只能关注它之前的上下文。
GPT的工作机制:
- 输入一段文本
- 模型预测下一个最可能的token
- 将预测的token加入输入,重复过程
这种设计使GPT非常适合文本生成任务,如故事创作、代码生成等。
3.2 GPT的训练方法
GPT使用标准的语言模型目标函数——最大化给定前文条件下当前token的概率:
L(θ) = Σ log P(x_t | x_{<t}; θ)
训练过程中,GPT通过teacher forcing方式学习——使用真实的前文token预测当前token,即使之前预测可能有误。
python复制# 伪代码展示GPT的训练过程
def train_gpt(model, text_corpus):
for text in text_corpus:
tokens = tokenize(text)
for i in range(1, len(tokens)):
# 使用前i-1个token预测第i个token
input_tokens = tokens[:i]
target_token = tokens[i]
output = model(input_tokens)
loss = cross_entropy(output[-1], target_token)
update_model(loss)
3.3 GPT的应用场景
- 文本生成:故事、诗歌、新闻等创作
- 对话系统:生成连贯的对话回复
- 代码生成:根据描述生成代码片段
- 文本补全:根据开头续写内容
提示:GPT生成的内容质量高度依赖提示(prompt)设计。精心设计的提示可以显著提高生成结果的相关性和质量。
4. T5:文本到文本的统一框架
4.1 T5的设计理念
T5(Text-to-Text Transfer Transformer)提出将所有NLP任务统一为"文本到文本"的转换框架。无论是分类、翻译还是问答,都视为将输入文本转换为输出文本的过程。
这种统一框架的优势:
- 简化了模型架构选择
- 可以使用相同的训练和推理流程处理不同任务
- 便于知识在不同任务间迁移
4.2 T5的关键技术
4.2.1 相对位置编码
T5采用相对位置编码而非BERT/GPT的绝对位置编码。其核心思想是:
- 词与词之间的相对位置比绝对位置更重要
- 对近距离位置使用精确编码
- 对远距离位置使用模糊编码(通过分桶和对数映射实现)
数学表达:
e_{ij} = f(i-j)
其中f(·)将位置差映射到嵌入向量,近距离差异精确表示,远距离差异粗略表示。
4.2.2 简化LayerNorm
T5对标准LayerNorm进行了简化:
- 移除了偏置项(bias)
- 仅保留缩放因子(scale)
- 减少了计算开销
这种简化在实践中几乎不影响模型性能,但提高了计算效率。
4.2.3 SentencePiece分词
T5使用SentencePiece直接在原始文本上训练分词器,不依赖空格等显式分隔符。这种方法对中文等无空格语言更加友好。
SentencePiece的特点:
- 基于子词(subword)单元
- 支持unicode字符
- 可以处理任意输入文本
4.3 T5的任务统一方法
T5将所有任务转换为文本到文本的形式:
-
分类任务:
- 输入:"情感分析:这部电影太棒了!"
- 输出:"正面"
-
翻译任务:
- 输入:"将英语翻译为法语:Hello world"
- 输出:"Bonjour le monde"
-
摘要任务:
- 输入:"摘要:长篇文章内容..."
- 输出:"文章摘要..."
这种统一框架极大简化了多任务学习的实现。
5. 预训练语言模型的实践建议
5.1 模型选择指南
- 理解任务优先选择BERT或其变体
- 生成任务优先选择GPT或其变体
- 多任务学习或需要统一框架时考虑T5
5.2 训练技巧
-
学习率设置:
- 预训练:1e-4到5e-4
- 微调:1e-5到5e-5
-
批次大小:
- 尽可能使用大batch(受硬件限制)
- 使用梯度累积模拟更大batch
-
训练时长:
- 预训练:至少1个epoch(通常更多)
- 微调:3-10个epoch(防止过拟合)
5.3 常见问题与解决方案
-
过拟合:
- 增加dropout率
- 使用早停(early stopping)
- 添加L2正则化
-
训练不稳定:
- 检查梯度裁剪
- 调整学习率
- 检查数据质量
-
推理速度慢:
- 使用模型蒸馏
- 尝试量化
- 考虑更小的模型变体
在实际项目中,我经常发现选择合适的预训练模型和恰当的微调策略比盲目使用更大模型更能带来实质性的性能提升。特别是在资源有限的情况下,精心设计的微调流程配合中等规模的预训练模型往往能达到最佳性价比。
