Skip to content

模型微调技术

一、微调基础

Q1: 什么是微调(Fine-tuning)?什么时候需要微调?

微调 = 在预训练模型的基础上,用小规模领域数据继续训练,让模型适应特定任务/风格/领域。

┌──────────────────────────────────────────────────────────────┐
│                    模型开发层级对比                           │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  预训练(Pre-training)                                       │
│  · 万亿token级通用文本                                        │
│  · 训练成本:数百万美元、数月                                │
│  · 目标:通用语言理解能力                                      │
│  · 适用:模型厂商(OpenAI/阿里/智谱等)                       │
│                                                              │
│  ↓ (产出基础模型:GPT-4、LLaMA、ChatGLM等)                 │
│                                                              │
│  指令微调(SFT - Supervised Fine-Tuning)                     │
│  · 高质量指令-回答对(百万级)                                │
│  · 训练成本:数万美元、数日                                   │
│  · 目标:理解并遵循指令                                        │
│  · 适用:模型厂商 + 有一定资源的大公司                        │
│                                                              │
│  ↓ (产出对话/指令模型:ChatGPT、各种聊天模型)              │
│                                                              │
│  轻量微调(LoRA / QLoRA / P-Tuning)                          │
│  · 领域定制数据(千条-万条)                                   │
│  · 训练成本:数百美元、数小时                                │
│  · 目标:适配特定领域风格/术语/输出格式                       │
│  · 适用:中小企业、应用开发者(⭐大多数项目在这里)            │
│                                                              │
│  ↓ (产出适配特定业务的模型)                                 │
│                                                              │
│  RAG / Prompt工程                                             │
│  · 零训练成本                                                │
│  · 目标:让模型基于特定知识问答                               │
│  · 适用:所有项目(先尝试这个,不行再微调)                   │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Q2: 需要微调的典型场景

✅ 适合微调的场景❌ 不适合微调(用RAG/Prompt)
需要特定输出风格/语气(如客服话术、品牌文案)事实性问答(产品说明书、公司制度)
需要适配特定行业术语(法律/医疗/金融)最新信息查询(新闻、实时数据)
需要稳定的JSON/格式输出(API对接)数据频繁变化(如动态库存)
需要减少Token消耗(让模型变小但保持效果)需要引用来源的问答
需要特定推理链(如代码生成模式)隐私数据(不想训练进模型)

Q3: 微调 vs RAG vs Prompt工程 决策树

开始


需要什么? ──知识/事实──► RAG + 向量数据库

  ├────风格/语气────► 先尝试Prompt工程(角色设定+示例)
  │                          │
  │                          ▼
  │                    效果不够? ──是──► SFT/LoRA微调
  │                          │
  │                          否
  │                          ▼
  │                      满意了

  ├────格式/结构────► Prompt + Function Calling

  └────推理能力────► CoT Prompt / Fine-tune with reasoning data

二、主流微调方法

Q4: 全量微调(Full Fine-tuning)

更新模型所有参数

优点:
  ✓ 效果最好,模型行为变化最彻底
  ✓ 可以注入大量新知识

缺点:
  ✗ 计算成本极高(需要多卡A100训练数日)
  ✗ 容易"灾难性遗忘"(忘记通用知识)
  ✗ 每个任务需要独立的模型副本
  ✗ 部署成本高(每个任务一个完整模型)

适用:
  · 拥有充足GPU资源
  · 需要彻底改变模型行为
  · 有大规模高质量训练数据

Q5: LoRA(Low-Rank Adaptation,最常用)⭐

核心思想:不修改原模型权重,在Attention层新增两个"低秩矩阵"(B×A),只训练这两个小矩阵。

原始权重 W (d_model × d_model,如:4096×4096)

新增 B × A (低秩分解,如 4096×r × r×4096,r=8/16/32)

新权重 W' = W + B × A

只训练 B 和 A 的参数!

参数对比(LLaMA-7B为例):

方法训练参数量总参数量显存需求
Full7B(100%)7B100GB+
LoRA(r=8)4.2M(0.06%)7B20GB
LoRA(r=16)8.4M(0.12%)7B25GB

LoRA的优势:

  1. ✓ 训练快、成本低(普通消费级GPU可训练7B模型)
  2. ✓ 不影响原模型推理(加载时合并权重,推理无额外延迟)
  3. ✓ 多任务灵活:同一基础模型可以有N个LoRA权重,按需切换
  4. ✓ 不会灾难性遗忘(原模型权重冻结)

关键参数:

r (rank): 8/16/32  → 越大效果越好,但训练成本更高
alpha: 通常设置为 r × 2 (缩放因子)
target_modules: ["q_proj", "v_proj"] / ["q_proj", "k_proj", "v_proj", "o_proj"]
              ↑ 作用在哪些注意力层
dropout: 0.05-0.1 (防止过拟合)

Q6: QLoRA(Quantized LoRA,4bit量化+LoRA)

LoRA的进一步优化:把模型量化到4bit,训练时仅更新LoRA参数

效果对比(LLaMA-7B):

方法显存质量说明
Full100GB+最佳需要A100
LoRA(FP16)20-25GB接近Full需要3090/4090
QLoRA(4bit)8-12GB几乎与Full相当消费级GPU即可!

QLoRA核心创新:

  1. 4-bit NormalFloat量化(比传统4-bit更保序)
  2. 双量化(对量化后的常数再次量化,进一步节省显存)
  3. Paged Optimizers(利用CPU内存补充GPU显存)

结论:目前几乎所有轻量微调都用QLoRA作为默认方案。

Q7: P-Tuning / Prefix-Tuning

在输入Embedding前加"可训练的虚拟Token",不修改模型任何参数。

[虚拟Token1][虚拟Token2][虚拟Token3] [真实输入Token1][真实输入Token2]...
         └──── 这些虚拟Token的Embedding是可训练的 ────┘

特点:参数量极小,但效果通常不如LoRA,适合数据量少的场景。

Q8: 方法选择指南

┌──────────────────────────────────────────────────────────┐
│              选择微调方法的决策流程                        │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  有多少训练数据?                                        │
│  <1000条 → 先别微调,优化Prompt工程                     │
│  1K-10K条 → QLoRA (r=8) + 简单SFT格式                  │
│  10K-100K条 → LoRA (r=16/32) 或 AdaLoRA                │
│  >100K条 → 考虑Full Fine-tuning(如果有足够算力)        │
│                                                          │
│  GPU资源?                                               │
│  单卡RTX 4090 (24GB) → QLoRA 7B / 13B 模型             │
│  单卡A100 (80GB) → LoRA 7B-33B / Full 7B              │
│  多机多卡 → Full Fine-tuning 70B+                       │
│                                                          │
│  任务类型?                                              │
│  风格迁移 → LoRA足够                                     │
│  注入行业知识 → 更大r值 + 更多数据                       │
│  指令跟随 → 高质量多样本SFT                              │
│                                                          │
└──────────────────────────────────────────────────────────┘

三、数据准备(最关键的一步)

Q9: SFT数据格式

通用SFT格式(可用于LLaMA-Factory/Axolotl等框架):

[
  {
    "instruction": "用户的指令/问题",
    "input": "(可选)额外输入,如需要处理的文本",
    "output": "期望的模型回答"
  },
  {
    "instruction": "把以下句子翻译成英文",
    "input": "我爱人工智能",
    "output": "I love artificial intelligence."
  },
  ...
]

另一种对话格式(ChatML):

[
  {"role": "system", "content": "你是一个专业的代码助手"},
  {"role": "user", "content": "如何优化Python循环?"},
  {"role": "assistant", "content": "可以用以下方法..."}
]

Q10: 数据质量 > 数据数量

高质量数据的特征:

  1. ✓ 指令清晰明确(真实用户意图)
  2. ✓ 回答准确专业(有经验的人写的,不是GPT合成的)
  3. ✓ 格式一致(语气/结构统一)
  4. ✓ 多样性(覆盖不同场景/问题类型)
  5. ✓ 无错误/幻觉(人工检查)

数据规模建议:

  • 实验/POC:50-200条
  • 可用水平:500-2000条
  • 高质量:5000-20000条
  • 再往上:边际收益递减(除非数据多样性很高)

Q11: 数据增强与合成策略

策略1: 让强模型生成弱模型的训练数据
   GPT-4生成高质量回答 → 训练自己的小模型
   (被称为"知识蒸馏")

策略2: 多样化改写
   同一指令用不同方式表达(同义词、句式变化)

策略3: 自指令(Self-Instruct)
   让模型自己生成新的训练样本,人工筛选

策略4: 困难样本挖掘
   收集线上失败案例,针对性补充训练数据

四、训练流程与超参数

Q12: 完整微调流程(QLoRA为例)

Step 1: 数据准备
   · 收集/购买/合成训练数据
   · 清洗:去重、去低质量、格式标准化
   · 切分:训练集(90%) / 验证集(10%)

Step 2: 环境准备
   · GPU: 至少24GB显存推荐
   · 框架:LLaMA-Factory / Axolotl / peft + transformers
   · 模型:下载基础模型(如LLaMA-2 7B)

Step 3: 训练配置
   · 量化:4-bit (QLoRA)
   · LoRA参数:r=16, alpha=32, target_modules=[q_proj,v_proj]
   · 学习率:1e-4 到 5e-5
   · Batch size: 8-32(根据显存调整)
   · Epochs: 2-5(根据数据量)

Step 4: 执行训练
   · 监控Loss曲线(训练损失、验证损失)
   · 定期保存检查点

Step 5: 效果评估
   · 人工评测:看关键案例效果
   · 自动评测:如BLEU/ROUGE(通用指标)
   · 与Prompt工程/RAG对比

Step 6: 部署
   · 合并权重(可选):把LoRA合并到原模型
   · 部署推理服务(vLLM/llama.cpp)
   · A/B测试

Q13: 关键超参数

参数推荐值影响
learning_rate1e-4 ~ 5e-5太大不稳定、太小收敛慢
LoRA rank (r)8/16/32越大效果越好,但参数越多
alphar×2缩放因子,与r配合
batch_size8-32根据显存调整
epochs2-5太多容易过拟合
warmup_steps总步数的5%稳定早期训练
weight_decay0.01L2正则,防止过拟合

Q14: 如何判断训练成功?

看Loss曲线:

Loss

  │\\              ← 理想曲线:快速下降后平稳
  │  \\
  │    \\
  │      \\________

  └──────────────── Step

  ✗ 不下降 → 学习率太小 / 数据问题
  ✗ 波动很大 → 学习率太大 / batch太小
  ✗ 验证损失先降后升 → 过拟合,应该早停
  ✓ 稳步下降到平稳 → 正常收敛

人工评测关键指标:

  1. 指令遵循度(是否按要求回答)
  2. 输出质量(准确性、完整性)
  3. 风格一致性(语气/用词是否符合预期)
  4. 与基线对比(比纯Prompt/RAG好多少?)

五、常见问题与调优建议

Q15: 微调常见失败原因

现象可能原因解决方法
Loss不下降学习率太小/数据格式错误调大学习率/检查数据格式
Loss爆炸(NaN)学习率太大减小学习率/加梯度裁剪
训练后回答质量下降数据质量差/过拟合清洗数据/减少epochs
模型只输出训练数据过拟合+数据太少增加数据多样性/降低LoRA rank
中英文混合输出训练数据语言不纯过滤数据/增加中文比例
显存不足OOMbatch太大/模型太大减小batch/用QLoRA/梯度检查点

Q16: 过拟合的解决方法

  1. 增加训练数据(尤其是多样性)
  2. 减小LoRA rank(如从32改到8)
  3. 减少训练步数/epochs
  4. 增大weight_decay(如0.05→0.1)
  5. 加入dropout
  6. 使用更大的基础模型(小模型更容易过拟合)

六、实际工具与框架

Q17: 主流微调工具

工具特点适用场景
LLaMA-Factory一站式、支持多种模型/量化方法新手推荐
Axolotl配置驱动、灵活进阶用户
peft + transformersHuggingFace官方库需要深度定制
Unsloth大幅优化训练速度(快2-5倍)追求效率
Firefly中文友好、多种微调方法中文场景

Q18: LLaMA-Factory快速上手(代码示例)

bash
# 1. 安装
git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e .

# 2. 准备数据(JSON格式,参考Q9)
# 放到 data/train.json

# 3. 训练(QLoRA 4-bit)
llamafactory-cli train \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --stage sft \
    --do_train \
    --dataset train \
    --template default \
    --finetuning_type lora \
    --quantization_bit 4 \
    --lora_rank 16 \
    --lora_alpha 32 \
    --lora_target q_proj,v_proj \
    --output_dir saves/LLaMA2-7B/lora/train \
    --per_device_train_batch_size 4 \
    --gradient_accumulation_steps 4 \
    --lr_scheduler_type cosine \
    --logging_steps 10 \
    --save_steps 100 \
    --learning_rate 5e-5 \
    --num_train_epochs 3.0 \
    --plot_loss \
    --bf16

# 4. 合并权重 & 推理
llamafactory-cli export \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --adapter_name_or_path saves/LLaMA2-7B/lora/train \
    --template default \
    --finetuning_type lora \
    --export_dir merged_model \
    --export_size 2 \
    --export_legacy_format False

微调核心要点速查

问题一句话答案
什么时候该微调?Prompt工程+RAG不够时,需要特定风格/格式/术语时
优先用什么方法?QLoRA(4bit量化+LoRA),性价比最高
需要多少数据?至少500条高质量,推荐2000+条
数据质量和数量哪个重要?质量 >> 数量,100条高质量>10000条低质量
如何评估效果?验证集Loss + 人工评测关键案例 + 线上A/B
过拟合怎么办?增加数据多样性、减小LoRA rank、减少训练步数
训练后如何部署?合并权重 → 用vLLM/llama.cpp部署推理
微调成本?7B模型QLoRA训练:消费级GPU几小时,电费$10-$100

Released under the MIT License.