第二课 · 用 peft + QLoRA
炼一个外贸小助手

从手撕 → 工程化

Qwen2.5-1.5B · 500 条 Incoterms + HS QA · Kaggle T4

📚 今日路线

  1. 第一课回顾:我们到哪里了?
  2. PEFT 家族与 QLoRA 原理 (15 min)
  3. 数据加载 + SFTTrainer 配置 (20 min)
  4. 训练、合并、推理、评测 (75 min)
  5. 部署 demo 一页纸 (15 min)
  6. 组间展示评比 (30 min)

1. 第一课回顾

第一课(原理课)

  • 手写 LoRALinear(~30 行)
  • 挂到 q_proj / v_proj
  • 可训练参数 0.16%
  • SVD 验证低秩假设

第二课(实战课)

  • 换 🤗 peft 工业级工具
  • 4bit 量化底座(QLoRA)
  • 更大模型(1.5B-Instruct)
  • 真·下游任务(外贸 QA)
手撕过一遍 → 用框架更有感觉:你知道 peft 底层每一步在做什么

② PEFT 家族 与 QLoRA 原理

15 min · 把"为什么 4bit 还能训"讲清楚

2.1 PEFT 家族全景

方法核心思想代表
Prompt Tuning学一段可训练的 soft promptGPT-3 soft prompt
Prefix Tuning每层注入可训练的 prefix KVLi & Liang 2021
LoRA权重更新低秩分解 $W + BA$Hu et al. 2021
QLoRA4bit 量化底座 + LoRADettmers 2023
DoRA / AdaLoRA幅度/方向解耦、自适应秩2024+

工业界主流:LoRA / QLoRA(简单、快、adapter 小)

2.2 QLoRA 一页纸

原模型 Qwen2.5-1.5B (fp16, 3GB) ↓ 4bit NF4 量化 量化底座 (0.9GB) ────冻结不训练──── + 每个 Linear 外挂 LoRA (A, B) ── fp16 训练 ── ↓ 前向:h = dequant(W_4bit) @ x + (α/r) · B·A·x 反向:只对 A, B 求梯度

三项关键技术:NF4 量化 · 双重量化 · Paged Optimizer

效果:1.5B 模型在 Kaggle T4 (16GB) 上训练占用 ~6GB

2.3 为什么能压到这么小?

存储项全量微调QLoRA
模型参数3 GB (fp16)0.9 GB (4bit)
梯度3 GB~35 MB
AdamW state6 GB (2×)~70 MB
激活 (MAX_LEN=512, bs=2)~4 GB~4 GB
合计~16 GB~5 GB
🎯 Kaggle T4 (16GB) 全量微调 1.5B 都已经很勉强,QLoRA 可以轻松跑 7B

③ 数据 与 Loss Mask

20 min · 让模型"学答不学问"

3.1 任务:外贸术语 QA

训练集:500 条
盲测集:50 条

数据格式(Alpaca-style):


{
  "instruction": "请解释 FOB 和 CIF 的区别。",
  "input": "",
  "output": "FOB(Free On Board)..."
}
    

覆盖面:Incoterms 11 术语 + HS 编码归类规则 + 中国出口实务

3.2 数据处理:Chat Template + Loss Mask

Qwen2.5-Instruct 用 ChatML:


<|im_start|>user
请解释 FOB。<|im_end|>
<|im_start|>assistant
FOB(Free On Board)...<|im_end|>
    

关键技巧:

labels = [-100]*len(prompt) + full_ids[len(prompt):]

→ 只对 assistant 段 计算 loss,模型学答不学问

④ peft 三板斧

75 min · 训练 + 合并 + 推理 + 评测

4.1 peft 三板斧

① LoraConfig(怎么挂)


LoraConfig(
    r=8, lora_alpha=16, lora_dropout=0.05,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    task_type="CAUSAL_LM", bias="none",
)
    

② get_peft_model(挂上去)


model = get_peft_model(base_model, config)
model.print_trainable_parameters()
# trainable: 8.8M / 1.55B (0.566%)
    

4.2 peft 三板斧(续)

③ save_pretrained / merge_and_unload


# 只存 adapter(30-40 MB)
model.save_pretrained("./adapter")

# 或:合并回底座,导出完整模型(需非量化底座)
merged = PeftModel.from_pretrained(base_fp16, "./adapter").merge_and_unload()
merged.save_pretrained("./merged")
    

两种部署形态:

  • Adapter only:热切换多任务,推理多一次矩阵乘
  • Merged model:部署简单,但失去热切换能力

4.3 训练配置(常用)


TrainingArguments(
    num_train_epochs=3,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=4,     # 有效 bs=8
    learning_rate=2e-4,                # LoRA 专用,比全量 FT 大 10×
    warmup_ratio=0.05,
    fp16=True,
    gradient_checkpointing=True,        # QLoRA 必开
    optim="paged_adamw_8bit",           # QLoRA 专属
)
    

Kaggle T4 训练时间:3-5 分钟 / 3 epochs

⑤ 评测 与 部署

BLEU / ROUGE-L · 三种部署形态

5. 评测:BLEU + ROUGE-L

中文评测必做:用 jieba 分词后再算


import jieba
preds_tok = [" ".join(jieba.lcut(p)) for p in preds]

# BLEU: sacrebleu.corpus_bleu
# ROUGE-L: rouge_scorer.RougeScorer(["rougeL"])
    

参考区间(500 训练 + 50 测):

BLEUROUGE-L
基座 Qwen2.5-1.5B-Instruct12-1828-35
LoRA 后20-2842-50
Δ+8+12
中文 QA 的 BLEU 绝对值不高,看相对提升更重要

6. 部署 demo

方案 A — HuggingFace Hub


huggingface-cli upload your-name/qwen-trade ./adapter
# 别人: base + PeftModel.from_pretrained("your-name/qwen-trade")
    

方案 B — Ollama(合并后转 GGUF)


ollama create trade-bot -f Modelfile
ollama run trade-bot "什么是 DPU 术语?"
    

方案 C — 微信云函数 (组 3 亮点)

  • 合并模型转 ONNX / TensorRT
  • 云函数挂载模型,HTTP 触发推理

7. Kaggle / Mac 对比

Kaggle T4Mac M1-M4
框架分支bitsandbytes (4bit)fp16 native
训练速度3-5 min / 3 epoch15-20 min
显存占用~6 GB~4 GB
代码差异MODE="qlora"MODE="fp16_lora"
同一份 notebook 两边跑——关键在于 prepare_model_for_kbit_training 只在 CUDA 下调用

8. 作业要求(摘要)

必做(100 分)

  1. 跑通训练 + 50 条盲测集评分 (30 分)
  2. 参数量报告 + adapter 大小 (20 分)
  3. 至少 1 个 ablation(rank / target / lr 三选一)(20 分)
  4. 失败案例分析 (20 分)
  5. 组间展示 (10 分,课堂打分)

加分(+20):部署 demo · HF Hub 发布 · unsloth 加速

详见 homework.md

🦞 开始训练吧

打开 notebook_qlora_kaggle.ipynb

Run All → 大约 10 分钟后你就有一个外贸小助手

有问题随时问 · 下次课带着盲测分来