
微调实操
环境配置 · 数据准备 · LoRA/QLoRA/全量微调/DPO全流程 · 评估与排查
为什么选LLaMA-Factory?
一站式:集成SFT/DPO/RLHF/预训练 | 低门槛:WebUI+YAML双模式 | 生态成熟:100+模型支持,社区活跃
在动手之前,先确认你的硬件能跑什么。这张表决定了你后续的所有选择:
LoRA微调
0.5B 最低4GB | RTX 3060 12GB | ~5000 tokens/s
1.5B 最低6GB | RTX 3060 12GB | ~3000 tokens/s
7B ★最常用 最低16GB | RTX 4090 24GB | ~800 tokens/s
14B 最低32GB | 2×RTX 4090 | ~400 tokens/s
QLoRA微调(4bit量化)
7B 最低6GB | RTX 3060 12GB | ~600 tokens/s
14B 最低10GB | RTX 4090 24GB | ~300 tokens/s
72B 最低48GB | 1×A100 80GB | ~100 tokens/s
全量微调
7B 最低56GB | 4×A100 80GB | ~400 tokens/s
14B 最低112GB | 8×A100 80GB | ~200 tokens/s
如果你没有GPU:可以使用云GPU服务(AutoDL、恒源云、趋动云等),RTX 4090约2~3元/小时,A100 80GB约8~12元/小时。
操作系统:Ubuntu 20.04/22.04(推荐) | CUDA 12.1+(推荐12.4) | Python 3.10
# 1. 创建Conda环境
conda create -n llama_factory python=3.10 -y
conda activate llama_factory
# 2. 安装PyTorch(CUDA 12.4)
pip install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1 \
--index-url https://download.pytorch.org/whl/cu124
# 3. 克隆LLaMA-Factory
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
# 4. 安装依赖
pip install -e ".[torch,metrics]"
# 5. 安装可选加速组件(强烈推荐)
pip install flash-attn==2.6.3
pip install bitsandbytes==0.43.1
pip install deepspeed==0.14.4
# 6. 验证安装
llamafactory-cli version
常见安装问题
flash-attn安装失败 需要CUDA编译环境 → pip install flash-attn --no-build-isolation
bitsandbytes报错 Windows不支持 → 使用WSL2或Linux
cuda.is_available()返回False CUDA版本不匹配 → 检查nvcc与PyTorch CUDA版本
OOM 显存不足 → 降低batch_size,开启梯度检查点,或换QLoRA
Qwen2.5系列模型可从Hugging Face或ModelScope下载。7B模型的FP16权重约14GB,建议先下载到本地。
Qwen2.5系列模型参数对照
0.5B 0.62B参数 | 24层 | Q=14,KV=2 | 上下文32K
1.5B 1.54B参数 | 28层 | Q=12,KV=2 | 上下文32K
3B 3.09B参数 | 36层 | Q=16,KV=2 | 上下文32K
7B ★最常用 7.61B参数 | 28层 | Q=28,KV=4 | 上下文128K
14B 14.7B参数 | 48层 | Q=40,KV=8 | 上下文128K
32B 32.5B参数 | 64层 | Q=40,KV=8 | 上下文128K
72B 72.7B参数 | 80层 | Q=64,KV=8 | 上下文128K
微调时建议使用Instruct版本作为起点——它已经"知道怎么对话",你只需要教它"怎么按你的方式对话"。
微调界有一句共识:数据决定上限,算法决定下限。再好的微调方法,配上垃圾数据,效果也是垃圾。
LLaMA-Factory支持两种主流格式:
Alpaca格式 — 适用于单轮问答
三个核心字段:instruction(用户指令,必填)+ input(用户输入,可选)+ output(模型响应,必填)
可选字段:system(系统提示)、history(历史对话)
ShareGPT格式 — 适用于多轮对话
核心字段:conversations(对话列表,from+value交替)+ 可选system
DPO偏好数据需要额外的chosen/rejected字段,ShareGPT扩展更方便
格式选择建议
单轮问答 → Alpaca 结构简单,三字段清晰
多轮对话 → ShareGPT conversations列表天然支持多轮
偏好数据(DPO)→ ShareGPT 需要chosen/rejected字段
原则一:准确性 模型输出的内容必须正确。如果训练数据中有错误回答,模型会"学会"错误。不确定的数据宁可删掉。
原则二:一致性 格式和风格必须统一。统一回答格式、长度、system prompt、人称和语气。
原则三:多样性 覆盖目标场景的各种情况。避免大量重复或高度相似的样本。
原则四:难度梯度 60%中等难度 + 20%简单 + 20%困难。
风格迁移 最少50~100条 | 推荐200~500条
格式适配 最少100~200条 | 推荐500~1K条
简单问答 最少200~500条 | 推荐1K~5K条
多轮对话 最少500~1K条 | 推荐5K~20K条
复杂推理 最少1K~5K条 | 推荐10K~50K条
代码生成 最少2K~5K条 | 推荐10K~100K条
粗略估算公式:推荐数据量 ≈ 可训练参数量 × 5~20
关键原则:数据质量 > 数据数量。1000条高质量数据的效果,往往好于10000条低质量数据。宁可花时间打磨数据,也不要堆量。
当你手头的数据量不够时,不要急着去标注——先试试数据增强和合成。
Self-Instruct 用大模型根据种子指令生成更多训练数据。5~10倍增量,质量风险中等,不超过总数据50%
指令改写 同一条指令用不同方式表达,增加多样性。2~5倍增量,质量风险低,可大量使用
反向翻译 中文→英文→中文,生成语义相同但表达不同的变体。1.5~3倍增量,需人工审核
数据增强是"锦上添花"不是"雪中送炭"。如果你只有50条数据,增强到500条也不会让模型变多好。数据增强最有效的场景是:你已经有1000条高质量数据,想增加到5000条来提升鲁棒性。
准备好数据后,将JSON文件放到 LLaMA-Factory/data/ 目录下,然后编辑 dataset_info.json 添加数据集描述。Alpaca格式用 formatting: alpaca,ShareGPT格式用 formatting: sharegpt。
本节是全书的核心实操内容之一。以Qwen2.5-7B-Instruct为例,走完LoRA微调的完整流程:配置→训练→评估→合并导出。
创建配置文件 qwen2.5_lora_sft.yaml:
### 模型配置
model_name_or_path: /path/to/Qwen2.5-7B-Instruct
template: qwen
trust_remote_code: true
### 微调方法
finetuning_type: lora
### LoRA参数
lora_rank: 16
lora_alpha: 32
lora_target: q_proj,v_proj
lora_dropout: 0.05
### 数据配置
dataset: my_medical_dataset
cutoff_len: 2048
### 训练超参数
stage: sft
learning_rate: 5.0e-5
lr_scheduler_type: cosine
warmup_ratio: 0.1
num_train_epochs: 3
per_device_train_batch_size: 2
gradient_accumulation_steps: 4
### 显存优化
fp16: true
gradient_checkpointing: true
### 保存与日志
output_dir: /path/to/output/qwen2.5-7b-lora-medical
logging_steps: 10
save_steps: 500
save_total_limit: 3
seed: 42
report_to: tensorboard
关键参数详解
lora_rank: 16 从16开始实验,效果不够再增大到32/64
lora_alpha: 32 通常设为2×rank,控制LoRA更新强度
lora_target: q_proj,v_proj 最保守选择;追求更好效果可加k_proj,o_proj
learning_rate: 5e-5 LoRA推荐1e-5~1e-4
num_train_epochs: 3 数据少时3~5轮,数据多时1~2轮
lora_target的选择
q_proj, v_proj ~0.1%参数 | 基线效果 | 简单任务
q_proj, k_proj, v_proj, o_proj ★推荐 ~0.2%参数 | 较好效果 | 通用推荐
+ gate_proj, up_proj, down_proj ~0.5%参数 | 最好效果 | 复杂任务
经验法则:先用q_proj,v_proj跑baseline,不够再加模块。加模块比加rank更有效。
# 单卡训练
CUDA_VISIBLE_DEVICES=0 llamafactory-cli train qwen2.5_lora_sft.yaml
# 多卡训练(2卡)
CUDA_VISIBLE_DEVICES=0,1 llamafactory-cli train qwen2.5_lora_sft.yaml
# 使用DeepSpeed ZeRO-2(推荐多卡时使用)
CUDA_VISIBLE_DEVICES=0,1 llamafactory-cli train qwen2.5_lora_sft.yaml \
--deepspeed examples/deepspeed/ds_z2_config.json
一条健康的loss曲线:前几十步快速下降 → 中期稳定下降 → 后期趋于平缓,小幅震荡。最终loss值通常在0.5~1.5之间。
异常loss形态及排查
水平线(不下降) 学习率过小或数据格式错误 → 检查lr和dataset_info.json
爆炸(飙升到inf/nan) 学习率过大或梯度爆炸 → 降低lr到1e-5,确认max_grad_norm=1.0
锯齿形(震荡剧烈) batch_size太小或lr过大 → 增大gradient_accumulation_steps
V形(先降后升) 过拟合 → 减少epoch,增大dropout
降到很低但效果差 过拟合到训练集 → 减少epoch,混入通用数据
训练时间预估(7B + LoRA + RTX 4090)
1K条 cutoff_len 2048 → ~30分钟
5K条 cutoff_len 2048 → ~2.5小时
10K条 cutoff_len 2048 → ~5小时
50K条 cutoff_len 2048 → ~25小时
训练完成后,先用LoRA适配器做推理测试,检查回答的格式、内容、风格和幻觉。确认效果满意后,再合并导出。
# 命令行推理测试
llamafactory-cli chat qwen2.5_lora_infer.yaml
确认效果满意后,将LoRA权重合并回原始模型。合并后推理行为与标准模型完全一致,没有额外的推理延迟。
# 合并导出
llamafactory-cli export qwen2.5_lora_merge.yaml
合并后的模型是完整的Hugging Face格式,可以直接用transformers加载,也可以用vLLM、SGLang等推理框架部署。
QLoRA的实操流程与LoRA几乎完全一致,只需要修改几个配置参数。
与LoRA的关键差异
新增 quantization_bit: 4 + quantization_method: bitsandbytes
lora_rank建议从16增到 32,补偿4bit量化的精度损失
lora_alpha相应增到 64(2×rank)
QLoRA显存实测(7B + RTX 4090 24GB)
r=16, bs=1, len=2048 → ~10GB ✅
r=16, bs=2, len=2048 → ~14GB ✅
r=32, bs=2, len=2048 → ~15GB ✅
r=32, bs=2, len=4096 → ~22GB ⚠️ 接近极限
r=64, bs=2, len=2048 → ~17GB ✅
QLoRA与LoRA的效果差距通常在1~2%以内。如果任务对精度极其敏感,先用QLoRA跑一版,效果不够再换LoRA或增大QLoRA的rank。
全量微调需要多卡分布式训练。使用DeepSpeed ZeRO进行全量微调。关键配置差异:finetuning_type改为full,学习率降到1e-5~2e-5,epoch通常1~2轮就够。
全量微调的踩坑经验
坑1:学习率过大导致预训练知识崩溃 全量微调学习率必须比LoRA小一个数量级。如果通用能力下降超过5%,说明学习率过大或epoch过多。
坑2:DeepSpeed ZeRO-3的通信瓶颈 4卡以上通信开销可能占30~40%。开启overlap_comm,或显存够时用ZeRO-2代替。
坑3:保存checkpoint时OOM ZeRO-3保存时需聚合分片参数,临时占用大量显存。设置stage3_gather_16bit_weights_on_model_save: true。
坑4:数据量不够时全量微调不如LoRA 数据量<5万条时,LoRA通常优于全量微调。LoRA的低秩约束天然起到了正则化的作用。
ZeRO-2 vs ZeRO-3选择指南
ZeRO-2 分片优化器状态+梯度 | 显存省约50% | 通信开销低 | 模型能装进单卡时首选
ZeRO-3 分片优化器+梯度+参数 | 显存省约75% | 通信开销高 | 模型装不进单卡时用
SFT教会模型"怎么回答",但对齐训练教会模型"哪种回答更好"。如果你的模型需要拒绝有害请求、选择更符合人类偏好的回答、减少幻觉——那就需要DPO或RLHF。
DPO vs RLHF
DPO ★首选 无需奖励模型 | 训练复杂度低 | 稳定性高 | 效果接近RLHF
RLHF (PPO) 需要4个模型 | 调参极难 | 容易reward hacking | 理论上限更高但实践中很难达到
DPO需要偏好数据——对同一个输入,提供一个"好的回答"(chosen)和一个"差的回答"(rejected)。获取方式:人工标注、模型生成+规则筛选、开源数据集(HelpSteer2、UltraFeedback)。
与SFT配置的关键差异:stage改为dpo,新增dpo_beta参数(推荐0.1,控制偏好强度),epoch通常1轮就够。DPO显存需求约为SFT的1.5倍。
DPO关键调参
dpo_beta: 0.1 太大(>0.5)训练不稳定;太小(<0.05)偏好信号弱
num_train_epochs: 1 DPO通常1轮就够,2轮以上容易过拟合
偏好数据量: 1K~10K 不需要太多,质量比数量重要
DPO训练后的效果验证三步法:
1. 安全性测试:用有害提示测试拒绝率是否提升
2. 质量对比:对比DPO前后输出,应拒绝更果断、幻觉减少
3. 通用能力测试:跑C-Eval/MMLU,确保没有严重退化
层次一:人工评估(最可靠) 随机抽50~100条测试样本,从准确性、完整性、格式、风格四维度评估
层次二:自动评估(最快捷) 用GPT-4等强模型做评判,设计评估Prompt含评估维度+评分标准+参考答案
层次三:基准测试(最客观) C-Eval(中文)/ MMLU(英文)/ GSM8K(数学)/ HumanEval(代码)/ MT-Bench(对话)
Loss不下降 → 检查学习率、数据格式、template配置
Loss下降但效果差 → 数据质量低或过拟合,清洗数据/减少epoch/增大dropout
通用能力退化 → 灾难性遗忘,减少epoch/降低lr/混入通用数据/改用LoRA
回复重复/啰嗦 → epoch过多或数据重复,减少到1~2轮/去重
OOM → 降低batch_size/开启gradient_checkpointing/改用QLoRA
最常见的新手错误 Top 5
1. 数据格式不匹配——Alpaca数据用了ShareGPT注册方式
2. template选错——Qwen模型必须用template: qwen
3. 学习率过大——LoRA不要超过1e-4
4. epoch过多——LoRA微调2~3轮就够,5轮以上几乎必然过拟合
5. 忘记合并适配器——用vLLM部署必须先合并LoRA权重
本章小结
- 我的GPU能跑什么?→ 翻2.1.1的显存需求表
- 数据用什么格式?→ 单轮用Alpaca,多轮用ShareGPT,DPO用偏好格式
- LoRA的rank怎么选?→ 从16开始,不够再加;加目标模块比加rank更有效
- QLoRA和LoRA差多少?→ 显存省60%+,效果差1%以内
- 全量微调什么时候该用?→ 数据>10万条 + 算力充足,否则LoRA更稳
- DPO和RLHF选哪个?→ 首选DPO,除非你有成熟的RLHF基础设施
- 训练完loss正常但效果差?→ 检查数据质量、template配置、epoch是否过多