模型一心想要變小的那個數字
你已經知道,一個模型接收輸入、產生預測,並在訓練過程中調整自己的參數以表現得更好。但「表現得更好」對機器來說實在太模糊了。電腦沒法去追逐一種「在進步」的感覺,它只能追逐一個數字。損失函數就是這個數字:一個單一的純量,用來給模型此刻對某一個樣本的預測打分,衡量它錯得有多離譜。越低越好;為零就意味著完全命中。
有三個詞常被幾乎不加區分地混用,把它們各自釘清楚會很有幫助。損失(loss)通常指單個樣本上的誤差。代價(cost)是一個批次或整個資料集上損失的平均值——也就是我們真正想要最小化的東西。目標(objective)則是最佳化器最終處理的那個運算式,它往往是代價再加上一些額外項(比如對複雜模型的懲罰)。日常交流裡,人們用這三個詞都指「我們要弄小的那個東西」,這沒問題——只要記住:最佳化器最終總會落到一個具體的數字上,去把它往下推。
迴歸問題:用 MSE 把差距平方
當模型預測的是一個數值——房價、明天的氣溫、一個人的年齡——我們就用預測值和真實標籤之間的差距來衡量錯誤。最經典的選擇是均方誤差(MSE):取每一個差距,把它平方,再對所有樣本求平均。平方一下子幹了兩件事。它讓每個誤差都變成正數(這樣一個偏高 3 的預測就不會和一個偏低 3 的預測相互抵消),並且它對大偏差的懲罰遠比小偏差狠得多——誤差為 10 要付出 100 的代價,誤差為 1 卻只付出 1。
這種狠勁是把雙刃劍,對此保持誠實很重要。因為單個巨大的誤差會主導整個平均值,MSE 對離群點非常敏感——一個被標錯的或詭異的資料點,就能把整個模型往它那邊拽。當你為此擔心時,平均絕對誤差(它對未平方的距離求平均)會更平等地對待所有誤差,並對離群點不以為然。這裡沒有放之四海皆準的最佳答案;沒有免費午餐定理提醒我們:合適的損失取決於你的資料,以及犯錯在你這個世界裡要付出的代價。
MSE 還有一個不動聲色的優點,使它成為線性迴歸以及成千上萬其他模型的預設選擇:它光滑且呈碗狀。它的斜率變化得溫和而可預測,而這正是下一篇要講的梯度下降找到下山之路所需要的。一個讓最佳化器容易導航的損失,價值不可小覷。
分類問題:為什麼我們不直接數錯了幾個
現在假設模型必須選一個類別:是不是垃圾郵件、是貓還是狗、是十個數字中的哪一個。你真正在意的誠實成績單是準確率——它答對了幾成?但準確率作為學習用的損失卻糟糕透頂。它幾乎處處是平的:把某個參數輕微挪動一點,答對的數量通常根本不變,於是沒有斜率能告訴最佳化器該往哪個方向邁步。我們需要一個損失,它對模型「當時有多自信」做出平滑的反應,而不只是看它最後對沒對。
解決辦法是讓模型輸出機率——比如,「這封郵件是垃圾郵件」的機率為 0.9——通常二分類用 sigmoid、多分類用 softmax 來實現。然後我們用交叉熵(也叫對數損失)給它打分。這個想法美得很簡單:只看模型分配給正確答案的那個機率,損失就是這個機率的負對數。自信且正確(機率接近 1)幾乎不付出代價。自信卻錯誤(它給真實類別的機率接近 0)則要付出巨大代價,因為一個極小數字的對數會向負無窮俯衝。
# cross-entropy for one example
p_true = model_probs[ correct_class ] # e.g. 0.9
loss = -log( p_true ) # 0.9 -> 0.105 (cheap)
# 0.01 -> 4.6 (painful)
# average this over all examples to get the cost這並不是一個隨意拼湊的公式。最小化交叉熵在數學上等價於極大似然估計——讓觀測到的資料在模型下盡可能地有可能發生——而且它本質上就是真實標籤與模型猜測之間的 KL 散度中真正起作用的那部分。正是這一深層聯繫,讓交叉熵(而非原始的準確率)訓練了幾乎所有分類器,從邏輯迴歸一直到龐大的語言模型。
從單個樣本到一條學習法則:經驗風險
損失給單個樣本打分,但我們想要的是一個全面表現良好的模型。在理想世界裡,我們會去最小化模型在所有可能輸入構成的整個宇宙上的平均損失——也就是它的真實風險。可我們做不到:我們從來看不到那整個宇宙,只看得到我們收集來的資料集。於是我們退而求其次,去最小化我們實際擁有的資料上的平均損失。這個平均值就是經驗風險,而最小化它正是整個遊戲的核心,這套做法有個氣派的名字:經驗風險最小化。
- 挑一個與任務匹配的損失函數(數值用 MSE,類別用交叉熵)。
- 讓訓練資料流過模型,並為每個樣本計算損失。
- 把這些損失求平均,得到經驗風險——一個總結了「總錯誤量」的數字。
- 調整參數讓這個數字變小,然後重複。
損失能告訴你什麼,又不能告訴你什麼
一條不斷下降的損失曲線讓人感覺是在進步,通常也確實如此——但要帶著懷疑的眼光去讀它。損失是你拿來最佳化的量,它很少是人類最終真正在意的那個量。一個垃圾郵件過濾器也許刷出一條漂亮的交叉熵曲線,卻悄悄放過了那封唯一要命的詐騙郵件,因為損失把每封郵件都看得同等重要。當類別嚴重失衡時——比如 99% 都是正常郵件這樣的類別不平衡——模型完全可以靠徹底無視那個稀有類別來取得很低的損失。
正是這道鴻溝,讓損失和評估指標各過各的日子。你針對一個光滑、可微的損失來訓練,因為最佳化器需要斜率;你卻用你真正在意的指標來評判——準確率、精確率、召回率、省下的錢——哪怕這些指標坑坑窪窪、根本沒法直接拿來最佳化。一個明智的工作流程總會先立一個基線(一個胡亂瞎猜的預測器能拿到多少損失?),這樣你才能看出,一個花俏的模型究竟是真的物有所值,還是不過在複述顯而易見的東西。
所以請對損失抱以恰如其分的敬重:它是那個不可或缺的指南針,把模糊的「表現得更好」變成機器能夠遵循的具體方向,而你現在已經認識了驅動大多數現代學習的那兩個損失。但指南針不等於目的地。損失一旦選定,剩下唯一的問題就是:到底該如何挪動參數才能把它弄小——而這恰恰是下一篇要踏上的那段下坡之旅。