L5.0 要怎麼替「這個模型有多符合資料」打一個分數?
本篇重用M5.1用錯的機率表下注一年會多輸多少:KL Divergence 與 Cross-Entropy·M1.0兩台體重計:Gaussian 的線性組合
起點:換一個問題
前面五個 class 都在做同一件事:給一個 ,猜一個 ,然後用某個損失檢查那個猜測有多準。台北的房仲去台中:風險與經驗風險 把「準」定義成風險,老師用考古題教學又出題:為什麼要切資料 說明那個數字要在哪份資料上讀,同一個實驗跑三次結果都不同,該報哪一個? 說明它自己也會抖。
現在換一個目標。不是「給 猜一個 」,而是把整份資料是從哪裡來的寫下來——一個分布 。
這個換法會立刻遇到一個問題。猜 的時候,「猜得準不準」有現成的意思: 就在那裡,比一下就知道。但一個分布要怎麼跟資料比?資料只是一堆點,它沒有附上一條密度曲線讓你對照。
一個模型說「這件事的機率是 」,另一個說 ,
而這件事發生了——後者一定比較好嗎?
如果有一個模型說機率是 ,它該被扣多少分?
課堂提問Q1
把「這個模型有多符合資料」翻成一個可以最小化的數字。要求兩件事:一, 筆獨立資料的總分應該可以由每一筆的分數加起來;二,分數只能用「模型給實際觀測到的那個值多少機率密度」算。在這兩個要求下,那個分數幾乎沒有選擇餘地——為什麼?
先想一想,再展開看整理後的答案
從可加性開始。 如果 獨立,模型給這整份資料的機率是乘積:
這個量叫似然(likelihood)。它已經是一個合理的分數了——模型給實際發生的事越高的機率,這個乘積越大。但它有兩個毛病。
第一個毛病是數值。 一千筆資料、每筆機率 ,乘起來是 ,浮點數直接變成 。任何比較都做不下去。
第二個毛病是形狀。 我們想要的是可加的分數,這樣它才能跟 台北的房仲去台中:風險與經驗風險 的經驗風險長得一樣、才能用 民調只問一千人:小批次與噪聲 的小批次無偏估計、才能丟給 霧中下山,一步該走多大:梯度下降的一頁。
兩個毛病同一個解法:取對數。乘積變加總, 變成 :
而「取對數」不只是一個方便的技巧,它是唯一的選擇。 如果你要一個把機率映到分數、而且滿足「獨立事件的分數相加」的函數 ,那就是要求 ;在連續性的假設下,這個方程式的解只有 。所以對數不是眾多選項裡比較好用的一個,它是「可加」這個要求本身的形狀。
最後加一個負號與除以 ,把它變成一個要最小化的、和樣本數無關的量——平均負對數似然(average negative log-likelihood,NLL):
回到 Ask 的第三問。 如果模型說某個實際發生的事機率是 ,那一項是 ——整份資料的分數變成無限大,一筆就毀掉全部。這不是公式的意外,這是「可加」這個要求的必然後果,而且它是一個實質的宣告:我的模型認為這件事不可能發生。 一個宣告不可能的事真的發生了,那個模型就被證偽了,沒有「稍微扣一點分」這種中間地帶。這一點在本篇最後會變成一個很具體的工程問題。
那個數字其實是兩個數字
平均 NLL 有一個分解,而那個分解把「模型好不好」拆成兩件可以分開讀的事。
把資料寫成經驗分布 (每一筆資料佔 的機率,這正是 台北的房仲去台中:風險與經驗風險 那個「把積分換成平均」的同一個對象)。那麼
左邊是你能算的、會拿去最小化的數字。右邊拆成兩項:
- 完全不含 。 它是資料本身的不確定性,你動不了它。
- 是唯一可以動的部分,而它 ,等號只在 時成立(用錯的機率表下注一年會多輸多少:KL Divergence 與 Cross-Entropy)。
實測。六個符號、真實機率 ,抽 筆之後算三個數字:
n= 30 MLE 的平均 NLL 1.4752 = 經驗分布的熵 1.4752
均勻模型的平均 NLL 1.7918 = 熵 1.4752 + KL(經驗‖均勻) 0.3165 = 1.7918
n= 300 MLE 的平均 NLL 1.6942 = 經驗分布的熵 1.6942
均勻模型的平均 NLL 1.7918 = 熵 1.6942 + KL(經驗‖均勻) 0.0975 = 1.7918
n=3000 MLE 的平均 NLL 1.6782 = 經驗分布的熵 1.6782
均勻模型的平均 NLL 1.7918 = 熵 1.6782 + KL(經驗‖均勻) 0.1136 = 1.7918
MLE 那一列的 KL 恰好是零。 因為六個符號的模型族包含所有分布,所以「模型族裡 KL 最近的成員」就是經驗分布本身,NLL 就等於經驗熵,一位小數都不差。
均勻模型的 NLL 永遠是 ,和 完全無關。 它不看資料,所以資料再多也不會變。
增加時經驗熵在往真實熵 爬。 的 明顯偏低——三十筆資料撒在六個格子裡,有些格子會意外地空或意外地滿,那讓經驗分布看起來比真實分布更集中,也就是熵更低。這是本篇第三節的主題的第一個徵兆。
最大似然不是在找「對的分布」,而是在模型族裡找一個離經驗分布 KL 最近的成員。
這句話把兩個限制同時講清楚了。模型族是一個限制:如果真實分布不在族裡,最好的成員也只是最好的近似(這就是 十個房仲各看一百間房:Bias 與 Variance 的 bias 換一個外衣)。經驗分布是另一個限制:你逼近的是手上這 筆資料算出來的分布,不是真實分布(這就是同一篇的 variance)。
Gaussian 假設就是最小平方
差一度與差十度:損失函數是一種宣告 說過:選一個損失就是在宣告你在乎什麼。那一篇把這句話停在直覺的層次。似然把它講完整了——那個宣告有一個具體的身分:你假設噪聲長什麼樣。
回到監督式的設定。假設
那麼 ,把負對數似然寫開(兩台體重計:Gaussian 的線性組合):
第二項不含 。所以最小化負對數似然,和最小化平方誤差,是同一件事——整個系列從 房仲怎麼估價:從例子學規則 用到現在的 MSE,其實一直是一個 Gaussian 假設。
換一個噪聲假設就換一個損失。拉普拉斯分布 給出
也就是最小絕對值誤差。而最小平方的解是平均數、最小絕對值的解是中位數——兩個大家都知道、看起來只是「不同的統計量」的東西,在這裡變成同一個框架下的兩個不同宣告。
實測。真實位置是 ,資料是 的 加上 偏移到 的離群點,,重複 2000 次:
95% N(0,1) + 5% 離群點 :
Gaussian 假設 → 最小平方 → 平均數 : 估計 +0.9965 ± 0.3165 均方誤差 1.0932
拉普拉斯假設 → 最小絕對值 → 中位數 : 估計 +0.0661 ± 0.0965 均方誤差 0.0137
純 N(0,1),沒有離群點 :
平均數 均方誤差 0.005007
中位數 均方誤差 0.007799 (比值 1.5578,理論 π/2 = 1.5708)
上半是「假設錯了」的代價: 的離群點讓最小平方的估計整整偏了 ,均方誤差差了 80 倍。原因不難看——Gaussian 的尾巴掉得像 ,一個 的點在這個假設下幾乎不可能存在,所以模型寧可把整條曲線拉過去,也不願意承認那個點。
下半是「假設對了」的回報:沒有離群點時,反而是最小平方比較好,比值 幾乎正中理論值 。那 的額外均方誤差是你為了防範離群點而付的保險費。
你選的不是損失,是噪聲模型;而那個假設錯得越離譜,代價越大。
補充這也解釋了為什麼分類用交叉熵而不是 MSE
分類的輸出是一個類別分布。把「模型給正確類別的機率」取負對數,就是大家熟知的交叉熵損失——它就是本篇的平均 NLL,只是換了一個名字。
那為什麼不能用 MSE 去配 one-hot 標籤?可以,但那是在宣告「標籤的噪聲是 Gaussian 的」,而標籤是 或 ,這個宣告明顯不對。實際的後果在梯度上:softmax 配交叉熵時,對 logit 的梯度恰好是 (見下方推導),乾淨且不會飽和;softmax 配 MSE 則會多乘一個 softmax 的雅可比,在模型信心很高但答錯的時候梯度反而趨近零——錯得越離譜、學得越慢,正好是反過來的。
展開細節softmax + 交叉熵對 logit 的梯度
設 logit 為 ,,標籤是類別 。損失 。
也就是 ( 是 one-hot)。這個式子沒有任何會飽和的因子:預測錯得越多,梯度越大。生產線出了瑕疵,怎麼知道是哪一站的責任? 提到的「把 softmax 和交叉熵合成一個節點」指的就是直接實作這一行,而不是分兩層各自微分——後者在數值上會經過 和除法,容易溢位。
小的時候,最大似然會說謊
前面兩節都在講 MLE 對的地方。這一節講它錯的地方,而且錯得比多數人預期的嚴重。
第一個實驗:一枚真實機率 的硬幣。 MLE 就是樣本比例。丟 次,重複很多次:
n= 5 MLE 說「這枚硬幣永遠不會出正面」的比例 16.61% MLE 的標準差 0.2043
n= 10 MLE 說「這枚硬幣永遠不會出正面」的比例 2.79% MLE 的標準差 0.1445
n= 50 MLE 說「這枚硬幣永遠不會出正面」的比例 0.00% MLE 的標準差 0.0652
n= 500 MLE 說「這枚硬幣永遠不會出正面」的比例 0.00% MLE 的標準差 0.0205
丟五次,有 的機率最大似然會告訴你「正面的機率是零」。 而根據第一節,「機率是零」是一個會讓 NLL 變成 的宣告——這個模型在下一次看到正面的時候會被無限扣分。它不是「有點不準」,它是在一個它其實會發生的事件上宣告不可能。
這不是 MLE 沒算好。 確實是那五次資料的最大似然解——如果五次都是反面,「正面機率為零」給那份資料的似然是 ,任何其他值都更低。問題在於「最符合手上的資料」和「最接近真相」是兩件不同的事,而這正是 背考古題的學生:過擬合與欠擬合 的主題換一個場景出現。
第二個實驗:模型離真相有多遠。 同一枚硬幣,量 的中位數:
n= 10 KL 中位數 0.08015
n= 100 KL 中位數 0.00732
n= 1000 KL 中位數 0.00070
n=10000 KL 中位數 0.00007
每把 乘十,KL 就掉大約十倍。 這是 ,不是 ——注意這和標準差那一欄不一樣( 是十倍 換 倍)。原因是 KL 在最小值附近是二次的:參數偏了 ,KL 大約是 乘上一個常數(那個常數就是 Fisher 資訊)。而 ,所以 。
第三個實驗:系統性的偏誤。 估計 的變異數,MLE 是 :
n= 3 E[σ²_MLE] = 0.6646 理論 (n-1)/n = 0.6667
n= 5 E[σ²_MLE] = 0.8014 理論 (n-1)/n = 0.8000
n= 10 E[σ²_MLE] = 0.9042 理論 (n-1)/n = 0.9000
n=100 E[σ²_MLE] = 0.9915 理論 (n-1)/n = 0.9900
MLE 系統性地低估變異數,而且這不是抖動——重複再多次,平均值仍然是 而不是 。理由很直白: 是從同一份資料算出來的,它會往資料的方向靠,所以資料到 的距離必然比到真實均值的距離短。這是「同一份資料用了兩次」的又一個版本,和 火力與時間是食譜的一部分,還是煮的時候決定的? 講的是同一件事。
注意偏誤與抖動是兩件事,而且縮得不一樣快
把上面三個實驗的縮放整理成一張表,會看到三個不同的速度:
| 量 | 速度 | ||
|---|---|---|---|
| MLE 的標準差 | |||
| 變異數估計的偏誤 | |||
偏誤比抖動縮得快,所以在 稍大之後,MLE 的誤差幾乎全部來自抖動。這就是為什麼「MLE 有偏」在實務上通常不是重點—— 時那 的偏誤,遠小於 的抖動。真正要擔心的是 小的時候,而那時候該做的不是換一個無偏估計量,是換一個限制更多的模型族,或者加先驗。
(把 換成 的那個「無偏變異數估計」確實存在,但它不是 MLE,而且它無偏的只有 —— 之後的 仍然有偏。無偏性不是在函數變換下保持的性質。)
似然曲面、樣本數,與零機率的懸崖
互動 demo:母體交叉熵與 KL 永遠平行、最小值同一個 μ;你手上只有抖動的那條經驗 NLL。
回到情境:零機率在訓練裡長什麼樣
第一節那個「」看起來像一個理論上的邊角,但它是實務上最常見的幾個 NaN 來源之一。
它會在哪裡出現。 一,語言模型遇到訓練時沒見過的 token;二,離散模型在 softmax 之前的 logit 太極端,數值上把某個機率壓成 ;三,連續模型把密度集中到一個點(限制筆記頁數,或考前一天停止補習:正則化與提早停止 提過的那種塌陷),那時候 NLL 可以往 跑,方向相反但一樣是發散。
三個標準對策,各自在宣告什麼。
- 平滑(Laplace / add-):在每個計數上加一個小常數。這等價於加一個先驗——你在說「我不相信任何事件的機率真的是零」,而 是這個不信的強度。它把 那 的災難直接消掉。
- 在 log 空間算:不要先算出機率再取對數,直接用
log_softmax、logsumexp這一類函式。這不改變數學,只是不讓浮點數在中途把一個很小的數變成零。 - 限制模型族:不給模型表達「機率為零」的能力(例如輸出層加一個下界,或用一個尾巴夠厚的分布族)。這是三個裡最強的宣告,也最容易在別的地方付出代價。
這一切依賴什麼。 一, 筆資料獨立——這是把乘積拆開的那一步用到的,而時間序列、同一位病患的多次量測、同一張圖片的多個 crop 都不滿足它。二,模型族裡有東西接近真相;不然 MLE 收斂到的是「族裡 KL 最近的成員」,而那可能離真相很遠,且第三節那些「隨 消失」的保證一個都不適用。三,似然本身算得出來——下一篇整篇就在處理算不出來的情況。
最大似然給你的保證是「 夠大時會收斂到模型族裡 KL 最近的成員」;它從來沒有保證那個成員是好的。
先消化一下
參考文獻
- Cover, T. & Thomas, J. Elements of Information Theory, 2nd ed. Wiley 2006, Ch. 2, 11.(熵、交叉熵與 KL 的標準處理,以及「NLL = 熵 + KL」這個分解的資訊論讀法。)
- Bishop, C. Pattern Recognition and Machine Learning. Springer 2006, Ch. 1.2, 2.3.(把最小平方還原成 Gaussian 似然,以及變異數 MLE 的偏誤來源。)
- Murphy, K. Probabilistic Machine Learning: An Introduction. MIT Press 2022, Ch. 4.(MLE 的一致性與漸近性質,以及平滑/先驗在小樣本的作用。)