10-Fine-tuning/微调:给AI上"专业课"

0 阅读7分钟

Fine-tuning/微调:给AI上"专业课"

这篇文章带你理解AI的"专业培训"——微调,让通用模型变成领域专家。

前言

预训练出来的AI,就像一个读完图书馆的"通识生":

  • 什么都知道一点
  • 但什么都不精通
  • 聊天还行,专业任务差点意思

怎么让它变专业?Fine-tuning(微调)

今天,我们来理解AI的"专业课"。


一、黑话原文 vs 人话翻译

场景模拟

🎯 AI算法团队:

工程师A:"我们用LoRA微调一下"
工程师B:"全量微调成本太高,用PEFT吧"
工程师C:"数据量不够,容易过拟合"
工程师A:"那用Few-shot微调"
工程师B:"记得冻结底层参数"

人话翻译表

黑话人话翻译一句话理解
Fine-tuning微调专业培训
Full Fine-tuning全量微调重新学所有内容
PEFT参数高效微调只改一小部分
LoRA低秩适应只学"差异"
冻结参数Freezing不改基础内容
过拟合Overfitting死记硬背

二、微调是什么?

2.1 一句话定义

Fine-tuning = 在预训练模型基础上,用特定数据继续训练

人话版:给"通识生"上专业课,让它变成某个领域的专家。

2.2 为什么需要微调?

┌─────────────────────────────────────────────────────────────┐
│                    预训练模型的局限                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  预训练模型(通识生):                                      │
│                                                             │
│  ✅ 能力:                                                  │
│  ├── 会说人话                                              │
│  ├── 有基本常识                                            │
│  └── 能简单对话                                            │
│                                                             │
│  ❌ 问题:                                                  │
│  ├── 不懂专业领域知识                                      │
│  ├── 说话风格不固定                                        │
│  ├── 输出格式不规范                                        │
│  └── 可能说"不合适"的话                                    │
│                                                             │
│  微调后(专家):                                           │
│                                                             │
│  ✅ 能力:                                                  │
│  ├── 懂专业领域知识                                        │
│  ├── 说话风格符合要求                                      │
│  ├── 输出格式规范                                          │
│  └── 知道什么该说什么不该说                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.3 生活类比

微调就像:

🎓 大学专业培训
预训练 = 高中毕业(什么都学过)
微调 = 大学专业(计算机/医学/法律...)

🏥 医生规培
医学院毕业 = 有医学知识
规培 = 学会临床技能

👔 入职培训
新人 = 有基本能力
培训 = 学会公司规范

三、微调的类型

3.1 Full Fine-tuning(全量微调)

┌─────────────────────────────────────────────────────────────┐
│                    全量微调                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  原理:更新模型的所有参数                                    │
│                                                             │
│  预训练模型 ────→ 所有参数都改 ────→ 微调模型               │
│  (7B参数)         (175亿个)          (7B参数)               │
│                                                             │
│  优点:                                                     │
│  ✅ 效果最好                                                │
│  ✅ 适应性强                                                │
│                                                             │
│  缺点:                                                     │
│  ❌ 成本高(需要更新所有参数)                              │
│  ❌ 显存要求大                                              │
│  ❌ 容易过拟合                                              │
│  ❌ 需要大量数据                                            │
│                                                             │
│  适用:                                                     │
│  - 大公司                                                   │
│  - 资源充足                                                 │
│  - 追求最佳效果                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 PEFT(参数高效微调)

┌─────────────────────────────────────────────────────────────┐
│                    PEFT - 只改一小部分                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  原理:冻结大部分参数,只更新少量参数                        │
│                                                             │
│  预训练模型                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ ████████████████████████████████████████ ← 冻结     │   │
│  │ ████████████████████████████████████████ ← 冻结     │   │
│  │ ░░░░░░░░ ← 只改这部分(新增的少量参数)             │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  优点:                                                     │
│  ✅ 成本低(只需1%的参数)                                  │
│  ✅ 显存要求小                                              │
│  ✅ 不容易过拟合                                            │
│  ✅ 可以保存多个微调版本                                    │
│                                                             │
│  缺点:                                                     │
│  ❌ 效果略差于全量微调                                      │
│                                                             │
│  代表方法:LoRA、Prefix Tuning、Adapter                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.3 对比表

方法更新参数量显存需求效果适用场景
全量微调100%很高最好大公司、追求极致
LoRA~1%很好个人、中小企业
QLoRA~1%很低消费级显卡
Adapter~1%多任务场景

四、LoRA:最流行的微调方法

4.1 LoRA原理

┌─────────────────────────────────────────────────────────────┐
│                    LoRA原理                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  原始矩阵 W (7B模型中的一个大矩阵)                           │
│                                                             │
│  传统微调:直接修改 W                                       │
│  W_new = W + ΔW   (ΔW也是大矩阵)                            │
│                                                             │
│  LoRA的思路:                                               │
│  ΔW = A × B   (两个小矩阵相乘)                              │
│  - A: n×r 矩阵                                              │
│  - B: r×n 矩阵                                              │
│  - r 很小(如816)                                        │
│                                                             │
│  举例:                                                     │
│  原始 W: 4096×4096 = 16,777,216 个参数                      │
│  LoRA: A(4096×8) + B(8×4096) = 65,536 个参数                │
│  只需要原来的 0.4%!                                        │
│                                                             │
│  ┌───────────────────────────────────────────────────────┐ │
│  │                    原始W (冻结)                        │ │
│  │   ┌─────────────────────────────────────────┐        │ │
│  │   │                                         │        │ │
│  │   │           4096 × 4096                   │        │ │
│  │   │                                         │        │ │
│  │   └─────────────────────────────────────────┘        │ │
│  │                        +                              │ │
│  │   LoRA (可训练)                                       │ │
│  │   ┌──────┐    ┌────────────────┐                     │ │
│  │   │ 4096 │    │                │                     │ │
│  │   │  ×8  │ ×  │      8×4096    │                     │ │
│  │   │      │    │                │                     │ │
│  │   └──────┘    └────────────────┘                     │ │
│  │      A              B                                 │ │
│  └───────────────────────────────────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 LoRA代码示例

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM

# 加载预训练模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")

# LoRA配置
lora_config = LoraConfig(
    r=8,                    # LoRA的秩
    lora_alpha=32,          # 缩放系数
    target_modules=["q_proj", "v_proj"],  # 应用到哪些层
    lora_dropout=0.1,
    bias="none",
    task_type="CAUSAL_LM"
)

# 应用LoRA
model = get_peft_model(model, lora_config)

# 查看可训练参数
model.print_trainable_parameters()
# 输出:trainable params: 4,194,304 || all params: 6,742,609,920 || trainable%: 0.06%

4.3 QLoRA:更省显存

# QLoRA = 量化 + LoRA
# 用4bit精度加载模型,再应用LoRA

from transformers import BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

# 4bit量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
)

# 加载4bit模型
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config
)

# 准备量化训练
model = prepare_model_for_kbit_training(model)

# 应用LoRA
model = get_peft_model(model, lora_config)

# 显存对比:
# 全量微调 7B: ~28GB
# LoRA 7B: ~16GB
# QLoRA 7B: ~6GB (单张RTX 3060就能跑!)

五、微调数据

5.1 微调数据格式

// 对话微调数据格式
{
  "conversations": [
    {"role": "user", "content": "什么是机器学习?"},
    {"role": "assistant", "content": "机器学习是一种让计算机从数据中学习的技术..."}
  ]
}

// 指令微调数据格式
{
  "instruction": "将下面的句子翻译成英文",
  "input": "今天天气真好",
  "output": "The weather is really nice today."
}

5.2 数据量需求

┌─────────────────────────────────────────────────────────────┐
│                    微调数据量参考                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  任务类型        最少数据量    推荐数据量                    │
│  ──────────     ─────────    ────────────                  │
│  风格调整        100-500条    1,000-5,000条                 │
│  简单任务        500-1,000条  5,000-10,000条                │
│  复杂任务        1,000+条     10,000+条                     │
│  领域知识        5,000+条     50,000+条                     │
│                                                             │
│  注意:                                                     │
│  - 数据质量 > 数据数量                                      │
│  - 宁缺毋滥                                                 │
│  - 数据要有多样性                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.3 数据准备技巧

微调数据准备:

  1. 数据清洗:
     - 去除重复
     - 过滤低质量
     - 检查格式

  2. 数据增强:
     - 改写
     - 扩展
     - 合成

  3. 数据平衡:
     - 类别均衡
     - 长度分布

  4. 数据划分:
     - 训练集 80%
     - 验证集 10%
     - 测试集 10%

六、微调的坑

6.1 过拟合

┌─────────────────────────────────────────────────────────────┐
│                    过拟合 = 死记硬背                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  症状:                                                     │
│  - 训练数据表现很好                                         │
│  - 新数据表现很差                                           │
│  - 输出和训练数据一模一样                                   │
│                                                             │
│  原因:                                                     │
│  - 数据太少                                                 │
│  - 训练太久                                                 │
│  - 学习率太高                                               │
│                                                             │
│  解决方案:                                                 │
│  ├── 增加数据量                                             │
│  ├── Early Stopping(提前停止)                             │
│  ├── 降低学习率                                             │
│  ├── 使用Dropout                                            │
│  └── 使用正则化                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 灾难性遗忘

┌─────────────────────────────────────────────────────────────┐
│                    灾难性遗忘 = 忘了老知识                   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  症状:                                                     │
│  - 学会了新任务                                             │
│  - 忘了旧能力                                               │
│  - 通用能力下降                                             │
│                                                             │
│  原因:                                                     │
│  - 微调数据太单一                                           │
│  - 全量微调改动太大                                         │
│                                                             │
│  解决方案:                                                 │
│  ├── 混合微调数据(旧任务+新任务)                          │
│  ├── 使用PEFT(只改小部分参数)                             │
│  └── 控制学习率                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

七、微调实战

7.1 完整微调流程

from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer
)
from peft import LoraConfig, get_peft_model
from datasets import load_dataset

# 1. 加载模型和tokenizer
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")

# 2. 应用LoRA
lora_config = LoraConfig(r=8, lora_alpha=32, ...)
model = get_peft_model(model, lora_config)

# 3. 加载数据
dataset = load_dataset("json", data_files="train_data.json")

# 4. 数据处理
def preprocess(examples):
    return tokenizer(examples["text"], truncation=True, padding="max_length")

tokenized_dataset = dataset.map(preprocess, batched=True)

# 5. 训练配置
training_args = TrainingArguments(
    output_dir="./output",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    learning_rate=1e-4,
    logging_steps=100,
    save_steps=500,
)

# 6. 开始训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
)

trainer.train()

# 7. 保存模型
model.save_pretrained("./my_finetuned_model")

小结

黑话人话记忆口诀
Fine-tuning微调专业培训
Full Fine-tuning全量微调全部重学
PEFT高效微调只改一点
LoRA低秩适应最流行的PEFT
过拟合死记硬背只会做原题
灾难性遗忘忘了老知识学新忘旧

关键认知

  • 微调让通用模型变成专家
  • LoRA是最流行的高效微调方法
  • 数据质量比数量重要
  • 注意避免过拟合和灾难性遗忘

黑话等级

⭐⭐⭐⭐ 中级
├── 理解微调的原理
├── 会用LoRA微调模型
└── 知道如何避免常见问题

下一期预告:RLHF - 让AI更"听话"的秘密

思考与练习

  1. 思考题

    • LoRA为什么能用很少的参数达到好的效果?
    • 什么时候用全量微调,什么时候用PEFT?
  2. 动手练习

    • 用LoRA微调一个开源模型
    • 对比微调前后的效果差异
  3. 延伸探索

    • 研究其他PEFT方法(Adapter、Prefix Tuning)
    • 了解多任务微调

下期预告

下一篇文章,我们来聊:RLHF - 让AI更"听话"的秘密

会解答这些问题:

  • RLHF是怎么让AI变"乖"的?
  • 为什么要用人类反馈?
  • PPO是什么?

关注专栏,不错过后续更新!


作者:ECH00O00 本文首发于掘金专栏《AI黑话翻译官》 欢迎评论区交流讨论,点赞收藏就是最大的鼓励