大模型SFT 22条实践经验,干活效率翻倍!

 Datawhale干货 

作者:王宸,编辑:丁师兄大模型

作者:王宸

知乎:https://zhuanlan.zhihu.com/p/49398269658

这个总结参考很多资料,也加了一些实践经验。

本文参考资料主要如下:

LLM训练-sft:https://zhuanlan.zhihu.com/p/809229182sft 的局限性:https://zhuanlan.zhihu.com/p/717275921大模型Pretrain和SFT阶段的Loss分析:https://zhuanlan.zhihu.com/p/652657011

01

为什么会有 SFT?

预训练、SFT、RLHF 是大模型的标配。

预训练让大模型获得了通用能力,SFT 让大模型提升了某个特定领域的能力,RLHF 则是让大模型的输出和人类意图对齐和接近。

02

SFT 和预训练的区别是什么?

预训练是让大模型获得通用能力,SFT 是为了提升大模型在特定领域的能力。

03

SFT 和 RLHF 的区别是什么?

第一,SFT 是为了提升大模型特定领域的能力,RLHF 则是为了让大模型的输出和人类意图接近,尤其是在 z 教、z 治、道德等方面进行一定的约束。

SFT 在预训练的基础上增强了模型在特定领域的表达能力, RLHF 则约束了模型的表达。

第二,SFT 是监督学习,RLHF 是强化学习。监督学习的上限是老师,而强化学习可以通过学习经验超越老师。

第三,SFT 给大模型提供正向反馈,而 RLHF 可以给大模型提供负反馈。

SFT 并没有告诉模型说,我不想要什么答案,只有我想要什么答案,这个时候就需要 RLHF 进行纠错,打造一个尽量不出错的领域大模型。

第四,训练优化方式不同。前者通过 loss 函数来对 token 进行优化和反向传播,每一个 token 相同的贡献,而后者可以对整个语句进行优化和反向传播。

04

SFT 和 RAG 的区别是什么?

第一,SFT 是通过一定量的监督训练数据提升大模型特定领域的能力,RAG 是指通用大模型本身没有特定领域的能力,但通过检索资料提升特定领域的能力。

第二,RAG 只能提取只是表层的特征,微调能够让模型的底层认知真正的去对齐行业领域。

第三,从应用场景角度:RAG 是外挂一个知识库,适合动态数据、相比于微调在处理幻觉、可解释性高、通用能力更强。

微调适合给模型定制能力、延迟低、但会造成模型遗忘。从实现的难易程度而言:promopt>RAG>微调。

05

SFT 和 continue-pretrain 区别是什么?

第一,从目的角度:SFT 是为了提升或者激发通用大模型在特定领域或某个 task 的能力。

而 continue-pretrain 是为了解决应用场景需求能力与通用大模型能力不匹配的问题,即基础模型支持的 domain 和要解决的 domain 差异很大,这个时候要考虑增量预训练。

第二,从流程角度:continue-pretrain 在 pretrain 之后,在 SFT 之前。

第三,从训练数据量角度:增量预训练所需要的数据略少于 pretrain,但远远大于 SFT 所需要的数据,99% 的情况下通常不会使用增量预训练。

06

SFT 和 in-context learning 的区别是什么?

In-context learning 目的是通过一个或者几个例子激发大模型对任务的能力(也就是 prompt)。

In-context learning 在 GPT3 论文中提出,并不会修改模型的参数和梯度,不参与反向传播过程。

07

SFT 和 LoRA、PEFT 区别是什么?

SFT 通常是指全参数微调,优点是精度上限更高,缺点是在训练过程中对计算资源和存储资源的需求高、容易产生过拟合、遗忘和幻觉。

PEFT 是一种微调方法的总称,主要包括 Prefix Tuning(在模型输入层添加可训练的前缀嵌入),LoRA(通过低秩矩阵近似模型参数更新),以及 Adapter Tuning(在模型层间插入小型神经网络 adapters)。

LoRA 是 PEFT 的一种,模型的参数不变,但对模型中在每个线性层引入额外的低秩矩阵进行参数微调。

优点是降低 SFT 过程对硬件内存的消耗(省内存),缺点是精度上限低于全量参数微调。

此外,模型部分参数微调部分参数冻结也是微调的一种方式,目前应用较少。

08

SFT 有哪些分类?

第一,按照任务不同可以划分为:对话任务、分类任务、相似性判定任务等。

第二,按照模型参数是否变化可以分为:

  • 全部参数微调,这也是大公司日常使用最多的方案。

  • PEFT 微调。包括 LoRA,Adapter 等。摘抄:在实际工作中几乎没用过 lora,身边同事也不怎么用。

  • 部分模型参数冻结部分模型参数微调。

09

SFT 的前提条件是什么?

共有 3 个基础条件,第一是选择基座模型,第二是微调数据,第三是微调环境。

微调基座模型可以直接从 modelscope 网站下载。

微调数据主要包括-特定的模型输入格式、数据数量、数据质量等。

微调环境主要包括-微调硬件、微调软件、微调工具等。

训练工具包括:Megatron-LM、Deepspeed、Accelerate、Unsloth。

LLaMA-Factory 是一个开源平台,是一个比较完善的微调工具,提供便捷的大型语言模型微调环境。

hugging face transformers 是一个开源的 Python 库,提供了数以千计的预训练 transformer 模型。

DeepSpeed 训练框架通过将模型参数拆散分布到各个 GPU 上,可以利用更少的硬件资源训练更大的模型,不再受限于单个 GPU 的显存限制。

Unsloth 是一款开源的大语言模型(LLM)微调工具,基于优化计算步骤和 GPU 内核,显著提升模型训练速度并减少内存使用。 

注意环境依赖,不要造成版本冲突。

硬件环境包括:GPU、CPU、内存、存储、操作系统、cuda 等。

10

如何选择 SFT 的基座模型?

第一,选择 base 模型还是 chat 模型作为 SFT 基座?

Base 模型提供了基本的语言理解和生成能力,而 Chat 模型通过指令微调和人工反馈强化学习等方法,使模型更加符合人类的价值观和指令要求。

一般情况下选择 chat 模型为微调基座,因为 base 模型还没有指令遵循或对话能力。

第二,基座模型选择大模型还是小模型?例如 Qwen3-235B 或 0.6B。取决于应用场景,对于单一任务来说,小模型已经够用。

第三,modelscope 社区一般会给出 3 种类型的模型,第一种是预训练模型,第二种有 chat 能力的微调模型,第三种是在 chat 能力基础上的量化模型(量化模型通俗来说就是把大模型中某些层参数由 float16 变为 int8 等)以节省显存。

11

SFT 的训练数据集如何构建?

第一,对于不同的微调任务和微调基座模型,生成特定输入格式的数据。

通常,微调任务主要包括根据指令简单对话,根据指令实现上下文对话(更加关注上下文的逻辑与联系)这两种。

目前被大家广泛使用的是两种微调数据格式为 Alpaca(JSON 结构)和 share GPT,前者使用较多,后者更加关注长对话。

微调数据中的 COT 更加适用的场景是-数学、证明等需要逻辑推理的场景,而 COT 数据通常包括 question、COT、Answer 这三个部分。多轮对话通常在最后一轮问答时使用思维链。

第二,微调数据获得方式主要包括人工生成,人工和大模型协助(RAG 或大模型 prompt)生成两种。

摘抄:要想尽各种办法去扩充 prompt 的任务多样性和表达方式多样性,甚至去刻意加一些 noisy prompt 去提升抗噪性。

摘抄:选一个默认的 json 格式:带不带 markdown,indent 设置成几,是否输出在一行,然后把 sft 中所有涉及到的 json 数据全部清洗成这种格式。

第三,获得高质量的微调训练数据是 SFT 的核心。作为 SFT 从业者,日常 95% 以上的时间就是生产数据、分析数据、清洗数据。

摘抄:这段时间天天 sft,怎么整都提不了效果,最后老老实实用规则+人工把数据一条条洗一遍,模型才终于稳定了。特别是复杂推理任务,数据里 answer 有 conflict 的点的话,模型经常学疯。

第四,Instructions 这个一定要给出,让大模型明确自身的定位。input 可以不给,模型也可以直接通过 instructions 给输出。

12

SFT 需要多少数据量?

2K-10W,当然要具体任务具体分析。

摘抄:通常情况下,仅需约“一万份样本”便足以达成理想的微调成果。

这一理念在 Meta 发布的《LIMA: Less Is More for Alignment》论文中得到了有力阐述,该文献强调了在指令微调过程中,高品质微调数据的决定性作用。

据此,我们应当将重心放在提升样本质量的打磨上,而非单纯追求数量的增长。

13

如何评价 SFT 训练数据集的质量?

有多个维度,包括样本多样性、答案质量、回答一致性等多项指标。

14

SFT 过程对硬件有什么要求?

第一,微调大模型需要多少显存?训练过程中的显存取决于:模型参数、梯度、优化器、中间激活变量,主要显存消耗在前三个。

经验来说,显存大概是模型参数量的 12 倍,例如模型是 1B,总共显存占用 12GB。

第二,V100 不支持 flash attention。

第三,V100 不支持 bf16,但支持 GPTQ 模型和 FP8。V100 不支持 fp16,但是可以通过修改 config.json 中的 dtype 将 bf16 变为 float32 或 float16。

第四,对于 LORA 微调而言,train 和 test 代码不同。在 test 时候,因为保存的 checkpoint 只有 linear 层,需要先把模型合并到一起。

第五,一般情况下 GPTQ 模型可以用来微调,但是不能全参数微调,必须和 PEFT 一起使用。

尽量不要使用量化后的模型进行 SFT,因为 LORA 是 float16,而量化后的模型不一定是 float16,这样串联在一起是有问题的。

例如,GPTQ 是 mixed int4/fp16,其中激活函数是 fp16,GPTQ 的模型没法和 LORA 层合并,因为 LORA 层都是 fp16 的。

15

SFT 训练过程是什么样?

第一,从 loss 角度,随着 steps 增加,train loss 先急剧下降,而后平缓;evl loss 先急剧下降,而后上升(过拟合)。

第二,为什么 SFT 通常在 epoch=2 时突然 loss 急剧降低?大模型参数量很大,在第一个 epoch 基本记住了整个训练集,所以在第二个 epoch 会突然下降,出现过拟合现象。

第三,摘抄:训 10 个 epoch,如果某些 case 还学不会,说明模型的能力就是不够。

16

SFT 过程如何调参?

关于 checkpoint 的选择:在欠拟合和过拟合之间找到临界点。

learning rate 一般设置为预训练阶段的 0.1 倍。小模型大学习率,大模型小学习率。降低学习率某种程度上可以缓解过拟合。

epoch 和数据量成反比,数据量越大,epoch 个数越少。较大的 epoch 会造成过拟合,epoch 基本上就是 1~3 个。

batchsize 主要取决于使用的硬件内存。

起始训练适当做点 warmup,几种主流的 lr_scheduler 可以都试一下。

gradient_accumulation_steps -16 / 32 / 64 / 128 等数字都可以尝试下(梯度累加就是,每次获取 1 个 batch 的数据,计算 1 次梯度,梯度不清空,不断累加,累加一定次数后,根据累加的梯度更新网络参数,然后清空梯度,进行下一次循环)。

按需求决定是否使用 dropout。

17

如何评价 SFT 之后的效果?

对于模型效果的评估,我们可以用客观+主观的标准来衡量。

主观的标准是根据自己对产品的预期,确定预期目标效果的评估框架。

客观的评价就是 loss 曲线。

18

SFT 有哪些不良后果?如何避免?

第一,过拟合现象,模型的特定领域能力增加,通用能力会降低。如何缓解 SFT 后模型通用能力的下降?

使用数据配比(增加一些通用生成的数据),也可以考虑PEFT的方法、学习率调整、正则化技术。

第二,出现大模型幻觉。什么是大模型幻觉?大模型乱说,上下文矛盾,prompt 与事实矛盾,荒谬的回复等。

为什么产生幻觉?数据存在噪声,用于训练的数据单一,过拟合,泛化能力弱。

19

如何评估 SFT 的推理耗时?

摘抄:模型的预测时间可以近似理解为:k*x+b,其中 b 是首个 token 的耗时,k 是后续每个 token 的耗时,x 是生成 token 的总数量。

更具体的,b 会是 k 的十几倍或更多,和 prompt 的长度几乎呈正相关。这个耗时的近似估算和 KV_cache 机制有关,不熟悉的可以自行搜索。

这也就是为什么众人都知 cot 效果好,众人又都不使用 cot,因为我们可以几乎下断言“模型的生成速度和生成 token 数量呈正相关”,而 cot 恰恰又引入了大量的生成 token。

20

什么是 SFT packing?

SFT packing 指的是在训练 sft 的过程中,将多个 sft 数据 pack 到一个样本内进行训练的方式,这种方式会加快模型训练速度。

如果不进行 SFT packing,那么对于短文本 sft,需要 padding 到一个 batch 的最长长度,会浪费很多计算 token。

优点:充分利用 GPU 算力。

缺点:不利于短文本和多轮对话,一般情况下不建议使用。

21

一句话形容 SFT 的原理?

预训练是 next token prediction 的自监督学习,SFT 是 next token prediction 的监督学习,二者的反馈粒度都是 token。

SFT 像是在背书,一般不存在学不会,只存在不会泛化。

22

代码部分

第一,大模型 model 和分词器 tokenizer 是配套的。

第二,最终结果的输出,可以启用思考的模式,也可以不使用思考的模式。要启用思考模式,您可以通过设置 enable_thinking 参数来实现。

在 Qwen3 模型中,您可以通过调用 tokenizer.apply_chat_template() 方法,并将 enable_thinking 参数设置为 True 来启用思考模式。

第三,模型加载代码:

import torchfrom transformers import AutoModelForCausalLM, AutoTokenizermodel_path = "./Mistral-7B-Instruct-v0.3-GPTQ-4bit"tokenizer = AutoTokenizer.from_pretrained(model_path,trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(    model_path,    torch_dtype="auto",      device_map="auto" ,       trust_remote_code=False,     cache_dir = "./model",     load_in_4bit=True )

第四,推理代码:

input_text = "Hello, World!"input_ids = tokenizer.encode(input_text,return_tensors="pt").to(model.device)with torch.no_grad():    output_ids = model.generate(        input_ids=input_ids,        max_length=50,    )output_text = tokenizer.decode(output_ids[0], skip_special_tokens=True)

第五,微调训练代码。

有两种常用的方式,一种是 transformers 中的 TrainingArguments 和 Trainer,另一种是 TRL 库中的 SFTTrainer。

from transformers import AutoTokenizer,TrainingArguments,Trainer

training_args = TrainingArguments(    output_dir='./results',              overwrite_output_dir=True,           evaluation_strategy="steps",    num_train_epochs=3,                  per_device_train_batch_size=8,       per_device_eval_batch_size=1,       save_steps=1000,                    eval_steps=100,    save_total_limit=2,          run_name="Qwen3-0.5B",     save_on_each_node = True,    logging_steps = 10,    gradient_checkpointing=True,    gradient_accumulation_steps=4,#batch size大小等于per_device_train_batch_size * gradient_accumulation_steps    learning_rate=1e-4,    weight_decay = 0,    max_steps=1000, #覆盖num_train_epochs。    lr_scheduler_type = "linear",)trainer = Trainer(    model=model,                            args=training_args,                    train_dataset=inputs_ids,                eval_dataset=inputs_ids,                 tokenizer=tokenizer,             )trainer.train()

第六,tokenizer.eos_token 一定要给出,否则大模型不知道什么时候结束。

EOS token 一定要加在文字的末尾。

图片

一起“赞”三连

课程设计报告:总体方案设计说明 一、软件开发环境配置 本系统采用C++作为核心编程语言,结合Qt 5.12.7框架进行图形用户界面开发。数据库管理系统选用MySQL,用于存储用户数据与小精灵信息。集成开发环境为Qt Creator,操作系统平台为Windows 10。 二、窗口界面架构设计 系统界面由多个功能模块构成,各模块职责明确,具体如下: 1. 起始界面模块(Widget) 作为应用程序的入口界面,提供初始导航功能。 2. 身份验证模块(Login) 负责处理用户登录与账户注册流程,实现身份认证机制。 3. 游戏主大厅模块(Lobby) 作为用户登录后的核心交互区域,集成各项功能入口。 4. 资源管理模块(BagWidget) 展示用户持有的全部小精灵资产,提供可视化资源管理界面。 5. 精灵详情模块(SpiritInfo) 呈现选定小精灵的完整属性数据与状态信息。 6. 用户名录模块(UserList) 系统内所有注册用户的基本信息列表展示界面。 7. 个人资料模块(UserInfo) 显示当前用户的详细账户资料与历史数据统计。 8. 服务器精灵选择模块(Choose) 对战准备阶段,从服务器可用精灵池中选取参战单位的专用界面。 9. 玩家精灵选择模块(Choose2) 对战准备阶段,从玩家自有精灵库中筛选参战单位的操作界面。 10. 对战演算模块(FightWidget) 实时模拟精灵对战过程,动态呈现战斗动画与状态变化。 11. 对战结算模块(ResultWidget) 对战结束后,系统生成并展示战斗结果报告与数据统计。 各模块通过统一的事件驱动机制实现数据通信与状态同步,确保系统功能的连贯性与数据一致性。界面布局遵循模块化设计原则,采用响应式视觉方案适配不同显示环境。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值