一、SFT 到底是什么?—— 让预训练模型学会“说人话”
各位同学好,我是你们的老朋友。今天咱们聊聊 SFT,也就是监督微调。
说实话,我刚接触这个领域时,也觉得 SFT 不就是“拿标注数据再训一训”嘛,有啥好讲的?但后来踩了不少坑才发现,这里面的门道比想象中深得多。
先问大家一个问题:预训练模型已经很强了,为什么还要做 SFT?
你想想看,像 LLaMA、ChatGLM 这些大模型,预训练阶段学的是“海量文本的统计规律”。它能续写句子,能填空,但你要它“像个助手一样回答问题”——嗯,它还真不会。
举个例子:
- 预训练模型看到“中国的首都是”,它会接“北京”。这没问题。
- 但如果你问“请用三句话介绍北京”,它可能给你写一篇论文出来。
说白了,预训练模型是个“知识渊博但不懂规矩”的天才。SFT 要做的,就是教会它“对话的规矩”。
SFT 的核心目标:让模型从“续写模式”切换到“对话模式”。
具体来说,就是让模型学会:
- 理解指令的意图(是问答、总结还是翻译?)
- 遵循输出格式(列表、段落、JSON?)
- 保持角色一致性(你是助手,不是用户)
二、SFT 的原理:其实就是在做“条件概率对齐”
从数学角度看,SFT 的原理并不复杂。
预训练阶段,模型学的是 P(x)——也就是文本本身的概率分布。而 SFT 阶段,我们要学的是 P(y|x)——给定输入 x(比如用户问题),输出 y(比如助手回答)的条件概率。
我习惯用一个比喻来理解:
- 预训练 = 让模型读完了整个图书馆的书
- SFT = 告诉模型“当别人问你问题时,你应该这样回答”
具体实现上,SFT 就是拿一批 (指令, 回答) 对,让模型去拟合这些回答。损失函数用的是交叉熵,后面会细讲。
一个小经验:我在项目中遇到过,SFT 数据量不是越多越好。有时候 1 万条高质量数据,效果比 10 万条噪声数据好得多。质量 > 数量,这句话在 SFT 里是铁律。
三、预训练模型怎么选?—— LLaMA vs ChatGLM 的实战对比
选基座模型,是 SFT 的第一步。我见过不少团队,模型选错了,后面怎么调都白搭。
目前主流的选择就两个方向:LLaMA 系列 和 ChatGLM 系列。我分别说说我的看法。
3.1 LLaMA:开源社区的“标准答案”
LLaMA 是 Meta 开源的模型,现在已经是事实上的行业标准了。为什么大家都爱用?
- 生态好:HuggingFace 上几乎所有的工具、微调框架都优先支持 LLaMA
- 可扩展性强:从 7B 到 70B,参数量选择多
- 社区活跃:遇到问题,搜一下基本都有解决方案
但 LLaMA 有个硬伤——中文能力偏弱。毕竟它的预训练数据里英文占了绝大多数。如果你要做中文对话系统,直接用 LLaMA 效果会打折扣。
避坑指南:我曾经直接用 LLaMA-7B 做中文 SFT,结果模型连“你好”都回不利索。后来加了中文继续预训练,才勉强能用。所以,中文场景慎用原生 LLaMA。
3.2 ChatGLM:中文场景的“本土选手”
ChatGLM 是智谱 AI 开源的模型,中文能力天然强。我个人的经验是:
- 中文理解力好:成语、俗语、古诗词,基本不在话下
- 部署友好:6B 的模型,一张 3090 就能跑推理
- 对话风格自然:预训练阶段就做了对话优化
但 ChatGLM 也有缺点:英文能力一般,且社区生态不如 LLaMA 丰富。有些最新的微调工具,可能不支持 ChatGLM。
3.3 我的选择建议
| 场景 | 推荐模型 | 理由 |
|---|---|---|
| 纯中文对话 | ChatGLM-6B | 中文能力强,开箱即用 |
| 中英混合 | LLaMA-2-7B + 中文继续预训练 | 平衡中英文能力 |
| 需要高可控性 | LLaMA-2-13B | 参数量大,微调后效果上限高 |
| 资源有限 | ChatGLM-6B 或 Qwen-7B | 显存占用小,训练成本低 |
补充一句:现在阿里开源的 Qwen 系列也值得关注。它在中文和英文上表现都不错,而且支持 8K 上下文。我最近几个项目都在用 Qwen,效果挺稳的。
四、SFT 的损失函数:交叉熵到底在算什么?
好,到了最核心的部分——损失函数。
SFT 用的损失函数就是 交叉熵损失(Cross-Entropy Loss)。公式长这样:
L = - Σ y_true * log(y_pred)
别被公式吓到,我用人话解释一下:
y_true是真实答案中每个 token 的 one-hot 编码y_pred是模型预测的每个 token 的概率分布- 交叉熵衡量的是“模型预测分布”和“真实分布”之间的差距
说白了,损失函数就是在惩罚“模型猜错”的行为。模型预测的概率越接近真实答案,损失就越小。
4.1 为什么用交叉熵,不用 MSE?
这个问题我面试时经常问。答案是:分类问题天然适合交叉熵。
- MSE(均方误差)对概率值的差异不敏感
- 交叉熵对“低概率高损失”非常敏感——模型一旦把正确答案预测成低概率,损失会飙升
举个例子:假设正确答案是 token ID 100,模型预测它的概率是 0.1。交叉熵会给出一个很大的损失,逼着模型调整参数。而 MSE 可能觉得“0.1 也不算太差”,更新力度就弱很多。
4.2 实际训练时的注意事项
我在项目中踩过这个坑:损失计算时,要不要忽略 padding token?
答案是:必须忽略。
因为我们在 batch 训练时,不同样本的长度不一样。短的样本会 padding 到和长的样本一样长。这些 padding token 没有实际意义,如果把它们也算进损失里,模型会学到“预测 padding 位置”这种无用的能力。
代码实现上,PyTorch 的 CrossEntropyLoss 有个 ignore_index 参数,设成 padding token 的 ID 就行:
loss_fn = nn.CrossEntropyLoss(ignore_index=tokenizer.pad_token_id)
另一个坑:有些同学会把“输入部分”也参与损失计算。比如用户问题“你好吗?”和助手回答“我很好”,如果连“你好吗?”也计算损失,模型会学到“预测用户问题”这种错误行为。记住:只计算“回答部分”的损失。
五、一张图看懂 SFT 全流程
说了这么多,我画了一张流程图,帮你把整个 SFT 的脉络理清楚:
这张图展示了 SFT 的完整闭环:从预训练模型出发,经过数据准备和模型选择,进入 SFT 训练,得到具备对话能力的模型,最后评估效果并迭代优化。
核心要点回顾:
- SFT 的目标是让模型学会“对话的规矩”
- 预训练模型选型要看场景:中文选 ChatGLM,中英混合选 LLaMA 或 Qwen
- 损失函数用交叉熵,只计算回答部分的损失,忽略 padding token
- 数据质量比数量更重要
好了,这一章的内容就到这里。SFT 是整个 RLHF 流程的基石,打好这个基础,后面学 RLHF 的奖励模型和强化学习阶段才会更顺畅。下一章我们聊聊 SFT 的数据构建——这可是个技术活,也是我踩坑最多的地方。