BERT:为什么遮住词再预测,能得到可迁移的文本表示
学术型精读 · 概念、公式、实验、源码与可验收练习
一句话总结
BERT 用双向 Transformer 编码上下文,通过掩码语言建模与下一句预测预训练,再用少量任务层进行微调;重点是分清预训练目标、输入掩码、冻结提取与端到端训练。
先确定它输出什么
BERT 的核心产品不是情感标签,而是每个输入位置的上下文表示。同一个“冷”字在“天气很冷”和“他的回答很冷”中应有不同表示,因为周围文字改变了它的含义。传统静态词向量通常给同一个词固定向量;上下文化表示让词义随句子改变,给下游任务提供更有用的输入。
原论文研究的关键是深层双向预训练。双向表示当前位置在编码时同时利用左侧与右侧上下文。它不同于把一个只看左边的模型与一个只看右边的模型在末尾简单拼接,而是在每一层都允许上下文交互。Figure 3 比较这些结构,但结构示意图不能替代具体实验中的数据与训练预算控制。
直接让双向模型预测每一个当前位置的原词会出现捷径:输入已经包含答案。因此作者随机选取一些位置作为预测目标,再改变这些位置的输入,要求模型依据上下文恢复原词。这就是掩码语言建模。下游情感分类并不需要继续遮词;遮词是训练表示的方法,不是用户输入必须遵循的格式。
读懂输入,才能读懂模型
Figure 2 展示输入由词片段嵌入、句段嵌入和位置嵌入相加而成。词片段来自 WordPiece,一个词可能被切成多个子词;句段嵌入区分句子 A 与 B;位置嵌入表示顺序。这三种表示维度相同,所以逐元素相加后维度不变,不能把它画成通道数翻三倍的拼接。
输入开头的分类标记用于聚合序列级信息,分隔标记用于界定句段。分类标记的最终隐藏向量可送给分类层,但它不是预先装好所有情感知识的固定向量;其作用来自预训练及下游优化。对词级任务通常使用各词对应位置,而不是把所有任务都强制压缩到开头一个位置。
基础模型有十二层、隐藏维度七百六十八、十二个注意力头,约一亿一千万参数;大型模型有二十四层、一千零二十四维、十六头,约三亿四千万参数。参数更多意味着更高的显存与优化成本,不意味着在小数据情绪任务上自动更可靠。首先弄清任务是否冻结文本编码器,比直接选择最大模型更重要。
注意力中的 padding mask 与掩码语言建模的遮词操作不能混淆。前者告诉模型哪些补齐位置没有内容,通常在注意力分数中屏蔽;后者改变真实词的输入并指定预测目标。把被遮住的词从注意力中彻底删除,或把所有补齐位置加入预测损失,都会改变原论文的学习问题。
预训练的两个目标
作者选择百分之十五的词片段位置作为预测对象。对这些被选中的位置,百分之八十替换为掩码标记,百分之十替换为随机词,百分之十保持原样。这些比例以“已被选中的位置”为分母;若以所有位置为分母,对应约百分之十二、百分之一点五和百分之一点五。保留原词并不意味着该位置不计损失。
随机词与保持原样的安排用于缓解预训练时总出现特殊掩码、下游时却不出现的差异。它没有完全消除这种差异,论文也明确讨论了不匹配。预测损失只针对选中的位置计算,不是对所有未改变的词一并计算普通语言模型损失。这个细节决定了代码里的标签权重与有效目标数量。
下一句预测构造句子对:一半是语料中真正相邻的下一句,一半是随机句子。模型根据开头分类标记判断是否相邻。它旨在学习句间关系,但“相邻”并不等于“语义必然一致”,随机负例也可能通过主题差异被区分。原论文的消融只能支持该训练设置下的作用,不能把这个目标推广成所有预训练模型都必须拥有的规则。
Figure 1 将预训练与微调分开:预训练使用大量无人工任务标签的文字构造监督信号,微调使用具体任务的标签。原文的语料包括 BooksCorpus 与英语维基百科。使用英文模型直接处理中文情绪语料,会同时改变分词覆盖和语言分布;这不是只调整分类头就能忽略的问题。
微调与冻结提取为什么不是一回事
微调时,通常同时更新 BERT 参数和新增任务层。冻结提取则把预训练表示当作固定特征,训练另外的模型。两种方式的显存、训练时间和过拟合风险不同;下游代码中调用 eval 只会改变 dropout 等层的行为,并不自动关闭梯度。真正冻结还需要禁止参数更新或在特征提取阶段关闭梯度。
在 ALMT 一类多模态工作中,你可能拿到已经缓存的文本特征。此时模型训练并不等于重新微调 BERT,文本分词、预训练权重、层选择和是否按词对齐都已在缓存阶段决定。若想换文本编码器,需要重建特征与元数据;不能只改融合网络中的输入维度便声称完成编码器比较。
Figure 4 展示不同任务头:句子分类使用序列表示,问答需要为每个位置预测答案起点和终点,词级任务使用逐词表示。输入编码可以共享,输出定义却由任务决定。阅读一篇应用 BERT 的论文时,至少要找到取的是哪个层、哪个位置、怎样池化、是否更新参数四个答案。
实验的口径与可解释结论
Table 1 的总体分数排除了 WNLI,与官方 GLUE 全任务分数不是同一个平均数。大型模型的表内平均值为 82.1,而论文讨论的官方 GLUE 分数为 80.5。本页保留表内口径,避免把两个不同平均方式误认为结果冲突。每个子任务的指标也不同,不能把所有列统称为准确率。
Table 5 的消融在开发集上比较完整模型、去掉下一句预测、改为从左到右的训练等设置。去掉目标会改变模型训练信号;从左到右同时改变上下文可见范围。它们支持双向预训练和任务组合在此实验中的价值,但不严格隔离全部可能影响,如训练数据构造、优化难度和目标信息量。
Table 2 的 SQuAD 最佳测试结果涉及集成与额外数据,不能拿来代表一个基础模型的一次前向输出。Table 7 则说明冻结的特征也具有价值:拼接最后四层的特征配合另外的序列模型,在命名实体识别开发集上取得较好结果。这不意味着所有任务都应盲目拼接四层,因为额外维度与任务头也会增加成本。
附录提供训练细节与层数实验,还讨论与 GPT 比较时的不同设置。理解基础方法时应把“架构带来的能力”与“更多语料、更多计算、不同目标”的共同作用区分开。不要把一张性能表压缩成“模型之所以好,唯一原因是双向”这样的单因素结论。
作者边界与独立判断
作者指出掩码标记带来预训练与微调之间的不匹配,掩码目标只利用部分位置预测也使收敛效率受到影响;小数据集的大模型微调可能不稳定。这些是原文讨论的边界。它们不否定方法,而是提醒读者记录随机种子、模型选择和训练预算,不能只保留效果最好的一次运行。
独立分析还应注意情绪表达中的反讽、否定、语调和说话人背景。文字“真不错”可能由语音表达相反情绪,BERT 只能根据文字及其训练经验推断,无法从缺失的音频中直接观察语调。因此跨模态融合应处理信息冲突,而不是默认文本永远正确或把文本高权重当作理解情绪的证据。
细粒度路线可以先研究否定词与程度词附近的表示变化,再比较词级与句级池化;跨场景路线可以检查词汇、语言风格和话题迁移造成的错误。选择其中一个可观察问题,固定其他模态,形成最小对照。若同时换分词器、预训练模型、池化策略和分类头,最终无法知道改进来自哪里。
当前官方仓库后来加入整词掩码等发布内容。原始论文使用的子词掩码规则与后续整词掩码模型不应混称;同样,下载目录中出现某个配置文件,并不表示它就是你当前使用权重的配置。保存权重名称、词表、大小写设置、最大长度和截断策略,才构成可追溯的文本特征定义。
公式逐步读:变量、运算与适用范围
教学整理:三种嵌入相加
依据 Section 3 输入表示。三项均为同维向量;这个公式为教学整理,原文没有给它单独编号。
教学整理:掩码词损失
M 是选中的预测位置集合,目标 x 是原词,输入是扰动后的序列。这里写平均形式方便理解,实现以权重和进行归一化。
教学整理:句间分类
两类表示是否真正相邻,参数 W 与 b 属于任务头;输出不是两个句子的语义相似度标量。
教学整理:联合目标
对应官方预训练脚本中的直接相加。两个损失分别经过各自归一化,不应擅自把它改成所有词与句子的混合平均。
教学整理:情绪分类微调
这是将论文句子分类结构写成显式公式,类别数由下游任务决定。冻结和微调的前向式可以相同,但参与梯度更新的参数集合不同。
实验读数:先固定协议,再比较数值
| 模型 | MNLI 匹配/失配 | SST-2 | 表内平均 |
|---|---|---|---|
| GPT | 82.1 / 81.4 | 91.3 | 75.1 |
| BERT BASE | 84.6 / 83.4 | 93.5 | 79.6 |
| BERT LARGE | 86.7 / 85.9 | 94.9 | 82.1 |
| 设置 | QNLI | SQuAD |
|---|---|---|
| 完整 BASE | 88.4 | 88.5 |
| 去 NSP | 84.9 | 87.9 |
| 左到右且去 NSP | 84.3 | 77.8 |
| 上项再加 BiLSTM | 84.1 | 84.9 |
计算流程图
flowchart LR A[Sentence pair] --> B[Tokens segments positions] B --> C[Bidirectional Transformer] C --> D[Masked token prediction] C --> E[CLS next sentence prediction] C --> F[Task representations] F --> G[Frozen features or fine tuning]
沿图逐条检查箭头:每个箭头传递的是张量或监督信号,并不代表额外的数据集;训练目标旁的分支在部署时未必保留。建议先在纸上填入批大小、序列长度、通道数,再阅读下面的源码。一个模块即使名字相同,只要输入轴、掩码或输出使用方式改变,也不能直接视作同一个实验。
论文方法与固定版本源码对照
run_pretraining.py:139–148
(masked_lm_loss,
masked_lm_example_loss, masked_lm_log_probs) = get_masked_lm_output(
bert_config, model.get_sequence_output(), model.get_embedding_table(),
masked_lm_positions, masked_lm_ids, masked_lm_weights)
(next_sentence_loss, next_sentence_example_loss,
next_sentence_log_probs) = get_next_sentence_output(
bert_config, model.get_pooled_output(), next_sentence_labels)
total_loss = masked_lm_loss + next_sentence_loss预训练脚本分别得到掩码词与句间预测损失,再组成总损失。这对应训练目标,不等于下游分类时仍必须保留两个头。
create_pretraining_data.py:391–405
masked_token = None
# 80% of the time, replace with [MASK]
if rng.random() < 0.8:
masked_token = "[MASK]"
else:
# 10% of the time, keep original
if rng.random() < 0.5:
masked_token = tokens[index]
# 10% of the time, replace with random word
else:
masked_token = vocab_words[rng.randint(0, len(vocab_words) - 1)]
output_tokens[index] = masked_token
masked_lms.append(MaskedLmInstance(index=index, label=tokens[index]))被选中位置按条件概率决定替换方式,最终标签保留原 token。注意百分之八十先判断,剩余部分再平分,才得到百分之十与百分之十。
代码核查固定在提交 eedf5716ce1268e56f0a50264a88cafad334ac61。这里展示的是公开仓库的实际文件,不把重新写的教学代码冒充作者实现。仓库后续可能包含新版本、工程兼容选项和不同默认参数;本文只将已核实的语句对应到论文机制。下载权重成功、模型能够前向传播、复现论文最终指标是三个不同的验收层级。
从读懂到能够独立实现:可执行学习任务
第一步,准备包含肯定、否定、程度变化和反讽歧义的十二个短句,用你实际选择的分词器输出 token、编号、有效长度和截断结果。验收:能解释一个词为何切成多个子词,并证明填充位置不会参与有效内容的池化。中文任务必须明确使用能够覆盖中文的词表。
第二步,手写掩码采样函数,在足够多的合成序列上统计选中比例及三种替换比例。验收:总体约百分之十五被选中,而三种处理比例在选中集合内接近八比一比一;保持原样的位置仍然出现在预测目标中。固定随机种子并保存统计结果。
第三步,同一小数据划分比较冻结最后一层平均池化、冻结分类标记、端到端微调三种方案。先检查分类头能否在少量训练样本上拟合,再使用验证集选择设置。验收:每种方案记录可训练参数数量与特征形状,不将缓存特征的训练时间算作包含文本编码的完整训练时间。
第四步,构造只有否定词变化的句子对,比较表示和预测变化,并人工检查其标签是否合理。验收:至少保存十组例子与失败解释;不要因为相似度降低就认定模型理解了否定,因为表示变化与分类正确是两件事。
第五步,为跨场景任务单独列出源域和目标域常见词汇、文本长度及截断比例。验收:能指出性能下降主要集中在哪类句子,并提出只改变一个因素的实验,例如保持编码器不变只替换池化方式,而不是一次更换整个系统。
建立可检查的实验记录
开始第一轮实验前,建立四份小文件:数据清单记录样本编号、来源、标签与划分;配置文件记录预处理、随机种子、模型名称和冻结范围;结果表记录验证指标、选中轮次与最后测试指标;错误清单保存预测错误的样本编号及观察理由。这些文件比一张最高准确率截图更能说明你真正控制了实验条件,也能让后续细粒度或跨场景拓展沿用同一条证据链。
对视频、语音或多模态情绪数据,必须优先检查主体、会话和视频来源是否跨集合重复。同一原始视频切出的多个片段高度相关,随机按片段划分可能让模型记住说话人、背景或录制设备。跨场景问题至少要明确源域训练集、源域验证集和目标域测试集;若使用目标域标签选择提示词或超参数,就不应再把它描述为完全未见目标域的泛化结果。
为避免把实现错误误认为研究发现,先运行一个极小批次,打印输入输出形状、数值范围、有效长度以及损失是否有限。随后在少量训练样本上尝试拟合,验证模型确实能够更新指定参数。如果极小训练集都学不会,优先检查标签编码、掩码方向、归一化、学习率和冻结设置;此时直接扩大数据量通常只会延长排查时间,而不能证明模型本身不适合任务。
消融实验一次只改变一个关键因素,其他预处理、划分、优化预算和选择规则保持一致。第一轮以发现实现问题为目标,只用一个种子;确认代码与趋势合理之后,再增加多个种子并保留每次独立结果。均值用于概括趋势,标准差用于展示训练波动,但都不能替代对样本泄漏和评价口径的检查。不同论文中的最优数字不能在协议不明时直接相减。
解释实验失败时,先区分三层原因:实现层是否正确地执行了计算;优化层是否在给定预算内学到了信号;数据层是否提供了任务需要的信息。比如文本缺少反讽语调、静态图像看不到表情变化、音频包含录音噪声,这些问题不能仅靠增加网络深度解决。把失败样本分组后再提出修改,每项修改应能对应一个可观察的问题和一个预先规定的验证指标。
学习笔记采用“论文本身说了什么—源码实际做了什么—我在本地验证了什么”三栏记录。第一栏附页码或图表编号,第二栏附固定提交与行号,第三栏附命令、环境和输出。本文已完成原文及源码核对,未宣称在你的机器上重训原论文。下面的练习属于待执行计划;只有真正运行并保存结果后,才能把相应项目改为“已完成”。
短引语与阅读定位
原文短语 deep bidirectional representations
(摘要):每层同时使用两侧上下文。
原文短语 Masked LM
(Section 3.1):利用部分扰动位置构造预训练监督。
原文短语 Next Sentence Prediction
(Section 3.1):相邻句判断任务,不能等同于一般语义相似度。
参考资料与核验边界
论文摘要与版本信息;完整论文 PDF;作者公开仓库固定版本。公式中标注“教学整理”的表达用于显式说明原文的计算步骤,不声称具有原文公式编号。所有实验数字均指原论文报告结果,不是本次新训练得到的结果。英文短引语合计不超过二十五个词。
自己的解释与验收记录
写出一条输入到输出的链路、一个关键公式的含义,以及你完成的最小检查。笔记仅保存在当前浏览器,可从主站「我的学习笔记」导出。