关于微调

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-51e-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 的核心是给目标层增加低秩适配矩阵。最关键的几个参数是 rlora_alphalora_dropouttarget_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 官方示例说明,最基础的训练方式就是:

llamafactory-cli train examples/train_lora/qwen3_lora_sft.yaml

它也说明可以通过环境变量控制使用哪些设备。

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/outputmessages 字段怎么读。


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

  • 训练刚启动就炸

  • 某个长样本导致炸

排查顺序:

  1. 降 batch

  2. 降 cutoff_len

  3. 增 gradient_accumulation

  4. 开 QLoRA

  5. 降 LoRA rank

  6. 检查是否有异常长样本


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-51e-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 能看清训练趋势