1584 字
8 分钟
BERT:预训练 + 微调范式

从特征提取到预训练微调#

ELMo 用预训练的双向 LSTM 提取上下文特征,下游模型结构不变;BERT 则把预训练模型本身放进下游任务,通过少量任务特定参数做端到端微调。

BERT(Bidirectional Encoder Representations from Transformers)只使用 Transformer 的编码器堆叠。编码器没有因果掩码,每个位置都能看到左右两侧的所有 token,因此得到的是双向上下文表示。

输入表示#

BERT 的输入由三个嵌入逐元素相加:

Einput=Etoken+Esegment+Eposition\mathbf{E}_{\text{input}} = \mathbf{E}_{\text{token}} + \mathbf{E}_{\text{segment}} + \mathbf{E}_{\text{position}}

Token 嵌入#

使用 WordPiece 分词,BERT-base 的词表大小为 30,522。序列以 [CLS] 开头,句子之间和结尾用 [SEP] 分隔:

[CLS] 句子A 的 token [SEP] 句子B 的 token [SEP]
  • [CLS]:序列起始标记,其最终隐藏状态 T[CLS]\mathbf{T}_{\text{[CLS]}} 作为整句的聚合表示,用于分类任务;
  • [SEP]:分隔句子,同时标记句子边界;
  • [MASK]:MLM 任务中遮蔽 token 的占位符。

Segment 嵌入#

用两个可学习的段向量区分句子 A 和句子 B:句子 A 的 token 加 eA\mathbf{e}_A,句子 B 的 token 加 eB\mathbf{e}_B。这种设计服务于句子对任务和 NSP。

Position 嵌入#

BERT 使用可学习的位置嵌入,而不是原始 Transformer 的正弦编码。最大序列长度为 512,因此有 512 个位置向量,维度与隐藏层一致(BERT-base 为 768)。

位置编码代表模型特点
正弦编码原始 Transformer可外推到训练时未见过的长度
可学习嵌入BERT、GPT更灵活,但无法直接外推

512 的选择与 self-attention 的 O(n2)O(n^2) 复杂度有关:在 2018 年的硬件条件下,512 是计算量和效果的折中。现代模型通过 Flash Attention、稀疏注意力等把窗口扩展到 32K 甚至更长。

预训练任务#

BERT 同时优化两个自监督任务,总损失为两项之和。

Masked Language Model#

随机选择输入中 15% 的 token 作为预测目标。若直接让双向编码器预测下一个词,每个位置都能看到答案,训练没有意义;MLM 改为遮住部分输入,让模型根据两侧上下文还原。

被选中的 token 按以下比例处理:

操作比例示例(原词为 apple)
替换为 [MASK]80%I eat an [MASK] today
替换为随机词10%I eat an car today
保持不变10%I eat an apple today

如果 100% 替换为 [MASK],模型只需学会“看到 [MASK] 就预测原词”,而下游微调时根本没有 [MASK],会造成预训练与微调的不匹配。随机替换迫使模型不能盲目信任输入;保持不变则让模型在正常输入上也能工作。

对被遮蔽位置集合 M\mathcal{M},MLM 损失为

LMLM=−1∣M∣∑i∈Mlog⁡P(wi∣Ti)\mathcal{L}_{\text{MLM}} = -\frac{1}{|\mathcal{M}|}\sum_{i \in \mathcal{M}} \log P(w_i \mid \mathbf{T}_i)P(wi∣Ti)=softmax⁡(WMLMTi+bMLM)P(w_i \mid \mathbf{T}_i) = \operatorname{softmax}(\mathbf{W}_{\text{MLM}}\mathbf{T}_i + \mathbf{b}_{\text{MLM}})

只有被遮蔽的位置参与损失计算。

Next Sentence Prediction#

NSP 判断句子 B 是否是句子 A 的真实后续。用 [CLS] 的表示做二分类:

P(IsNext∣A,B)=σ(wNSPTT[CLS]+bNSP)P(\text{IsNext} \mid A,B) = \sigma(\mathbf{w}_{\text{NSP}}^T \mathbf{T}_{\text{[CLS]}} + b_{\text{NSP}})

训练时 50% 的样本取真实相邻句对,50% 从语料中随机抽取第二句。NSP 的初衷是让模型理解句子间关系,但后续研究发现它对许多任务并非必要:RoBERTa 移除 NSP、使用更大批次和更长序列后效果反而更好。NSP 还可能让模型学到“主题是否一致”,而不是“逻辑是否连贯”。

微调#

预训练完成后,在 BERT 顶部加一个任务特定输出层,用标注数据端到端更新所有参数。不同任务共享同一个编码器,只替换输出头。

单句分类#

情感分析等任务使用 [CLS] 表示:

P(y∣text)=softmax⁡(WT[CLS]+b)P(y \mid \text{text}) = \operatorname{softmax}(\mathbf{W}\mathbf{T}_{\text{[CLS]}} + \mathbf{b})

句子对分类#

自然语言推断等任务把两个句子用 [SEP] 拼接,仍用 [CLS] 表示做分类。

序列标注#

命名实体识别等任务对每个 token 的输出独立分类:

P(yi∣text)=softmax⁡(WTi+b)P(y_i \mid \text{text}) = \operatorname{softmax}(\mathbf{W}\mathbf{T}_i + \mathbf{b})

同一个词在不同上下文中可以得到不同标签,例如 “Apple” 在 “Apple Inc.” 中是组织名,在 “I eat an apple” 中不是实体。

抽取式问答#

SQuAD 风格的任务预测答案在原文中的起始和结束位置:

Pstart(i)=softmax⁡(wstartTTi),Pend(i)=softmax⁡(wendTTi)P_{\text{start}}(i) = \operatorname{softmax}(\mathbf{w}_{\text{start}}^T \mathbf{T}_i), \qquad P_{\text{end}}(i) = \operatorname{softmax}(\mathbf{w}_{\text{end}}^T \mathbf{T}_i)

训练时最大化真实起止位置的对数似然;预测时在合法跨度中选得分最高的一段。

与 LLM 的 SFT 区分

BERT 的微调是任务特定微调:每个下游任务训练一个输出头,通常需要几千到几万条标注数据。大语言模型中的 SFT(Supervised Fine-Tuning)通常指指令微调:用“指令—回答”数据让模型学会遵循指令,一个模型可以适配多种任务。二者都是有监督微调,但数据形式、训练目标和目的不同。

预训练与微调的成本差异正是该范式的价值:预训练需要大规模无标注语料和大量算力,微调只需要少量标注数据和单卡几小时。一次预训练可以适配多种任务。

局限与后续模型#

局限说明后续改进
双向编码不适合生成MLM 训练目标与自回归生成不一致GPT 使用因果注意力,专为生成设计
固定长度最大 512 token,长文档需截断或分段长上下文模型与高效注意力
任务特定微调每个任务需要单独微调一份模型instruction tuning、in-context learning
预训练-微调目标不一致[MASK] 在微调时不存在RoBERTa、ELECTRA 等改进预训练任务

BERT 之后的主要改进:

  • RoBERTa:更大批次、更多数据、动态遮蔽,并移除 NSP;
  • ALBERT:用参数共享降低参数量;
  • ELECTRA:把“预测被遮蔽词”改成“判断每个 token 是否被替换”,训练效率更高。

BERT 的编码器结构也成为后续句子表示模型和检索模型的常用 backbone。

相关阅读#

BERT:预训练 + 微调范式
https://biscuit0613.github.io/posts/nlp/06-07-bert/
作者
Biscuit
发布于
2026-10-20
许可协议
CC BY-NC-SA 4.0
NLP 评价指标:从分类、回归到文本生成
GPT、BART 与 T5:三种预训练范式