0. 什么是“微调”?为什么必须微调?

方式 数据量 计算资源 效果 场景
提示工程 0 CPU 即可 60~70 分 临时对话
RAG 千级文档 CPU/GPU 70~80 分 动态知识
微调(SFT) 万~百万样本 1~8×A100 85~95 分 领域专家
预训练 千亿 token 千卡 100 分 底座模型

微调 = 用 1% 算力拿到 90% 能力,是绝大多数企业的“甜点区”。


1. 微调技术演进图

2018  Fine-Tune 全参量  
     ↓  
2021  Adapter / LoRA / AdaLoRA(参数高效)  
     ↓  
2023  QLoRA(4-bit 量化 + LoRA)+ RLHF(人类偏好)  
     ↓  
2024  GaLore、DoRA、LongLoRA(继续降显存 / 长文本)

本文聚焦生产落地最成熟SFT + LoRA/QLoRA 路线。


2. 概念速览(3 分钟弄懂)

缩写 全称 一句话
SFT Supervised Fine-Tuning 有监督指令微调,让模型“说人话”
LoRA Low-Rank Adaptation 只训练两个小矩阵,冻结原模型
QLoRA Quantized LoRA 先量化到 4 bit,再 LoRA,显存减半
RLHF Reinforcement Learning from Human Feedback 用人类打分训练奖励模型,再 PPO
PEFT Parameter-Efficient Fine-Tuning 所有“小参数”技巧统称

3. 微调全流程(9 步)

  1. 场景定义 → 2. 数据制备 → 3. 基座选型 → 4. 环境搭设
  2. 参数高效策略 → 6. 训练 → 7. 评估 → 8. 合并导出 → 9. 上线推理

4. Step-by-Step 实战:中文医疗问答模型

4.1 场景定义

目标:让 7B 模型回答“感冒能喝咖啡吗”等中文医疗咨询,减少幻觉

4.2 数据制备

来源 量级 处理要点
医学百科 15 万条 清洗 HTML、去广告
医患对话开源集 5 万条 脱敏、去隐私
自建指令集 1 万条 医生审核,标注“是否可答”

格式:Alpaca 指令模板

{
  "instruction": "患者问:感冒能喝咖啡吗?",
  "input": "",
  "output": "感冒期间不建议大量饮用咖啡..."
}

经验:领域指令 ≥ 1 万条即可让 7B 模型脱胎换骨

4.3 基座选型

候选 参数量 中文 商用 选择
Llama-3-8B 8 B ★★☆ 英文优
Qwen2.5-7B 7 B ★★★
Baichuan2-7B 7 B ★★★ 备选

最终锁定 Qwen2.5-7B-Instruct(已 SFT 一次,继续二次增强)。

4.4 环境搭设

# CUDA 12.1 驱动
pip install transformers>=4.41 peft accelerate bitsandbytes \
            datasets transformers_stream_generator

单卡 A100 40 GBRTX 4090 24 GB 均可跑 QLoRA

4.5 参数高效策略(QLoRA)

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

model_id = "Qwen/Qwen2.5-7B-Instruct"
tokenizer = transformers.AutoTokenizer.from_pretrained(model_id)

# 4-bit 量化加载
model = transformers.AutoModelForCausalLM.from_pretrained(
    model_id,
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    device_map="auto"
)
model = prepare_model_for_kbit_training(model)

# LoRA 配置
lora_config = LoraConfig(
    r=64,
    lora_alpha=128,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()  # 仅 0.8% 参数参与训练!

4.6 训练脚本(Trainer 版)

train_dataset = load_dataset("json", data_files="med_zh.jsonl", split="train")
def template(example):
    prompt = f"Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instruction:\n{example['instruction']}\n\n### Response:\n{example['output']}"
    return {"text": prompt}

train_dataset = train_dataset.map(template, remove_columns=train_dataset.column_names)

trainer = transformers.Trainer(
    model=model,
    train_dataset=train_dataset,
    args=transformers.TrainingArguments(
        per_device_train_batch_size=1,
        gradient_accumulation_steps=32,
        num_train_epochs=3,
        learning_rate=2e-4,
        fp16=True,
        logging_steps=10,
        output_dir="./qwen_med_qlora",
        optim="paged_adamw_8bit",
        save_strategy="epoch",
    ),
    data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
trainer.train()

显存占用:7B/4-bit + LoRA ≈ 18 GB(4090 即可跑)。

4.7 评估(自动化 + 人工)

  1. 自动化:BLEU-4 / ROUGE-L / perplexity
  2. 对抗测试
    • 输入:“一岁宝宝发烧 39 度怎么办?”
    • 要求:必须出现“及时就医”关键词 → 未出现即判负
  3. 医生盲审:100 条样本双盲打分,胜率 85% 即达标。

4.8 合并导出(LoRA 与基座合一)

from peft import PeftModel

# 加载 LoRA
model = PeftModel.from_pretrained(model, "./qwen_med_qlora/checkpoint-xxx")
# 合并
merged = model.merge_and_unload()
merged.save_pretrained("./qwen_med_merged")
tokenizer.save_pretrained("./qwen_med_merged")

产出 单文件 .bin.safetensors,方便 vLLM / TensorRT-LLM 部署。

4.9 上线推理(vLLM 高并发)

pip install vllm
python -m vllm.entrypoints.openai.api_server \
  --model ./qwen_med_merged \
  --tensor-parallel-size 2 \
  --served-model-name qwen-med-7b

业务侧 零改造 替换 base_url 即可。


5. 超参数经验表(直接抄)

参数 医疗 7B 闲聊 13B 代码 34B 备注
LoRA r 64 128 256 越大越贵
lora_alpha 128 256 512 一般 2×r
learning_rate 2e-4 1e-4 5e-5 大模型要更小
batch_size 1 2 4 显存决定
gradient_accum 32 64 128 线性放大
num_epochs 3 2 1 早停防止过拟
max_seq_len 1024 2048 8192 长文本用 LongLoRA

6. 成本与速度实测(单卡 A100 40 GB)

方案 可训练参数量 显存 速度 (token/s) 3 万条 1024 长度耗时
全参量 7 B 28 GB 2100 38 h
LoRA 16 0.1 B 22 GB 2000 36 h
QLoRA 64 0.05 B 18 GB 1900 34 h

QLoRA 仅 2% 参数、显存降 35%,效果与 LoRA 持平 → 生产首选。


7. 进阶:RLHF 让模型“说人话”

流程:

  1. 训练奖励模型(RM)—— 医生对回答打分 → 训练 BERT 回归器
  2. PPO 强化学习 —— 用 RM 当奖励,微调策略模型
  3. KL 惩罚 —— 防止模型“放飞”

工具:

  • TRLX / ColossalChat 已封装 PPO,3 万样本 8×A100 一天跑完
  • 医疗场景 RLHF 后,有用性 +9.2%,有害率 -4.1%(内部盲审)

8. 常见坑 & 解决

症状 解决
loss=0 学习率太高 降到 1e-5
显存爆 没开梯度检查点 model.gradient_checkpointing_enable()
生成乱码 模板不一致 推理模板必须与训练完全一致
过拟合 评估指标下降 LoRA r 减小 + dropout 0.1 + early stopping

9. 总结:一张思维导图带走

场景定义 → 数据 1w+ → Qwen2.5-7B
                ↓
        QLoRA 4-bit + r=64
                ↓
        3 epoch + 2e-4 + GPU 24 GB
                ↓
        merge → vLLM 部署 → RLHF(可选)

记住:“大模型微调不是炼金术,而是数据工程 + 参数高效策略 + 系统评估”

AI大模型学习代码仓库

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐