微调实践指南
问题
实际进行微调时有哪些框架和技巧?常见问题怎么解决?
答案
一、微调框架对比
| 框架 | 特点 | 适用场景 |
|---|---|---|
| Unsloth | 速度快 2x、省内存 60% | 首选,消费级 GPU |
| LLaMA Factory | GUI + CLI,一站式 | 不想写代码 |
| TRL | HuggingFace 官方 | 灵活定制 |
| Axolotl | 配置文件驱动 | 批量实验 |
| OpenAI Fine-tuning | 全托管 | 使用 OpenAI 模型 |
二、Unsloth 完整示例
from unsloth import FastLanguageModel
from trl import SFTTrainer
from transformers import TrainingArguments
# 1. 加载模型(4-bit 量化)
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Meta-Llama-3.1-8B-bnb-4bit",
max_seq_length=2048,
load_in_4bit=True,
)
# 2. 添加 LoRA 适配器
model = FastLanguageModel.get_peft_model(
model,
r=16,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
lora_alpha=16,
lora_dropout=0,
use_gradient_checkpointing="unsloth", # 节省内存
)
# 3. 训练
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
args=TrainingArguments(
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
warmup_steps=5,
num_train_epochs=3,
learning_rate=2e-4,
fp16=True,
output_dir="outputs",
),
max_seq_length=2048,
)
trainer.train()
# 4. 保存(多种格式)
model.save_pretrained_gguf("model-gguf", tokenizer, quantization_method="q4_k_m")
model.save_pretrained_merged("model-merged", tokenizer)
三、常见问题与解决
| 问题 | 表现 | 解决方案 |
|---|---|---|
| 过拟合 | 验证 loss 上升 | 减少 epoch、增加数据、加 dropout |
| 灾难性遗忘 | 通用能力下降 | 降低学习率、混入通用数据 |
| 训练不收敛 | loss 不下降 | 检查数据格式、调低学习率 |
| OOM | GPU 内存不足 | 用 QLoRA、减小 batch_size、gradient checkpointing |
| 输出格式不稳定 | 微调后格式混乱 | 增加格式相关数据比例 |
四、GPU 选择
| GPU | 显存 | 适合模型 | 价格参考 |
|---|---|---|---|
| RTX 4090 | 24GB | QLoRA 7B-13B | 消费级 |
| A100 40GB | 40GB | LoRA 7B-70B | 云 GPU |
| A100 80GB | 80GB | 全量微调 7B | 云 GPU |
| H100 | 80GB | 全量微调 70B | 企业级 |
消费级 GPU 微调方案
RTX 4090 (24GB) + QLoRA + Unsloth = 可以微调 LLaMA-3.1-8B,训练速度约 15 tokens/s
常见面试问题
Q1: 微调后模型变差了怎么办?
答案:
- 检查数据质量:抽检训练数据,是否有错误样本
- 降低学习率:从 2e-5 降到 5e-6
- 减少训练轮次:从 3 epoch 减到 1
- 混入通用数据:加入 20-30% 通用对话数据
- 回退到检查点:对比不同 epoch 的检查点