搜尋課程與筆記

搜尋筆記

輸入主題、關鍵字或單元編號,例如 Flow Matching、U4。

    按 Esc 關閉 · ⌘ / Ctrl K 開啟搜尋

    L1.0 14 分鐘閱讀 2026年10月

    L1.0 背考古題的學生:過擬合與欠擬合

    本篇重用2 篇

    兩個都考不好的學生

    期中考結束,兩個學生都考 40 分。

    甲把過去五年的考古題全部背下來,每一題的答案、每一個數字都記得。模擬考(考古題原題)滿分。正式考換了數字,他不會。

    乙只讀了課本的前半,讀得很認真。模擬考也只有 45 分,正式考 40 分。

    同樣的成績,但病因相反。甲的問題是他學到的東西不是「規則」而是「這幾份考卷」;再給他十份考古題背,他還是不會新題。乙的問題是他沒學夠;再給他十份考古題,他真的會進步。

    如果你只看正式考的分數,你分不出他們。 你需要第二個數字——模擬考的分數。甲是 100/40,乙是 45/40。

    訓練誤差(模擬考)與泛化誤差(正式考)的組合才構成診斷。

    診斷要兩個數字,不是一個。

    要讓模型學會新題,而不只是把舊題答對,我們該怎麼看這兩個分數? 下面先整理可能的原因,再用同一份 toy 觀察容量與資料量的影響。

    兩個學生都考 40 分,
    你怎麼知道誰在背答案、誰只是沒讀完?
    「模型太複雜」這句話要拿什麼來判斷?

    課堂提問Q1

    把「背」與「學到規則」翻成數學。兩個誤差構成四種組合,把它們列出來——哪一格對應甲、哪一格對應乙、哪一格是成功、哪一格幾乎不可能?各自的處方是什麼?

    先想一想,再展開看整理後的答案

    兩個數字(沿用 台北的房仲去台中:風險與經驗風險):訓練誤差 R^n(f^)\widehat R_n(\hat f) 與母體風險 R(f^)R(\hat f)。「背」是 R^n\widehat R_n 很小而 RR 很大;「沒學夠」是兩個都大。

    RR 小RR 大
    R^n\widehat R_n 小成功過擬合(甲):縮小 F\mathcal F、加資料、加正則化
    R^n\widehat R_n 大檢查抽樣與計分是否一致檢查欠擬合、特徵與最佳化(乙)

    四格都可能出現。訓練誤差較高時,可能是抽樣波動、訓練資料較難,或兩邊計分方式不同,例如 training augmentation、dropout、regularization penalty。先用同一個 evaluation mode 與相同 loss 重算,才適合比較。

    兩個處方彼此相反,這是為什麼診斷不能跳過:對甲用乙的處方(加大模型)會讓他更會背;對乙用甲的處方(加正則化)會讓他讀得更少。

    一個設定,兩種失敗

    把「假設空間有多大」做成一個可以連續調整的設定——多項式的次數、樹的深度、網路的寬度、正則化強度的倒數。往兩端轉,會遇到兩種相反的失敗:

    • 轉太小(欠擬合):F\mathcal F 裡沒有一個函數接近真相。這時兩個誤差都大而且互相接近——模型在訓練集上就已經做不好,沒有「偷背」的空間。這對應 L0 的 approximation error。
    • 轉太大(過擬合):F\mathcal F 裡有太多函數在這 nn 個點上一樣好,而資料沒有辦法把它們分開。訓練誤差可以壓到接近零,母體風險卻在上升。這對應 estimation error。

    中間某處有一個最佳點。但這個點不是模型的性質,是「模型與資料量」這一對的性質——設定的最佳位置隨 nn 移動。這是本篇最重要的一句話,因為它決定了你聽到「這個模型太複雜」時該問的下一個問題:相對於多少資料?

    四格診斷,與同一個設定的兩端

    圖說: 同一個容量設定的兩端是欠擬合與過擬合;最佳位置同時取決於模型與資料量。

    U 形是怎麼來的,以及它為什麼會移動

    固定資料量 nn,讓假設空間沿著一條巢狀的鏈成長 F1⊂F2⊂…\mathcal F_1\subset\mathcal F_2\subset\dots(次數 ≤d\le d 的多項式正是這樣一條鏈)。兩條曲線的方向是可以先驗證明的:

    • 訓練誤差對 dd 單調不增。 因為 Fd⊂Fd+1\mathcal F_d\subset\mathcal F_{d+1},在更大的集合裡取 min⁡\min 不可能更大。這條曲線永遠往下,所以它自己不含任何關於泛化的資訊。
    • 母體風險還包含 estimation 與不可約誤差。 Approximation 隨 nested family 放大不會增加,但 estimation 不保證單調;古典 U 形是一種常見現象,不是僅靠集合包含就能證明的曲線 [1]。

    U 形的谷底在兩者的邊際變化相抵之處。把 nn 加大,estimation 那一項整體壓低(L0.2 的界裡它以 log⁡∣F∣/n\sqrt{\log|\mathcal F|/n} 的形式出現),於是谷底往右移、而且整條 U 變平。

    順帶一提,這條 U 只描述「容量還沒超過資料量」的那一段。把容量繼續往上推到遠遠超過 nn,測試誤差會先在插值點附近衝高、然後再次下降——這個現象叫 double descent(參考文獻 2),也是現代大模型所處的位置。本篇的 d≤25d\le25、n=30n=30 還在古典的那一段。

    平方損失下這條 U 有一個絕對的地板:天氣預報該報幾度:MSE 的最小值是 Conditional Expectation 說最好的可能是 f⋆=E[Y∣X]f^\star=\mathbb E[Y\mid X],而 R(f⋆)=E[Var(Y∣X)]R(f^\star)=\mathbb E[\mathrm{Var}(Y\mid X)] 是不可約誤差。共用 toy 裡它正好是 0.152=0.02250.15^2=0.0225。這個數字是讀懂訓練曲線的參考線——下一節會用到。

    注意「訓練誤差降不下去」什麼時候不是問題

    一個常見的焦慮:訓練 loss 掉到某個正值就不動了,是不是模型不夠好、是不是該加層?

    要比較的是相同任務的 population MSE 下界 E[Var(Y∣X)]\mathbb E[\mathrm{Var}(Y\mid X)],不是 training loss 的硬下界。有限樣本上低於噪聲水準仍可能發生,停在它附近也不自動證明成功;還需要獨立驗證資料與基準。

    所以診斷需要一個對不可約誤差的估計。取得方式:同一個輸入重複量測看散佈多大、人類專家在同一份資料上的一致性、或者(像這個 toy 一樣)你自己造資料時就知道答案。沒有這個參考線,「loss 停在 0.3」既不能說好也不能說壞。 這個判斷在任何有噪聲的回歸任務上都會反覆用到。

    兩個學生的處方,與一個容易搞錯的方向

    甲(過擬合)。 處方有三類,都在做同一件事——讓資料相對於假設空間變多:縮小 F\mathcal F(降次數、減層、剪枝)、加資料(或資料增強)、加限制(正則化、提早停止,見 限制筆記頁數,或考前一天停止補習:正則化與提早停止)。

    乙(欠擬合)。 處方是相反方向:放大 F\mathcal F、加更有資訊的特徵、訓練更久或更好(有時「欠擬合」其實是最佳化沒收斂——霧中下山,一步該走多大:梯度下降的一頁 裡 η=0.01\eta=0.01 跑 2000 步的結果就是一個假的欠擬合)。

    最常見的誤判是把「最佳化沒跑完」讀成「模型不夠大」。兩者的訓練誤差都高,但一個加大模型會更慢、更難訓,另一個才真的需要容量。分辨方法很直接:先確認在一小批資料上能不能過擬合。 拿 50 筆資料訓到訓練誤差接近零——做得到,表示容量與最佳化都沒問題,真正的問題在資料或正則化;做不到,問題在最佳化或架構。這是一個五分鐘的實驗,卻能擋掉很多天的猜測。

    這一切依賴什麼。 一,用來當「泛化誤差」的那個數字必須來自沒被拿去挑選過的資料——這正是下一篇的主題。二,訓練與評估同分佈;否則你看到的是偏移,不是過擬合(L0.2 已經處理過這個鑑別診斷)。三,「複雜度」沿著一條巢狀的鏈成長;換架構、換演算法時兩個模型不可比,U 形的圖像不適用。

    把 U 形跑出來,再把它攤平

    共用 toy,n=30n=30,多項式次數從 00 掃到 2525:

    import numpy as np, warnings; warnings.filterwarnings("ignore")
    from numpy.polynomial import Polynomial
    from ml_toy import toy_1d, truth, NOISE
    
    xs, ys = truth()
    risk = lambda f: ((f(xs) - ys)**2).mean() + NOISE**2      # 母體風險(近似)
    x, y = toy_1d()                                            # n = 30
    for d in (0, 1, 2, 3, 5, 7, 9, 12, 15, 20, 25):
        f = Polynomial.fit(x, y, d)
        print(f"  degree {d:2d}   訓練 {((f(x) - y)**2).mean():8.4f}   母體風險 {risk(f):12.4f}")
      degree  0   訓練   0.3897   母體風險       0.5575
      degree  1   訓練   0.2118   母體風險       0.2679
      degree  2   訓練   0.2117   母體風險       0.2668
      degree  3   訓練   0.0178   母體風險       0.0312
      degree  5   訓練   0.0147   母體風險       0.0280
      degree  7   訓練   0.0134   母體風險       0.0296
      degree  9   訓練   0.0122   母體風險       0.0285
      degree 12   訓練   0.0114   母體風險       0.0314
      degree 15   訓練   0.0104   母體風險       0.0334
      degree 20   訓練   0.0043   母體風險       0.0659
      degree 25   訓練   0.0016   母體風險    8032.3199

    左欄單調下降,右欄是 U 形,谷底在 d=5d=5(0.02800.0280,距離不可約誤差 0.02250.0225 只差一點點)。d≤2d\le2 是乙:兩欄都大而且接近(0.21180.2118 對 0.26790.2679),這是欠擬合的簽名——兩個數字的比值接近 1。d≥20d\ge20 是甲:訓練誤差 0.00430.0043 已經低於噪聲水準 0.02250.0225,母體風險開始跳,到 d=25d=25 完全失控。

    注意 d=1d=1 到 d=2d=2 幾乎沒有進步(0.2118→0.21170.2118\to0.2117)。這也有意義:sin⁡(2πx)\sin(2\pi x) 在 [0,1][0,1] 上大致對稱,二次項幫不上忙,要到三次才抓得到形狀。「加容量沒有用」有時是加錯了方向的容量。

    同一個設定,換一個資料量。 把 nn 從 30 加到 300,其他完全不動:

    x3, y3 = toy_1d(n=300, seed=1)
    for d in (1, 3, 9, 15, 20, 25):
        f = Polynomial.fit(x3, y3, d)
        print(f"  degree {d:2d}   訓練 {((f(x3) - y3)**2).mean():8.4f}   母體風險 {risk(f):10.4f}")
      degree  1   訓練   0.2106   母體風險     0.2207
      degree  3   訓練   0.0266   母體風險     0.0277
      degree  9   訓練   0.0198   母體風險     0.0242
      degree 15   訓練   0.0197   母體風險     0.0243
      degree 20   訓練   0.0196   母體風險     0.0244
      degree 25   訓練   0.0194   母體風險     0.0283

    U 形不見了。 d=25d=25 在 n=30n=30 時是 80328032,在 n=300n=300 時是 0.02830.0283——同一個模型、同一個設定位置,從災難變成幾乎最佳。而且從 d=9d=9 到 d=20d=20,母體風險穩定停在 0.0240.024 附近,緊貼不可約誤差 0.02250.0225:多出來的容量沒有造成傷害。

    這推翻了一個非常普遍的說法:「25 次多項式太複雜了。」同一句話的正確版本是「25 次多項式相對於 30 筆資料太複雜」。

    複雜度沒有絕對的刻度,它只相對於資料量存在。

    這也是為什麼現代的大模型能 work:不是因為誰推翻了統計學,而是因為 nn 大了很多個數量級。

    再把噪聲關掉。 不可約誤差變成零,但新位置是否準確仍需量測。30 個不同輸入足以唯一決定 25 次多項式的 least-squares 解;唯一不等於正確,也不能直接宣稱這個無噪聲版本一定過擬合。

    調整設定,看 U 形怎麼隨資料量移動

    互動 demo:拉資料量,U 形的谷底往右移——「最佳複雜度」不是模型的性質,是資料量的函數。

    檢查理解

    想一想

    一個模型訓練誤差 0.210.21、驗證誤差 0.220.22,而你知道這個任務的標籤噪聲水準大約是 0.020.02。最合適的下一步是:

    想一想

    同事說「我們的 25 次多項式太複雜了,一定會過擬合」。根據本篇的兩張表,最準確的回應是:

    想一想

    在 n=30n=30 那張表裡,d=20d=20 的訓練誤差是 0.00430.0043,而不可約誤差是 0.02250.0225。這個比較說明:

    參考文獻

    1. Hastie, T., Tibshirani, R., Friedman, J. The Elements of Statistical Learning, 2nd ed. Springer 2009, Ch. 7.(訓練誤差為何樂觀、模型複雜度與測試誤差的 U 形、樂觀量的估計。)
    2. Belkin, M. et al. Reconciling modern machine-learning practice and the classical bias–variance trade-off. PNAS 2019.(把容量繼續往上推會發生什麼:double descent,以及古典 U 形適用的範圍。)
    3. Ng, A. Machine Learning Yearning 2018, Ch. 20–27.(把兩個誤差的組合當成日常診斷流程的實務版本,含「小資料過擬合測試」。)