笔记七:大模型微调与高效训练——从 SFT 到 MoE 的完整指南

📅 2026/7/18 18:08:46 👁️ 阅读次数 📝 编程学习
笔记七:大模型微调与高效训练——从 SFT 到 MoE 的完整指南

目录

  • 第一部分:监督微调(SFT)与损失计算
    • 1.1 SFT 是什么?
    • 1.2 SFT 的损失是怎么计算的?(重点)
    • 1.3 预训练(CLM)和微调(SFT)的损失计算有什么区别?
    • 1.4 SFT 训练的最佳实践
  • 第二部分:LoRA 与参数高效微调
    • 2.1 为什么需要 LoRA?
    • 2.2 LoRA 的核心思想
    • 2.3 LoRA 的两个模块加在哪里?
    • 2.4 为什么只改 1% 的参数,影响却不小?
    • 2.5 为什么推理时要"吸收(合并)"LoRA?
    • 2.6 LoRA 的秩(Rank)怎么选?
    • 2.7 LoRA 的变种们
    • 2.8 QLoRA 和 DoRA 的区别
    • 2.9 QLoRA 的显存账单
  • 第三部分:混合专家模型(MoE)
    • 3.1 为什么需要 MoE?
    • 3.2 MoE 的架构拆解
    • 3.3 速度悖论
    • 3.4 负载均衡
    • 3.5 训练的核心谜团:TopK 不可导,路由器怎么学?
    • 3.6 著名的 MoE 模型
    • 3.7 总结:MoE 的优缺点

摘要:本文系统梳理了大模型训练中的三大核心主题:监督微调(SFT)的损失计算原理与最佳实践、参数高效微调方法 LoRA 及其变种的核心思想与选型指南,以及混合专家模型(MoE)的架构设计、训练谜团与工业界方案。文章以通俗易懂的比喻和手算示例,帮助读者从原理到实战全面理解这些关键技术。

第一部分:监督微调(SFT)与损失计算

1.1 SFT 是什么?

SFT(Supervised Fine-Tuning,监督微调),就是把一个已经会“文字接龙”的预训练大模型,调教成一个能听懂人话、按指令办事的智能助手。

  • 预训练模型:像个看过海量书籍的“书呆子”,只会根据上文猜下文(比如看到“今天天气真”,会接“好”)。
  • SFT 之后:变成了能回答问题的“助理”。你问它“今天天气怎么样?”,它能回答“今天天气晴朗,适合出游”。

这个过程需要给它看大量的“问题-标准答案”对,让它学习如何给出高质量的回答。

1.2 SFT 的损失是怎么计算的?(重点)

这是很多人的困惑:模型是一字一字地预测,那损失也是一字一字算的吗?

答案是:是的,数学上是“一字一字”算的,但显卡是“一眼”全看完一起算的(矩阵并行计算)。它的核心机制叫做“教师强制(Teacher Forcing)”

1.2.1 什么是“教师强制”?

在训练时,我们把“问题”和“答案”拼成一条完整的序列送进模型。模型会并行地预测每一个位置的下一个字。但关键点在于:模型预测时看到的“上文”,永远是正确的原文,而不是自己猜错的结果。

举个具体例子,我们要训练模型回答“我爱你”:

  • 训练数据:输入是 [我, 爱, 你]。
  • 模型内部计算
    • 看到 [我],预测下一个字是
    • 看到 [我, 爱],预测下一个字是

注意:在预测的时候,模型看到的输入是 [我, 爱],其中“爱”是数据里给的正确答案,而不是模型自己在第一步预测出来的结果(哪怕它第一步预测错了,算第二步时依然用正确的“爱”)。

打个比方:这就像老师给你做完形填空,句子是“我( )你”。

  • 训练时(Teacher Forcing):老师直接把正确答案“爱”写在括号里,让你看着“我爱”去填后面的“你”。就算你第一空填了“恨”,老师也会用板擦把“恨”擦掉,强行把“爱”写回去,再让你填第二空。
  • 推理时(生成答案):没有老师管你了,你第一空填了“恨”,第二空就只能基于“我恨”去填,所以会生成“我恨你”。
1.2.2 那损失到底怎么算?

我们用上一步的例子来手算一遍。

  1. 第一步:看位置 1(预测“爱”)
    • 模型根据输入的[我],预测下一个词。
    • 模型输出的原始分数(Logits)经过 Softmax 变成概率:概率(我)=0.4,概率(爱)=0.5,概率(你)=0.05,概率(EOS)=0.05
    • 计算这个位置的损失(负对数似然):Loss₁ = -log(概率_爱) = -log(0.5) ≈ 0.693
  2. 第二步:看位置 2(预测“你”)
    • 模型根据输入[我, 爱],预测下一个词。
    • 输出的概率:概率(我)=0.1,概率(爱)=0.2,概率(你)=0.6,概率(EOS)=0.1
    • 计算这个位置的损失:Loss₂ = -log(概率_你) = -log(0.6) ≈ 0.511
  3. 第三步:算出最终的 Loss
    • 因为答案长度是 2,所以总损失 = (Loss₁ + Loss₂) / 2 = (0.693 + 0.511) / 2 = 0.602
    • 这个 0.602,就是最终传回给模型、用来更新参数的那一个数字(标量)。
1.2.3 提示词(Prompt)有损失吗?

绝对没有!在 SFT 中,我们只计算“答案部分”的损失,提示词部分的标签会被设为 -100。PyTorch 的 CrossEntropyLoss 函数看到 -100 就会自动跳过,不计算损失,也不传回梯度。

打个比方:这就像老师改卷子,只改学生在答题卡上写的答案(Response),至于试卷上的题目(Prompt)本身写了什么,看都不看,更不会扣分,因为题目是本来就印在上面的!

1.3 预训练(CLM)和微调(SFT)的损失计算有什么区别?

对比维度预训练 (CLM)微调 (SFT)
数据长什么样连续的一段话:[A, B, C, D]拼凑的两段话:[问题, 答案]
标签(Label)设置[B, C, D, EOS](全是正常ID,没有-100)[-100, -100, 答案, 答案](问题部分挖掉,答案部分保留)
哪些位置算损失每个位置(除了开头的第一个字)只有“答案”部分的位置
学习目标学会预测任何一个下文单词(学语法、常识)只学会预测针对特定问题的回答(学指令跟随)

一句话总结:CLM 算所有位置,是因为全是正文;SFT 只算答案,是因为人为把前半段标记成了只读的“上下文”。

1.4 SFT 训练的最佳实践

1.4.1 数据质量:LIMA 原则

重质不重量:论文证明,1000 条极其精良的问答数据,训练效果能超过 5 万多条的粗糙数据。

好数据必须满足:

  • 多样性:涵盖问答、摘要、代码、数学、创意写作、多轮对话等。
  • 正确性:每个回答必须事实准确、格式规范。
  • 长度平衡