搜尋課程與筆記

搜尋筆記

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

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

    L0.1 14 分鐘閱讀 2026年10月

    L0.1 差一度與差十度:損失函數是一種宣告

    本篇重用2 篇

    糟十倍,還是糟一百倍?

    你在做明天最高溫的預報。報 25 度、實際 26 度,這是一個小錯;報 25 度、實際 35 度,這是一個大錯。

    大錯比小錯糟幾倍?

    差距放大十倍,後果卻不一定只放大十倍。MSE 會扣一百倍的分,絕對誤差扣十倍;若在意的是有沒有因此忘了帶外套,可能還有一個門檻。要把「估得準」變成可以訓練的目標,得先決定我們究竟在意哪一種錯。

    沒有一個實驗能告訴你哪個對。這是宣告,不是發現。 資料裡沒有「差 10 度有多痛」這個資訊——那來自使用這個預報的人。

    而一旦宣告完,剩下的事情就不再自由了:天氣預報該報幾度:MSE 的最小值是 Conditional Expectation 已經證明,平方誤差下的最佳策略是條件平均,換絕對誤差就變中位數。這一篇處理的是這個選擇在實務上的三個後果:學到的東西不同、對髒資料的抵抗力不同、以及好不好訓不同。

    選損失就是選你要學的統計量。

    差 10 度比差 1 度糟十倍,還是糟一百倍?
    這個比例是資料告訴你的,
    還是你自己宣告的?

    課堂提問Q1

    把「宣告」翻成數學:損失是什麼型別的物件?「換一個損失會學到不同的東西」這句話,精確地說是什麼在變?如果我只是想「訓練得順一點」而換損失,我付出了什麼?

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

    型別。 損失是 ℓ:Y^×Y→R\ell:\hat{\mathcal Y}\times\mathcal Y\to\mathbb R,把「你說的」與「實際的」變成一個扣分。注意第一個參數不一定和第二個同型:分類時 y∈{0,1}y\in\{0,1\} 但 y^\hat y 是一個機率。

    在變的是誰。 對每個 xx,最佳答案是

    f⋆(x)=arg⁡min⁡a E[ℓ(a,Y)∣X=x],f^\star(x)=\arg\min_{a}\ \mathbb E\big[\ell(a,Y)\mid X=x\big],

    也就是「在這個桶子裡,哪個回答的期望扣分最小」。這個 arg⁡min⁡\arg\min 只由 ℓ\ell 與桶內分佈決定。所以換 ℓ\ell 不是換一個計分板——是換掉你要模型逼近的那張表:ℓ\ell 是平方就是 E[Y∣X]\mathbb E[Y\mid X],是絕對值就是中位數,是 cross-entropy 就是整條 p(y∣x)p(y\mid x)。

    為了好訓而換損失的代價。 你把目標換掉了。有時無害(Huber 在小殘差上就是平方,逼出的東西和平均很接近),有時致命(把 0–1 錯誤率換成平方損失去學機率,最佳解仍然是機率,但梯度會在錯得很自信的地方消失——本篇實作會把這個現象跑出來)。所以要分開問兩件事:這個損失逼出的統計量是我要的嗎?它好不好訓? 兩題都要過。

    扣分表:你對錯誤的偏好長什麼形狀

    把損失畫成「殘差 r=y^−yr=\hat y-y 對應扣多少分」的一條曲線,三種常見宣告的形狀差別一眼可見:

    • 平方 r2r^2:越錯,每多錯一單位的邊際懲罰越大。它宣告「大錯特別不能忍」,代價是一顆離群值就能買走整條曲線——把它拉過去比讓其他二十九點各差一點更划算。
    • 絕對 ∣r∣|r|:每多錯一單位,代價固定。大錯不會被額外放大,所以離群值只算一票。
    • Huber:∣r∣|r| 小的時候用平方(在合理範圍內保留平滑與「大錯更糟」的直覺),超過 δ\delta 之後切成線性(不讓極端值買走曲線)。它是把「我相信多數點,但不相信極端點」寫成式子。

    同一個形狀語言也解釋了分類:cross-entropy −log⁡p^-\log \hat p 在「你說機率 0.01、答案卻是這一類」時扣分是 log⁡100≈4.6\log 100\approx4.6,說 0.0001 就扣 9.29.2——錯得越自信,罰得越重且沒有上限。平方損失 (p^−y)2(\hat p-y)^2 的上限是 11:錯到底也只扣一分。

    四張扣分表,四個最佳答案

    圖說: 同一個條件分布,會因扣分方式不同而選出平均數、中位數或偏向特定分位數的答案。

    換一張扣分表,最佳答案會跑到哪裡

    固定 xx,令 YY 的條件分佈是 p(⋅∣x)p(\cdot\mid x)。逐項求 arg⁡min⁡aE[ℓ(a,Y)∣x]\arg\min_a \mathbb E[\ell(a,Y)\mid x]:

    損失 ℓ(a,y)\ell(a,y)最佳回答 f⋆(x)f^\star(x)一句話理由
    (a−y)2(a-y)^2條件平均 E[Y∣x]\mathbb E[Y\mid x]三行證明,見 M1.2
    ∣a−y∣\lvert a-y\rvert條件中位數P(Y<a)≤1/2≤P(Y≤a)P(Y<a)\le1/2\le P(Y\le a)
    (1−τ)(a−y)++τ(y−a)+(1-\tau)(a-y)_++\tau(y-a)_+(pinball)條件 τ\tau-分位數P(Y<a)≤τ≤P(Y≤a)P(Y<a)\le\tau\le P(Y\le a)
    −log⁡p^y-\log \hat p_y(cross-entropy)整條條件機率 p(⋅∣x)p(\cdot\mid x)期望扣分 =H(p)+KL(p ∥ p^)=H(p)+\mathrm{KL}(p\,\Vert\,\hat p),見 M5.1
    1[a≠y]\mathbb 1[a\ne y](0–1)條件眾數 arg⁡max⁡yp(y∣x)\arg\max_y p(y\mid x)猜中機率最大的那一類

    下面推導 cross-entropy 那一列。先不限制模型能輸出哪些機率表,把期望扣分寫開:

    EY∼p[−log⁡p^Y]=H(p)⏟與 p^ 無關+KL(p ∥ p^)⏟≥0, p^=p 時為 0.\mathbb E_{Y\sim p}\big[-\log \hat p_Y\big] =\underbrace{H(p)}_{\text{與 }\hat p\text{ 無關}}+\underbrace{\mathrm{KL}(p\,\Vert\,\hat p)}_{\ge 0,\ \hat p=p\text{ 時為 }0}.

    也就是說最小化 cross-entropy 就是最小化到真實條件分佈的 KL(M5.1 已經把這個等式證過)。這種「唯一最小點恰好是真實分佈」的損失叫 strictly proper scoring rule;平方損失作用在機率上(Brier score)也是 proper 的,0–1 錯誤率則不是——它只在乎哪一類最大,所以模型可以把機率報得離譜而分數不變。如果你之後要用機率做決策(門檻、期望成本、拒答),這個差別是關鍵的。

    展開細節proper 不等於好訓:平方損失在分類上的梯度會消失

    用 sigmoid p^=σ(z)\hat p=\sigma(z) 作輸出,對 logit zz 微分:

    ∂∂z[−log⁡p^]∣y=1=p^−1,∂∂z[(p^−y)2]=2(p^−y) p^(1−p^).\frac{\partial}{\partial z}\big[-\log\hat p\big]\Big|_{y=1}=\hat p-1, \qquad \frac{\partial}{\partial z}\big[(\hat p-y)^2\big]=2(\hat p-y)\,\hat p(1-\hat p).

    當模型錯得很自信(y=1y=1 但 p^≈0\hat p\approx 0):cross-entropy 的梯度是 −1-1,滿檔;平方損失的梯度多了一個 p^(1−p^)≈0\hat p(1-\hat p)\approx 0 的因子,整個梯度被壓成幾乎零。錯得越離譜,修正的力道越小——這是最壞的組合。

    兩個損失的最佳解是同一個(都是真實機率),但一個從錯誤的地方走得回來,一個走不回來。這就是「宣告」與「最佳化性質」必須分開檢查的原因:本篇的第二段實作會把它跑成一個 400 步之後準確率 0.180.18 對 0.890.89 的對比。

    預報員、房仲、與「先用 MSE 再說」

    預報員。 若高估氣溫、讓人穿得太少,比低估氣溫更糟,可以讓高估的斜率較大;pinball 的 τ<1/2\tau<1/2 就會選較低的溫度分位數。這裡比較的是預測溫度與真實溫度,要先把哪一邊代價較大說清楚。

    房仲。 上一篇留下的問題現在有答案了:如果客戶對低估的痛苦是高估的三倍,宣告 τ=3/4\tau=3/4 的 pinball,模型會直接學條件的 75% 分位數,不需要事後修正。

    MSE 什麼時候合適? 當我們想估條件平均、有有限二階矩,並認為平方誤差符合用途。它也能用來估分類機率(Brier score),不是機率輸出就不能用;只是 sigmoid 的飽和可能讓最佳化比較慢。

    這一切依賴什麼。 一,ℓ\ell 真的代表你的偏好,而不是你會微分的東西。二,離群值是雜訊而不是訊號——如果那三個「離群值」其實是海嘯前兆,穩健損失會把最重要的資訊丟掉。三,最佳解存在且模型有能力逼近它;否則對照表講的是理想目標,不是你會拿到的東西。

    換一個損失,同一份資料

    第一段:離群值。 共用 toy 的 30 個點,把其中三個往上推 2.52.5(想像三筆打錯的成交價),用三次多項式配三種損失擬合,再量擬合曲線到真值 sin⁡(2πx)\sin(2\pi x) 的距離:

    import numpy as np
    from scipy.optimize import minimize
    from ml_toy import toy_1d, truth
    
    x, y = toy_1d(); y = y.copy()
    y[[5, 14, 23]] += 2.5                      # 三筆打錯的資料
    xs, ys = truth()
    V, Vs = np.vander(x, 4, increasing=True), np.vander(xs, 4, increasing=True)
    
    def fit(rho):                               # rho 把殘差變成扣分
        w0 = np.linalg.lstsq(V, y, rcond=None)[0]
        return minimize(lambda w: rho(V @ w - y).mean(), w0, method="Powell",
                        options=dict(xtol=1e-10, ftol=1e-12, maxfev=200000)).x
    
    losses = {
        "平方 (MSE)":    lambda r: r**2,
        "絕對 (MAE)":    lambda r: np.abs(r),
        "Huber δ=0.3":  lambda r: np.where(np.abs(r) <= .3, .5*r**2, .3*(np.abs(r) - .15)),
    }
    for name, rho in losses.items():
        w = fit(rho)
        print(f"{name:12s}  到真值的均方距離 {((Vs @ w - ys)**2).mean():.4f}")
    平方 (MSE)      到真值的均方距離 0.1005
    絕對 (MAE)      到真值的均方距離 0.0183
    Huber δ=0.3   到真值的均方距離 0.0148

    同一份資料、同一個假設空間、同一個最佳化器,只換扣分表,離真相的距離差了五倍以上。 三筆髒資料佔 10%,在平方損失下它們的話語權遠超過 10%——因為每一筆的扣分和距離的平方成正比,把曲線拉向它們是「划算」的。Huber 比 MAE 再好一點,因為在乾淨的那 27 點上它仍然是平方(更有效率),只對超過 δ\delta 的殘差鬆手。

    第二段:宣告對了,也可能訓不動。 二維月牙 toy,同一個線性 logistic 模型、同一個學習率、同樣 400 步,只換損失,並且從兩種起點出發:

    import numpy as np
    from ml_toy import toy_2d
    
    X, y = toy_2d()
    A = np.c_[np.ones(len(X)), X]
    sig = lambda z: 1/(1 + np.exp(-z))
    
    def train(kind, w0, steps=400, lr=0.5):
        w = np.array(w0, float)
        for _ in range(steps):
            p = sig(A @ w)
            g = (A.T @ (p - y))/len(y) if kind == "ce" else (A.T @ ((p - y)*p*(1-p)))/len(y)
            w -= lr*g
        p = sig(A @ w)
        nll = -(y*np.log(p+1e-12) + (1-y)*np.log(1-p+1e-12)).mean()
        return ((p > .5) == y).mean(), nll
    
    for w0, tag in (([0, 0, 0], "從零初始化"), ([0, -8, 8], "從一個很自信但錯誤的起點")):
        for kind, name in (("ce", "cross-entropy"), ("sq", "平方損失")):
            acc, nll = train(kind, w0)
            print(f"{tag:14s} {name:14s} 準確率 {acc:.3f}   NLL {nll:.4f}")
    從零初始化         cross-entropy  準確率 0.890   NLL 0.2603
    從零初始化         平方損失          準確率 0.865   NLL 0.2946
    
    從一個很自信但錯誤的起點  cross-entropy  準確率 0.890   NLL 0.2610
    從一個很自信但錯誤的起點  平方損失          準確率 0.180   NLL 9.0023

    從零出發,兩者差不多——這是大部分教科書示範停下來的地方,於是「平方損失也行」變成一個常見的誤解。刻意違反假設:把起點換成一個「錯得很自信」的權重(模型堅信答案相反)。cross-entropy 完全恢復(0.8900.890),平方損失卡在 0.1800.180——比亂猜還差,而且 400 步之後幾乎沒有移動。原因就是上面那個 p^(1−p^)\hat p(1-\hat p) 因子:模型越自信,梯度越小,錯誤越沒有被修正的力道。

    實務上「錯得很自信的起點」不是人造的怪例——深層網路的初始化、學習率一次過大之後的狀態、分佈偏移之後的舊模型,都會把你放在那裡。

    proper 保證你要的東西在最小點上,不保證你走得到。

    換扣分表,看最佳答案與梯度同時改變

    互動 demo:換損失函數,同一批資料的最佳擬合線就跟著換——扣分表決定你追到的是平均數還是中位數。

    檢查理解

    想一想

    一個外送平台要對每張訂單預測送達時間。晚到 10 分鐘的客訴成本,大約是早到 10 分鐘的四倍。工程團隊用 MSE 訓練,然後把預測值統一「加 5 分鐘」當作補償。最合適的評論是:

    想一想

    關於「cross-entropy 與作用在機率上的平方損失(Brier)都是 strictly proper」,正確的推論是:

    想一想

    在離群值那段實驗裡,如果把被改動的三個點從 +2.5+2.5 改成 +0.3+0.3(只是稍微偏),三種損失的差距會怎麼變?

    參考文獻

    1. Gneiting, T., Raftery, A. E. Strictly Proper Scoring Rules, Prediction, and Estimation. JASA 2007.(哪些損失的唯一最小點是真實分佈,以及損失與統計量的完整對照。)
    2. Huber, P. J., Ronchetti, E. M. Robust Statistics, 2nd ed. Wiley 2009, Ch. 1, 7.(Huber 損失的來源、效率與抵抗力的取捨、δ\delta 該怎麼設。)
    3. Bishop, C. M. Pattern Recognition and Machine Learning. Springer 2006, Ch. 1.5.5, 4.3.2.(Minkowski loss 一族;logistic 輸出下 cross-entropy 與平方損失的梯度差異。)