SFT 的全称是 Supervised Fine-Tuning(监督微调) ,它的核心目标是:让预训练好的大模型,在人工标注的「指令-回答」数据上学习,精准匹配人类的指令意图。
而 Loss(损失值)的作用,就是衡量模型生成的回答和人工标注的「标准答案」之间的差距------差距越小(Loss 越低),模型学得越好。
一、白话入门:用「老师批改作业」理解 SFT Loss
我们把 SFT 微调的过程,比作 「老师教学生写作业」:
- 学生 = 预训练大模型:已经有了基础的语言能力(比如认识字、懂语法),但还不会按指令写标准答案。
- 作业题 = SFT 训练样本 :格式是
指令 + 标准答案,比如: 指令:解释什么是 LoRA?标准答案:LoRA 是低秩适配技术,能轻量化微调大模型。
- 老师批改 = Loss 计算 :老师只看「学生的答案」和「标准答案」的差异,扣分规则如下:
- 学生写的每个字(对应模型生成的每个 token),和标准答案越像,扣分越少;
- 只给「答案部分」扣分,指令部分不算分(因为指令是题目,不是学生要写的内容);
- 所有字的扣分加起来求平均,就是这次作业的「总 Loss」------Loss 越低,学生学得越到位。
核心结论 :SFT 的 Loss 本质是 「只计算回答部分的 token 预测误差」,和预训练阶段的 Loss 最大区别就是「不计算指令部分的损失」。
二、基础原理:SFT Loss 的核心是「交叉熵损失」
大模型生成文本的过程,是逐 token 预测 (比如先预测第一个字,再用第一个字预测第二个字,以此类推)。SFT Loss 用的是生成任务的「标配损失函数」------交叉熵损失(Cross-Entropy Loss),计算分 3 步走。
步骤1:准备 SFT 训练样本的格式
SFT 的训练数据必须是「结构化的」,标准格式是:
<指令> [SEP] <标准答案>
其中 [SEP] 是分隔符(区分指令和答案),模型训练时会被编码成特殊 token。
举个和你项目相关的例子:
指令:检测到人手进入侧身危险区域,请生成告警文本
标准答案:告警!人手进入侧身危险区域,存在安全风险,请立即处理
关键规则 :计算 Loss 时,只对「标准答案」部分的 token 计算,指令 + 分隔符部分的 token 全部「屏蔽」(不计算损失)。
步骤2:模型输出每个 token 的概率分布
把训练样本输入模型后,模型会对「标准答案」的每个位置,输出一个「全词表概率分布」:
- 假设模型的词表大小是 30000(常用量级),那么每个位置会输出 30000 个概率值,分别对应「这个位置是词表中第 1 个 token、第 2 个 token......第 30000 个 token」的概率;
- 这些概率值的总和是 1(满足概率分布的基本要求)。
比如「标准答案」的第一个 token 是「告」,模型输出的概率分布里,「告」这个 token 的概率是 0.8,其他 token 的概率加起来是 0.2。
步骤3:计算交叉熵损失(逐 token 计算,再平均)
交叉熵损失的核心思想是:对每个位置,计算「标准答案 token 的概率」的负对数,然后求和取平均。
单个 token 的 Loss 计算公式
对于标准答案的第 iii 个 token(记为 yiy_iyi),模型预测它的概率是 pip_ipi(pip_ipi 是模型输出的概率分布中,yiy_iyi 对应的概率值),那么这个 token 的 Loss 是:
lossi=−log(pi)loss_i = -log(p_i)lossi=−log(pi)
- 这个公式的直观意义:pip_ipi 越大(模型越确定这个位置是 yiy_iyi),lossiloss_ilossi 越小 ;
比如 pi=0.8p_i=0.8pi=0.8 → lossi=−log(0.8)≈0.223loss_i=-log(0.8)≈0.223lossi=−log(0.8)≈0.223;
比如 pi=0.1p_i=0.1pi=0.1 → lossi=−log(0.1)≈2.303loss_i=-log(0.1)≈2.303lossi=−log(0.1)≈2.303;
极端情况 pi=1p_i=1pi=1 → lossi=0loss_i=0lossi=0(完全预测正确)。
整个回答的总 Loss 计算公式
假设标准答案的 token 长度是 NNN,那么整个回答的平均 Loss 就是:
LSFT=1N∑i=1Nlossi=−1N∑i=1Nlog(pi)L_{SFT} = \frac{1}{N} \sum_{i=1}^N loss_i = -\frac{1}{N} \sum_{i=1}^N log(p_i)LSFT=N1i=1∑Nlossi=−N1i=1∑Nlog(pi)
举个极简例子
假设标准答案只有 2 个 token:「告警」,模型预测的概率分别是 p1=0.8p_1=0.8p1=0.8(「告」)、p2=0.7p_2=0.7p2=0.7(「警」)。
总 Loss = 12×(−log0.8−log0.7)≈12×(0.223+0.357)=0.29\frac{1}{2} \times (-log0.8 - log0.7) ≈ \frac{1}{2} \times (0.223 + 0.357) = 0.2921×(−log0.8−log0.7)≈21×(0.223+0.357)=0.29
三、进阶细节:SFT Loss 计算的关键技巧与注意事项
1. 「屏蔽指令部分」的实现:用 Mask 矩阵
实战中,我们不会手动区分指令和答案,而是用一个 Mask 矩阵(掩码矩阵)来标记「哪些位置需要计算 Loss」:
- Mask 矩阵是和输入序列等长的 0/1 向量;
- 指令 + 分隔符部分的 Mask 值为 0 → 计算 Loss 时跳过;
- 标准答案部分的 Mask 值为 1 → 计算 Loss 时保留。
比如输入序列的 token 索引是 [0,1,2,3,4,5],其中 0-2 是指令,3 是分隔符,4-5 是答案,那么 Mask 矩阵就是 [0,0,0,0,1,1]。
最终 Loss 计算公式会变成:
LSFT=−1∑i=1Mmaski∑i=1Mmaski×log(pi)L_{SFT} = -\frac{1}{\sum_{i=1}^M mask_i} \sum_{i=1}^M mask_i \times log(p_i)LSFT=−∑i=1Mmaski1i=1∑Mmaski×log(pi)
其中 MMM 是整个输入序列的长度,∑i=1Mmaski\sum_{i=1}^M mask_i∑i=1Mmaski 就是标准答案的 token 数 NNN。
2. 为什么不用 MSE(均方误差)?
有同学会问:为什么不用回归任务的 MSE 损失?
- 大模型的 token 预测是 「多分类任务」(每个位置从 3 万 token 里选 1 个),而 MSE 适合「连续值预测」;
- 交叉熵损失能直接衡量「概率分布的差距」,对多分类任务的优化效果远好于 MSE。
3. SFT Loss 的优化目标:让 Loss 稳步下降
训练过程中,我们通过 AdamW 等优化器,不断调整模型参数,让 SFT Loss 逐渐降低:
- 理想情况:训练 Loss 稳步下降,验证 Loss 也同步下降 → 模型在学懂任务;
- 过拟合情况:训练 Loss 持续下降,但验证 Loss 上升 → 模型「死记硬背」训练数据,泛化能力差;
- 欠拟合情况:训练 Loss 和验证 Loss 都很高 → 模型没学懂任务,需要调大学习率或增加训练数据。
4. 和 RLHF 的关系:SFT 是 RLHF 的第一步
SFT 是 RLHF(基于人类反馈的强化学习) 的基础:
- SFT 用「监督信号」(标准答案)训模型,Loss 是硬指标;
- RLHF 用「人类偏好」训模型,会在 SFT 的基础上,用奖励模型(RM)和强化学习(PPO)进一步优化。
四、实战补充:SFT Loss 计算的常见坑
- 坑1:忘记屏蔽指令部分 → 模型会浪费算力去拟合指令,导致回答任务的效果变差;
- 坑2:标签平滑(Label Smoothing) → 为了防止过拟合,可以给标准答案 token 的概率加一点「噪声」(比如把 1.0 改成 0.95),其他 token 分一点概率(比如 0.05/词表大小);
- 坑3:长序列截断 → 如果标准答案太长,超过模型的上下文窗口,需要截断,否则会报错,且 Loss 计算会失真。
五、总结
SFT Loss 的计算可以浓缩成 3 句话:
- 核心是 交叉熵损失,衡量模型预测 token 和标准答案 token 的概率差距;
- 关键是 只计算回答部分的 Loss,用 Mask 矩阵屏蔽指令和分隔符;
- 目标是 让训练 Loss 和验证 Loss 稳步下降,避免过拟合或欠拟合。