从零入门领域大模型训练:SFT、Continue PreTrain、RAG、评测与训练排错全流程教程
这是一套面向初学者的领域大模型训练教程,围绕大模型从 Base Model 到 Chat Model、从通用模型到领域模型的完整训练流程展开。
教程系统讲解 Pretrain、Continue PreTrain、SFT、RAG、RLHF/DPO 等核心概念,重点回答领域大模型训练中最常见的问题:SFT 到底在学什么?为什么 SFT 后模型会变“傻”?领域数据应该如何构建?什么时候应该继续预训练,什么时候应该使用 RAG?Base 模型和 Chat 模型应该如何选择?中文大模型训练有哪些经验?词表扩增有没有必要?如何构建领域评测集?微调模型需要多大显存?batch size、优化器、LoRA、QLoRA 应该怎么设置?训练中遇到 OOM、loss spike、灾难性遗忘时又该如何排查?
本教程不追求堆砌公式,而是从实际工程问题出发,帮助读者建立一套完整的大模型训练思维框架:知道什么时候该预训练,什么时候该微调,什么时候该检索增强,如何准备数据,如何设计评测,如何调参和排错。适合刚接触大模型训练、领域模型微调、LLM 应用落地和 AI 工程实践的同学阅读。
第一章:大模型训练全流程总览
这一章只解决一个问题:
一个大模型到底是怎么从“只会续写文本”变成“能和人聊天、能做领域任务、能遵守指令”的?
一个典型大模型的成长路径大概是这样:
海量文本
↓
预训练 Pretrain
↓
Base Model
↓
继续预训练 Continue PreTrain,(可选)
↓
领域 Base Model
↓
指令微调 SFT
↓
Chat / Instruct Model
↓
偏好对齐 RLHF / DPO,可选
↓
更符合人类偏好的对话模型
可以把它理解成一个学生的成长过程:
读大量书籍 → 打基础知识
做专业阅读 → 学某个领域
看标准答案 → 学会怎么答题
接受老师偏好反馈 → 学会什么答案更讨人喜欢
对应到大模型:
| 阶段 | 类比 | 主要作用 |
|---|---|---|
| Pretrain | 读全网书籍 | 学语言、知识、基本推理模式 |
| Continue PreTrain | 读专业书 | 学某个领域的语言和知识 |
| SFT | 看标准答案 | 学会按照指令回答 |
| RLHF / DPO | 老师打分纠偏 | 学会更符合人类偏好的回答 |
什么是 Pretrain?
Pretrain,中文一般叫 预训练。
它是大模型最基础、最核心的阶段。
预训练在做什么?
简单说,预训练就是让模型做一件事:
根据前面的文本,预测下一个 token。
比如给模型一句话:
中国的首都是
模型要预测下一个 token 很可能是:
北京
再比如:
牛顿提出了
模型可能预测:
万有引力
训练数据非常大,可能包含:
网页;书籍;论文;新闻;代码;百科;论坛;问答;多语言文本
模型通过不断预测下一个 token,慢慢学会:
- 语言规律
- 词语搭配
- 世界知识
- 基础推理模式
- 代码模式
- 数学表达
- 常见事实
- 文本结构
所以预训练不是简单背书,而是在海量文本中学习统计规律和知识结构。
预训练结束后,我们得到的模型一般叫:
Base Model,基座模型。
比如:
LLaMA-Base
Qwen-Base
Baichuan-Base
InternLM-Base
Base 模型有一个特点:
它很会续写文本,但不一定很会聊天。
比如你问 Base 模型:
请解释一下什么是监督学习?
它可能会继续生成:
请解释一下什么是无监督学习?
请解释一下什么是强化学习?
它不一定知道你是在“提问”,也不一定会按照助手风格回答你。
因为 Base 模型在预训练阶段学的是:
给定前文,继续生成合理文本。
它不是专门学:
用户问问题,我作为助手来回答。
这就是 Base 和 Chat 模型的核心区别。
什么是 Chat Model?
Chat Model,也叫:
Instruct Mode;l对话模型
比如:
Qwen-Chat
LLaMA-Instruct
ChatGLM
Baichuan-Chat
Chat 模型一般是在 Base 模型基础上经过 SFT、RLHF 或 DPO 得到的。
它更擅长:
- 回答问题
- 遵守指令
- 保持助手身份
- 多轮对话
- 按格式输出
- 拒绝不合适请求
- 生成更符合人类偏好的答案
举个例子。
你问 Base 模型:
帮我写一个请假邮件。
Base 模型可能续写成:
帮我写一个请假邮件。要求:语气礼貌,内容简洁……
它可能在续写你的需求。
而 Chat 模型会直接回答:
尊敬的老师:
您好!由于我身体不适,今天无法正常到课,特此向您请假一天……
此致
敬礼
这就是 Chat 模型和 Base 模型的差别。
什么是 Continue PreTrain?
Continue PreTrain,中文常叫:继续预训练
它是在已有 Base 模型上,继续用某类文本训练。
比如你想做一个法律大模型,就可以用:法律条文;判决书;合同,继续训练模型。
它主要解决:
模型对某个领域不够熟的问题。
比如普通模型可能知道一点法律知识,但不够深入。继续预训练后,模型会更熟悉:
- 领域术语
- 领域表达方式
- 领域知识分布
- 专业文档结构
- 领域中的常见推理模式
举个例子。普通模型看到:
抗辩权、形成权、除斥期间、善意取得
可能知道一点,但不够稳定。
法律继续预训练后,它更容易理解这些词之间的关系。
但是:模型会有灾难性遗忘(Catastrophic Forgetting): 如果你只喂法律数据,模型很快就会连简单的加减法或日常对话都忘了。因此,CPT 的核心难点在于数据配比(Data Mixture)。通常需要混入 10% - 20% 的通用 Pretrain 数据,以此来“稳住”模型的通用底盘。
Continue PreTrain 和 SFT 的区别
| 对比项 | Continue PreTrain | SFT |
|---|---|---|
| 数据形式 | 大量普通文本 | 指令-回答数据 |
| 目标 | 学领域知识和语言分布 | 学会按指令输出 |
| 数据例子 | 法律条文、论文、手册 | “请解释某条法律” + 标准回答 |
| 更像什么 | 读书 | 看参考答案 |
| 适合注入知识吗 | 适合 | 不适合大量注入 |
| 适合改变回答风格吗 | 不太适合 | 适合 |
举个例子。
Continue PreTrain 数据长这样:
《民法典》第五百零二条规定,依法成立的合同,自成立时生效……
SFT 数据长这样:
{
"instruction": "请解释合同成立和合同生效的区别。",
"input": "",
"output": "合同成立是指当事人意思表示达成一致;合同生效是指合同具备法律效力……"
}
前者是让模型读专业材料。后者是让模型学习怎么回答用户问题。
什么是 SFT?
SFT,全称是:
Supervised Fine-Tuning,监督微调。
它的核心思想是:
给模型很多“问题 + 标准回答”,让模型模仿这些标准回答。
比如:
{
"instruction": "请用通俗语言解释什么是机器学习。",
"output": "机器学习就是让计算机通过大量数据总结规律,然后用这些规律对新问题做判断。"
}
模型训练时会看到:
用户:请用通俗语言解释什么是机器学习。
助手:机器学习就是……
然后它会学习:
- 用户问问题时,助手应该回答
- 回答应该完整
- 回答应该符合格式
- 回答应该符合语气
- 回答应该解决用户需求
SFT 主要学什么?
-
格式对齐: 学会了按步骤解答、学会了总结、学会了拒绝看不懂的问题。
-
激发而非注入: 业界有一句名言:“知识来自预训练,SFT 只教格式”。SFT 阶段的数据量很少(通常几万到几十万条),指望靠 SFT 灌输大量新知识是不现实的,它的作用是“激发”模型在 Pretrain 阶段积累的知识,让其以对话的形式输出。
在计算 Loss(损失)时,绝不能对 Prompt 部分计算 Loss,只能对 Output 部分计算 Loss(这叫 Loss on target only)。因为你的目的是让模型学会生成答案,而不是去记忆人类的提问。
什么是 RLHF?
RLHF,全称是:
Reinforcement Learning from Human Feedback,基于人类反馈的强化学习。
它的作用是:
让模型输出更符合人类偏好。
SFT 后的模型已经能很好地对话了,但它可能喜欢说脏话、可能会一本正经地胡说八道(幻觉),或者提供制造炸弹的教程。对齐阶段就是为了让模型符合人类的“3H”标准:Helpful(有用)、Honest(诚实)、Harmless(无害)。
比如同一个问题:
请解释一下梯度下降。
模型生成了两个回答:
回答 A:
梯度下降是一种优化算法,通过沿着损失函数下降最快的方向更新参数。
回答 B:
你可以把梯度下降想象成下山。你站在山坡上,每次都朝最陡的下坡方向走一点,最后就可能走到山谷底部。机器学习里,这个“山谷底”就是损失较小的位置。
人类标注者可能更喜欢 B,因为它更通俗。RLHF 就是让模型学习这种偏好。
RLHF 和 SFT 的区别
| 阶段 | 主要数据 | 主要目标 |
|---|---|---|
| SFT | 标准答案 | 模仿好答案 |
| RLHF | 人类偏好排序 | 知道哪个答案更好 |
SFT 是告诉模型:
你应该这样回答。
RLHF 是告诉模型:
这几个回答里,哪个更受人喜欢。
什么是 DPO?
DPO,全称是:
Direct Preference Optimization,直接偏好优化。
它和 RLHF 的目标类似,都是让模型学习人类偏好。但是 DPO 通常比 RLHF 简洁一些。
它的数据一般长这样:
问题:请解释什么是深度学习。
chosen:深度学习是机器学习的一个分支,使用多层神经网络从数据中学习复杂模式……
rejected:深度学习就是很深奥的学习。
也就是:
问题 + 好答案 + 差答案
DPO 要做的是:
增加模型生成 chosen 的概率,降低生成 rejected 的概率。
对于很多团队来说,DPO 比 RLHF 更容易上手,因为它不一定需要复杂的强化学习流程。
知识、能力、风格分别在哪个阶段学到?
这是非常关键的一张表。
| 模型能力 | 主要来自哪里 |
|---|---|
| 基础语言能力 | Pretrain |
| 世界知识 | Pretrain |
| 领域知识 | Continue PreTrain / RAG |
| 专业术语理解 | Continue PreTrain |
| 指令遵循 | SFT |
| 输出格式 | SFT |
| 多轮对话 | SFT |
| 回答风格 | SFT |
| 安全拒答 | SFT + RLHF/DPO |
| 人类偏好 | RLHF/DPO |
| 最新知识 | RAG / 工具调用 |
| 企业私有知识 | RAG / CPT / SFT 结合 |
第二章:SFT 到底在学什么?
这一章解决一个核心问题:
SFT 不是万能的。它主要让模型学会“怎么回答”,而不是让模型系统掌握大量新知识。
很多初学者一开始做大模型微调,会遇到这种情况:
我明明用领域数据 SFT 了,为什么模型反而变差了?
为什么它回答更死板了?
为什么通用问题不会了?
为什么感觉模型变傻了?
这些现象都和 SFT 的本质有关。
先回顾:SFT 是什么?
SFT 全称是:
Supervised Fine-Tuning
监督微调
它做的事情非常直接:
给模型很多“输入 + 标准输出”,让模型模仿这些标准输出。
比如一条 SFT 数据可能长这样:
{
"instruction": "请解释什么是监督学习。",
"input": "",
"output": "监督学习是一种机器学习方法,它使用带有标签的数据训练模型,使模型能够根据输入预测对应的输出。"
}
训练时,模型会学习:
用户问:请解释什么是监督学习。
助手应该答:监督学习是一种……
从形式上看,SFT 就像老师给学生很多标准答案,让学生模仿标准答案的写法。
SFT 到底在学什么?
学术界有一篇极其著名的论文叫 LIMA (Less Is More for Alignment)。这篇论文做了一个震撼业界的实验:他们只用了区区 1000 条高质量的 SFT 问答对,没有用任何强化学习,就把一个 Base 模型微调成了一个可以和 GPT-3.5 匹敌的对话模型。
这证明了一个铁律:SFT 不注入知识,SFT 只做“格式对齐”(Alignment)和“能力唤醒”。
-
它在学风格: 学会像一个贴心助手一样开头说“好的,为您解答”,结尾说“希望对您有帮助”。
-
它在学拒绝: 学会遇到不合规的问题时回答“我是一个人工智能,不能回答……”。
-
它在学注意力分配: 学会关注 Prompt(提示词)中的约束条件,比如“用 50 个字总结”、“用 JSON 格式输出”。
你可以把 Base 模型想象成一个拥有整个图书馆知识的“雨人”(智者但无法交流),SFT 仅仅是教他怎么使用对讲机和人类说话。
为什么 SFT 后,模型反而会变“傻”?
在学术界和工业界,这个现象有一个专门的词汇,叫做 对齐税 (Alignment Tax)。为了让模型像个人类助手,我们付出了让它变笨的代价。原因有以下三点:
A. 概率分布的坍缩 (Collapse of Probability Distribution) 在 Pretrain 阶段,模型看过莎士比亚、看过互联网暴躁老哥的对骂、看过严谨的物理论文,它生成下一个词的概率分布是非常平滑且广阔的(充满了创造力和多样性)。 但是在 SFT 阶段,你喂给它的数据全是干巴巴的“人工智障风”——例如“首先...其次...最后...”。模型为了降低 Loss,会疯狂收敛到这种单一的表达方式上。它的词汇量变贫乏了,思维路径变窄了。 这就是为什么现在的 AI 写出来的文章“AI 味”极重。
B. 迎合人类的“偷懒” (Sycophancy / 谄媚现象) SFT 的数据是人写的,而人是有偏见且容易出错的。如果你的 SFT 数据中,回答复杂的数学题时缺乏详细的推导步骤,或者逻辑经常跳跃,模型就会学到这种“偷懒”的行为。它不再像 Pretrain 时那样展现严密的逻辑,而是学会了“装作在推理”,最后瞎蒙一个答案。
C. 灾难性的格式过拟合 (Overfitting to Format) 如果你在 SFT 里放了大量的单轮对话,模型就会变笨,处理不了多轮长对话;如果你的回答长度总是 100 个字,模型就会得“字数强迫症”,就算一句话能说清楚的事,它也要凑满 100 个字。它把所有的智力都用来“对齐格式”,从而牺牲了“内容质量”。
既然如此,大厂是怎么做 SFT 的?
-
克制: 宁缺毋滥。宁愿要 1 万条字斟句酌、逻辑严密、多轮转折的高质量数据,也绝对不要 100 万条网上随便爬下来的低质问答对。
-
系统提示词的威力 (System Prompt): 数据不仅要包括 Q (问题) 和 A (回答),必须加入 System Prompt。比如
<System>你是一个冷酷的杀手</System> <User>你好</User> <Assistant>滚。</Assistant>。这样才能训练出能角色扮演的模型,而不是只有一个干巴巴的 AI 人格。 -
多样性 (Diversity): 数据必须包含各种指令:写代码、做数学题、写诗、翻译、信息抽取。保证模型思维分布的广度,减少“对齐税”。
SFT 数据中的 label mask 是什么?
这一节对初学者稍微偏工程,但很重要。
做对话 SFT 时,通常我们只希望模型学习 assistant 的回答,而不是学习 user 的问题。
例如一条训练样本:
用户:什么是机器学习?
助手:机器学习是让计算机从数据中学习规律的方法。
训练时一般只计算助手部分的 loss:
机器学习是让计算机从数据中学习规律的方法。
而不计算用户部分的 loss:
用户:什么是机器学习?
这叫做:
label mask
也就是把不需要学习的 token 屏蔽掉。
一个完整的 SFT 样本长什么样?
以多轮对话为例。
{
"messages": [
{
"role": "system",
"content": "你是一个耐心、严谨的机器学习老师。"
},
{
"role": "user",
"content": "什么是过拟合?"
},
{
"role": "assistant",
"content": "过拟合是指模型在训练数据上表现很好,但在新数据上表现较差。它通常说明模型记住了训练集中的细节和噪声,而没有学到真正泛化的规律。"
},
{
"role": "user",
"content": "能举个生活中的例子吗?"
},
{
"role": "assistant",
"content": "可以。比如一个学生只背熟了练习册里的题目,但没有真正理解解题方法。考试时遇到稍微变化的新题,他就做不好。这就类似机器学习中的过拟合。"
}
]
}
这条数据教会模型:
保持老师角色
回答初学者问题
结合上文
用生活例子解释
多轮对话连贯
这就是 SFT 真正擅长的地方。
第三章:SFT 指令数据怎么构建
在业界有一句黑话:“有多少人工,就有多少智能”。SFT 数据构建绝对不是网上随便爬点网页那么简单,它是决定你模型最终性格、智商、甚至商业价值的核心壁垒。
如果把预训练比作“大满灌”,SFT 就是“精雕细琢”。我们来看看这道工序到底是怎么做的。
SFT 数据的关键不是“堆很多文本”,而是设计好:
用户会怎么问?
模型应该怎么答?
答案应该是什么风格?
遇到边界问题该不该拒答?
多轮对话中怎么衔接上下文?
一条 SFT 数据,本质上是在告诉模型:
当用户这样问时,你应该这样回答。
比如:
{
"instruction": "请解释什么是过拟合。",
"input": "",
"output": "过拟合是指模型在训练数据上表现很好,但在新数据上表现较差。它通常说明模型过度记住了训练集中的细节和噪声,而没有学到真正泛化的规律。"
}
这条数据教模型三件事:
1. 用户问概念解释时,模型应该直接解释。
2. 回答要准确,不要空泛。
3. 面对初学者问题,要用清晰语言。
SFT 数据不是简单的“知识文本”。比如下面这段不是标准 SFT 数据:
过拟合是机器学习中的一种现象,指模型在训练集上表现很好,但在测试集上表现较差……
这更像预训练语料。而 SFT 数据要有明确的“用户指令”和“助手回答”:
用户:什么是过拟合?
助手:过拟合是……
SFT 数据常见有三种格式。
格式一:Alpaca 格式
这是初学者最常见的一种格式
{
"instruction": "请解释什么是梯度下降。",
"input": "",
"output": "梯度下降是一种优化算法,它通过不断调整模型参数,使损失函数逐渐减小。"
}
三个字段分别是:
| 字段 | 含义 |
|---|---|
| instruction | 用户要模型做什么 |
| input | 额外输入材料,可为空 |
| output | 模型应该输出的答案 |
例如翻译任务:
{
"instruction": "请把下面这句话翻译成英文。",
"input": "我今天学习了监督微调。",
"output": "I studied supervised fine-tuning today."
}
这里:
instruction = 任务要求
input = 被处理的内容
output = 标准答案
格式二:ShareGPT / messages 格式
现在很多 Chat 模型更推荐 messages 格式:
{
"messages": [
{
"role": "user",
"content": "什么是梯度下降?"
},
{
"role": "assistant",
"content": "梯度下降是一种优化算法,用来不断调整模型参数,使损失函数变小。"
}
]
}
多轮对话可以写成:
{
"messages": [
{
"role": "user",
"content": "什么是过拟合?"
},
{
"role": "assistant",
"content": "过拟合是指模型在训练集上表现很好,但在新数据上表现较差。"
},
{
"role": "user",
"content": "能举个生活中的例子吗?"
},
{
"role": "assistant",
"content": "可以。比如一个学生只背熟了练习册里的题,但没有真正理解方法,考试遇到新题就不会做,这就类似过拟合。"
}
]
}
这种格式更接近真实聊天。
格式三:system / user / assistant 格式
很多对话模型还支持 system prompt。
例如:
{
"messages": [
{
"role": "system",
"content": "你是一个耐心、严谨的机器学习老师,回答时要适合初学者。"
},
{
"role": "user",
"content": "什么是监督学习?"
},
{
"role": "assistant",
"content": "监督学习是一种机器学习方法,它使用带有标签的数据训练模型。模型通过学习输入和标准答案之间的关系,来预测新数据的输出。"
}
]
}
system 的作用是告诉模型:
你是谁?
你应该用什么风格回答?
你应该遵守什么边界?
比如法律助手:
{
"role": "system",
"content": "你是一个法律知识助手。回答应谨慎、清晰,不能替代律师意见。"
}
医学助手:
{
"role": "system",
"content": "你是一个医学科普助手。回答仅供健康科普参考,不能替代医生诊断。"
}
当前高质量 SFT 数据的获取主要有三条路径:
-
人工标注(Human Annotation): 最昂贵、最优质。大厂会雇佣各个领域的专家(医生、律师、程序员)来手写问答对。一条高质量的专家级 SFT 数据,成本可能高达几十到上百元人民币。
-
开源数据集洗稿: 开源社区有大量的指令集(如 FLAN、UltraChat 等)。但这些数据鱼龙混杂,必须经过极其严格的清洗。
-
蒸馏/自指导(Self-Instruct / Distillation): 这是目前最主流的“白嫖”大法。也就是用更强大的闭源模型(比如 GPT-4、Claude 3.5)来生成数据,训练我们自己的小模型。我们写好 Prompt,让 GPT-4 帮我们批量生成“问题”和“标准答案”。
一个优秀的全能助手,它的 SFT 数据集必须像一份营养均衡的食谱。通常,一个几十万条的 SFT 数据集会这样配比:
-
核心能力(占比约 40%): 逻辑推理、数学计算、代码编写。这是拉高模型智商上限的“蛋白质”。
-
通用指令(占比约 30%): 摘要、翻译、信息抽取、改写。这是日常工作最常用的“碳水”。
-
多轮对话(占比约 20%): 教会模型如何承接上下文,如何在第五轮对话中依然记得第一轮设定的规则。
-
安全性与价值观(占比约 5%): 拒绝写病毒代码、拒绝回答歧视性问题。这是“免疫剂”。
-
格式控制(占比约 5%): 强制要求输出 JSON、Markdown 表格等特定格式。
真正的高手在构建 SFT 数据时,不仅关注“量”,更关注以下三个极其隐蔽的细节:
A. 负样本(Hard Negatives)的价值 我们不仅要教模型“怎么做是对的”,有时候还要在数据里教它“什么是不对的”。比如,遇到模棱两可或信息缺失的问题,SFT 数据应该教模型回答:“您提供的信息不足,我无法给出准确答案,请补充...”,而不是让它顺着问题去胡编乱造(幻觉)。
B. System Prompt (系统提示词) 的深度绑定 不要只用纯粹的 User 和 Assistant 两层结构。必须在数据中大量引入 System 层。
-
差的数据:
<User>帮我写个贪吃蛇</User> <Assistant>好的,代码如下...</Assistant> -
顶级数据:
<System>你是一个精通 Python 的资深工程师,你的代码必须包含详细的中文注释和异常处理。</System> <User>帮我写个贪吃蛇</User> <Assistant>没问题,下面是带有完整注释和防错机制的 Python 贪吃蛇代码...</Assistant>这样训练出来的模型,才能被用户灵活地“定制人格”。
C. 数据清洗的“去毒”与“去污染” (Decontamination)
-
去污染: 很多模型在发布前,不小心把评测集(比如考研真题 MMLU、GSM8K)混进了 SFT 数据里。这就像让学生在考试前偷看了答案,虽然分数高,但其实是个草包。
-
去 AI 味: 如果你用 GPT-4 生成数据,数据里会充斥着“作为人工智能语言模型”、“首先、其次、总之”这种八股文。如果不把这些固定话术洗掉,你的模型就会丧失表达的多样性,变得极其乏味。
第四章:领域 Continue PreTrain (CPT) 数据怎么选
我们在第一章说过,如果你想让开源大模型(比如 Llama-3)变成“医疗大模型”或“法律大模型”,因为 SFT 不能注入大量新知识,你必须在 SFT 之前加一步 CPT(持续预训练)。
CPT 的本质,是把模型重新塞回“图书馆”,只不过这次图书馆里全是某个专业领域的硬核书籍。这看起来很简单——把领域文档拼在一起喂给模型就行了,对吧?大错特错。CPT 是大模型训练中最容易把模型“练废”的环节。
1. 数据的选择:只要“干货”,拒绝“水文”
在 Pretrain 阶段,我们崇尚“大力出奇迹”,只要是互联网上的字,基本上都吃进去。但在 CPT 阶段,模型已经有了基础认知,这时候喂垃圾数据会严重污染它的思维。
-
黄金数据(高信息密度): 行业教科书、学术论文、专利文档、高质量的研报、经过脱敏的真实病历/法律判决书。这些数据的特点是逻辑严密、因果关系明确。
-
剧毒数据(低信息密度与格式混乱): 爬取的行业问答论坛(充满口水话和错误答案)、格式错乱的 PDF 解析文本(里面夹杂着页眉、页脚、乱码表单)。如果喂入乱码,模型会把“乱码”当成一种新语言去学习,导致 Loss 飙升。
2. 核心大坑:灾难性遗忘 (Catastrophic Forgetting)
这是 CPT 阶段 100% 会遇到的噩梦。 如果你收集了 100GB 的纯医疗数据,连续让模型看一个星期。看完之后,模型确实变成了“医学狂人”,但当你问它“李白是谁”或者“1+1等于几”时,它大概率会胡言乱语,或者强行用医学术语来解释(比如回答“李白是一种草药”)。
为什么? 因为神经网络的容量是有限的(参数量固定)。当你高强度地用新知识“冲刷”原有的权重时,模型为了记住生涩的医学名词,会把原来用来存“常识”和“逻辑”的脑区给覆盖掉。
为了防止模型“学了专业,忘了常识”,大厂在做 CPT 时,绝对不会只用 100% 的领域数据。我们必须混入通用数据(General Data)。
-
科学的配比(Mix Ratio): 通常,我们会将 领域数据 : 通用数据 按照 8:2 或者 7:3 的比例混合。
-
通用数据选什么(锚点数据): 不要选八卦新闻。要选能够维持模型“逻辑盘”和“常识盘”的高质量预训练数据。比如:高质量的维基百科(维持常识)、维基百科的数学/代码部分(维持逻辑推理能力)。这些通用数据就像是“锚点”,死死拉住模型,不让它的参数偏离常识轨道太远。
在处理长文本时,我们通常会把多个不同的文档拼接到一起,凑满模型的最大上下文长度(比如 8K Token),以提高显卡的计算效率。
-
外行的做法: 把文档 A 和文档 B 直接头尾相连,中间没有任何隔断。模型在学习时,会误以为文档 A 的结尾和文档 B 的开头存在逻辑关系,学到错误的“跨文档幻觉”。
-
大师的做法: 必须在每个独立文档的末尾插入一个特殊的截断符
<|endoftext|>。当模型预测到这个符号时,它的注意力机制(Attention)就会重置,明白“哦,这篇文章到此结束了,下面是全新的内容”,从而切断错误的因果关联。
第五章:知识注入:预训练、SFT、RAG 怎么选
如果你在企业里做大模型落地,每天被问到最多的一个问题绝对是:“我们的模型不知道公司昨天刚发的内部规定,怎么把这个知识教给它?”
新手通常的反应是:“拿去微调(SFT)啊!”或者“再做一次 CPT!” 而真正的大师会告诉你:停止盲目微调,拥抱 RAG。 这三种手段究竟怎么选?我们可以把大模型回答问题比作“参加考试”。
1. 三种“知识注入”手段的本质区别
A. CPT(持续预训练):闭卷考试,重塑大脑
-
原理: 把知识硬生生地烤进神经网络的权重(Weights)里。
-
特点: 极其昂贵,耗时极长。而且知识是静态的,一旦考完(训练完),知识就固化了。
-
致命缺点: 无法精准遗忘或更新。 比如,公司上一任 CEO 叫张三,你通过 CPT 让模型记住了。今天 CEO 换成了李四,你很难把“张三”这个知识点从模型几十亿的参数里精确抠出来并替换掉。
B. SFT(有监督微调):考前突击复习“答题技巧”
-
原理: 第二章我们讲过,SFT 是学格式的。如果你硬要用 SFT 注入新知识(比如死记硬背公司员工手册),模型就会产生“幻觉”。
-
特点: 成本极高且效果极差。它能让模型学会“用公文格式回答问题”,但很难让它记住“第 43 条规定的具体金额”。
C. RAG(Retrieval-Augmented Generation,检索增强生成):开卷考试,带小抄进考场
-
原理: 当用户提问时,系统先去公司的数据库(向量数据库)里搜索最相关的文档(比如找到了《员工手册第 43 条》),然后把文档和用户的问题一起打包,放到提示词(Prompt)里送给模型:“请根据以下参考资料,回答用户的问题”。
-
特点: 知识与模型解耦。 模型不需要把知识背下来,它只需要具备“阅读理解能力”。知识库可以随时更新、随时删除,成本几乎为零。
2. 工业界黄金法则:什么时候用什么?
在实际工程中,知识注入遵循一个严格的“倒三角法则”:
-
底层(通用规律与深层逻辑)用 Pretrain / CPT。
-
比如:教会模型什么是“医学思维”、什么是“C++ 语法特性”、某个小语种的词汇。这些是短期内不会改变的硬核底盘。
-
-
中层(交互规范与语气) 用 SFT。
-
比如:教会模型“遇到不懂的问题要说不知道,不能瞎编”、“输出格式必须是 Markdown”。
-
-
顶层(实时资讯与长尾动态知识) 用 RAG。
-
比如:公司今天的股价、昨天刚发布的规章制度、用户的个人订单信息。
-
只用 RAG 就万事大吉了吗?不是的。 如果你拿一个开源的 Base 模型或者普通的 Chat 模型直接做 RAG,经常会遇到一个极其棘手的问题:“不听话”。
-
症状: 你明明在 Prompt 里塞了正确的参考文档,但模型“太自负”了。它觉得自己在 Pretrain 阶段背的(可能是过时的)知识是对的,于是它无视了你给的参考文档,坚持用自己的内部幻觉回答问题。
-
(RAFT - Retrieval Augmented Fine Tuning): 为了解决这个问题,会做一种专门针对 RAG 的 SFT。 构造这样的 SFT 数据:
-
正向数据:
<Context>正确的文档</Context> <Question>问题</Question> <Answer>根据文档,答案是...</Answer>(教会它抄答案)。 -
干扰数据:
<Context>完全无关的文档</Context> <Question>问题</Question> <Answer>提供的参考资料中无法回答该问题。</Answer>(教会它抵御诱惑,不要瞎编)。 经过这种 SFT 微调后,模型才会变成一个完美的“开卷考试满分选手”。
-
第六章:中文训练和词表扩增
中文和英文不太一样。英文天然有空格:
I love machine learning.
模型很容易按单词或子词切分。中文没有天然空格:
我喜欢机器学习。
模型需要自己通过 tokenizer 把文本切成 token。比如可能切成:
我 / 喜欢 / 机器 / 学习 / 。
也可能切成:
我 / 喜 / 欢 / 机器学习 / 。
不同 tokenizer 切法不同。这会影响:
训练效率
上下文长度利用率
领域术语表达
中文生成质量
中英混排表现
所以中文训练不只是“放中文数据”这么简单。
中文模型训练的核心难点
主要有七个。
难点一:中文语料噪声很多
中文网页语料里常见很多噪声:
广告
导航栏
相关推荐
版权声明
乱码
重复标题
采集站内容
营销软文
低质量问答
伪原创文章
例如:
点击查看更多
上一篇:什么是机器学习
下一篇:深度学习入门
分享到微信
本站内容仅供参考
这些内容如果大量进入训练,会让模型学到很多无意义模式。
难点二:繁简混杂
中文语料可能包含:
简体中文
繁体中文
港澳台表达
日文汉字混入
繁简转换错误
例如:
後台 / 后台
資料 / 资料
演算法 / 算法
軟體 / 软件
是否统一繁简,要看目标用户。如果你的模型主要面向大陆简体用户,可以考虑统一为简体。
如果面向港澳台或多地区用户,可以保留繁简,但要保证质量。
难点三:中英文混排
AI、金融、医学、代码领域经常中英混排:
Transformer 使用 self-attention 机制。
LoRA 通过 low-rank matrix 降低训练参数量。
Batch size 太大会导致显存 OOM。
如果处理不好,中英混排会变乱。
例如:
Transformer使用self - attention机制
LoRA通过low rankmatrix降低训练参数量
这种文本质量就比较差。
难点四:标点和空格混乱
中文里常见:
全角标点:,。!?:()
半角标点: , . ! ? : ()
奇怪空格
多个连续换行
无意义缩进
比如:
什么是SFT ? 它 和 CPT 有 什么 区别 ?
这种文本会影响模型学习自然中文表达。
难点五:网页模板重复
很多网页有相同模板:
当前位置:首页 > 新闻中心 > 正文
免责声明:本文仅代表作者观点
相关推荐:
热门文章:
这些如果不清理,模型会学会输出类似废话。
难点六:低质量自动翻译文本
很多中文网页是机器翻译的,语言不自然。
比如:
这个模型是采取一个强大的方式去执行文本生成的任务。
这种中文不地道。训练多了,模型输出也会变得翻译腔。
难点七:领域术语切分问题
比如医学领域:
糖尿病酮症酸中毒
非小细胞肺癌
肾小球滤过率
法律领域:
善意取得
除斥期间
无权处分
不安抗辩权
如果 tokenizer 把这些术语切得很碎,训练效率会下降。但这并不意味着一定要扩词表。这个后面会重点讲。
中文预训练数据怎么选?
中文 CPT 或预训练数据应该优先选高质量文本。
比较适合的中文数据包括:
高质量百科
教材
书籍
论文
官方文档
行业报告
法律法规
技术文档
新闻深度报道
高质量问答
专业论坛精华
代码与中文注释
不太适合大量直接使用的数据包括:
低质量采集站
营销软文
标题党文章
重复转载内容
垃圾问答
无审核医疗建议
过时政策
乱码 OCR
机器翻译腔文章
中文数据尤其要注意:
不要让模型学到“中文互联网垃圾话风”。
比如:
震惊!
速看!
太全了!
建议收藏!
看完你就懂了!
少量没问题,大量进入训练会明显影响模型风格。
中文语料清洗重点
中文数据清洗可以重点做这几类。
1. 去广告和网页模板
删除:
相关推荐
上一篇
下一篇
分享到
点击查看
广告合作
免责声明
版权声明
关注公众号
这些不是正文知识。
2. 去乱码
常见乱码包括:
锟斤拷
� � �
机器å¦ä¹
中文
3. 去重复
中文网页重复转载很多。
需要做:
精确去重
近似去重
段落级去重
标题重复过滤
重复数据太多会导致模型过拟合,也浪费训练 token。
4. 统一或保留繁简
如果面向简体中文,可以统一成简体。
例如:
資料 → 资料
軟體 → 软件
學習 → 学习
但如果你的目标是繁体用户,或者希望模型同时支持繁简,就不能简单全部转简体。要根据目标定。
什么是 tokenizer?
讲词表扩增前,先理解 tokenizer。大模型不能直接处理文字。它会先把文本切成 token。
国外开源大模型(如 Llama-2/3、Mistral)的词表主要是基于英文语料训练的。
-
英文的待遇: "apple" 这个词,在 Tokenizer 看来是一个极其高频的词,它会被切成 1 个 Token。
-
中文的待遇: 遇到“苹果”这两个汉字,因为 Tokenizer 不认识,它只能采用最底层的 UTF-8 字节(Byte)来进行强行拆分。一个汉字通常会被拆成 3 个字节。于是,“苹果”会被切成类似
<0xE8> <0x8B> <0xB9> <0xE6> <0x9E> <0x9C>这样毫无语义的 6 个 Token。
不扩表强行训练中文,会带来三个毁灭性的后果:
-
算力极度浪费: 模型每生成一个 Token 的计算量是固定的。原本 1 次计算就能吐出 "apple",现在要算 6 次才能吐出“苹果”。你的推理成本直接飙升 6 倍。
-
上下文长度(Context Window)大缩水: 假设模型最大支持 8K Token。如果是英文,可以输入 8000 个单词(大约一篇长论文);如果是中文,因为一个字占 3 个 Token,你最多只能输入 2600 个汉字,连个短篇小说都塞不下。
-
语义割裂: 中文的词义被物理切碎成了毫无意义的十六进制字节,模型极难学到“苹”和“果”组合在一起的深层含义。
所以为了更好地切分中文,我们要训练一个中文专属的 Tokenizer 收集海量的中文高质量语料(几十个 GB 的维基百科、新闻等),使用 BPE(Byte-Pair Encoding,字节对编码)算法,训练出一个能完美切分中文的词表(比如包含 2 万个最常用的中文词组:[“我们”, “中国”, “大模型”, “人工智能”...])。
比如中文句子:
我喜欢机器学习。
可能被切成:
我 / 喜欢 / 机器 / 学习 / 。
也可能被切成:
我 / 喜 / 欢 / 机 / 器 / 学 / 习 / 。
这些 token 会被映射成数字 ID,再输入模型。
tokenizer 影响:
同样一句话占多少 token
训练效率
上下文长度利用率
领域术语表示
生成质量
假设一个模型的上下文长度是 4096 token。
如果 tokenizer 对中文效率很高,一篇中文文档可能占:
2000 token
如果 tokenizer 对中文效率很差,同样内容可能占:
3500 token
这意味着:
同样上下文长度下,可放入的信息更少
训练成本更高
推理成本更高
长文本任务更吃亏
所以中文模型最好选择中文 tokenizer 表现不错的基座。
但是:
tokenizer 重要,不等于你应该随便扩词表。
词表扩增就是给 tokenizer 增加新的 token。
比如原来的 tokenizer 没有:
糖尿病酮症酸中毒
它可能切成:
糖 / 尿 / 病 / 酮 / 症 / 酸 / 中 / 毒
如果扩词表,可以把它加入成一个 token:
糖尿病酮症酸中毒
理论上,这样模型处理这个术语更高效。
为什么微调阶段不建议随便扩词表?
主要有五个原因。
原因一:新 token 的 embedding 是新的
模型原来的词表里,每个 token 都有一个向量表示。如果你新增一个 token,比如:
不安抗辩权
这个 token 对应的 embedding 是新初始化的。也就是说,模型一开始并不知道它是什么意思。
你需要大量训练,让模型学会这个新 token 的含义。如果训练数据不够,新 token 反而可能学不好。
原因二:小规模 SFT 训练不充分
SFT 数据通常不是特别大。
如果你只训练几千条、几万条样本,新 token 出现次数有限。
模型很难充分学习新增 token。
结果可能是:
词表扩了
训练复杂了
效果没明显提升
甚至变差
原因三:会影响模型兼容性
扩词表后:
tokenizer 变了
embedding 大小变了
模型权重结构变了
加载方式变了
部署时必须使用新 tokenizer
如果你忘记同步 tokenizer,模型会直接出问题。
原因四:LoRA 场景下收益有限
LoRA 通常只训练一小部分参数。
如果你新增 token,但没有很好训练 embedding,收益有限。
有时你还需要额外训练 embedding 层,这会让流程复杂。
原因五:很多术语拆开也能学
例如:
监督微调
即使被切成:
监督 / 微调
模型也能理解。再比如:
不安抗辩权
即使切成几个子词,只要训练数据充足,模型仍然可能学会含义。大模型并不要求每个术语都必须是一个 token。
什么时候可以考虑扩词表?
虽然不建议轻易扩,但有些情况可以考虑。
情况一:从头预训练中文模型
如果你不是微调,而是从零训练一个中文大模型,那么 tokenizer 很重要。
这时可以专门设计适合中文的词表。
例如考虑:
中文常用字词
中英混排
代码符号
数学符号
领域术语
多语言覆盖
从头训练时,词表和模型一起训练,比较合理。
情况二:大量领域术语切得非常碎
比如某些专业领域有大量长术语、符号、编号。
例如:
医学疾病名称
化学分子式
基因名称
法律术语
工业设备型号
专有产品编码
如果它们被 tokenizer 切得特别碎,导致 token 数暴涨,可以考虑扩词表。
但要先做统计,不要凭感觉。
如果你确实决定扩词表,大致流程是:
第一步:收集高质量领域语料
第二步:统计高频术语和切分情况
第三步:筛选候选新词
第四步:扩展 tokenizer
第五步:扩展 embedding 层
第六步:初始化新 token embedding
第七步:进行充分 CPT
第八步:再做 SFT
第九步:评测效果和兼容性
大模型的输入层有一个巨大的“词向量矩阵(Embedding Layer)”,输出层有一个“预测矩阵(LM Head)”。比如你的词表增加了 2 万个,这两个矩阵的维度必须随之扩大。原来是 128000 x 4096,现在必须硬生生撑大成 148000 x 4096。
刚才说了,矩阵变大了。那么那 2 万个新增加出来的参数(权重),里面填什么数字呢?
-
外行/新手的做法(随机初始化): 直接用随机数填进去。这时候如果立刻开始用中文数据做 CPT 训练,灾难就会发生(Loss Spike)。 因为这 2 万个新词的向量是完全随机的“白噪音”,一旦反向传播(Backpropagation)开始计算梯度,这些巨大的噪音梯度会像洪水一样倒灌进模型原有的网络里,瞬间把模型在 Pretrain 阶段学到的通用知识冲刷得干干净净。模型直接变智障。
-
正确的做法(启发式初始化 / Heuristic Initialization): 我们绝不能用随机数。我们要用“英语老师带中文翻译”的思路。 比如,新增了
“人工智能”这个 Token。我们在初始化它的向量时,去原来的英文词表里找到“artificial”和“intelligence”这两个 Token。把它们俩的向量拿出来,求一个平均值,然后赋给“人工智能”这个新 Token 作为初始权重。 通过这种“语义对齐”的初始化,新的中文词在训练的第一步,就已经拥有了接近英文对应词的智商!
扩表并初始化完成后,绝不能直接拿去做 SFT 问答。因为新词的向量毕竟是拼接的,还不稳定。你必须先做一次 CPT(持续预训练)。
在 CPT 的前几个步骤中,业界通常有两种保平安的做法:
-
Freeze(冻结)大法: 冻结模型的主干网络(Transformer 隐层),只训练新加入的 Embedding 层和 LM Head。让新词汇先适应一下环境,等 Loss 降下来平稳了,再解冻全局网络一起练。
-
超低学习率(Warmup): 如果不冻结,就必须把初始学习率压得极低(比如
),缓慢预热,防止梯度爆炸。
第七章:显存、Batch Size、优化器和 OOM
在大模型圈,有一个所有人都绕不开的恐怖缩写:OOM (Out Of Memory,显存溢出)。
假设你有一张 80GB 显存的 A100 显卡,你要微调一个 8B(80亿参数)的模型。显存是怎么被吃光的?
-
第一大吸血鬼:模型权重 (Model Weights) 如果你用半精度(bf16 或 fp16)加载 8B 模型,1 个参数占 2 个字节(Byte)。那么纯模型本身就要占掉 16GB 的显存。这只是它“安静躺在那里”的体积。
-
第二大吸血鬼:优化器状态 (Optimizer States) 这是新手最容易忽略的致命点!大模型目前标配的优化器是 AdamW。为了让参数平滑更新,AdamW 会为每一个参数记住过去的“动量”和“方差”(fp32 精度)。 惊人的真相:AdamW 占用的显存,是模型本身的两倍甚至四倍! 那个 16GB 的模型,它的优化器可能会一口气吃掉 32GB 到 64GB 的显存。
-
第三大吸血鬼:梯度 (Gradients) 反向传播时计算出的梯度,通常也需要占用和模型体积等同的显存(16GB)。
-
第四大吸血鬼:激活值 (Activations) 在前向传播时,模型每一层产生的临时计算结果。这个东西的体积取决于你的 Batch Size(批次大小) 和 Sequence Length(上下文长度)。如果你一次性塞入很长的数据,激活值会瞬间爆炸。
算算账,16 + 32 + 16 = 64GB,再加上激活值,一张 80G 的 A100 瞬间就被吃干抹净,直接 OOM。
遇到 OOM,一般用这三种方式效果不错:
Gradient Checkpointing (梯度检查点 / 激活值重算)
-
痛点: 激活值太占空间了!
-
原理: “用时间换空间”。我们在前向传播时,不把所有层的激活值都存下来,而是每隔几层存一个“检查点”。等反向传播需要用到中间结果时,我们临时重新计算一次。
-
效果: 显存占用大幅下降,代价是训练速度变慢了 20% 左右。这是目前大模型训练必须开启的选项。
Gradient Accumulation (梯度累加)
-
痛点: 你的显卡太烂,Batch Size 设为 8 就 OOM,只能设为 1。但 Batch Size 太小,模型学得一塌糊涂,Loss 疯狂震荡。
-
原理: 你保持 Batch Size = 1。但是你告诉代码:不要算完 1 条数据就去更新参数。你算完 1 条,把梯度“攒着”(Accumulate),连续算 8 条数据,把这 8 条的梯度加起来,再去更新一次模型参数。
-
效果: 在数学上,这等效于 Batch Size = 8!完美绕过了单次显存不足的问题。
LoRA / QLoRA (参数高效微调)
-
痛点: 优化器状态(AdamW)吃的显存太多了,占了 60% 以上!
-
原理: Freeze(冻结) 原模型 99% 的参数,只在模型旁边挂载几个极小规模的“旁路矩阵(LoRA 层)”。这时候,计算梯度和优化器状态时,只需要算那 1% 的参数。
-
效果: 显存占用呈断崖式下跌。原本需要 4 张 A100 才能微调的模型,现在一张 24GB 的 RTX 3090 游戏显卡就能跑起来了。这是开源社区平民玩家的终极福音。
在调参时,Batch Size(一次看多少条数据)和 Learning Rate(每次步子迈多大)是一对生死兄弟。
-
新手常犯的错误: 为了用上多张显卡,把 Batch Size 从 16 加大到了 128,但是忘记调整学习率。结果模型死活收敛不了。
-
(Linear Scaling Rule): 当你把 Batch Size 放大 N 倍时,你的学习率通常也要跟着放大相应的倍数(或者是
倍),因为单次更新看到的样本更全面了,你有了底气,就可以让模型步子迈得更大一些。
第八章:灾难性遗忘、loss spike 和训练排错
什么是灾难性遗忘?
灾难性遗忘,英文叫:
Catastrophic Forgetting
简单说就是:
模型学习新任务、新领域、新数据时,原来已经掌握的一些能力下降了。
比如原来的模型会:
写作
翻译
总结
写代码
常识问答
多轮对话
数学推理
你用大量法律问答微调后,它变得更像法律助手了。
但是你再问它:
帮我写一首关于春天的小诗。
它可能回答:
从法律角度看,春天并不构成一个法律事实……
这就说明模型被领域数据“带偏”了。
微调本质上是在原模型参数的基础上继续更新。
原模型的参数里包含了很多能力:
语言能力
常识能力
代码能力
数学能力
对话能力
多语言能力
安全边界
当你只用某一类数据继续训练时,比如:
法律问答
法律问答
法律问答
法律问答
法律问答
模型参数会不断朝法律问答这个分布移动。
好处是:
法律回答风格更明显
法律术语更熟悉
法律任务更像样
坏处是:
通用能力可能下降
输出风格变窄
其他任务被覆盖
模型变得模板化
所以灾难性遗忘不是神秘现象,本质就是:
新数据分布过强,覆盖了旧能力分布。
如何缓解灾难性遗忘?
常见方法如下。
方法一:混入通用数据
这是最直接、最常用的方法。例如领域 SFT 可以混合:
70% 领域数据
20% 通用指令数据
10% 安全和拒答数据
通用数据可以包括:
写作
翻译
总结
代码
数学
常识
多轮对话
格式输出
安全拒答
目的不是让模型重新学全部能力,而是提醒模型:
你还是一个通用助手,不只是一个领域答题机器。
方法二:降低学习率
如果微调后能力掉得厉害,学习率是优先检查项。
可以尝试:
5e-5 → 2e-5
2e-5 → 1e-5
学习率降低后,模型更新更温和,原能力更容易保留。
方法三:减少 epoch
如果模型变得模板化、泛化下降,可以减少训练轮数。
例如:
3 epoch → 2 epoch
2 epoch → 1 epoch
尤其是小数据集,不要训太久。
方法四:使用 LoRA / QLoRA
相比全参微调,LoRA 只训练少量 adapter 参数,通常对原模型破坏更小。
适合:
业务适配
领域 SFT
格式训练
风格训练
小中规模数据
什么是 loss spike?
loss spike,中文常叫:
loss 突刺
loss 尖峰
loss 突然升高
它指的是训练过程中,loss 本来比较平稳,突然某一步或某几步大幅升高。
例如正常 loss 曲线:
2.1 → 2.0 → 1.9 → 1.85 → 1.8
出现 loss spike:
2.1 → 2.0 → 1.9 → 8.7 → 1.95 → 1.85
如果只是偶尔一次,然后很快恢复,可能问题不大。
如果频繁突刺,甚至之后 loss 不再恢复,就说明训练不稳定。
类型一:偶发小突刺
表现:
loss 偶尔升高
下一两步恢复
模型输出正常
可能原因:
某个 batch 比较难
样本长度变化
数据分布波动
batch size 较小
通常不用太紧张。
类型二:频繁突刺
表现:
loss 经常突然升高
曲线很不稳定
评测效果波动大
可能原因:
学习率偏大
batch size 太小
数据质量不稳定
超长样本太多
梯度裁剪不足
需要排查。
类型三:突刺后崩溃
表现:
loss 突然升高
之后不再恢复
甚至变成 NaN
模型输出乱码或重复
这是严重问题。
可能原因:
学习率过大
数值溢出
混合精度不稳定
梯度爆炸
脏数据严重
label mask 错误
为什么会出现 loss spike?
常见原因有十类。
原因一:学习率过大
这是最常见原因之一。
学习率太大时,一次参数更新可能跨得太远,导致 loss 突然升高。
表现:
loss 抖动明显
训练不稳定
模型输出逐渐异常
解决:
降低 learning rate
增加 warmup
使用学习率衰减
原因二:warmup 不够
训练刚开始时,如果学习率直接升到较高值,模型可能不适应。
解决:
增加 warmup_ratio
例如 0.01 → 0.03 或 0.05
原因三:batch size 太小
batch size 太小时,每一步梯度受单个样本影响很大。
某个异常样本就可能导致 loss 突刺。
解决:
增加 gradient_accumulation_steps
降低学习率
清洗异常样本
原因四:脏数据
例如:
乱码
错误格式
极端重复文本
答非所问
超长无意义文本
错误 label
这些都可能造成异常 loss。尤其是某个 batch 混入极端异常样本,loss 会突然升高。
原因五:超长样本
超长样本可能导致:
padding 大量浪费
显存压力突增
训练不稳定
截断后语义混乱
解决:
统计 token 长度分布
过滤极端长样本
合理设置 max_length
按长度分桶
原因六:label mask 错误
SFT 时通常只应该计算 assistant 部分的 loss。
如果把 user、system 也算进 loss,或者 mask 错位,训练目标会混乱。
表现可能是:
模型复读用户问题
生成 role 标记
多轮格式混乱
loss 异常
解决:
检查 labels
确认 user 部分是否为 -100
确认 assistant 部分参与 loss
抽样打印 token 和 label
原因七:chat template 错误
如果训练格式和模型预期格式不一致,模型可能学坏。
例如 Qwen、LLaMA、ChatGLM 等模型都有自己的对话模板。
错误模板可能导致:
模型分不清 user / assistant
生成特殊 token
回答混乱
原因八:混合精度数值溢出
FP16 训练时可能出现数值不稳定。
表现:
loss 变 NaN
梯度变 NaN
训练突然崩溃
解决:
优先使用 BF16
开启 gradient clipping
降低学习率
检查是否有异常输入
原因九:梯度爆炸
梯度突然变得很大,导致参数更新异常。
解决:
设置 max_grad_norm = 1.0
降低学习率
增加 warmup
清洗异常样本
原因十:数据分布突然变化
如果数据没有 shuffle 好,训练过程可能先看到一类数据,再突然看到另一类数据。
例如:
前 1000 step 全是普通问答
后面突然全是超长法律条文
loss 可能明显突变。
解决:
充分 shuffle
按比例混合数据
不要按数据源顺序直接训练
其余常见问题:
新手最喜欢看到 Loss 降到接近 0,比如 0.0001。但大师看到这种数字,后背会发凉。大模型的 Loss 降得太低,通常意味着灾难:
-
死记硬背(Memorization): 模型不再试图理解逻辑,而是把你的几十万条训练数据一字不差地背了下来。这时候如果让它做训练集里的题,它是神;如果稍微换个说法,它是傻子。
-
标点符号过拟合(EOS 丢失): 如果你发现模型在推理时,死活停不下来,比如输出:
“你好,请问有什么可以帮您?\n\n\n\n\n\n...”一直复读到显存爆炸。这往往是因为训练时,由于数据格式没清洗好,模型没有学到<|endoftext|>(结束符)的触发条件,导致它变成了一台没有刹车的车。
我们在第二章和第四章都提过灾难性遗忘,但到了工程实战中,它极其隐蔽。Loss 曲线完全看不出来它忘记了常识。
不要等到模型训练了半个月结束了,才拿去评测。大师会在训练脚本里埋下“探针”。
-
每训练 500 步,代码会自动暂停,调用几个外部的通用评测集(比如考几道高中数学题、问几个常识问题)。
-
观察通用能力的指标变化。如果你在注入“法律知识”时,发现“高中数学题”的正确率呈现断崖式下跌,立刻停止训练!调整第四章讲过的 Data Mixture(增加通用数据占比),重新开始。
开源社区的底层训练代码(如 LLaMA-Factory、Megatron、DeepSpeed)已经被成千上万的天才验证过了。大模型训练中 95% 的灵异事件,都是数据造成的。
长度截断错误:你以为你喂给了模型一篇文章,其实 Tokenizer 设置错了,截断了前 50 个字,剩下的全被丢弃了。
标签错位:在 SFT 时,User 的提问也被错误地算入了 Loss 进行反向传播,导致模型满脑子都是“怎么问问题”而不是“怎么回答”。
在开始大规模训练前,手工把模型即将吃进去的前 10 条数据(Token IDs),用 Tokenizer 反向解码(Decode)成人类文字,一个字一个字地读一遍! 看有没有乱码,看 <System> 和 <User> 的特殊字符有没有放错位置。
更多推荐


所有评论(0)