这是一套面向初学者的领域大模型训练教程,围绕大模型从 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,慢慢学会:

  1. 语言规律
  2. 词语搭配
  3. 世界知识
  4. 基础推理模式
  5. 代码模式
  6. 数学表达
  7. 常见事实
  8. 文本结构

所以预训练不是简单背书,而是在海量文本中学习统计规律和知识结构。

预训练结束后,我们得到的模型一般叫:

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 得到的。

它更擅长:

  1. 回答问题
  2. 遵守指令
  3. 保持助手身份
  4. 多轮对话
  5. 按格式输出
  6. 拒绝不合适请求
  7. 生成更符合人类偏好的答案

举个例子。

你问 Base 模型:

帮我写一个请假邮件。

Base 模型可能续写成:

帮我写一个请假邮件。要求:语气礼貌,内容简洁……

它可能在续写你的需求。

而 Chat 模型会直接回答:

尊敬的老师:

您好!由于我身体不适,今天无法正常到课,特此向您请假一天……

此致
敬礼

这就是 Chat 模型和 Base 模型的差别。

什么是 Continue PreTrain?

Continue PreTrain,中文常叫:继续预训练

它是在已有 Base 模型上,继续用某类文本训练。

比如你想做一个法律大模型,就可以用:法律条文;判决书;合同,继续训练模型。

它主要解决:

模型对某个领域不够熟的问题。

比如普通模型可能知道一点法律知识,但不够深入。继续预训练后,模型会更熟悉:

  1. 领域术语
  2. 领域表达方式
  3. 领域知识分布
  4. 专业文档结构
  5. 领域中的常见推理模式

举个例子。普通模型看到:

抗辩权、形成权、除斥期间、善意取得

可能知道一点,但不够稳定。

法律继续预训练后,它更容易理解这些词之间的关系。

但是:模型会有灾难性遗忘(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": "机器学习就是让计算机通过大量数据总结规律,然后用这些规律对新问题做判断。"
}

模型训练时会看到:

用户:请用通俗语言解释什么是机器学习。
助手:机器学习就是……

然后它会学习:

  1. 用户问问题时,助手应该回答
  2. 回答应该完整
  3. 回答应该符合格式
  4. 回答应该符合语气
  5. 回答应该解决用户需求

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 (系统提示词) 的深度绑定 不要只用纯粹的 UserAssistant 两层结构。必须在数据中大量引入 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. 去乱码

常见乱码包括:

锟斤拷
� � �
机器学ä¹
&#x4E2D;&#x6587;

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

不扩表强行训练中文,会带来三个毁灭性的后果:

  1. 算力极度浪费: 模型每生成一个 Token 的计算量是固定的。原本 1 次计算就能吐出 "apple",现在要算 6 次才能吐出“苹果”。你的推理成本直接飙升 6 倍。

  2. 上下文长度(Context Window)大缩水: 假设模型最大支持 8K Token。如果是英文,可以输入 8000 个单词(大约一篇长论文);如果是中文,因为一个字占 3 个 Token,你最多只能输入 2600 个汉字,连个短篇小说都塞不下。

  3. 语义割裂: 中文的词义被物理切碎成了毫无意义的十六进制字节,模型极难学到“苹”和“果”组合在一起的深层含义。

所以为了更好地切分中文,我们要训练一个中文专属的 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 的前几个步骤中,业界通常有两种保平安的做法:

  1. Freeze(冻结)大法: 冻结模型的主干网络(Transformer 隐层),只训练新加入的 Embedding 层和 LM Head。让新词汇先适应一下环境,等 Loss 降下来平稳了,再解冻全局网络一起练。

  2. 超低学习率(Warmup): 如果不冻结,就必须把初始学习率压得极低(比如 $1e^{-6}$),缓慢预热,防止梯度爆炸。

第七章:显存、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 倍时,你的学习率通常也要跟着放大相应的倍数(或者是 $\sqrt{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> 的特殊字符有没有放错位置。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐