共计 2044 个字符,预计需要花费 6 分钟才能阅读完成。
一、BERT 预训练任务核心思想
BERT 的成功很大程度上归功于它的两个预训练任务:掩码语言模型 (MLM) 和下一句预测(NSP)。这两个任务让模型学会了理解单词在上下文中的含义以及句子之间的关系。

1.1 掩码语言模型(MLM)
MLM 的核心思想很简单:随机遮盖输入文本中的一些单词,然后让模型预测这些被遮盖的单词。这迫使模型不仅要理解单个单词的含义,还要理解单词在上下文中的关系。
- 具体操作时,BERT 会随机遮盖 15% 的输入 token
- 其中 80% 用 [MASK] 替换,10% 用随机词替换,10% 保持不变
- 这种策略防止模型过度依赖 [MASK] 标记
数学上,MLM 是一个分类问题,使用交叉熵损失函数:
L_MLM = -∑ y_i * log(p_i)
其中 y_i 是真实单词的 one-hot 编码,p_i 是模型预测的概率分布。
1.2 下一句预测(NSP)
NSP 任务让模型判断两个句子是否是连续的。这在理解段落和文档级别的语义时非常有用。
- 正样本:从语料中取连续的句子对
- 负样本:随机组合不相关的句子
- 这是一个二分类问题,使用二元交叉熵损失
二、PyTorch 实现详解
2.1 数据预处理
from transformers import BertTokenizer
import torch
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
def prepare_mlm_inputs(text):
inputs = tokenizer(text, return_tensors='pt', truncation=True, max_length=512)
# 随机选择 15% 的 token 进行 mask
mask_indices = torch.randperm(inputs['input_ids'].size(1))[:int(0.15*inputs['input_ids'].size(1))]
labels = inputs['input_ids'].clone()
# 80% 用 [MASK] 替换
inputs['input_ids'][0, mask_indices[:int(0.8*len(mask_indices))]] = tokenizer.mask_token_id
# 10% 用随机词替换
random_words = torch.randint(len(tokenizer), size=(int(0.1*len(mask_indices)),))
inputs['input_ids'][0, mask_indices[int(0.8*len(mask_indices)):int(0.9*len(mask_indices))]] = random_words
# 剩下 10% 保持不变
return inputs, labels
2.2 模型构建
from transformers import BertForPreTraining
model = BertForPreTraining.from_pretrained('bert-base-uncased')
# 训练参数设置
optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5)
2.3 训练循环
def train_step(batch):
inputs, labels = prepare_mlm_inputs(batch['text'])
outputs = model(**inputs, labels=labels, next_sentence_label=batch['is_next'])
loss = outputs.loss
loss.backward()
optimizer.step()
optimizer.zero_grad()
return loss.item()
三、任务性能影响分析
通过消融实验发现:
- 单独使用 MLM:模型在单句任务上表现良好,但在需要理解句子关系的任务 (如问答) 上表现较差
- 单独使用 NSP:模型理解句子关系能力提升,但单词级理解能力下降
- 两者结合:在 GLUE 基准测试上平均提升 3 - 5 个点
四、生产环境实践建议
4.1 处理长文本
- 对超过 512token 的文档,推荐使用滑动窗口方法
- 窗口重叠建议在 64-128token 之间
- 对特别长的文档,可以先分段处理再合并结果
4.2 Batch Size 选择
- NSP 任务对 batch size 比较敏感
- 建议 batch size 至少为 32
- 太小的 batch size 会导致 NSP 任务学习不稳定
4.3 学习率设置
- MLM 和 NSP 任务可以共用学习率
- 推荐初始学习率在 5e- 5 到 3e- 4 之间
- 可以使用线性 warmup 策略
五、未来改进方向
- 目前的 MLM 随机遮盖策略是否最优?是否有更智能的遮盖方法?
- NSP 任务是否能够更好地建模多句关系?比如预测句子在段落中的位置。
- 如何平衡 MLM 和 NSP 两个任务的学习进度?是否需要动态调整任务权重?
BERT 的预训练策略虽然强大,但仍有改进空间。希望这些实现细节和思考能帮助你在实际项目中更好地应用和优化 BERT 模型。
正文完
