JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

錯誤分析與模型除錯

一個測試分數只告訴你模型表現如何,卻從不告訴你它為什麼會失敗。這篇導讀教你做偵探:去讀模型真正犯下的錯誤,按子群體把分數切開來看,並判斷你面對的究竟是偏差問題、變異數問題,還是資料問題——這樣你才能修對地方。

走出計分板:真正去看那些錯誤

到現在為止,你已經能在留出集上算出一個乾淨的測試分數,並且信任它,因為前面幾階教過你誠實的驗證和混淆矩陣。但"91%"這樣的數字是一個*判決*,而不是一個*解釋*。它告訴你模型*多久*錯一次;卻從不告訴你錯的是*哪一種*,或*為什麼*。錯誤分析就是這樣一個習慣:關掉試算表,親眼一個一個地去讀模型真正答錯的那些案例。

下面是從業者真正在用的具體做法,它比聽起來要樸實得多:拉出 100 到 150 個被模型分錯的樣本,放進一張表裡,給每一個標上一個簡短的原因——"照片模糊"、"反諷"、"標籤本身就錯了"、"罕見犬種"。然後數一數這些標籤。錯誤幾乎總會成簇出現:也許 40% 的失誤來自某一個你一下午就能修好的原因,外加一條長長的、各式各樣只出現一次的怪例——後者你眼下應當忽略。這一個小時的閱讀,常常勝過一週盲目的超參數調優。

切片:一個數字底下藏著十個故事

一個彙總分數是一個*平均值*,而平均會透過抹平來說謊。一個整體 92% 的模型,可能在簡單、常見的案例上是 97%,而在某個雖小卻重要的子群體上只有 61%——如果這個子群體恰好是夜間拍攝的照片,或是某種少數方言的說話者,那麼這個平均值就悄悄掩埋了一個在實際部署中極其要緊的失敗。切片的意思,就是在資料有意義的子集上分別計算你的指標,而不是只在整體上算。

選擇那些對人類有意義的切片:按類別(你前一階講過的類別不平衡已經說明了為什麼稀有類別值得單獨佔一行)、按輸入屬性(長度、影像尺寸、一天中的時段)、按資料來源,以及——這點至關重要——當決策會影響到人時,按人口統計群體來切。讀切片也是你抓到模型依賴偽相關的途徑:如果一旦你把那種"洩底"的偽影不存在的案例切出來、準確率就崩塌了,那說明模型一直在騎著那個偽影,而不是在學習真正的任務。

偏差對變異數:最核心的診斷

一旦你知道了*哪些*錯誤最傷人,下一個問題就是模型*為什麼*會犯它們——而幾乎每一種原因,最終都歸結為你在偏差-變異數權衡中見過的兩種診斷之一。高偏差欠擬合)意味著模型太簡單或太懶,連訓練資料都擬合不了:它連自己已經見過的東西都答錯。高變異數過擬合)則意味著它把訓練集的怪癖都背了下來,無法泛化:訓練集上很棒,測試集上很差。

區分它們的辦法,是去比較兩個誤差和一個參照。先挑一個目標:人類水準的表現,或一個已有的基線,給出你現實中能夠搆到的下限。然後看從這個目標到你*訓練*誤差之間的差距,再看從訓練誤差到*驗證*誤差之間的差距。第一個差距大,是偏差;第二個差距大,是變異數。那第二個差距,正是你學過要盯緊的訓練-測試差距——在這裡它成了一個方向盤,而不只是一盞警示燈。

target (human/baseline) = 2%
train error             = 3%   -> bias gap  = 1%  (small)
val   error             = 12%  -> var. gap  = 9%  (big!)

=> low bias, HIGH variance: model overfits.
   fix: more data, regularize, simpler model, augment.

( if train error were 11% instead:
  bias gap = 9% (big) -> underfitting;
  fix: bigger model, train longer, better features. )
兩個差距的診斷法。哪個差距更大,就為你的問題命名,並指向相應的修法。

兩邊的修法是相反的,這正是為什麼必須先做診斷。對高偏差,你要增加模型容量、訓練更久,或設計更好的特徵。對高變異數,你要反過來做:收集更多資料、加正則化、簡化模型,或做資料擴增。把一個治變異數的招用到偏差問題上,只會越弄越糟——更小的模型欠擬合得更厲害。這也是為什麼沒有免費午餐的直覺成立:不存在萬能旋鈕,只有針對*這個*具體失敗的那個對的旋鈕。

學習曲線:看著差距移動

除錯中資訊量最大的一張圖,就是學習曲線:隨著你餵給模型越來越多的資料(或越來越長的訓練時間),把訓練誤差和驗證誤差畫出來。兩條曲線會把整個故事講清楚,不用你去猜。如果兩條曲線都在一個偏高的誤差處變平、並且彼此靠得很近,那你被偏差卡住了——再加資料也沒用,因為模型連手頭已有的都擬合不了;你需要一個更強的模型。

如果情況相反,存在一道又寬又持久的豎直縫隙——訓練誤差很低,驗證誤差卻頑固地居高不下——那道縫隙就是變異數,而曲線的形狀會告訴你:再加資料能不能把它合攏(驗證誤差仍在往下走),還是你已經觸頂了(它已經平了)。這正是對那個老問題"我該不該多收集些資料"的誠實答案。別去爭辯;把曲線畫出來,看就是了。

除錯是一個迴圈,而不是一時靈感

把這些拼起來,[[model-debugging|模型除錯]]就不再是神秘的瞎鼓搗,而成了一個有紀律的迴圈。新手常犯的錯誤是一次改五樣東西,然後搞不清是哪一樣起了作用;而紀律在於:從你的錯誤分析中提出*一個*假設,做*一個*改動,再到*同一個*固定的驗證集上重新測量。分數動了或沒動——無論哪樣,你都學到了一件真東西。

  1. 讀錯誤。抽樣 100 個以上的錯誤,給每個標上原因,數標籤,按影響排序。
  2. 切分分數。把指標按類別、來源、群體拆開;找出那些遠低於平均的切片。
  3. 診斷偏差還是變異數。比較 目標 -> 訓練 -> 驗證 的差距,並讀學習曲線。
  4. 只改一樣。施加診斷所指向的修法——偏差就加容量,變異數就加資料/正則化。
  5. 在同一個集合上重新測量,記錄你嘗試了什麼,然後迴圈,直到達到誤差預算——而不是直到你累了。

最後留兩句誠實的提醒。第一,當你實在想不通模型為什麼在某個案例上失敗時,就借助後面某一階的可解釋性工具——一份特徵重要性讀數或一張顯著性圖,可能揭示出模型盯的是浮水印,而不是腫瘤。第二,要警惕你針對驗證集除錯了太多次,以至於悄悄開始對它過擬合;這正是為什麼最終那句不帶偏的話,永遠屬於一個你只碰過一次的測試集。錯誤分析能讓模型變好,卻從不能讓它無所不知——一個被除錯好的模型,是一個你終於*理解*了其餘下失敗的模型,而不是一個毫無失敗的模型。