跳到主要內容

LV.13

初次鍛造

第一次讓模型學會找出病歷裡的個資

BOSS
考古題背誦魔
時間
約 90 分鐘
建議先過
LV.12

先看 Boss:考古題背誦魔

你有沒有遇過這樣的同學:歷屆考古題背得滾瓜爛熟,題目一換就不會?考古題背誦魔就是這種模型。它在訓練資料上的 loss(損失,可以想成答錯的程度)一路降到接近 0,換一份沒看過的病歷,卻開始亂答。

這一關要完成你的第一次 fine-tune,同時學會看出牠什麼時候出現。

訓練任務與資料

任務很單純:輸入一份中英夾雜的合成病歷,輸出一個 PHI 清單 JSON(格式見 LV11)。遮蔽由程式執行。資料是你在 LV11 切好的 train.jsonl 與 valid.jsonl。

基底模型是 Gemma 4 E2B(Apache-2.0 授權)。截至 2026-10,本站在 Mac 使用 4-bit 的 MLX 版本,在 Colab 使用 Unsloth 的 Gemma 4 E2B。

🍎 Mac:mlx_lm lora

下面是作者實測 E1 使用的設定(M5、32GB、mlx-lm 0.32.0)。--model 等路徑請換成你自己的。

mlx_lm lora \
  --model ./models/gemma-4-E2B-it-MLX-4bit \
  --train \
  --data ./data/sft \
  --adapter-path ./adapters/chartkeeper \
  --iters 100 \
  --batch-size 4 \
  --max-seq-length 2048 \
  --learning-rate 1e-4 \
  --mask-prompt \
  --grad-checkpoint

逐個參數解釋:

  • mlx_lm lora:呼叫 mlx-lm 的 LoRA 訓練功能。
  • --model:要微調的底座模型。這個是 4-bit 量化版,因此整個流程屬於 QLoRA。
  • --train:告訴它要訓練(不加則不訓練)。
  • --data:資料夾,裡面要有 train.jsonl、valid.jsonl(需要時還有 test.jsonl)。
  • --adapter-path:訓練出的 LoRA adapter 存放處。adapter 只有幾 MB,原模型沒有被改動。
  • --iters 100:訓練 100 次更新。每次看 4 筆,大約等於看了 400 筆次。資料量比這小時,同一筆資料會被重複看到。
  • --batch-size 4:一次看 4 筆再更新。數字大,每步更穩,但吃更多記憶體。
  • --max-seq-length 2048:每筆資料最多算 2048 個 token,超過的截掉。一份病歷加答案要能放進去,不然會被截斷。
  • --learning-rate 1e-4:每次更新的步伐大小,1e-4 就是 0.0001。太大容易震盪、太小學得慢。
  • --mask-prompt:只對回答的部分計算 loss,不對 system 與 user 的部分。因為我們要模型學的是「看到病歷後該輸出什麼」,不是去學怎麼複誦病歷。
  • --grad-checkpoint:用時間換記憶體。只保留一部分中間計算結果,需要時重算。

作者在 M5 32GB 的實測。先看冒煙測試(FINDINGS E1,--iters 100,只用來確認流程跑得通,不是正式訓練):

  • 可訓練參數 6.8M,占總參數 4,628M 的 0.147%。
  • 100 次迭代用 1076 秒,約 18 分鐘,吞吐約每秒 60–66 個 token。
  • peak memory footprint 為 14.8GB。
  • 備註:訓練期間同時有網路下載,速度可能偏低。

正式訓練(公開資料集 v1.0,train 700 份,--iters 350,約 2 個 epoch,其餘參數同上):

  • 總時間 3361 秒,約 56 分鐘(M5 32GB,同時沒有其他重負載)。
  • peak memory footprint 為 15.3GB。
  • val loss 由 0.564 降到 0.047(iter 50)、再到 0.015(iter 350),這 350 次迭代中沒有看到 val loss 回升。
  • 提醒:val loss 很低只代表模型在驗證集上擬合得好;合成資料分布單純,仍需用 LV14 的 span recall 評估,不能只看 loss。

16GB Mac 的降配建議(【待實測】)

冒煙測試的 14.8GB、正式訓練的 15.3GB 在 32GB 機器上輕鬆,在 16GB 上餘裕很小,系統與其他程式也要用記憶體。方向是降低以下設定,但具體能否順利跑完【實測數據待補】:

  • --batch-size 1
  • --num-layers 8(只在最後 8 層加 LoRA;mlx-lm 預設為 16 層)
  • --max-seq-length 1024(先確認你的資料長度夠用,否則答案會被截掉)

建議關掉其他大型程式後再試,若出現記憶體錯誤,再往下調。

☁️ Colab:Unsloth

本站改寫的 notebook 對應如下,打開後由上往下逐格執行(Runtime 選 T4 GPU):

  • FastModel.from_pretrained("unsloth/gemma-4-E2B-it", max_seq_length=2048, load_in_4bit=False):載入模型。T4 若出現 CUDA out of memory,把 load_in_4bit 改成 True。
  • FastModel.get_peft_model(..., r=16, lora_alpha=16, ...):加上 LoRA adapter。這裡只訓練語言層,關閉視覺層。
  • SFTTrainer 與 SFTConfig:批次大小 2、gradient accumulation 4(等效 batch 8)、2 個 epoch、learning rate 1e-4。
  • train_on_responses_only(trainer):和 Mac 的 --mask-prompt 目的相同,只對回答計 loss。
  • 每個 epoch 結束會在 valid 集上算一次 loss(eval_strategy="epoch")。

Colab 免費 T4 實測(2026-10,Unsloth 2026.10.1):

  • Unsloth 會提示 Gemma 4 在 T4 改用 float32(T4 無 bf16),模型在訓練前就佔約 10.3GB。
  • 可訓練參數 25.3M(0.49%);176 steps(2 epochs)訓練 1419 秒(23.7 分鐘);peak reserved 11.41GB(78%)。
  • 推論很慢:逐份生成下 base 約 45 秒/份、LoRA 約 25 秒/份,所以 notebook 預設只評估 20 份(EVAL_LIMIT = 20),全測 200 份需數小時。

評估結果(test 前 20 份):

span recall(95% CI)valid JSONprecision
base(float32)0.837(0.692–0.942)90%0.958
+ LoRA1.000(1.000–1.000)100%1.000

解讀時要注意:

  • 樣本只有 20 份,與 Mac 的 200 份結果不可直接比較。
  • LoRA 的 CI 為 1.000–1.000,是因為 20 份全部答對、bootstrap 沒有變異,不代表真實表現完美;在合成資料上的小樣本結果,不能推論到真實病歷。
  • Colab 未量化的 base(0.837)遠好於 Mac 的 4-bit base,可能與量化或推論框架差異有關,但原因未驗證,樣本也不同。

看 loss 曲線

訓練時,終端機或 notebook 會印出 train loss 與 valid loss。把它們畫成曲線:

現象解讀常見處理
train 與 valid 都下降並趨於平穩正常學習可停止
train 持續下降,valid 下降後轉為上升overfitting(考古題背誦魔)提早停止、減少 epoch、增加資料多樣性、降低 rank
兩者都降不下去under-fitting 或資料有問題檢查格式與 mask、調整 learning rate
loss 上下劇烈震盪learning rate 可能太大降低 learning rate

兩個提醒:

  1. 合成資料很容易 overfit,因為句型單純。這是為什麼 LV11 要以骨架切分,這樣 valid loss 才有參考價值。
  2. loss 低不等於好用。loss 只是語言模型的猜字誤差,能不能找出 PHI,要看下一關的評估指標。

本關重點

  • 設定:--mask-prompt 讓 loss 只計回答;--grad-checkpoint 用時間換記憶體;batch 與 max seq 決定記憶體用量。
  • 作者實測(M5 32GB、Gemma 4 E2B 4-bit):100 iter 約 18 分鐘、峰值 14.8GB、可訓練參數 0.147%。
  • 16GB Mac 的降配設定只是方向,本站標示【待實測】;Colab T4 實測訓練約 24 分鐘、peak 11.41GB(見上)。
  • 看曲線:train 降、valid 升 = overfitting,也就是考古題背誦魔。
  • loss 低只代表擬合訓練資料,要用獨立 test 集與評估指標才能說有沒有學會。

BOSS 戰:考古題背誦魔

HP0/5
  1. 訓練 loss 一路下降到接近 0,但 validation loss 在某個點之後開始上升。最可能的解讀是?

  2. mlx-lm 指令中的 `--mask-prompt` 主要做什麼?

  3. 作者在 M5 32GB 上實測 batch 4、max seq 2048、開 --grad-checkpoint 的 peak memory footprint 為 14.8GB。若你只有 16GB Mac,較合理的作法是?

  4. 為什麼 grad-checkpoint(gradient checkpointing)能省記憶體?

  5. 下列哪一個結論,在只有 loss 曲線的情況下最難成立?