想象有一位叫“小贝”的同学,手里捧着一本厚厚的语料库笔记本,准备参加一场没有标准教材的语文考试。老师布置的任务很奇特:用荧光笔随机涂掉句子里约15%的词语,然后让同桌根据上下文把涂掉的字猜回来。刚开始小贝觉得这纯属自虐——明明有答案,为什么要遮住?可练了一个月后,他发现自己对词语搭配、语序逻辑、同义替换的理解突飞猛进,甚至能凭前后几个词推断出陌生词的意思。 这个故事其实就是 BERT 的训练方式。BERT 从成千上万句无标签文本中随机遮挡一部分词,让模型通过左右两侧的上下文预测被遮住的原词——这种“自己出题、自己猜”的方法叫掩码语言模型(Masked Language Model,MLM)。学完后,BERT 脑中已经沉淀了丰富的语言知识,只需少量标注数据微调,就能胜任问答、情感分析、信息检索等下游任务。这篇内容将用小贝备考的故事,把 BERT MLM 的掩码机制、15%比例、80/10/10 规则、双向上下文和迁移应用讲得明明白白。
如果你正在学习深度学习或做 NLP 工程师,理解 BERT MLM 是打开预训练模型大门的钥匙——几乎所有现代中文大模型的前身,都离不开这次“完形填空”式的自监督预训练。
可视化演示
动态演示BERT MLM掩码的核心机制,通过入门/进阶/实战/优化四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
BERT MLM掩码:MLM掩 MLM掩码机制核心原理与设计动 15%掩码比例选取与平衡考量 核心机制可视化 BERT MLM掩码整体架构与关键组件
预训练背景
小贝备考的第一步,是去图书馆搬回上千本没有标准答案的课外书。没有老师画重点、没有人工标注,他只能靠一种“自己出题自己答”的方式从书里学到语言规律。这种不依赖人工标签的学习,就是预训练阶段的核心精神——自监督学习。所谓自监督,是指标签不是人给的,而是从输入数据本身构造出来的。BERT 从海量无标签文本中随机遮住一些词,把“被遮住的词”当作天然答案,这就是自监督的经典实现。
在 BERT 之前,语言模型通常沿着“预测下一个词”的方向前进,像小贝逐字朗读课文,只往左看。BERT 采用的 Transformer 编码器则像一个全景扫描仪,可以把整个句子同时收入眼底。它的基础架构是 Transformer 编码器堆叠,每一个 token 都能通过自注意力看到句子里的所有其他 token。预训练的目的,就是让模型在大规模语料上先“读万卷书”,把通用的语法、语义和常识存储在参数里,为后续下游任务做准备。
预训练结束时,小贝已经积累了庞大的“阅读量”。这些从掩码填空中学来的知识,并不针对某个特定任务,而是通用的语言能力——就像小贝读过的书让他学会了语感,而不是只记住某篇课文。这种“先大量阅读打底,再针对性刷题”的思路,正是预训练与后文微调衔接的桥梁。
- 遍历语料\(\sum_{x \in \mathcal{D}}\) 表示把训练语料里所有句子都过一遍,每个句子都要参与学习。
- 随机位置期望\(\mathbb{E}_{i \sim M(x)}\) 表示随机选择句子中的若干个位置,求平均情况下的损耗。
- 对数条件概率\(\log P_{\theta}(w_i \mid x_{\setminus i})\) 表示在去掉位置 \(i\) 后的上下文条件下,模型预测出原词 \(w_i\) 的对数概率,值越大代表预测越准。
掩码机制
小贝做拼写练习时,会举起荧光笔,随机挑出句子里的词语,用黑色墨水盖住,然后在旁边画一个问号。这一动作对应 BERT 的随机掩码:对于一句话中的每个 token,BERT 以一定概率判定它是否进入“候选池”,选中后就用特殊的 [MASK] 符号替换。[MASK] 就像小贝画的那个黑团,把原词遮得严严实实,只留下一个“待猜”的信号。
有了掩码符号之后,模型的任务就不再是预测下一个词,而是根据剩余可见的所有词预测被遮挡位置的原词。这个过程同时在句子的左右两边“打探情报”:左边能看到“我 喜欢 在”,右边能看到“下 阅读 一本”,中间的词虽然被挡住,却可以从左右两边的语义线索推断出来。这正是掩码语言模型与普通语言模型最大的不同。
小贝的荧光笔从来不会把整句话涂满,而是有选择地遮盖。这样他才能保留足够多的上下文线索来猜词。BERT 同样如此:掩码机制的关键不是“遮得多”,而是“遮得巧”——在制造训练难度的同时,保留了足够的上下文信号,让模型能真正学会推理。
- 目标词\(w_i\) 是位置 \(i\) 被掩码后的原始词语,也是模型的预测目标。
- 左侧上下文\(x_{1}, \dots, x_{i-1}\) 表示位置 \(i\) 左边的所有可见词,它们为判断词义提供前半部分信息。
- 右侧上下文\(x_{i+1}, \dots, x_{n}\) 表示位置 \(i\) 右边的所有可见词,提供后半部分信息,这是双向模型与单向模型的分水岭。
掩码策略
如果小贝每次都用同样粗细的黑笔把词涂成均匀的黑块,到了期末考试(即微调阶段),他一定会傻眼:真实考试卷子上根本没有黑块。只见过 [MASK] 的模型,一旦遇到完整句子就会手足无措。为了解决这个问题,BERT 在选中的 15% token 中用了三种不同的处理方式,即著名的 80/10/10 规则。
具体来说:80% 的概率把选中的 token 替换成 [MASK];10% 的概率替换成词表中任意一个随机词;剩下 10% 的概率保持不变。为什么 10% 要换成随机词?因为模型需要学会:即使输入中出现了一个和原句毫无关系的词,它也要努力推断出正确的原词,而不是盲目相信输入。为什么 10% 要保留原词?因为微调阶段不会出现 [MASK],模型需要适应“没有遮挡”的正常句子,避免对掩码符号产生过度依赖。
这个策略就像小贝在练习时,不仅把词涂黑,还会偶尔把“阳光”改成“果冻”,或者假装涂了一下却保留原字。真正考试时,考卷上不会再有大黑块,但小贝已经学会了接受任何输入状态并保持判断力。80/10/10 规则是 BERT 最容易被忽视却至关重要的设计细节。
[MASK],10% 伪装成随机词,10% 保持原样。- 八成盖黑块\(P(\tilde{x}_i = [\text{MASK}]) = 0.8\),这是最常见的情形,迫使模型认真做填空。
- 一成换错词\(P(\tilde{x}_i = w_{\text{rand}}) = 0.1\),把原词替换成词表里的随机词,锻炼模型抗干扰能力。
- 一成当无事发生\(P(\tilde{x}_i = w_i) = 0.1\),保留原词,缓解预训练与微调的输入分布差异。
双向上下文
小贝做填空题时有一个优势:他的目光可以同时扫过空格的左右两侧。好比这句话“窗外的_非常明亮”,他既能看到“窗外”提示这是景物,又能看到“明亮”提示这个词和光线有关。双向上下文就是这样的能力:预测某个词时,同时参考它左边和右边的全部可见词。
与之相对的是自回归语言模型。想象小贝的另一个同学“小 G”,他读书时只能从左往右逐字念,看到“窗外的”之后,必须立刻猜下一个词,完全看不到后面的“非常明亮”。GPT 系列就是这样典型的自回归模型:它只能利用左侧信息预测右侧下一个词。BERT 之所以能做到双向,是因为它使用了 Transformer 的编码器结构,每个 token 在自注意力层中都会与其他所有 token 建立联系,因此信息是全面互通的。
双向上下文让 BERT 对语言的理解更加“立体”。小贝能同时看到整句话,自然比只能看到半句话的小 G 更能把握全局含义。但这并不意味着双向一定更优越——GPT 在生成长文本时依然有独特优势。理解两者的差异,是选择模型架构时的重要判断依据。
- BERT 的双向条件\(P_{\theta}(w_i \mid w_{<i}, w_{>i})\) 预测位置 \(i\) 时,同时使用所有两侧 token 的信息。
- GPT 的单向条件\(P_{\theta}(w_i \mid w_{<i})\) 只能看左侧 token,这是自回归模型“逐字向右”的代价。
训练目标
小贝做完一页完形填空后,会翻到书末的参考答案,把预测错误的词用红笔圈出来。BERT 的训练目标与此类似,只不过“红笔纠错”变成了数学上的交叉熵损失。模型对每个掩码位置输出一个覆盖整个词表的概率分布,计算预测分布与真实原词的差距,差距越小越好。
具体来说,模型最后一层会给每个候选词一个分数(logit),全部 logit 经过 softmax 变成概率。损失函数只对被掩码的位置计算,未掩码位置不参与。原因是:我们只在乎模型能否猜对被遮住的词,而不是让它背下所有可见词。对每个掩码位置,正确的原词应该获得尽可能高的概率,交叉熵恰好度量了“模型给正确词分配的概率有多低”。
训练过程就像小贝反复对答案、反复订正。每次前向传播,模型根据上下文猜测原词,接着用交叉熵损失衡量偏差,最后通过梯度反向传播更新参数。日积月累,模型对每个掩码位置的预测越来越准,损失曲线逐渐下降,语言表示也在这一过程中越来越丰富。
- 掩码位置集合\(\mathcal{M}\) 记录所有被选中做预测的位置,损失只在这些位置累加。
- 正确词的指数分数\(\exp(z_{i, w_i^*})\) 是第 \(i\) 个掩码位置对应正确词的未归一化得分取指数。
- 词表归一化\(\sum_{j=1}^{V}\exp(z_{i,j})\) 将整个词表共 \(V\) 个词的分数做总和,形成 softmax 分母。
- 负对数前面加负号后,正确词概率越大,损失越小,训练就在不断减小这个值。
迁移应用
小贝完成预训练后,已经具备了很强的语感,但考试题型千变万化:阅读理解要判断作者态度,完形填空要选正确搭配,作文要决定用词风格。他不可能为每种题型都从头学一遍,而是把已掌握的语感迁移到新任务上。BERT 的做法同样如此:预训练完成后,保存下来的模型参数就是一个“语言通”,下游任务只需在它基础上做微调(Fine-tuning)。
微调时,我们会给 BERT 接一个轻量级的任务头。比如做情感分类,就把句首的 [CLS] 向量取出,接一个线性分类器;做命名实体识别,就把每个 token 的输出向量接上标签分类器;做问答,则预测答案在文中的起始和结束位置。无论哪种任务,模型都从预训练参数出发,以很小的学习率在标注数据上继续训练几步。由于 BERT 已经学会了通用语法和语义,下游任务只需要很少的标注样本就能达到好效果。
小贝带着预训练积累的语感,面对情感判断、意图分类、命名实体识别等考题,只需要做少量专项训练就能稳定发挥。这正是预训练语言模型的“降维打击”:通用知识先行,任务知识微调,用最小成本解决最多任务。理解这个流程,就理解了为什么 BERT 能在各类 NLP 榜单上风靡一时。
[CLS] 向量通过线性层和 softmax 映射到类别概率。- 句子汇总向量\(\mathbf{h}_{\text{[CLS]}}\) 是输入句首
[CLS]位置经过多层 Transformer 编码后的输出向量,宛如整句话的“摘要”。 - 线性映射矩阵\(W_h\) 是把 BERT 向量维度映射到类别数的可训练矩阵,相当于给“语言通”加一个任务专属的答题卡。
- 分类概率归一化\(\operatorname{softmax}(W_h \mathbf{h}_{\text{[CLS]}} + b)\) 输出每个类别的概率分布,概率最大的类别即为预测结果。
AI 应用场景
智能客服意图分类
阶段:下游任务微调与部署
解决的问题:传统客服系统依赖关键词规则匹配,用户稍换一种说法就识别失败,难以应对口语化表达。BERT 预训练模型通过 MLM 积累了丰富的语义理解能力,微调后只需少量标注样本,就能准确区分“查余额”与“办挂失”等意图,无需人工设计规则。
具体案例:某银行智能客服接入 BERT 意图分类模型,将“我卡丢了快帮我冻结”自动识别为“卡片挂失”意图,并触发冻结流程。得益于 MLM 预训练对同义句的深层理解,即便用户说“我的银行卡好像不见了”,也能被准确识别。
文档问答与信息抽取
阶段:预训练 + 特征抽取 + 问答微调
解决的问题:传统关键词检索在长文档问答中无法理解“谁、何时、何地”的语义关系。BERT 的表示学习能力可以把问题和文档映射到同一语义空间,结合微调后的问答头定位答案区间。
具体案例:医疗领域的智能导诊系统利用 BERT 对患者主诉进行问答式理解,从科室介绍文档中抽取对应科室信息。比如“最近总是失眠、心慌挂什么科”,模型定位到答案是“神经内科”。
文本纠错与完形填充
阶段:预训练模型推理 + 后处理
解决的问题:语音转写和手打输入常常产生同音错别字,传统纠错依赖词典和编辑距离,无法结合语境判断。BERT 本身就是一个强大的完形填空模型,通过掩码替换候选位置,可以预测最合适的原词,从而实现基于上下文的纠错。
具体案例:某输入法团队利用 BERT MLM 对“我今天去公园散步”中的错字进行掩码式纠正。当用户打出“我今天去公圆散步”时,系统掩住“圆”并给出候选“园、苑、源”,结合上下文正确选取“园”。
Python 演示
import randomimport torchimport torch.nn as nnfrom torch.utils.data import Dataset, DataLoader # 微型词表:0为PAD,1为MASK,其余为真实词vocab = ['<PAD>', '<MASK>', '我', '爱', '北京', '天安门', '猫', '喜欢', '鱼', '阳光', '阅读', '有', '照', '在']w2i = {w: i for i, w in enumerate(vocab)}i2w = {i: w for i, w in enumerate(vocab)}V = len(vocab) # 构造玩具语料sentences = [ ['我', '爱', '北京'], ['北京', '有', '天安门'], ['猫', '喜欢', '鱼'], ['我', '喜欢', '阅读'], ['阳光', '照', '在', '北京'],] class ToyDataset(Dataset): def __init__(self, sents): self.sents = sents def __len__(self): return len(self.sents) def __getitem__(self, idx): toks = self.sents[idx] ids = [w2i[t] for t in toks] labels = [-100] * len(toks) # 非掩码位置忽略loss n_mask = max(1, round(len(toks) * 0.15)) for _ in range(n_mask): p = random.randrange(len(toks)) labels[p] = ids[p] # 掩码位置保留原词作为标签 r = random.random() if r < 0.8: ids[p] = w2i['<MASK>'] elif r < 0.9: ids[p] = random.randrange(2, V) # 剩余10%保持原词不变 return torch.tensor(ids), torch.tensor(labels) class TinyMLM(nn.Module): def __init__(self, vocab_size, d_model=32, nhead=2): super().__init__() self.emb = nn.Embedding(vocab_size, d_model) self.encoder = nn.TransformerEncoderLayer(d_model, nhead, batch_first=True) self.fc = nn.Linear(d_model, vocab_size) def forward(self, x): h = self.encoder(self.emb(x)) return self.fc(h) def train_model(): model = TinyMLM(V) loss_fn = nn.CrossEntropyLoss(ignore_index=-100) optimizer = torch.optim.Adam(model.parameters(), lr=0.01) loader = DataLoader(ToyDataset(sentences), batch_size=2, shuffle=True) for epoch in range(200): for x, y in loader: optimizer.zero_grad() out = model(x) loss = loss_fn(out.view(-1, V), y.view(-1)) loss.backward() optimizer.step() return model def predict(model, sent): model.eval() ids = torch.tensor([[w2i.get(t, w2i['<PAD>']) for t in sent]]) out = model(ids) pred_ids = out.argmax(-1)[0] return [i2w[pid.item()] for pid in pred_ids] if __name__ == '__main__': model = train_model() print('训练完成,预测:', predict(model, ['我', '<MASK>', '北京'])) print('训练完成,预测:', predict(model, ['猫', '<MASK>', '鱼']))
labels[p] = ids[p]把被选中位置的原词记录下来,作为模型预测的监督标签;未选中位置的标签设为-100,训练时会被损失函数自动忽略。ids[p] = w2i['<MASK>']80% 概率把选中的 token 替换成[MASK]符号,让模型做真正的完形填空。ids[p] = random.randrange(2, V)10% 概率替换成词表里的随机词,模拟输入噪声,让模型学会抗干扰。loss_fn = nn.CrossEntropyLoss(ignore_index=-100)交叉熵损失只关注掩码位置,非掩码位置用-100标记忽略。model(x)` 中的 `out.view(-1, V)把每个 token 位置的预测概率展平,与展平的标签逐一对齐计算损失。
常见误区
误区我以为是先把 15% 的词永久删掉,再喂给 BERT 学习。那么 BERT 看到的句子总是残缺的,怎么能学会完整语言呢?
正解15% 指每句话中被选中作为预测候选的 token 比例,而且每次前向传播都会重新随机采样。原始词并没有被删除,而是以 [MASK]、随机词或原样的形式参与输入。下一次训练时,模型看到的掩码位置又换了一批,所以它能多次见到每个词的不同上下文。
为何常见:很多人把“掩码”理解成“删除”,忽略了数据增强式的随机采样本质,导致后续理解 80/10/10 规则时产生偏差。
误区既然要训练模型猜词,为什么不全部替换成 `[MASK]`?保留原词不是浪费训练机会吗?
正解10% 保留原词是为了让模型知道,输入中的 token 不一定总是被遮住。微调阶段真实任务里根本没有 [MASK] 符号,如果预训练时模型只见过掩码,它会对 [MASK] 产生过度依赖,微调时反而表现不佳。保留原词可以缩小预训练与微调之间的分布差异。
为何常见:初学者只看到“训练要制造难题”,没意识到预训练最终要服务于下游微调,因此忽略了分布匹配的设计哲学。
误区我理解的“双向”像读文章时先读一遍左边再读一遍右边,或者像 RNN 那样先正向再反向。
正解BERT 的双向不是“串行地来回扫两遍”,而是依赖 Transformer 编码器的自注意力机制,在每一层同时吸收所有 token 的信息。预测某个词时,左右两侧的信息是并行参与计算的,不存在先后顺序。这与 BiLSTM 式的“正向+反向拼接”也有本质区别。
为何常见:人们习惯用“先看左边再看右边”的时序直觉理解双向,却忽视了 Transformer 自注意力是对整句并行处理这个关键特点。
误区如果 15% 掩码能让 BERT 学会语言,那 50% 甚至 80% 的掩码率会不会让 BERT 更强?
正解并非如此。掩码比例过高时,句子被破坏得过于严重,模型能得到的有效上下文太少,任务难度剧增,训练收敛缓慢且效果下降。BERT 论文通过实验证明 15% 左右是性能与训练效率的平衡点。掩码的使命是制造“适量”的挑战,而不是让模型玩猜字谜。
为何常见:很多人认为“难度越大、模型越强”,但忽略了训练信号的可学性——模型需要足够的可见词才能建立有效的语义关联。
面试题
Q1. BERT在MLM预训练中,每个句子大约有多少比例的token会被选中作为预测候选?
- A.5%
- B.10%
- C.15%← 正确答案
- D.25%
答案:C。BERT 论文规定每句约 15% 的 token 被随机选中参与掩码预测,既要保证足够训练信号,又不能过度破坏句子可读性。5% 信号太少,25% 上下文损失过大。
Q2. 按80/10/10规则,被选中的token有多少概率被替换成[MASK]符号?
- A.50%
- B.70%
- C.80%← 正确答案
- D.90%
答案:C。80/10/10 规则中,80% 概率将选中 token 替换为 [MASK],10% 替换为随机词,10% 保持原样。80% 占绝对主导地位,目的是让模型大量练习完形填空。
Q3. BERT与GPT在预训练方式上的核心区别是什么?
- A.BERT参数量更大,GPT参数量更小
- B.BERT是双向掩码训练,GPT是单向自回归训练← 正确答案
- C.BERT使用CNN,GPT使用RNN
- D.BERT需要人工标注,GPT不需要
答案:B。BERT 通过 MLM 同时利用左右上下文预测掩码词,GPT 则按从左到右的顺序预测下一个词。二者都是 Transformer 架构,且都使用无标签文本进行自监督学习,核心差异在于条件方向。
Q4. 为什么80/10/10规则中要保留10%的token不替换?
- A.为了减少训练计算量
- B.为了增强数据随机性
- C.为了缓解[MASK]与微调阶段输入的分布差异← 正确答案
- D.为了增加掩码比例
答案:C。微调阶段真实任务中不会出现 [MASK],如果预训练时模型只见过掩码符号,就会对它过度依赖。保留 10% 原词让模型适应“输入未被遮挡”的正常情况,从而更好地迁移到下游任务。
Q5. 下列哪些是BERT MLM训练的特征?
- A.使用[MASK]替换部分token← 正确答案
- B.预测被掩码的原始词← 正确答案
- C.模型只能利用左侧上下文
- D.依赖人工标注数据
答案:AB。MLM 使用 [MASK] 替换部分 token,并预测原词,选项 A、B 正确。BERT 是双向模型,左右上下文都能看到,C 错误。MLM 属于自监督学习,不需要人工标注,D 错误。
Q6. BERT借助什么结构实现对掩码位置的双向上下文建模?
- A.BiLSTM循环网络
- B.Transformer编码器中的自注意力机制← 正确答案
- C.两层全连接网络
- D.卷积神经网络的感受野
答案:B。BERT 使用 Transformer 编码器,自注意力机制让每个 token 同时关注句子中的所有其他 token,从而实现真正的双向信息融合。BiLSTM 是循环网络时代的方法,不是 BERT 的核心结构。
Q7. 在MLM的交叉熵损失中,未被掩码的token位置对损失函数的影响是?
- A.完全不影响,被忽略不计← 正确答案
- B.参与计算但不能反向传播
- C.以较小权重参与损失
- D.作为正则项约束
答案:A。MLM 的损失只对被掩码位置计算。例如 PyTorch 中通过 ignore_index=-100 将非掩码位置排除,这些位置不产生损失值,也不参与梯度更新,模型不需要重复背诵已给出的词。
Q8. 关于BERT的15%掩码比例,以下说法正确的是?
- A.每次训练前向传播都会重新随机采样掩码位置← 正确答案
- B.掩码比例越大,模型效果一定越好
- C.未被选中的token仍然作为上下文参与编码← 正确答案
- D.掩码位置固定不变,防止模型偷看答案
答案:AC。每轮训练都会重新随机采样掩码位置,A 正确。未选中 token 保留在输入中作为上下文,C 正确。掩码比例过大会损害上下文可读性,B 错误。掩码位置若固定会过拟合,D 错误。
Q9. 在80/10/10规则中,若某token被替换成随机词,模型的监督标签应该是什么?
- A.随机替换词
- B.原来的真实词← 正确答案
- C.[MASK]符号
- D.不提供标签
答案:B。无论输入 token 被替换成 [MASK] 还是随机词,模型的目标始终是还原原始词,因此标签是原来的真实词。随机词的干扰作用在于让模型学会排除噪声输入,而非改变监督目标。
Q10. 迁移应用阶段,BERT在下游任务上的训练方式通常称为?
- A.从零训练
- B.微调← 正确答案
- C.蒸馏
- D.强化学习
答案:B。从预训练模型出发,用少量标注数据在特定任务上继续小幅更新参数,这种策略称为微调(Fine-tuning)。BERT 的通用语言知识在预训练中已经沉淀,微调只需适配任务头和学习任务特定的输出形式。