外观
第1章 预训练
约 6891 字大约 23 分钟
2025-10-05
mindmap
root((第1章 预训练))
范式
自监督
目标 下一词 片段还原
特性 无标注 可规模
解码器
任务 因果建模
用途 生成 对话
编码器
任务 掩码建模
用途 表征 抽取
编解码器
任务 去噪 序列到序列
用途 翻译 摘要
语料与分词
数据
来源 网页 书籍 代码 多语
处理 清洗 去重 去毒
分词
方法 BPE SentencePiece
词表 大小 稀有词
长度
策略 截断 拼接
目标 利用率 稳定
训练流程
目标
损失 交叉熵
变体 标签平滑
优化
学习率 预热 退火
稳定 混合精度 裁剪
正则
Dropout 权重衰减
归一 残差 预归一
多语与跨域
词表
共享 子词 对齐
采样 温度 上采样
代码 专业
代码 切分 注释
专业 术语 实体保护
BERT与变体
任务
MLM
NSP 或 替代
结构
双向 注意力
位置 残差 堆叠
变体
RoBERTa 去NSP 长训
DistilBERT 蒸馏
mBERT 多语言
应用
特征
冻结 编码器
线性 分类头
微调
全量 微调
参数高效 LoRA 前缀 适配器
评测
基准 GLUE SuperGLUE
任务 分类 标注 抽取式问答
风险与治理
泄露 重复
指纹 去重
审计 数据切分
偏见 毒性
采样 再平衡
安全 过滤 列表
合规 版权
来源 审核
删除 机制
1.1 预训练 NLP 模型
在自然语言处理(NLP)中,预训练指的是先用海量的文本数据训练一个通用的模型,然后再将这个模型应用到具体任务上。这有点像在正式工作前打好基础:模型通过阅读大量“书籍”和“文章”学会语言的一般规律和知识,然后我们再教它执行特定任务。
类比:预训练模型好比一个阅读了百科全书的大脑,已经掌握了广泛的知识和语言模式;而直接训练专用模型则像是不参考任何资料从零开始解题,既费时效果又未必好。通过预训练,我们先“内置”通识知识,然后再 微调模型解决特定问题,就像程序员先使用成熟框架,再针对具体需求写少量代码。
1.1.1 无监督、监督和自监督预训练
无监督预训练是指在训练过程中不需要人工标注的正确答案。模型从海量未标注文本中学习模式和结构。例如,让模型阅读很多英文文章,纯粹根据文本本身找规律,这就是无监督方法。早期的词向量(word embeddings)训练(如 Word2Vec)就是一种无监督学习:模型通过统计词在上下文中共同出现的频率来学习词语的向量表示,而不需要人为提供“正确输出”。
监督预训练则使用带有标签的任务来训练模型。例如,可以在机器翻译的平行语料(成对的源语言-目标语言句子)上预训练一个模型,使其学会翻译 。这里每对句子都有明确的参考答案(译文),这属于监督信号。这有点类似于用特定任务直接训练模型,只不过规模可能很大。监督预训练在 NLP 中相对少见,因为获取大规模标注数据昂贵,但有时会作为辅助(例如,先在大型翻译语料上训练,然后再微调到对话任务)。
自监督预训练是一种介于两者之间的方法,实际上是当今预训练的核心。它不需要人工标签,但会从数据本身构造训练信号。简单来说,我们设计一个"假任务",让模型用原始文本的一部分去预测另一部分,从而获得监督信号。例如,在一句话中遮住某些单词,让模型根据上下文猜测这些被遮住的单词是什么。这种方式不需要人工标注答案,因为被遮住的单词原本就在句子里,模型预测后可以直接与原句比对对错。由于训练所需的"正确答案"来自数据本身,这称为自监督学习。自监督让我们利用海量原始文本(如网页、书籍)来训练模型了解语言规律,而无需人工逐句标注。
示例:
假设有一句话:"猫在垫子上睡觉"
- 无监督预训练:不会刻意遮盖任何词,让模型通过阅读上百万句类似的句子自行领会"猫""垫子""睡觉"这些词经常一起出现。
- 监督预训练:让模型学一个相关任务,比如这句的情感是正面/负面(需要人标注答案)。
- 自监督预训练:把句子改成"猫在垫子上[MASK]觉",要求模型填空预测被遮住的词是"睡"。模型用这种填空游戏不断训练,就在没有人工帮助下学会了语言知识。
1.1.2 适应预训练模型
预训练完模型后,我们通常需要让它适应特定任务,这一步称为模型的适配或微调。因为预训练的目标(例如预测下一个词或填空)与我们最终想解决的任务(例如情感分类、问答等)往往不同,我们需要稍微调整模型使其在目标任务上表现更好。
有两种主要的方法来适应预训练模型:
- 微调(Fine-tuning):这类似于在预训练模型基础上“继续训练”,不过这次使用的是针对某个下游任务的标注数据。例如,有了预训练的 BERT 模型后,我们可以用一批标注好的情感评论数据来微调它。具体做法是:在 BERT 最后加一层分类器(比如一个全连接网络),用带有情感标签的句子微调整个网络的参数,使其能输出正确的情感类别。因为预训练模型已经学会了语言的基本表示,所以只需要用少量数据就能让它学会新任务。对 Java 程序员来说,这有点像继承已有的类然后改写/扩展:预训练模型提供了通用能力,我们在子类中微调一些参数,就能完成特定功能。微调的计算开销相对预训练要低很多,因为数据量小且训练轮数少,这使开发者可以高效地针对不同任务调教同一个基础模型。
- 提示(Prompting):对于大型的序列生成模型,我们还有另一种不改变模型参数的方法——通过提示来引导模型完成任务。提示就像给模型下指令或提供范例,让模型按我们期望的方式输出结果。比如我们有一个预训练的 GPT 模型(只生成文本的解码器架构),我们可以直接问它:"这句话的情感是积极、消极还是中性?句子:I love the food here. It's amazing!",看它输出"积极"而不需要专门再训练模型。在提示方法中,模型本身的参数不变,我们巧妙地设计输入让模型发挥出解决新任务的能力。这有点类似于函数式编程里的使用:预训练模型是一个已经写好的函数,我们通过不同的输入(prompt)来得到不同的输出,而无需修改函数内部。
比较示例:
对于一句评论“I love the food here. It's amazing!”:
微调方法:
- 用许多标注了“正面/负面”的例子训练模型
- 输入这句话,模型输出概率分布 [0.9, 0.05, 0.05](正面 90%,负面 5%,中性 5%)
- 选概率最大的作为预测结果“正面”
提示方法:
- 不经过额外训练,直接转换为模型擅长的文本生成形式
- 在输入后加上:“这句话的情感是:”,让 GPT 续写“正面”
- 可以提供示例作为提示的一部分(少样本学习):
- 例 1:“…” -> 情感:负面
- 例 2:“…” -> 情感:正面
- 实际问题:“这句话的情感是:”
这种利用上下文示例的做法被称为in-context learning(上下文学习),模型相当于从提示里的示例中即时学习如何完成任务。
提示和微调各有优势:提示不需要重新训练模型,灵活快速;微调能针对任务优化模型参数,通常在特定任务上性能更高。大型语言模型往往先预训练,再经过适度微调(例如指令微调,使其更好地遵循人类指令),最后用户通过提示来使用模型 。我们会在后续章节更深入讨论提示和微调的高级技巧。
1.2 自监督预训练任务
大语言模型的预训练主要是通过自监督任务来完成的。本节介绍几种针对不同模型架构的自监督预训练方法,包括仅解码器架构、仅编码器架构和编码器-解码器架构。这些方法都是让模型"自娱自乐"地从海量文本中学习,无需人工标签。下面我们分别说明每种架构常用的预训练任务,并用通俗类比帮助理解。
1.2.1 仅解码器的预训练
仅解码器架构的模型专注于文本生成,即根据已有的文本内容预测下一个词。这正是传统所说的"语言模型"任务。Transformer 的解码器可以看作一个只能看见前文的模型:在生成文本时,当前单词只能依赖它之前的单词信息,不能窥视后面的未生成单词。这种架构通过自回归方式生成序列:从开头开始一个词接一个词地往后写。
预训练时,我们给模型很多自然语言序列(句子或段落),训练它在每个位置上预测下一个词。模型输出的是一个概率分布,表示下一个词可能是词典中每个词的概率 。训练的目标就是使正确的下一个词概率被模型尽量提高——通俗来说,就是模型要学会猜对下文。通过不断地猜测并根据真实下文调整参数,模型会逐渐掌握语言结构、语法以及一定的常识知识。这就像我们玩“接龙”游戏:给出开头几个词,模型需要自己续写后面的词,一开始可能错很多,经过大量练习后就越来越擅长。
类比:仅解码器预训练类似于让模型看一部小说,只给它看到小说逐字逐句展开的过程,每当读到一半就盖住后面的内容,考它下一个情节会是什么。通过这种方式,模型学会了写故事的能力,因为它总是在练习"下一句话怎么说"。
现实例子: OpenAI 的 GPT 系列模型(如 GPT-2、GPT-3)就是典型的仅解码器预训练。以 GPT-3 为例,它在上千亿字的互联网文本上训练,每次读取一段文本并预测下一个词。经过长时间训练,GPT-3 学会了如何续写各种风格的文本。当我们给它一句话开头作为提示时,它就会根据训练中学到的概率分布,源源不断地生成后续内容。比如给 GPT 模型提示:“从前有座山,山里有座庙,庙里有个和尚在讲故事,说——”,它可能续写一个故事情节。这种语言模型预训练任务使 GPT 具备了很强的文本生成能力。
小思考: 为什么在仅解码器架构中不让模型看到后面的词再预测当前词呢?原因是如果模型知道了答案(后面的词是什么),那预测任务就失去了挑战,它无法从中学习如何根据前文推断后文。因此通过遮蔽未来的信息,模型被迫真正“理解”上下文来做好预测。
1.2.2 仅编码器的预训练
仅编码器架构的模型旨在理解文本而非生成文本。编码器可以看作是阅读全文然后把文本变成某种内部理解表示的模型。因为它没有解码器部分直接生成序列输出,所以往往需要配合一个额外的预测层才能完成特定任务。然而,通过预训练,我们可以让编码器学到把文本编码成有用表示的方法。
仅编码器预训练中最流行的方法是 掩码语言模型(MLM)。它的核心思想是:随机地将输入序列中一些词用特殊标记(如[MASK])遮住,然后训练模型根据上下文猜出这些被遮住的词 。模型需要充分利用句子中其他未被遮盖的词来推断答案,相当于做“填字游戏”或完形填空。这种任务迫使模型学会理解上下文语义和句法关系,因为只有真正理解句子,才能正确地填补缺失的词。
BERT是这一方法的代表性模型。例如,对于句子"我昨天去[MASK]公园",模型会学习到根据上下文,"[MASK]"最可能的词是"了"或"了趟"等,使句子通顺。这种掩码预测过程,让模型的编码器逐步掌握了词与词之间的依存关系和语义联系。因为掩盖的词可以在句子任意位置,模型需要双向地考虑上下文(既看前文也看后文),因此 MLM 培养了模型的双向理解能力。
然而,MLM 引入了一个额外的符号[MASK],这个符号只在训练时出现,实际应用时不会出现。这造成训练和使用时的不一致:模型习惯了看到[MASK]来提示有词缺失,但实际应用如句子分类时并没有[MASK]提供线索。为缓解这个问题,有些变体方法不直接插入特殊标记,而是采用不同策略,比如置换语言模型(Permutation LM) 和去噪自编码。Permutation LM(如 XLNet 模型采用)让模型预测句子中随机顺序的下一个词,避免使用特殊标记,但实现较复杂。而去噪自编码(如 BART 模型的预训练)则是将句子打乱或损坏后训练模型重建原句,我们稍后介绍。
类比:掩码语言模型好比给模型出阅读理解题:拿一篇文章,涂掉其中一些词,让模型根据上下文猜。模型就像学生一样,必须真正读懂文章才能把缺的词填上。通过无数次这样的练习,模型的“阅读理解”能力大幅提升。
小例子:“巴黎是法国的首都。埃菲尔铁塔位于[MASK]。” 给定这句话,大多数人都能猜出[MASK]应是“巴黎”。BERT 通过类似的过程学习:当它看到“埃菲尔铁塔位于[MASK]”,结合前一句知道谈论的是法国巴黎,那么[MASK]极可能是“巴黎”。这说明模型已经学到了巴黎和埃菲尔铁塔之间的常识联系。这样的预训练让模型积累了大量知识,后续我们只需稍加引导,就能让模型回答各类关于常识或语言的问题。
1.2.3 编码器-解码器预训练
编码器-解码器架构结合了编码器的理解能力和解码器的生成能力,是一种序列到序列(Seq2Seq)的模型形式。它先用编码器读取并"理解"输入序列,然后用解码器生成输出序列。许多需要将一段文本转换成另一段文本的任务(如机器翻译、摘要等)都采用这种架构。在预训练阶段,我们并没有特定的下游任务让模型去翻译某种语言或摘要新闻,而是设计自监督任务来练习 "将损坏的文本复原",从而训练这种架构。
一种常见的编码器-解码器自监督预训练任务被称为去噪自编码(Denoising Autoencoder)。具体来说,我们先对一段原始文本进行“破坏”:例如随机删除一些词、打乱句子顺序,或者用[MASK]替换若干词;总之让输入变得不完整或有噪音。然后,训练模型的编码器读取这段被损坏的文本,解码器的任务是根据编码器的表示重建出原始的、完好的文本。模型只有成功“还原”出正确文本,损失才小。这种训练驱动模型学会如何将含糟糕信息的输入恢复成正确流畅的句子。
类比:编码器-解码器预训练就像玩“解谜游戏”。我们把一句完整的话偷偷改乱,然后让模型去猜原句是什么。比如原句是“机器学习改变世界”,我们可能给模型的输入是“世界 改变 机器学习”(单词顺序被打乱)。模型必须理解这些词的关系,然后用正确的语序生成“机器学习改变世界”。通过无数这样的解谜,模型的编码能力和生成能力都得到提高。
现实例子: Google 的 T5 和 Facebook 的 BART 模型采用的就是这种策略。以 BART 为例,它会随机地删除原句中的一些片段,然后让模型把缺失的部分填回去,或者把句子顺序打乱再重排回来。举例来说,对于输入“天气 [MASK1] 好,[MASK2] 去公园。”(这里[MASK1],[MASK2]代表较长片段被掩盖),模型解码器需要还原出诸如“天气 非常 好,适合 去公园。”这样的完整句子。这训练了模型既能理解破损文本的大意,也能流畅地生成缺失内容。在 T5 中,任何 NLP 任务都被统一转换成文本到文本的问题作为预训练的一部分,例如给定英语句子输出法语句子、给定问题输出答案等等,因而 T5 被称为“Text-to-Text”模型。通过这些多样化的自监督任务,编码器-解码器模型学会了将一段文本映射为另一段文本的通用本领。
1.2.4 预训练任务的比较
我们介绍了三类主要的预训练任务,它们各有适用场景和优势:
- 仅解码器(自回归语言模型):利用前文预测下文,适合生成任务。这类模型(如 GPT 系列)预训练后本身就能独立生成连贯文本,是如今聊天机器人和文本创作的核心。但由于只能利用单向上下文,它对需要整体理解的任务可能不如双向模型直接有效。
- 仅编码器(掩码语言模型等):利用上下文预测缺失词,擅长理解任务。这类模型(如 BERT)因为看到双向上下文,善于捕捉句子整体意义。它们适合作为特征提取器,用于分类、问答等需要理解文本的下游任务。不过这些模型不能直接生成新句子,需要额外的输出层或解码模块才能完成生成类任务。
- 编码器-解码器(序列到序列重建):通过将损坏文本恢复来训练,平衡了理解和生成能力。这类模型(如 T5、BART)既能读懂输入又能产生输出,天生适合翻译、摘要这类需要读写的任务。在预训练时,它们有多种自监督形式,可以兼顾学习语义理解和语言生成。但架构相对复杂,训练也需要更多算力。
总的来说,大型语言模型可以基于上述任何一种架构预训练。实际选择哪种,取决于我们希望模型擅长什么:要写文章、续写对话,就选解码器模型(GPT);要文本分类或信息抽取,就选编码器模型(BERT)并在下游接分类器;要问答或翻译,则常用编码器-解码器模型(T5/BART),它能先读问题再写答案。
思考:有没有可能把这些能力合而为一?事实上,一些新模型尝试结合多种预训练任务或多种架构的优点,使模型既能理解又能生成。比如 GPT-4 这样的最新模型,在单纯的解码器架构基础上,通过后期的微调和提示工程,也展现出强大的理解能力,几乎可以胜任各种 NLP 任务。这说明随着模型规模增大和训练策略改进,不同预训练范式的界限变得模糊,大模型往往可以一模型多用。
1.3 典型示例:BERT 模型
要更具体地理解预训练如何赋能下游任务,我们来看一个经典的预训练模型——BERT。BERT 由 Google 在 2018 年提出,名字代表"双向编码器表示(Bidirectional Encoder Representations)"。它使用了上文提到的仅编码器架构,预训练任务包括掩码语言模型和下一句预测。
- 掩码语言模型(MLM):BERT 在每个句子中随机选择 15%的词,将这些词替换为[MASK]标记,然后让模型预测这些位置原本的词 。比如原句“我爱机器学习”可能变为“我爱[MASK][mask]”,模型要填回“机器学习”。通过这种方式,BERT 学到了细粒度的词语关系和句子理解。
- 下一句预测(NSP):这是 BERT 预训练的另一任务。当给定两段文本 A 和 B 时,让模型判断 B 是否是 A 的续句。训练时,有一部分真实的相邻句子对作为正例,也有随机不相干的句子对作为反例。通过学习这个任务,BERT 获得了基本的句间关系和上下文连贯性的判断能力。不过值得一提,后来的研究发现 NSP 的效果可能有限,某些 BERT 改进版(如 RoBERTa)甚至取消了 NSP 任务而主要依靠更大的数据和纯 MLM 训练。
经过上述预训练(BERT 用了 Wikipedia 和 BooksCorpus 等大型语料,总词数达数十亿),BERT 模型已经对语言有了相当深入的理解。不过预训练完的 BERT 不能直接用于实际 NLP 任务,因为它输出的只是每个词的表示向量,没有给出具体的答案或分类。我们还需要对 BERT 进行微调,即在任务数据上训练一个小的附加网络,让整个系统完成特定任务 。
1.4 应用 BERT 模型
假设我们要用预训练好的 BERT 模型做情感分类(判断评论是正面还是负面)。具体做法是:在 BERT 的最后一层我们会得到每个输入词的位置的向量表示。约定俗成,BERT 在输入序列开头引入一个特殊标记[CLS],它对应的输出向量可以被看作整句话的聚合表示 。我们在这个向量后接一个分类器层(比如一个全连接层加上 Softmax),使其输出“正面”或“负面”的概率分布 。然后我们利用一组带标签的示例句子(有人为每句标注了情感倾向)来训练这个附加的分类器以及(通常)BERT 模型参数的最后几层。这个过程就是对 BERT 的微调:调整模型参数让[CLS]向量对于正面句子和负面句子显现出区别,从而分类器能学会分辨。
BERT 情感分类示例:
一条影评:“这部电影情节紧凑,演技精湛,非常好看。”
1.预训练阶段:BERT 处理后,输出 [CLS] 对应的向量代表了这句话的大致语义 2.微调阶段:这个向量被映射成概率分布 [0.95, 0.05](正面 95%,负面 5%) 3.结果:模型预测正面,判定这条评论情感为正面
BERT 在预训练时已经学会了“紧凑”“精湛”“好看”等词语的积极含义和语境,所以只需较少样本就能把这种知识转化为判断情感的能力。
需要注意,如果不微调 BERT,仅用预训练的 BERT 直接上任务,它往往表现不好。继续类比的话,预训练 BERT 就像一个通才,知道大量知识但不知道我们的具体需求;微调就好比岗前培训,让通才针对特定任务发挥所长。因此绝大部分 BERT 的应用都会经过微调阶段。
BERT 展示了预训练+微调范式的强大:它问世后迅速刷新了众多 NLP 任务的最佳成绩。预训练提供泛化的语言表示,微调实现个性化的任务适配。这一套路后来被无数模型采用,开启了 NLP 的预训练时代。即使在现在更先进的 GPT 模型时代,预训练打底 + (明示或隐式的)微调/对齐,依然是打造强大语言模型的标准流程。
1.5 小结
- 预训练通过海量数据的自监督任务,让模型学到通用的语言知识,就像让模型阅读百科全书打好基础。
- 预训练范式包括无监督(无人工标签,模型自行找规律)、监督(有人工标注的特定任务)和自监督(从数据自身生成训练信号)三类,其中自监督预训练是大型语言模型的核心方式。
- 预训练任务因模型架构而异:仅解码器模型通过下一词预测学会生成文本(如 GPT 系列),仅编码器模型通过掩码填空学会理解文本(如 BERT),编码器-解码器模型通过重建损坏文本同时拥有理解和生成能力(如 T5、BART)。
- 适配预训练模型有两种主要途径:一是微调参数,使模型在少量标注数据上进一步优化;二是通过提示设计输入,在不改模型参数的情况下让模型按照要求输出。大型模型往往结合两种手段,即先用指令微调对齐模型行为,再通过用户提示完成具体任务。
- BERT 等模型的成功证明了“预训练+微调”范式的有效性:预训练赋予模型广博知识,微调让模型在特定任务上大放异彩。这一思想为后续更大型的 GPT 类模型奠定了基础。