关于微调
1. 微调到底在做什么 微调,本质上是让一个已经具备通用能力的预训练模型,在你的特定任务、特定语料、特定风格上进一步适配。常见目标包括:指令跟随、领域问答、分类抽取、代码补全、对话风格迁移、推荐理由生成等。完整训练通常成本极高,所以现在主流实践多用 PEFT(参数高效微调),也就是只训练一小部分附加参数,而不是改动全…
作者:lh
1. 微调到底在做什么
微调,本质上是让一个已经具备通用能力的预训练模型,在你的特定任务、特定语料、特定风格上进一步适配。常见目标包括:指令跟随、领域问答、分类抽取、代码补全、对话风格迁移、推荐理由生成等。完整训练通常成本极高,所以现在主流实践多用 PEFT(参数高效微调),也就是只训练一小部分附加参数,而不是改动全部模型权重。Hugging Face 的 PEFT 文档把 LoRA 这类方法作为重点推荐方案之一。
从训练方式上看,常见分为三类:
全参数微调:更新全部模型参数,效果上限高,但显存、算力、存储成本最大。
LoRA 微调:在部分线性层插入低秩矩阵,只训练新增参数,速度快、显存省、最常用。
QLoRA 微调:在 LoRA 的基础上,把底座模型以 4-bit 量化后加载,再训练 LoRA Adapter,显存占用进一步下降,适合单卡或小显存环境。QLoRA 的核心思想就是“冻结量化后的底模,只回传梯度到 LoRA 层”。
2. 什么时候选全参、LoRA、QLoRA
如果你追求最高上限,并且有足够显存,比如多张 80GB 卡,数据质量也很高,可以考虑全参数微调。但在大多数工程里,LoRA / QLoRA 才是性价比最高的方案。PEFT 文档明确说明,LoRA 通过低秩分解减少可训练参数,从而显著降低训练成本。
经验上可以这样选:
选 LoRA:
-
你有较充足显存
-
希望训练更稳定
-
不想引入量化带来的额外兼容性问题
-
底模规模不算特别大,比如 7B / 8B / 14B
选 QLoRA:
-
显存紧张
-
需要在 24GB / 32GB / 48GB 卡上训更大模型
-
接受训练与推理链路更复杂一些
-
希望先快速验证数据和方案
选全参:
-
你要做深度领域改造
-
数据规模足够大
-
显存资源很充足
-
你能接受长时间训练、检查点更大、运维更重
LLaMA-Factory 官方示例也把 LoRA、QLoRA、Full-Parameter Fine-Tuning 分开作为主要训练路径。
3. 微调全流程
一个标准的微调流程通常是:
任务定义 → 数据整理 → 选择微调方式 → 配置训练参数 → 启动训练 → 评估 → 合并/部署 → 回归测试
Transformers 的训练文档和 Trainer 文档都强调,训练是围绕 TrainingArguments 和训练循环展开的,核心在于你如何设置 batch、学习率、混合精度、梯度累积、保存策略与评估策略。
你可以把整个过程理解成三层:
第一层:业务层
你到底想让模型学什么?
比如:
-
根据用户画像推荐课程
-
根据金融行为生成商品推荐理由
-
根据领域语料回答专业问题
-
把原始文本转结构化 JSON
第二层:数据层
你给模型什么样的监督信号?
比如:
-
instruction / input / output
-
messages 对话格式
-
system + user + assistant
-
带负样本的偏好数据
-
pairwise preference 数据
第三层:训练层
你如何控制训练过程?
比如:
-
学习率多大
-
训练几轮
-
每卡 batch 多大
-
是否开启 LoRA / QLoRA
-
是否用 bf16 / fp16
-
是否多卡
-
是否 deepspeed / fsdp
4. 常见微调任务类型
4.1 SFT(监督微调)
这是最常见的。你给模型“输入 → 标准输出”,让它学会按你的格式回答。
适用于:
-
问答
-
摘要
-
信息抽取
-
分类
-
生成推荐理由
-
生成学习路径
-
JSON 输出任务
如果你当前是在做“用户画像 + 候选课程 + 推荐理由 + 学习规划”,本质上最常用的就是 SFT。
4.2 DPO / PPO / RLHF
这是偏好优化路线。先有一个基础 SFT 模型,再通过人类偏好或奖励信号,让模型更符合“更好答案”的分布。
LLaMA-Factory 也支持这类训练模式,但工程复杂度明显高于 SFT。
4.3 Continued Pretraining
也叫继续预训练,适合你有大量领域原始语料,想先提升模型的领域语言建模能力,再做 SFT。这个更偏“补领域知识”。
5. 数据格式怎么设计
对于指令微调,最常见的是以下几种格式:
5.1 Alpaca 风格
{
"instruction": "根据用户画像推荐课程",
"input": "用户最近关注趋势交易,偏好中级课程,近30天浏览过技术分析内容",
"output": "推荐课程:XXX。理由:..."
}
5.2 ChatML / messages 风格
{
"messages": [
{"role": "system", "content": "你是一名金融课程推荐助手。"},
{"role": "user", "content": "根据以下画像推荐课程:..."},
{"role": "assistant", "content": "推荐课程如下:..."}
]
}
如果你的底模原生就是对话模型,通常更推荐 messages 风格,因为这和模型预训练/指令训练阶段更一致。不同模型有各自的对话模板,LLaMA-Factory 会根据模型模板进行适配。
5.3 结构化 JSON 输出
如果你希望模型输出稳定字段,建议在 output 中直接放严格 JSON。例如:
{
"recommended_courses": [
{
"goods_id": 1309,
"course_name": "趋势交易实战",
"reason": "与用户近30天兴趣方向高度匹配"
}
],
"learning_plan": [
"先学习K线基础",
"再学习趋势识别"
]
}
这类任务在训练时要特别注意:
-
标签格式必须统一
-
尽量不要同一任务混多种输出风格
-
所有字段名固定
-
空值也统一表示
-
不要一部分样本输出中文键,一部分输出英文键
6. 核心训练参数怎么理解
下面是最关键的一部分。
6.1 学习率 learning_rate
这是最重要的参数之一,决定每次参数更新的步长。Transformers 的训练接口把它作为核心训练参数。
经验值:
LoRA / QLoRA 常见起点:
-
1e-4 -
5e-5 -
2e-5
一般来说:
-
数据量小、怕过拟合:学习率小一点
-
数据量大、任务明确:可以适当大一点
-
LoRA 通常可以比全参用更大的学习率
-
全参微调一般更保守
实战建议:
-
先用
5e-5或1e-4做首轮试验 -
如果 loss 震荡很大,就降到
2e-5 -
如果 loss 降得很慢,可以适当增大
6.2 训练轮数 num_train_epochs
表示整个数据集要过几遍。
经验上:
-
小数据集:
3 ~ 10 -
中等规模:
2 ~ 5 -
很大数据集:
1 ~ 3
不要迷信轮数越大越好。很多时候,高质量数据 + 合适学习率 + 合理步数 比盲目加 epoch 更重要。
6.3 每卡 batch 大小 per_device_train_batch_size
这是每张 GPU 一次前向/反向处理的样本数。Transformers 的 TrainingArguments 中将它作为最基本的吞吐参数之一。
受显存影响很大。大模型训练常见是:
-
1
-
2
-
4
-
8
如果显存不够,就把它调小。
6.4 梯度累积 gradient_accumulation_steps
当单卡 batch 太小但你又想模拟更大总 batch 时,就用这个参数。
等效总 batch 公式大致是:
effective_batch_size
= per_device_train_batch_size × gradient_accumulation_steps × GPU数量
例如:
2 × 8 × 4 = 64
这表示 4 卡训练时,总等效 batch 约为 64。
6.5 最大序列长度 cutoff_len / max_seq_length
这个参数非常关键。它决定一次送进模型的 token 上限。
长度越大:
-
能容纳更长上下文
-
显存占用越高
-
训练速度越慢
长度越小:
-
显存省
-
训练快
-
可能截断有效信息
经验上:
-
短任务:512 / 1024
-
一般问答:1024 / 2048
-
长上下文:4096 甚至更高
如果你的输入里塞了“用户画像 + 候选课程池 + 历史行为 + 输出理由”,很容易爆长度,所以一定要先做 token 长度统计。
6.6 调度器 lr_scheduler_type
学习率调度器控制学习率如何变化。Trainer 文档支持多种调度方式。
常用:
-
cosine -
linear -
constant_with_warmup
多数 SFT 实战里:
-
cosine很常见 -
或者
constant_with_warmup
6.7 预热比例 warmup_ratio
训练开始时先用较小学习率热启动,再逐渐升高到目标学习率,有助于稳定训练。
常见:
-
0.03 -
0.05 -
0.1
如果数据少、模型大,适当 warmup 往往更稳。
6.8 混合精度 fp16 / bf16
Trainer 支持混合精度训练。
一般建议:
-
优先
bf16,如果硬件支持 -
不支持时再用
fp16
原因通常是 bf16 更稳,不容易数值溢出。
6.9 日志、保存、评估步数
常见参数:
-
logging_steps -
save_steps -
eval_steps -
save_strategy -
evaluation_strategy
建议:
-
小数据集:步数设置小一些,方便及时观察
-
大数据集:步数设置大一些,减少 I/O 压力
例如:
logging_steps: 10
save_steps: 200
eval_steps: 200
7. LoRA 关键参数详解
PEFT 文档说明,LoRA 的核心是给目标层增加低秩适配矩阵。最关键的几个参数是 r、lora_alpha、lora_dropout 和 target_modules。
7.1 lora_rank / r
表示低秩矩阵的秩。越大,表达能力越强,但参数量和显存也会增加。
常见值:
-
8
-
16
-
32
-
64
经验建议:
-
小规模试验:8 / 16
-
稍复杂任务:16 / 32
-
高要求任务:32 / 64
通常 16 是一个很稳的起点。
7.2 lora_alpha
LoRA 的缩放系数,常和 r 配合。
常见值:
-
16
-
32
-
64
经验上常见搭配:
-
r=8, alpha=16 -
r=16, alpha=32 -
r=32, alpha=64
7.3 lora_dropout
LoRA 层 dropout,用来减轻过拟合。
常见值:
-
0 -
0.05 -
0.1
如果数据量小、风格重复,建议 0.05 左右。
7.4 target_modules
指定把 LoRA 挂到哪些层上。PEFT 支持对目标模块进行配置。
LLM 中常见目标模块:
-
q_proj -
k_proj -
v_proj -
o_proj -
up_proj -
down_proj -
gate_proj
保守方案通常先只训注意力相关层;想提升能力再扩大到 MLP 层。
8. QLoRA 关键参数详解
QLoRA 建立在 4-bit 量化加载之上。bitsandbytes 文档明确支持 4-bit / 8-bit 量化,Transformers 文档也把 bitsandbytes 作为 4-bit / 8-bit 量化的主要路径。
常见关键项:
8.1 quantization_bit=4
表示底模用 4-bit 加载。
8.2 bnb_4bit_compute_dtype
通常选:
-
float16 -
bfloat16
如果硬件支持,优先 bfloat16 更稳。
8.3 bnb_4bit_quant_type
常见是:
-
nf4
QLoRA 论文和相关实现中,NF4 是非常常见的选择。
8.4 double quantization
有些实现会启用双重量化以进一步节省显存,这也是 QLoRA 方案中的经典配置之一。
9. 工具链怎么选
9.1 Transformers
这是 Hugging Face 的基础训练框架,提供 Trainer 和模型加载、tokenizer、数据处理等能力,是底层通用工具。
适合:
-
自己写训练代码
-
灵活控制数据流程
-
自定义 loss、评估逻辑、回调
9.2 PEFT
这是 LoRA、AdaLoRA 等 PEFT 方法的核心库。要做 LoRA 训练,几乎绕不开它。
适合:
-
想轻量微调
-
想快速集成 LoRA
-
想后续合并 Adapter
9.3 bitsandbytes
主要用于 8-bit / 4-bit 量化加载,是 QLoRA 的关键依赖之一。
适合:
-
显存不够
-
想训更大模型
-
做 QLoRA
9.4 LLaMA-Factory
这是目前非常实用的一站式微调工具,直接支持 LoRA、QLoRA、Full、DPO 等模式,并提供 CLI、WebUI、示例 YAML 和推理/合并流程。官方 examples 里明确给出了 LoRA、QLoRA、全参训练以及 LoRA 合并与推理示例。
适合:
-
你想快速起训
-
不想自己从零写 Trainer 代码
-
要频繁试参数
-
要多模型、多格式、多训练方式切换
这也是目前最贴合你使用习惯的一套。
10. LLaMA-Factory 怎么用
LLaMA-Factory 官方示例说明,最基础的训练方式就是:
它也说明可以通过环境变量控制使用哪些设备。
10.1 安装思路
通常你需要准备:
-
Python 环境
-
PyTorch
-
Transformers
-
PEFT
-
bitsandbytes(如果做 QLoRA)
-
LLaMA-Factory
具体版本要看你 CUDA、PyTorch、模型类型是否兼容。版本不匹配是最常见问题之一。相关能力分别来自 Transformers、PEFT、bitsandbytes 和 LLaMA-Factory。
10.2 数据集注册
LLaMA-Factory 一般需要你在数据配置里声明:
-
数据文件路径
-
数据集名称
-
字段映射
-
模板类型
例如你可能会维护:
-
dataset_info.json -
data/xxx.jsonl
让框架知道你的 instruction/input/output 或 messages 字段怎么读。
10.3 典型 YAML 参数结构
一个典型的 LoRA SFT 配置大概会包含这些区块:
model_name_or_path: /mnt/workspace/model/Qwen2.5-7B-Instruct
stage: sft
do_train: true
finetuning_type: lora
dataset: my_sft_data
template: qwen
cutoff_len: 2048
max_samples: 50000
overwrite_cache: true
preprocessing_num_workers: 16
output_dir: /mnt/workspace/train/qwen_lora_exp1
logging_steps: 10
save_steps: 500
plot_loss: true
per_device_train_batch_size: 2
gradient_accumulation_steps: 8
learning_rate: 5e-5
num_train_epochs: 3.0
lr_scheduler_type: cosine
warmup_ratio: 0.05
bf16: true
ddp_timeout: 180000000
lora_rank: 16
lora_alpha: 32
lora_dropout: 0.05
lora_target: all
这些参数的意义,本质上就是前面第 6、7 节讲的内容。
11. 参数应该怎么配
这里直接给你工程里的常用起步模板。
11.1 7B / 8B 模型,LoRA 起步配置
finetuning_type: lora
cutoff_len: 2048
per_device_train_batch_size: 2
gradient_accumulation_steps: 8
learning_rate: 5e-5
num_train_epochs: 3
lr_scheduler_type: cosine
warmup_ratio: 0.05
bf16: true
lora_rank: 16
lora_alpha: 32
lora_dropout: 0.05
适合:
-
首轮试验
-
中等规模 SFT
-
JSON 生成/推荐理由/问答任务
11.2 14B / 32B 模型,QLoRA 起步配置
finetuning_type: lora
quantization_bit: 4
cutoff_len: 2048
per_device_train_batch_size: 1
gradient_accumulation_steps: 16
learning_rate: 1e-4
num_train_epochs: 3
lr_scheduler_type: cosine
warmup_ratio: 0.05
bf16: true
lora_rank: 16
lora_alpha: 32
lora_dropout: 0.05
适合:
-
显存紧张
-
想快速跑通大模型微调
-
先验证数据质量
QLoRA 之所以常能在较小显存上完成更大模型微调,核心就在 4-bit 量化加载。
11.3 小数据集更稳妥配置
如果你的数据只有几千到几万条,建议保守些:
learning_rate: 2e-5
num_train_epochs: 3
lora_dropout: 0.1
因为小数据更容易过拟合。
12. 多卡训练怎么理解
Transformers 的 Trainer 支持分布式训练,LLaMA-Factory 也支持多卡场景。
多卡训练你最需要理解三件事:
12.1 可见设备
CUDA_VISIBLE_DEVICES=0,1,2,3
LLaMA-Factory 官方示例也提到,可通过 CUDA_VISIBLE_DEVICES 选择设备。
12.2 总 batch 会变大
如果你保持每卡 batch 不变,GPU 数量增加后,总 batch 会增加,因此有时学习率也要配合调整。
12.3 显存分布式不等于无限大
多卡能分摊部分负担,但:
-
激活值
-
optimizer state
-
通信开销
-
checkpoint 保存
仍然可能成为瓶颈。
13. 显存不够怎么办
这是最常见问题。
处理顺序建议如下:
第一步,减小 per_device_train_batch_size
第二步,增大 gradient_accumulation_steps
第三步,减小 cutoff_len
第四步,改用 LoRA / QLoRA
第五步,减少 lora_rank
第六步,启用梯度检查点
第七步,多卡或更高规格 GPU
LLaMA-Factory 在其功能说明和讨论中也强调了更省显存的训练路径,例如 QLoRA、FSDP+QLoRA、GaLore 等思路。
14. 训练日志怎么看
训练时你主要看这几个指标:
14.1 loss
最基础。
正常情况:
-
初期较高
-
逐渐下降
-
后期趋于平稳
如果:
-
一直不降:学习率可能太小,数据有问题,模板不对
-
剧烈震荡:学习率可能太大
-
很快降到特别低:可能过拟合或数据泄漏
14.2 eval_loss
如果你有验证集,eval_loss 比训练集 loss 更有参考价值。
判断标准:
-
train loss 下降,eval loss 也下降:正常
-
train loss 下降,eval loss 上升:过拟合
14.3 吞吐、显存、步速
你要同时关注:
-
每 step 时间
-
GPU 利用率
-
显存是否接近满载
-
是否频繁保存导致卡顿
15. 微调后的产物是什么
这取决于你用的是哪种方式。
15.1 LoRA / QLoRA
通常输出的是 adapter 权重,不是完整模型。
优点:
-
文件小
-
便于版本管理
-
一个底模可挂多个 adapter
15.2 Full Fine-tuning
输出的是完整模型权重。
优点:部署简单
缺点:大、贵、难管理
LLaMA-Factory 官方示例中也单列了 Merging LoRA Adapters 的步骤,说明 LoRA 训练后的常见下一步就是合并。
16. LoRA 合并是什么意思
LoRA 训练完成后,有两种部署方式:
16.1 推理时动态加载底模 + adapter
优点:
-
灵活
-
便于切换不同任务 adapter
-
节省重复存储
16.2 先 merge,再导出完整模型
优点:
-
推理链路简单
-
某些部署环境更方便
缺点:
-
体积变大
-
丢失 adapter 的灵活性
17. 常见工具使用建议
17.1 用 LLaMA-Factory 做训练
适合你这种高频试验、多数据集、多模型切换的场景。
优势是:
-
省去大量样板代码
-
YAML 管理方便
-
支持 LoRA / QLoRA / DPO
-
支持多种模板与模型族
这些能力在官方仓库和示例中都直接列出来了。
17.2 用 Transformers + PEFT 自己写训练
适合:
-
你要自定义损失函数
-
要做复杂数据拼接
-
要特殊评估逻辑
-
要接业务特征融合
17.3 用 bitsandbytes 做量化训练
适合显存不足场景,尤其是 QLoRA。Hugging Face 文档明确说明 bitsandbytes 提供 4-bit / 8-bit 量化能力。
18. 常见报错与排查
18.1 显存溢出 OOM
表现:
-
CUDA out of memory
-
训练刚启动就炸
-
某个长样本导致炸
排查顺序:
-
降 batch
-
降 cutoff_len
-
增 gradient_accumulation
-
开 QLoRA
-
降 LoRA rank
-
检查是否有异常长样本
18.2 tokenizer / template 不匹配
表现:
-
loss 不正常
-
输出格式混乱
-
模型学不会
-
特殊 token 异常
原因往往是:
-
模型模板选错
-
tokenizer 配置不一致
-
数据格式和模型期望不一致
这类问题尤其容易出现在 chat 模型上,因为不同模型的对话模板不同。LLaMA-Factory 正是通过模板机制来适配不同模型族。
18.3 输出目录已存在
这是训练框架常见保护机制,防止覆盖已有结果。
处理思路:
-
换新
output_dir -
或显式允许覆盖
-
或先删除旧目录
18.4 量化相关报错
比如:
-
bitsandbytes 不兼容
-
CUDA 版本不匹配
-
4bit 加载失败
因为 QLoRA 依赖 bitsandbytes 与底层环境兼容。出现这类问题时,先确认:
-
PyTorch 版本
-
CUDA 版本
-
bitsandbytes 版本
-
GPU 是否支持对应精度和算子
bitsandbytes 文档本身就强调它是依赖底层硬件加速能力的量化工具。
19. 评估怎么做
训练完不能只看 loss,要做任务级评估。
19.1 生成类任务
看:
-
ROUGE
-
BLEU
-
人工评估
-
格式正确率
-
JSON 可解析率
19.2 分类类任务
看:
-
Accuracy
-
Precision
-
Recall
-
F1
19.3 推荐理由/问答类任务
更建议结合:
-
人工打分
-
格式合规率
-
幻觉率
-
命中业务规则的比例
如果你在做金融教育推荐,单纯看 BLEU/ROUGE 不够,最好再加:
-
推荐课程是否真实存在
-
goods_id 是否在候选池中
-
推荐理由是否与画像一致
-
学习路径是否遵循先易后难
20. 最佳实践
20.1 先做小样本试训
先用 100~1000 条数据跑通:
-
数据格式
-
模板
-
loss 是否正常
-
输出目录
-
保存逻辑
-
推理链路
别一开始就几十万条直接开训。
20.2 先训小模型,再放大
先拿 7B / 8B 跑通数据和提示格式,再上 14B / 32B。
因为很多问题和模型大小无关,而是数据与模板的问题。
20.3 数据质量高于堆数量
一万条高质量数据,往往胜过十万条脏数据。
尤其是:
-
输出风格不一致
-
字段缺失
-
推荐对象是编造的
-
instruction 和 output 不对应
20.4 保持任务单一
一套数据最好只做一件事。
不要一半样本让模型输出散文,一半样本输出 JSON,一半样本又让它做分类。
20.5 做版本管理
建议至少记录:
-
模型版本
-
数据版本
-
参数版本
-
模板版本
-
评估结果
-
推理示例
否则几轮实验后很容易混乱。
21. 一个适合你的实战建议
结合你平时的使用习惯,我建议你的默认路线是:
第一阶段:
-
用 LLaMA-Factory + LoRA/QLoRA
-
做 SFT
-
数据统一成
messages或严格instruction/input/output -
输出尽量固定格式
第二阶段:
-
做自动评估脚本
-
重点检查 JSON 合法率、候选命中率、推荐真实性
第三阶段:
-
再考虑 DPO 或偏好优化
-
用人工偏好数据提升“推荐理由质量”“解释可信度”
如果你是训 Qwen 指令模型,优先建议:
-
模板正确
-
先 2048 长度
-
先 LoRA rank 16
-
学习率从
5e-5或1e-4起步 -
小样本先跑通再扩大
22. 一份最简微调清单
你每次开训前,按这个检查就行:
数据
-
字段名统一
-
输出格式统一
-
没有脏样本
-
没有超长异常样本
模型
-
model_name_or_path正确 -
tokenizer 能正常加载
-
template 正确匹配模型
参数
-
cutoff_len合理 -
batch_size不会爆显存 -
gradient_accumulation_steps已补偿总 batch -
learning_rate不激进 -
warmup_ratio已设置
LoRA
-
lora_rank合理 -
lora_alpha合理 -
lora_dropout合理 -
target_modules没写错
输出
-
output_dir是新目录 -
save_steps不过密 -
logging_steps能看清训练趋势