BERT预训练原理详解:从掩码语言模型(MLM)到下一句预测(NSP)的实战指南

1次阅读
没有评论

共计 3221 个字符,预计需要花费 9 分钟才能阅读完成。

image.webp

1. BERT 预训练概览

BERT(Bidirectional Encoder Representations from Transformers)是一种基于 Transformer 架构的预训练语言模型。与传统的单向语言模型不同,BERT 通过以下两个关键任务进行预训练:

BERT 预训练原理详解:从掩码语言模型 (MLM) 到下一句预测 (NSP) 的实战指南

  • 掩码语言模型(MLM):让模型学会根据上下文预测被掩盖的单词
  • 下一句预测(NSP):让模型理解句子间的关系

这种双向训练方式使 BERT 能够捕获更丰富的语义信息,在各种 NLP 任务中表现出色。

2. 掩码语言模型 (MLM) 详解

2.1 输入表示和掩码策略

BERT 的输入由三部分组成:

  1. Token Embeddings:词嵌入表示
  2. Segment Embeddings:区分不同句子的嵌入(用于 NSP)
  3. Position Embeddings:位置编码

MLM 的核心策略是随机掩盖输入文本中的部分单词,然后让模型预测这些被掩盖的单词。具体实现:

  • 随机选择 15% 的 token 进行掩码
  • 其中 80% 替换为 [MASK] 标记
  • 10% 替换为随机单词
  • 10% 保持不变

2.2 损失函数设计

MLM 使用交叉熵损失函数,只计算被掩盖位置的预测损失:

criterion = nn.CrossEntropyLoss(ignore_index=-100)  # 忽略未被掩盖的位置
loss = criterion(masked_lm_logits.view(-1, vocab_size), masked_lm_labels.view(-1))

2.3 15% 掩码比例的科学依据

这个比例是经过实验验证的平衡点:

  • 太低:模型学习信号不足
  • 太高:破坏句子结构,影响模型理解

3. 下一句预测 (NSP) 详解

3.1 正负样本构建

NSP 任务需要构造句子对:

  • 正样本:实际连续的句子(50%)
  • 负样本:随机组合的句子(50%)

3.2 二分类任务设计

模型需要预测第二个句子是否是第一个句子的实际后续:

# [CLS] token 的表示用于 NSP 分类
seq_relationship_logits = nn.Linear(hidden_size, 2)(pooled_output)

3.3 对下游任务的影响

NSP 特别有利于需要理解句子关系的任务,如:

  • 问答系统
  • 文本蕴涵
  • 对话系统

4. PyTorch 实现示例

4.1 数据处理

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# 处理 MLM
def mask_tokens(inputs, tokenizer):
    labels = inputs.clone()
    # 创建掩码矩阵 (15% 概率)
    probability_matrix = torch.full(labels.shape, 0.15)
    masked_indices = torch.bernoulli(probability_matrix).bool()

    # 80% 替换为[MASK]
    indices_replaced = torch.bernoulli(torch.full(labels.shape, 0.8)).bool() & masked_indices
    inputs[indices_replaced] = tokenizer.convert_tokens_to_ids(tokenizer.mask_token)

    # 10% 替换为随机词
    indices_random = torch.bernoulli(torch.full(labels.shape, 0.5)).bool() & masked_indices & ~indices_replaced
    random_words = torch.randint(len(tokenizer), labels.shape, dtype=torch.long)
    inputs[indices_random] = random_words[indices_random]

    # 剩余 10% 保持不变
    return inputs, labels

4.2 模型定义

import torch.nn as nn
from transformers import BertModel

class BertForPretraining(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.bert = BertModel(config)
        self.cls = BertOnlyMLMHead(config)
        self.seq_relationship = nn.Linear(config.hidden_size, 2)

    def forward(self, input_ids, attention_mask=None, token_type_ids=None):
        outputs = self.bert(input_ids, attention_mask, token_type_ids)
        sequence_output = outputs.last_hidden_state
        pooled_output = outputs.pooler_output

        # MLM 预测
        prediction_scores = self.cls(sequence_output)

        # NSP 预测
        seq_relationship_score = self.seq_relationship(pooled_output)

        return prediction_scores, seq_relationship_score

4.3 训练循环

# 初始化模型和优化器
model = BertForPretraining(config)
optimizer = AdamW(model.parameters(), lr=5e-5)

for epoch in range(epochs):
    for batch in dataloader:
        input_ids, attention_mask, token_type_ids, masked_lm_labels, next_sentence_labels = batch

        # 前向传播
        masked_lm_logits, seq_relationship_logits = model(input_ids, attention_mask, token_type_ids)

        # 计算损失
        mlm_loss = criterion(masked_lm_logits.view(-1, vocab_size), masked_lm_labels.view(-1))
        nsp_loss = criterion(seq_relationship_logits.view(-1, 2), next_sentence_labels.view(-1))
        total_loss = mlm_loss + nsp_loss

        # 反向传播
        optimizer.zero_grad()
        total_loss.backward()
        optimizer.step()

5. 生产环境注意事项

5.1 预训练数据准备

  • 使用多样化语料:维基百科、书籍、新闻等
  • 保持文本质量:过滤低质量内容
  • 领域适配:针对特定领域增加相关语料

5.2 学习率设置

  • 初始学习率:3e- 5 到 5e-5
  • 使用学习率 warmup:前 10% 训练步数线性增加学习率
  • 学习率衰减:线性或余弦衰减

5.3 常见失败案例

  1. 损失不下降:检查数据质量、学习率设置
  2. 过拟合:增加 dropout 率、使用更大数据集
  3. 梯度爆炸:使用梯度裁剪(torch.nn.utils.clip_grad_norm_

6. 总结与思考

BERT 通过 MLM 和 NSP 两个任务的协同训练,能够同时学习单词级和句子级的语言表示:

  • MLM 让模型理解单词在上下文中的含义
  • NSP 让模型掌握句子间关系

针对特定领域应用时,可以考虑:

  • 调整掩码比例(如技术文档可降低比例)
  • 增加领域特定词汇的掩码频率
  • 使用领域数据进行二次预训练

BERT 的强大之处在于其预训练任务的通用性,理解这两个核心任务,就能更好地应用和微调 BERT 模型。

正文完
 0
评论(没有评论)