你的門檻憑什麼是 0.05:先去量你的 σ
我的模型交付鏈最後一棒是 promotion gate,其中一條規則是:
新模型不能比現行基準差超過
tol = 0.05
寫這行的時候我沒多想。直到有人問我:「為什麼是 0.05?」
我答不出來。
這個問題等於在問「你的產線抖多大」
用 benchmark 想最快。
你改了一段程式,跑 benchmark 從 100 ms 變成 103 ms。變慢了嗎?
答不出來——因為你不知道「什麼都不改、重跑十次」會落在哪個範圍。 如果是 98–105 ms 之間跳,那 103 ms 什麼都不代表。
tol 就是「我容許多少抖動」。要填對它,得先知道它實際抖多少。
- 如果實際抖動是 0.5,
tol=0.05太嚴 → 好模型天天被擋 - 如果實際抖動是 0.001,
tol=0.05太鬆 → 真的退步了也放行
量法:只換 seed,其他全部固定
我跑了五次訓練,唯一變因是 random seed——同一份資料、同樣的步數、 同一條 pipeline、同樣的超參數。
| seed | val_loss | test_loss |
|---|---|---|
| 7 | 7.2547 | 7.1439 |
| 42 | 7.2507 | 7.1677 |
| 1337 | 7.2371 | 7.1240 |
| 2024 | 7.2531 | 7.1672 |
| 31337 | 7.2194 | 7.1267 |
test_loss mean 7.1459 σ = 0.0211 2σ = 0.0422
所以 tol = 0.05 = 2.37 σ。
好消息是:它落在合理區間的上緣(統計上常用的管制界限是 2σ 到 3σ)。 我猜對了。但在量之前,我說不出這句話。
而差別不在數字要不要改,在能不能回答「為什麼是 0.05」。 一個答不出理由的門檻,改起來沒有心理成本——這才是它容易被調鬆的真正原因。
⭐ 順便分離出兩種完全不同的雜訊
我之前有另一組數字:同一個 seed 重跑三次,val_loss 分別是
7.2370 / 7.2428 / 7.2343,全距 0.0085,σ ≈ 0.004。
我一度想拿這個 0.004 當 tol 的依據。那是錯的。
| 雜訊源 | σ | 它在量什麼 |
|---|---|---|
| 同 seed 重跑 | 0.004 | 評估時隨機抽 batch 的變異(評估腳本沒固定 seed) |
| 不同 seed | 0.0211 | 初始化 + 資料順序造成的模型差異 |
seed 變異是評估雜訊的 5.3 倍。
用 Java 講:同 seed 重跑像對同一個物件呼叫兩次 toString();
不同 seed 像 new 出五個不同的 instance。
你上線時拿到的是「某一次訓練的結果」,那次的運氣是隨機的。
所以 gate 要容忍的是 instance 之間的差異(0.0211),不是同一個物件的兩次讀數(0.004)。
拿後者當 tol 會嚴 5 倍,天天擋掉健康的模型。
論文界怎麼處理這件事
這不是新問題,ML 學界被公開打臉過。
最有名的是 Henderson et al. 2018《Deep Reinforcement Learning that Matters》: 同一個演算法、同一組超參數,只換 random seed 跑 10 次, 拆成兩組各 5 個 seed 分別平均——兩條學習曲線看起來像來自不同的統計分布。
也就是說,「A 演算法贏 B」這種結論,可以純粹是 seed 造成的。
標準做法因此是報 mean ± std over N seeds,而不是單一數字。 Bouthillier et al. 2021 更進一步: 與其固定其他條件只換 seed,不如同時隨機化多個變異源(seed、資料切分、資料順序), 估得更準而且省算力。
但誠實講,實務上做得很差:很多論文只報最好的那個 seed, 而 LLM 級別的模型根本跑不起多 seed——GPT-3 就訓練那一次。
⭐ 但你不該照抄論文的做法
這是這篇最重要的一段。
| 論文 | 你的 gate | |
|---|---|---|
| 問題 | 這個差異是真的嗎 | 這顆能不能上線 |
| 工具 | 顯著性檢定 | 二元決策 |
| 允許的答案 | 「不顯著」→ 不下結論 | 不能說「無法判斷」 |
論文可以說「證據不足」然後停在那裡。你的 gate 不行——它必須放行或擋下。
而且 p 值需要樣本數與檢定力,你上線時手上只有一顆模型,做不了檢定。
所以你該借的不是統計檢定,是統計製程管制(SPC)的管制圖:
- 先量製程本身的自然變異(σ)
- 訂管制界限(常見 2σ 或 3σ)
- 超出界限 = 製程異常,停線查
你的 promotion gate 本質上就是一張管制圖,不是一個假設檢定。 這個框架在製造業和金融風控裡都是常識,而且比 p 值更貼近你的用途。
還沒解決的:改小 tol 治不好的病
量出 σ 之後,tol 有依據了。但有一個缺陷不是門檻大小的問題:
tol 比的是「跟上一筆上線的模型比」。就算收緊成 2σ = 0.042,
每次退步 0.042 都合法,二十次之後跟最初那顆比已經退了 0.84——而每一步都通過了 gate。
用 Java 講:像 code review 規定每個 PR 最多只能多欠 5 行技術債。 每一次 review 都是對的,一年後系統爛掉,而且找不到哪一次該負責。
修法不是改小 tol,是再釘一個人工凍結的原點基準,雙重檢查:
(比上一筆差 > tol) OR (比凍結基準差 > tol_total) → 擋
這個我還沒實作。
三句話帶走
- 沒量過 σ 的門檻,是一個你答不出理由的數字——而答不出理由的門檻,改起來沒有代價
- 要量的是「同配方重做一次」的變異,不是「同一次量兩遍」的變異——後者會小 5 倍
- 借管制圖,不要借 p 值——你要的是決策,不是推論
⚠️ 最後一個限度:我量到的 σ 只對這一組設定成立(2 MB 語料 / 300 步 / BPE 500)。 換資料量或步數都要重量。
你們系統的關鍵門檻——不管是模型、效能還是告警——有哪一個是量出來的?其他的是怎麼來的?
🧪 這篇的實驗環境與 lab 檔案(最後更新 2026-08-30)
叢集
- CRC 2.63.0 · OpenShift 4.22.7 · Kubernetes v1.35.6
- 單節點:13 vCPU / 40 GiB RAM / 120 GB disk
- 宿主:Framework Laptop 16(Ryzen AI 7 350 · 8C/16T · 64 GB RAM · 1 TB NVMe · RTX 5070 顯卡模組)
- ⚠️ 叢集內看不到 GPU(CRC 是 VM,RTX 5070 未 passthrough)
Operator
opendatahub-operator.v3.5.0← 即 RHOAI 3.x 的上游開源版cert-manager-operator.v1.20.0(3.x 的必要相依;2.x 不需要)openshift-pipelines-operator-rh.v1.23.2、openshift-gitops-operator.v1.21.3
DataScienceCluster 開啟的元件
kserve、aipipelines、dashboard、workbenches、modelregistry、kueue(Unmanaged)- 其餘(
ray/trustyai/feast/aigateway…)為Removed
叢集外的依賴(跑在宿主的 podman 上,crc start 不會帶起來)
- Harbor v2.15.2(私有 registry)· MinIO(S3)
模型端
- Python 3.12.13 · PyTorch 2.11.0+cu128 · FastAPI + uvicorn · prometheus-client
lab 檔案
- YAML/Containerfile/腳本:github.com/ryanGTR/openshift-ai-30days
(含 Day 對照表;主機名是佔位符,跑
set-lab-host.sh換成你自己的) - 服務的那個模型:llm-from-scratch(從零手刻的小 GPT)
⚠️ ODH ≠ RHOAI:元件同源,但 namespace 與部分名稱不同
(我這裡是 opendatahub,商用版是 redhat-ods-* 那一套)。
指令的邏輯可以照用,字串要自己對一次。
留言與指正
我特別想知道:你們系統的關鍵門檻(不管是模型、效能還是告警)有哪一個是量出來的?其他的是怎麼來的?