用 LoRA 與 QLoRA 微調
微調調的是行為,不是知識。模型懂材料卻跳錯舞時它是對的工具:輸出格式錯、語氣錯、領域方言錯、拒絕校準錯。它不是「認得我的文件」的工具——那是檢索:RAG。
微調還是不微調
| 目標 | 伸手拿 |
|---|---|
| 從我的文件回答問題 | RAG |
| 永遠輸出我精確的 JSON/XML 格式 | LoRA——或文法約束解碼 |
| 用一致的機構風格寫作 | LoRA |
| 不再拒絕合理的領域請求 | LoRA,搭配謹慎的資料 |
| 流利說我的領域方言 | LoRA,再疊 RAG |
| 推理更好 | 更大或更好的基底模型——微調不加智商 |
提示詞或 schema 做得到的,優先用提示詞或 schema。當你發現自己每次呼叫都在貼同樣 300 token 的指令時,才微調。
一段話講完 LoRA
凍結所有基底權重。對每個目標權重矩陣,加兩個小的可訓練矩陣——A(r×d)與 B(d×r)——只訓練它們。更新是低秩的:
W' = W + (alpha / r) · B·A # A 是 r×d,B 是 d×r,秩 r << d
具體:d = 4096 的矩陣在秩 r = 16 下,需要 2 × 4096 × 16 = 131k 個配接器參數,而不是 4096² ≈ 16.8M 個稠密參數——那張矩陣的 0.8%。整個 7–8B 模型,配接器共約 40–80M 參數:基底的 0.5–1%、幾百 MB。那足以強力推動風格與格式,因為那些行為住在強低秩方向上。
QLoRA:一張消費級顯示卡
QLoRA 在訓練期間把凍結的基底量化在 4-bit(NF4),配接器以 16-bit 跑。目前工具鏈的實際數字:7–8B 模型在單張 24GB GPU 上做 QLoRA 訓練;3B 在 8GB 內綽綽有餘。梯度檢查點與分頁最佳化器由工具處理——你要提供的是預算數學:VRAM 用量計算。
資料勝過一切
500–5,000 對高品質配對,每次都贏過 100k 對爬來的配對。重要的規則:
- **格式前後一致。**用你部署時的同一個對話模板——訓練/部署模板不匹配會毀掉整次訓練。
- **品質勝過數量。**每一對都該是你能接受的模型輸出。去重複;丟掉偷懶的範例。
- **涵蓋率。**納入你希望模型拒絕或特別處理的情況——否則它會把新行為過度概化到所有事情上。
- **污染檢查。**確認評測問題沒有出現在訓練資料裡——否則你在評的是背誦。
- **保留評測集。**50–100 個從不拿來訓練的範例,訓練前後各評一次。
一對資料長什麼樣(多數工具吃的 messages 格式):
{"messages": [{"role": "system", "content": "You are a 1998-era equipment manual assistant."},
{"role": "user", "content": "How do I reset the service counter?"},
{"role": "assistant", "content": "Press MENU and hold for 3 seconds..."}]}
工具
| 工具 | 選它的理由 |
|---|---|
| Unsloth | 最快的單 GPU 訓練器、免費社群筆記本——輕鬆的起點 |
| Axolotl | 設定驅動、支援多種資料集格式、可重現的配方 |
| LLaMA-Factory | GUI 加 CLI、多語資料集生態強大 |
截至目前三者都活躍維護中:unsloth、axolotl、llama-factory。
真正重要的超參數
按影響排序:
- 學習率——QLoRA 用 1e-4 到 2e-4 是合理區間;過高是糊掉的常見原因。
- Epoch 數——1–3。更多就養出應聲蟲。
- 秩/alpha——r 8–32 配 alpha 16–32 涵蓋多數行為調整;領域重度轉變用更大的秩。
- 上下文長度——設成你最長的真實範例,不是訓練器預設。
- 批次大小——單卡 QLoRA 用 1–8 很正常;它是吞吐量旋鈕,不是品質旋鈕。
結果令人失望時,先修資料、再修學習率、最後才動秩。
時間與成本
QLoRA、2,000 對、3 個 epoch、7–8B 模型:單張 RTX 3090/4090 級顯示卡預期 1–3 小時。那是電費,不是 API 帳單,迭代最多隔夜。這就是本機微調是嗜好、不是採購流程的原因。
為迭代編預算:第一次跑教你資料的問題,第二次才是留下的那個。
出貨前先評估
出貨前後各跑一次固定的 30–50 個提示詞——包含保留集——並排 diff 輸出。然後回歸檢查一般對話:經典失敗是領域微調模型用錯誤報告格式回答一切。若一般品質下降,減少 epoch、降低學習率,或在訓練中混入 10–30% 的一般指令資料。
loss 曲線用來看出發散,不用來打分數:訓練 loss 應該下降後趨平。評測集才是裁判。
匯出與部署
訓練好的配接器有兩條路:
- 把 LoRA 以 fp16 合併進基底,再轉成 GGUF 給 llama.cpp——論壇友善的成品:一個檔案、任何引擎:模型格式、量化。
- 為 transformers/vLLM 保留獨立配接器,它們在執行時載入基底+配接器——迭代更便宜、綁定引擎。
失敗模式
- 過擬合/「應聲蟲」——複誦你的提示詞、同意一切;訓練 loss 低、評測更差。解法:更少 epoch、更低學習率、更多樣的資料。
- 災難性遺忘——領域技能上升、一般能力下降。解法:混入一般資料;降低學習率。
- 模板漂移——用一個對話模板訓練、用另一個部署;症狀就是 疑難排解 裡的經典款。
SFT 之後的 DPO
格式對了但偏好不對——太冗長、語氣錯、過度拒絕——對偏好配對(chosen 對 rejected 回應)跑一輪小型 DPO,不必再跑一次 SFT 就能調整行為。便宜、穩定,是 SFT 然後 DPO 配方的標準第二階段。