SFT 训练模式选择
在进行领域任务的监督微调(SFT)时,通常有以下几种训练模式可供选择。根据领域任务、领域样本情况及业务需求,选择合适的训练模式至关重要。
模式一: 基于 Base 模型 + 领域任务的 SFT; 模式二: 基于 Base 模型 + 领域数据 Continue Pre-train + 领域任务 SFT; 模式三: 基于 Base 模型 + 领域数据 Continue Pre-train + 通用任务 SFT + 领域任务 SFT; 模式四: 基于 Base 模型 + 领域数据 Continue Pre-train + 通用任务与领域任务混合 SFT; 模式五: 基于 Base 模型 + 领域数据 Continue Pre-train(混入 SFT 数据) + 通用任务与领域任务混合 SFT; 模式六: 基于 Chat 模型 + 领域任务 SFT; 模式七: 基于 Chat 模型 + 领域数据 Continue Pre-train + 领域任务 SFT。
a. 是否需要 Continue Pre-train
大模型的知识主要来自于预训练阶段。如果你的领域任务数据集与预训练的数据集差异较大(例如领域任务数据来自公司内部,预训练样本基本不可能覆盖到),则一定要进行 Continue Pre-train。 如果领域任务数据量较大(Token 在 1B 以上),且只追求领域任务的效果,不考虑通用能力,建议进行 Continue Pre-train。
b. 是选择 Chat 模型还是 Base 模型
如果有好的 Base 模型,在 Base 模型与在 Chat 模型上进行领域数据的 SFT,效果上差异不大。 基于 Chat 模型进行领域 SFT,很容易导致灾难性遗忘,在进行领域任务 SFT 之后,模型的通用能力会降低。如果只追求领域任务的效果,则不用考虑此问题。 如果领域任务与通用任务有很大的相关性,这种二阶段 SFT 会提升领域任务的效果。 如果既追求领域任务的效果,并且希望通用能力不下降,建议选择 Base 模型作为基座模型。 在 Base 模型上进行多任务混合训练时,需要关注各任务间的数据配比。
c. 其他情况的选择方案
在资源允许的情况下,如只考虑领域任务效果,我会选择模式二;在资源允许的情况下,如考虑模型综合能力,我会选择模式五;在资源不允许的情况下,我会考虑模式六。
SFT 训练参数设置
a. 学习率
学习率是非常重要的参数,如果设置不当,很容易让 SFT 模型效果变差。在 SFT 数据集不是特别大的情况下,建议设置较小学习率,一般 SFT 的学习率设置为 Pre-train 阶段学习率的 0.1 左右。如在 Pre-train 阶段的学习率为 9e-5,则 SFT 学习率设置为 9e-6。在 10 万 SFT 样本上,采用与 Pre-train 一样的学习率,发现 Loss 一直不收敛,在调低学习率至原来 0.1 之后,Loss 在两个 Epoch 之后就收敛。
b. Warmup Ratio
通常 Pre-train 训练的 Warmup Ratio 在 0.01~0.015 之间,Warmup Steps 在 2000 左右。在 SFT 的时候,建议使用更小的 Ratio,因为相较于 Pre-train,SFT 样本非常小,较小 Warmup Ratio 可以使模型收敛更平滑。但如果你的学习率设置较大,那可以增大你的 Warmup Ratio,两者呈正相关。
c. Epoch
Epoch 设置可以根据 Loss 收敛情况设置。如果 SFT 样本较少,可以设置较大 Epoch,在较小的 Epoch 上 Loss 会不收敛,指令都很难遵循。较大 Epoch 会容易导致过拟合,但过拟合要优于欠拟合。如果 SFT 样本数量较多,如在十万以上,一般 2 个 Epoch 即可收敛。
SFT 训练注意事项
- 如果 SFT 任务类型较多,可以尝试添加
_system_prompt,不同的任务使用不同的 System Prompt。 - 一个好的基座模型非常重要!模型的参数量也非常重要。
- 在 SFT 的时候,Loss 依然是你最重要的指标!一般在 SFT 过程中,Loss 会先升后降。
- 可以尝试多种模式训练方案,如在 Continue Pre-train 中添加 SFT 数据,在 SFT 数据中添加高质量的 Pre-train 数据。
关于微调的一些新尝试
- 全参数 SFT+LoRA 微调模式: 尝试将全参数 SFT 与 LoRA 进行结合。具体微调方式:前 10%-30% Step 采用全参数 SFT 的方式,后面的 Step 采用 LoRA 的方式。比单纯的 LoRA 更加稳定,比全部采用全量参数 SFT 更加节省资源。动机在于,通常大模型微调的时候,前面 Step 中模型参数变化最快,Loss 也是下降的最快,后面 Step 模型参数变化幅度越来越小,Loss 变化幅度变小,逐渐收敛。因此,可以在微调的最开始 Step 采用全参数 SFT,让模型能够尽快学习到指令,后面采用 LoRA 的方式,让模型能够更好地遵循指令。全参数 SFT 与 LoRA 训练 Step 配比,可以依据自己的 Tokens 来定。
- 尝试 LoRA 的升级版本: DoRA (Weight-Decomposed Low-Rank Adaptation)。目前还没有看出 DoRA 较 LoRA 的特别大的优势,后续还需做更多的实验进行观察。
垂直领域微调核心经验
本篇从基座模型选择、模型整体架构、数据设计、训练微调四个角度总结垂直领域大模型微调经验。
一、基座模型选择
推荐 BLOOMZ 模型系列使用了 PILE 语料库进行训练,该语料库包含各种医学文本,包括 PubMed Central 和 PubMed Abstracts 等。BLOOMZ 模型的医学知识体系比较丰富。
二、模型整体架构
- 不要指望一个单个垂直领域的 LLM 就可以满足所有需求,合理的做法可能是实时更新的知识库 + 微调的医疗 LLM。
- 超大参数模型(至少百亿)即使被量化其能力依然能保持较好。
三、数据设计
- 在 LLM 时代,需要牢记 数据质量 > 数量 这个真理。超大规模的 SFT 数据会让下游任务 LLM 减弱或者失去 ICL、CoT 等能力。
- 为防止灾难性遗忘,在算力充足情况下推荐使用医疗数据和通用语料数据进行训练,这样模型既可以有医学上的训练学习,也可以保持通用能力(如指令遵循)。
- 大量数据进行二次预训练需要配比各类型其他数据:
- 语言模型训练完成后,参数各个区域负责部分已经确定,如果大量增加某类在预训练时没有的知识,会造成参数的大幅度变化,造成整个语言模型能力损失。
- 进行大规模数据的二次预训练,需要添加 5-10 倍原始预训练中的数据,并打混后一起训练。
- 训练数据要严格控制噪音:
- 预训练数据中如果出现少量连续的噪音数据,比如连续重复单词、非单词序列等,都可能造成特定维度的调整,从而使得模型整体 PPL 大幅度波动。
- 有监督微调指令中如果有大量与原有大语言模型不匹配的指令片段,也可能造成模型调整特定维度,从而使得模型整体性能大幅度下降。
- 大模型混合多种能力数据微调时呈现:高资源冲突,低资源增益。所以混合不同数据进行微调需要一定的工程技巧,翻译总结一下就是:低资源但高质量,并结合不同领域需求进行配比。
- 对于静态数据集,在多轮训练中多次迭代可能效果不佳,会导致过拟合,使训练结果恶化。
- 对于静态数据集,想要让 LLM 强化成「全能选手」,在所有基线任务中都表现优异是不可能完成的。想要解决这个问题需要多样化的数据源,或者使用 LoRA 以外的技术。
四、训练微调
- 全流程的 LLM 训练包括:预训练、监督微调、奖励模型、强化学习,多数情况下监督微调即可满足自身需求。
- 对于垂类模型,更应该关注 PT 的过程,而不是采集千万百万的 SFT 数据做训练,一般建议是 大规模预训练 + 小规模监督微调 = 超强的 LLM 模型。
- 指令微调阶段不能够进行过多轮次训练:
- 针对少量数据进行多个 Epoch 的训练,可能会造成语言关键区域变化,从而导致整个模型失效。
- 为了特定任务提升的指令微调,为了保证模型语言能力关键区不被大幅度调整,需要添加通用指令微调数据或者预训练数据。
- 通常来说,使用 LoRA 的效果不如 Full-tuning(如 LoRA results in 4-6% lower performance compared to full fine-tuning)。
- 7B 系列模型请优先采用全参数微调方式(条件不满足就 P-tuning,动的参数越多效果通常会更好),13B 及以上参数模型可使用 LoRA、QLoRA 等方法。
- 如果要结合 LoRA,确保它在所有层上应用,而不仅仅是 Key 和 Value 矩阵中,这样才能最大限度地提升模型的性能。
- 虽然 LLM 训练(或者说在 GPU 上训练出的所有模型)有着不可避免的随机性,但多轮训练的结果仍非常一致。
- 如果受 GPU 内存的限制,QLoRA 提供了一种高性价比的折衷方案。它以运行时间增长 39% 的代价,节省了 33% 的内存。
- 在微调 LLM 时,优化器的选择不是影响结果的主要因素。无论是 AdamW、具有调度器 Scheduler 的 SGD,还是具有 Scheduler 的 AdamW,对结果的影响都微乎其微。
- 虽然 Adam 经常被认为是需要大量内存的优化器,因为它为每个模型参数引入了两个新参数,但这并不会显著影响 LLM 的峰值内存需求。这是因为大部分内存将被分配用于大型矩阵的乘法,而不是用来保留额外的参数。
- 调整 LoRA Rank 和选择合适的 Alpha 值至关重要,可以把 Alpha 值设置成 Rank 值的两倍。
SFT 实践落地问答
Q1: 常见 SFT 的开发流程是如何的?
第一步,根据业务场景调整提示词(Prompt):业务团队会提供具体场景,或者给出他们编写的 Prompt,也可能只提供场景和数据,需要算法工程师自行编写。编写优秀的 Prompt 对发挥模型的最大性能至关重要,一个出色的 Prompt 可能将性能提升至 80 分以上直接得到业务要求,而一个普通的 Prompt 可能只能得到 50 分。 个人经验:越详细越好,给到的定义越细越好;不要让模型理解任何歧义;遵循 System message, Input, Instruction 三段式;通过模型输出的解析调整 Prompt。 第二步,尝试闭源和开源,并进行对比:实测下来,确实不同的开源模型擅长点不一样。如果开源模型效果不佳,这时考虑闭源模型,以评估这闭源领先的 LLM 是否能解决这类场景问题。若业务接受闭源模型的效果和成本,则直接调 API 就好。若不接受,则需转向微调闭源模型。 第三步,认真准备数据集:选定最佳闭源模型后,精选数据集,通常每个子任务的数据量不应超过 1K 条,数据集必须包含任务的边界样本和困难样本,并确保数据的多样性和标签的平衡。 第四步,上线迭代:最后,进行训练、上线和持续地迭代优化,以确保模型性能不断提升并满足业务需求。
Q2: 训练数据要注重什么?
确保回答格式和风格的统一。经验是,训练数据的格式和风格越统一,越能最大限度地发挥模型在具体任务的效果上限。数据集既要包含难也要包含易,注意任务的多样性和标签的平衡。避免引入模型在预训练阶段未接触过的知识,以减少模型产生幻觉的风险。
Q3: 大 Size 和小 Size 模型的选择?
在效率和资源都达标和到位的情况上,优先用大 Size 的模型进行实验和微调,因为大 Size 的模型在容错性上比小 Size 的好太多。尽管大尺寸模型也可能存在多任务不稳定、标签不平衡等问题,但其表现通常会比小尺寸模型更为稳定。因此,选用大尺寸模型其实是节省了人力成本,避免了很多之后可能会遇到的各种坑。
Q4: 多任务训练时怎么确保每个任务都优秀?
任务的相互影响是一个普遍现象。有两种方法应对这种挑战:
- 不同任务独立训练模型:针对每个任务单独训练一个模型。当某个任务至关重要,且要求性能指标高度稳定时,这是不得不采用的方法。
- 任务取舍与额外训练:例如,在四个任务中,若其中两个任务尤为重要,可以在全部任务训练完毕后,对这两个关键任务额外训练多一个 Epoch。这种做法能最大程度地确保重要任务的效果。
Q5: SFT 真的不能学到知识?
经过一年的实践和普遍的认知,常识和世界知识难以通过 SFT 灌输给模型。SFT 更应该关注激发模型在预训练中已学到的知识、让模型学习业务所需要的特定规则、以及输出格式稳定。SFT 并不能学得常识、世界知识,但这并不意味着我们应该放弃 SFT。相反,我们应当关注 SFT 在以下方面:激发预训练知识、稳定格式输出、更遵循具体任务、学习业务逻辑。
Q6: 怎么科学挑选数据集?
众多论文均印证了 "Quality is all you need" 的观点。对于大部分业务场景,50 条~几百条数据足矣,本人倾向于让工程师与业务团队共同审核每条数据,并确保数据的多样性。数据挑选涉及几个场景:精简业务数据、筛选开源数据、探索训练集中哪些数据对具体的业务场景带来增益最大。
Q7: 怎么解决幻觉问题?
幻觉问题是影响业务精准度的一个重要因素。实际体验下来,不论开源还是闭源模型,都容易'过度联想'。目前,尚缺乏完美的解决方案,但可以考虑通过 SFT 或当积累更多相关场景数据后尝试运用强化学习方法来改善。
Q8: BERT 开发与 LLM 开发有什么不同之处?
相同点:标签不平衡问题、多任务平衡。不同点:开发体验差异(LLM 往往仅需标注 2~4 条数据即可解决 Bad Cases)、模型规模调整策略不同(LLM 效果达到预期时,反而考虑减小模型规模)。
Q9: 该选什么微调方法,Full tuning/P-tuning/Lora?
经过实际测试,发现在某些特定场景下,全量调优(Full Tuning)确实表现更佳,但优势并不明显。在数据量有限且应用场景不多的情况下,为了保持模型的泛化能力,LoRa 方法表现得最为稳定。考虑到泛化性,LoRa 已经足够应对大多数需求。DeepMind 的一篇研究指出,当数据量仅在几千条时,P-tuning 是最佳选择;数据量在几千至万条之间时,LoRa 更为适合;而当数据量达到百万级别时,Full-tuning 效果最佳。因此在大多数场景下,仍推荐使用 LoRa,因为稳定,效果不差,能尽可能保留模型原来的泛化性。
Q10: SFT 还有什么方面值得研究?
现在开源的 SFT 越来越完备了,SFT 需要做的东西越来越少,多做实验,快速迭代才是王道。重点方向包括:消除幻觉、精选数据集和任务配比、设置科学设计问答格式和 Data format、探寻更高效的微调技巧(如 LoRA+、PLora、PiSSA 等)。
生产环境微调建议
- 切勿微调: 尽量写 Prompt,利用大模型本身的能力 Zero-shot,必要时辅以 Few-shot examples 或 RAG。微调成本高、速度慢且复杂,仅在确实需要时才进行。
- 务必调调 Prompt: 用一个 Prompt 创建一个 Baseline,并通过写 Prompt 证明这个场景或者任务是可行的。如果 Prompt 不起作用,微调成功的可能性就很低。
- 好好搞数据: 如果必须微调,确保你完全理解你的数据。大力修正问题数据。数据质量直接决定模型质量。
- 用真实的数据: 确保训练数据尽可能接近生产环境中模型将处理的数据。同分布也是机器学习古老的训诫,在大模型微调中也是如此。
- 必须保留测试集: 始终保留一部分数据用于测试,以评估模型的性能。
- 必须选择合适的模型: 模型参数越多,训练就越昂贵且速度越慢。根据任务和预算选择适当的模型。规模和参数量要匹配任务难度。
- 必须小步快跑评估: 编写快速计算的评估指标,以便快速迭代。高频自动化评估,可以及时 Early Stop 和监控模型异常。
- 必须慢工细活评估: 花点时间编写更全面、更可靠的评估标准和评估指标,目的是为了更深入地了解模型的性能。
- 不要即发即弃: 不要执行一次性的模型训练后就结束。持续优化模型和 Pipeline。
- 别太认真: 不要死板地遵循这些建议。根据具体情形调整建议的适用性,拥抱变化。
领域模型训练技巧与思考
- 领域数据是关键: 领域技术标准文档或领域相关数据是领域模型 Continue Pre-train 的关键。现有大模型在预训练过程中都会加入书籍、论文等数据,那么在领域预训练时这两种数据其实也是必不可少的,主要是因为这些数据的数据质量较高、领域强相关、知识覆盖率大。
- 缓解遗忘: 领域数据训练后,往往通用能力会有所下降,需要混合通用数据以缓解模型遗忘通用能力。目前还没有一个准确的答案,个人感觉应该跟领域数据量有关,当数据量没有那么多时,一般数据比例在 1:5 到 1:10 之间是比较合适的。
- MIP 策略: 领域模型 Continue Pre-train 时可以同步加入 SFT 数据,即 MIP (Multi-Task Instruction Pre-training)。预训练过程中,可以加下游 SFT 的数据,可以让模型在预训练过程中就学习到更多的知识。
- 资源与模型选择: 仅用 SFT 做领域模型时,资源有限就用在 Chat 模型基础上训练,资源充足就在 Base 模型上训练。如果你只有 5k 数据,建议你在 Chat 模型上进行微调;如果你有 10w 数据,建议你在 Base 模型上进行微调。
- 遵循原有格式: 在 Chat 模型上进行 SFT 时,请一定遵循 Chat 模型原有的系统指令 & 数据输入格式。否则当你数据量不足时,可能会导致训练效果不明显。并且建议不采用全量参数训练,否则模型原始能力会遗忘较多。
- 评测集建设: 领域评测集是必要内容,建议有两份,一份选择题形式自动评测、一份开放形式人工评测。一定要有自己的领域数据集来验证模型效果,来选择最好的 Checkpoint。
- 词表扩增: 领域模型词表扩增是不是有必要的?个人感觉,领域词表扩增真实解决的问题是解码效率的问题,给模型效果带来的提升可能不会有很大。
- 未来趋势: 所谓的领域大模型会更新的越来越快,越来越多。由于很多人&公司并没有资源搞底座,因此需要在现有底座模型上进行增量预训练、微调等。而以目前各厂抢占开源社区占比的架势,感觉会有很多 7B、13B 级别模型开源。
总结
大模型微调是一项系统工程,涉及基座选择、数据清洗、训练策略及评估体系。核心原则在于平衡领域能力与通用能力,重视数据质量而非单纯数量,并根据资源约束灵活选择微调方法(Full/LoRA/QLoRA)。在生产环境中,应坚持 Prompt 优先策略,仅在必要时进行微调,并建立完善的自动化评估与持续迭代机制,以确保模型在实际业务中的稳定性与有效性。


