Skip to content
CloudZun
Go back

LLaMA Factory微调实战 - 理论讲义

编辑此文章

LLaMA Factory微调实战 - 理论讲义

目录

微调的本质 - 为什么需要微调?

预训练模型的能力与局限

类比理解

实际案例

场景预训练模型表现微调后表现
客服对话回答正确但不专业
”可以退货,联系客服”
回答专业且规范
”您可以在订单页面点击’申请退货’…”
法律咨询给出通用建议
”建议咨询律师”
引用具体法条
”根据《民法典》第XXX条…”
代码生成生成基础代码符合公司代码规范
包含完整注释和错误处理

什么时候需要微调?

决策树

 是否需要微调?

 ├─ 需要特定领域知识? → 是 → 微调
 │  └─ 例:医疗诊断、法律文书、金融分析

 ├─ 需要特定输出格式? → 是 → 微调
 │  └─ 例:结构化报告、特定JSON格式

 ├─ 需要特定语言风格? → 是 → 微调
 │  └─ 例:品牌语气、古文风格、儿童语言

 ├─ 需要遵循特定流程? → 是 → 微调
 │  └─ 例:客服SOP、诊断流程、审批流程

 └─ 通用任务 + Prompt工程够用? → 否 → 不需要微调

└─ 例:简单问答、文本摘要、翻译

微调 vs 其他方案对比

方案成本效果适用场景示例
Prompt工程💰 最低⭐⭐简单任务、快速验证”你是客服,请回答…”
RAG检索增强💰💰 低⭐⭐⭐需要实时知识、文档问答查询知识库后回答
微调💰💰💰 中⭐⭐⭐⭐特定领域、固定模式今天的实验
预训练💰💰💰💰💰 极高⭐⭐⭐⭐⭐从零构建基础模型Qwen、GPT的训练

关键洞察

微调不是改变模型的知识,而是调整模型的行为模式


微调方法对比

Full Fine-tuning(全量微调)

原理

┌─────────────────┐
│ 预训练模型     │
│ (70亿参数)     │ ← 全部参数都更新
└─────────────────┘

训练数据 ↓

┌─────────────────┐
│ 微调后模型     │
│ (70亿参数)     │ ← 全部参数都改变
└─────────────────┘

特点

优点缺点
✅ 效果最好❌ 显存需求大(7B模型需要>80GB)
✅ 适应能力强❌ 训练时间长
✅ 实现简单❌ 容易过拟合
❌ 每个任务需要完整模型副本

资源需求(7B模型)

LoRA(Low-Rank Adaptation)

核心思想

不改变原模型,只训练小的”补丁”

原理图解

原始权重矩阵 W (4096×4096)
┌─────────────────────────┐
│                       │
│      冻结不动         │ ← 16M参数
│   (预训练权重)        │
│                       │
└─────────────────────────┘
 +
A (4096×8) × B (8×4096) ← 只训练这两个小矩阵
 └──────┬──────┘
   LoRA补丁 (只有65K参数!)

最终输出 = W·x + A·B·x

数学直觉

关键参数

# LoRA配置示例
lora_config = {
 "r": 8, # rank:矩阵的秩(越大效果越好,但参数越多)
 "lora_alpha": 16, # 缩放因子(通常设为 r 的 2倍)
 "lora_dropout": 0.05,# dropout率(防止过拟合)
 "target_modules": ["q_proj", "v_proj"] # 对哪些层应用LoRA
}

参数选择指南

rank (r)参数量适用场景训练时间
4很少简单任务、数据少最快
8通用推荐
16中等复杂任务中等
32+较多需要强适应性较慢

资源需求(7B模型)

QLoRA(Quantized LoRA)

核心创新

LoRA + 量化 = 更低的显存需求

原理

步骤1: 量化基础模型
┌─────────────────┐
│ FP16 模型      │ 28GB显存
│ (70亿参数)     │
└─────────────────┘

量化到4bit

┌─────────────────┐
│ INT4 模型      │ 7GB显存 (减少75%!)
│ (70亿参数)     │
└─────────────────┘

步骤2: 在量化模型上训练LoRA
┌─────────────────┐
│ INT4 模型      │ 冻结
│ + LoRA (FP16)  │ 训练
└─────────────────┘

三种方法对比

方法显存需求训练速度效果存储推荐场景
Full FT80GB⭐⭐⭐⭐⭐14GB有A100资源
LoRA24GB⭐⭐⭐⭐50MB通用推荐
QLoRA12GB中等⭐⭐⭐⭐50MB显存受限

实际选择建议

你的GPU显存是多少?

 ├─ 80GB+ (A100/H100)
 │  └─ 可以尝试 Full Fine-tuning

 ├─ 24GB+ (3090/4090)
 │  └─ 使用 LoRA ✅ (今天的实验)

 ├─ 12-16GB (3060/4060)
 │  └─ 使用 QLoRA

 └─ <12GB

└─ 考虑更小的模型或云服务


数据准备

数据格式

标准格式(Alpaca)

{
 "instruction": "任务描述",
 "input": "具体输入(可选)",
 "output": "期望输出"
}

三种常见场景

场景1: 问答对(无额外输入)

{
 "instruction": "什么是机器学习?",
 "input": "",
 "output": "机器学习是人工智能的一个分支..."
}

场景2: 带上下文的任务

{
 "instruction": "将以下文本翻译成英文",
 "input": "今天天气很好",
 "output": "The weather is nice today"
}

场景3: 多轮对话

{
 "conversations": [
  {"role": "user", "content": "你好"},
  {"role": "assistant", "content": "你好!有什么可以帮助你的?"},
  {"role": "user", "content": "介绍一下你自己"},
  {"role": "assistant", "content": "我是AI助手..."}
 ]
}

数据质量要求

黄金法则

质量 > 数量。100条高质量数据 > 1000条低质量数据

高质量数据的特征

维度好的示例差的示例
准确性”根据《劳动法》第XX条…""好像是这样…”
完整性包含步骤、注意事项、示例”可以退货”
一致性风格统一、术语统一有的正式、有的口语
多样性覆盖各种问法和场景重复相似的问题

数据清洗检查清单

✅ 检查项目:
□ 没有HTML标签或特殊字符
□ 没有过长的文本(>2048 tokens)
□ 没有空白的output
□ 没有明显的错别字
□ 格式符合JSON规范
□ instruction和output对应正确

数据量需求

经验法则

任务类型最少数据量推荐数据量说明
风格迁移50-100条200-500条如:改变语气、格式
简单分类100-200条500-1000条如:情感分析、意图识别
知识注入500-1000条2000-5000条如:领域问答
复杂推理1000+条5000+条如:代码生成、数学题

实用建议

阶段1: 先准备50-100条核心数据

快速微调测试

阶段2: 根据效果补充数据

迭代优化

常见数据问题

问题1: 数据泄露

// ❌ 错误:output中包含了不该有的信息
{
 "instruction": "用户问:如何退货?",
 "output": "根据我们的内部文档XYZ..."
}
// ✅ 正确
{
 "instruction": "如何退货?",
 "output": "您可以在订单页面申请退货..."
}

问题2: 过拟合特定模式

// ❌ 所有问题都是"如何..."开头
"如何查询订单?"
"如何申请退货?"
"如何联系客服?"

// ✅ 多样化的问法
"查询订单的方法"
"我想退货"
"联系客服"
"订单在哪里看"

问题3: 分布不均

❌ 100条数据中:
- 80条关于退货
- 15条关于物流
- 5条关于支付

✅ 均衡分布:
- 30条关于退货
- 30条关于物流
- 30条关于支付
- 10条其他

超参数解析

学习率 (Learning Rate)

类比理解

可视化

Loss曲线对比
学习率太大 (1e-3):    学习率合适 (5e-5):    学习率太小 (1e-6):

Loss Loss Loss │ ╱╲╱╲ │ ╲ │ ╲___ │ ╱ ╲ │ ╲___ │ ╲___ │╱ ╲ │ ╲___ │ ╲___ └─────────→ Steps └─────────→ Steps └─────────→ Steps 震荡不收敛 平稳下降 ✅ 下降太慢

推荐值

模型大小Full FTLoRAQLoRA
7B1e-55e-51e-4
13B5e-63e-55e-5
70B+1e-61e-53e-5

调优策略

1. 从推荐值开始
2. 观察loss曲线:
   - 震荡 → 减小学习率(÷2)
   - 下降太慢 → 增大学习率(×2)
3. 使用学习率调度器(cosine/linear)

Batch Size 与 Gradient Accumulation

概念

Batch Size = 每次喂给模型多少条数据
Gradient Accumulation = 累积多少次才更新参数

实际Batch Size = Batch Size × Gradient Accumulation

示例

# 配置1: 直接使用大batch
per_device_train_batch_size = 8
gradient_accumulation_steps = 1
# 实际batch = 8

# 配置2: 累积梯度(推荐)
per_device_train_batch_size = 2
gradient_accumulation_steps = 4
# 实际batch = 2×4 = 8(效果相同,但显存需求小)

显存与Batch Size的关系

Batch Size显存占用训练速度推荐场景
1最低显存紧张
2-4中等通用推荐
8+显存充足

实用公式

目标实际Batch Size = 16-32 (经验值)

如果显存不够:
per_device_batch_size = 2
gradient_accumulation = 16 # 实际batch=32

如果显存充足:
per_device_batch_size = 8
gradient_accumulation = 4 # 实际batch=32

Epoch(训练轮数)

定义

1 epoch = 模型看完所有训练数据一遍

选择指南

数据量推荐Epoch原因
<100条5-10数据少,需要多看几遍
100-1000条3-5通用推荐
1000-10000条2-3数据多,避免过拟合
10000+条1-2大数据集,一遍就够

过拟合判断

训练集Loss vs 验证集Loss
正常情况:                过拟合:

Loss Loss │ ╲___训练集 │ ╲训练集 │ ╲验证集 │ ╲╱ 验证集开始上升 │ ╲ │ ╱ └─────────→ Epoch └─────────→ Epoch

其他重要参数

Warmup Steps

作用:训练开始时逐渐增大学习率
学习率变化: ↗ warmup阶段(逐渐增大)

  ╱ ╲___ 正常训练(逐渐衰减)
推荐值:总步数的 5-10%

Max Length / Cutoff Length

作用:限制输入文本的最大长度
选择依据:
- 数据中最长文本的长度
- 显存限制
- 模型的最大支持长度
推荐值:
- 对话任务:512-1024
- 文档任务:2048-4096

保存策略

save_strategy = "steps" # 按步数保存
save_steps = 100 # 每100步保存一次
save_total_limit = 3 # 只保留最近3个checkpoint

快速参考卡片

微调配置速查表

# 🚀 快速开始配置(7B模型 + 3090/4090)
model: Qwen2.5-7B-Instruct
method: LoRA

# LoRA参数
lora_rank: 8
lora_alpha: 16
lora_dropout: 0.05

# 训练参数
learning_rate: 5e-5
batch_size: 2
gradient_accumulation: 4 # 实际batch=8
epochs: 3
max_length: 1024

# 数据要求
min_samples: 50
recommended_samples: 200-500

# 预期结果
training_time: 10-20分钟
lora_size: ~50MB
memory_usage: ~24GB

问题诊断流程

训练遇到问题?
Loss不下降?
├─ 检查学习率(是否太小?)
├─ 检查数据质量(是否有错误?)
└─ 增加训练轮数

显存不足?
├─ 减小batch_size
├─ 增大gradient_accumulation
├─ 减小max_length
└─ 尝试QLoRA

过拟合?
├─ 减少epoch
├─ 增加数据量
├─ 增大lora_dropout
└─ 使用验证集早停

训练太慢?
├─ 增大batch_size
├─ 减少logging频率
└─ 使用更快的GPU

总结:核心要点

  1. 微调的本质:调整模型行为,不是灌输知识
  2. 方法选择:LoRA是性价比最高的方案
  3. 数据为王:100条高质量 > 1000条低质量
  4. 超参数:从推荐值开始,根据loss曲线调整
  5. 迭代优化:小步快跑,快速验证

记住这个公式

微调成功 = 高质量数据 × 合适的方法 × 正确的参数 × 充分的迭代

课后思考题

  1. 为什么LoRA能用这么少的参数达到接近全量微调的效果?
  2. 如果你有一个客服场景,只有30条对话数据,应该怎么做?
  3. 训练时loss从2.5降到0.3,是好事还是坏事?

编辑此文章
Share this post on:

Previous Post
从零开始部署Next.js博客到Vercel:一次完整的技术实践
Next Post
Hugo博客运维最佳实践