1 引入
上一篇介紹了圖像分類問題。圖像分類的任務,就是從已有的固定分類標簽集合中選擇一個並分配給一張圖像。我們還介紹了k-Nearest Neighbor (k-NN)分類器,該分類器的基本思想是通過將測試圖像與訓練集帶標簽的圖像進行比較,來給測試圖像打上分類標簽。k-Nearest Neighbor分類器存在以下不足:
(1)分類器必須記住所有訓練數據並將其存儲起來,以便於未來測試數據用於比較。這在存儲空間上是低效的,數據集的大小很容易就以GB計。
(2)對一個測試圖像進行分類需要和所有訓練圖像作比較,算法計算資源耗費高。
我們將要實現一種更強大的方法來解決圖像分類問題,該方法可以自然地延伸到神經網絡和卷積神經網絡上。這種方法主要有兩部分組成:一個是評分函數(score function),它是原始圖像數據到類別分值的映射。另一個是損失函數(loss function),它是用來量化預測分類標簽的得分與真實標簽之間一致性的。該方法可轉化為一個最優化問題,在最優化過程中,將通過更新評分函數的參數來最小化損失函數值。
2 評分函數
評分函數將圖像的像素值映射為各個分類類別的得分,得分高低代表圖像屬於該類別的可能性高低。下面會用一個具體例子來展示該方法。現在假設有一個包含很多圖像的訓練集\(x_{i} \in R^{D}\),每個圖像都有一個對應的分類標簽\(y_{i}\)。這里\(i=1,2 \ldots N\)並且\(y_{i} \in 1 \ldots K\)。這就是說,我們有N個圖像樣例,每個圖像的維度是D,共有K種不同的分類。
舉例來說,在CIFAR-10中,我們有一個N=50000的訓練集,每個圖像有D=32x32x3=3072個像素,而K=10,這是因為圖片被分為10個不同的類別(狗,貓,汽車等)。我們現在定義評分函數為:\(f : R^{D} \rightarrow R^{K}\),該函數是原始圖像像素到分類分值的映射。
2.1 線性分類器
在本模型中,我們從最簡單的概率函數開始,一個線性映射:
在上面的公式中,假設每個圖像數據都被拉長為一個長度為D的列向量,大小為[D x 1]。其中大小為[K x D]的矩陣W和大小為[K x 1]列向量b為該函數的參數(parameters)。還是以CIFAR-10為例,\(\mathcal{x}_{i}\)就包含了第i個圖像的所有像素信息,這些信息被拉成為一個[3072 x 1]的列向量,W大小為[10x3072],b的大小為[10x1]。因此,3072個數字(原始像素數值)輸入函數,函數輸出10個數字(不同分類得到的分值)。參數W被稱為權重(weights)。b被稱為偏差向量(bias vector),這是因為它影響輸出數值,但是並不和原始數據\(\mathcal{x}_{i}\)產生關聯。在實際情況中,人們常常混用權重和參數這兩個術語。
需要注意的幾點:
(1)一個單獨的矩陣乘法\(W x_{i}\)就高效地並行評估10個不同的分類器(每個分類器針對一個分類),其中每個類的分類器就是W的一個行向量。
(2)注意我們認為輸入數據\(\left(x_{i}, y_{i}\right)\)是給定且不可改變的,但參數W和b是可控制改變的。我們的目標就是通過設置這些參數,使得計算出來的分類分值情況和訓練集中圖像數據的真實類別標簽相符。我們以后將詳細介紹如何做到這一點,但是目前只需要直觀地讓正確分類的分值比錯誤分類的分值高即可。
(3)該方法的一個優勢是訓練數據是用來學習到參數W和b的,一旦訓練完成,訓練數據就可以丟棄,留下學習到的參數即可。這是因為一個測試圖像可以簡單地輸入函數,並基於計算出的分類分值來進行分類。
(4)注意只需要做一個矩陣乘法和一個矩陣加法就能對一個測試數據分類,這比k-NN中將測試圖像和所有訓練數據做比較的方法快多了。
2.2 理解線性分類器
線性分類器計算圖像中3個顏色通道中所有像素的值與權重的矩陣乘,從而得到分類分值。根據我們對權重設置的值,對於圖像中的某些位置的某些顏色,函數表現出喜好或者厭惡(根據每個權重的符號而定)。
舉個例子,可以想象“船”分類就是被大量的藍色所包圍(對應的就是水)。那么“船”分類器在藍色通道上的權重就有很多的正權重(它們的出現提高了“船”分類的分值),而在綠色和紅色通道上的權重為負的就比較多(它們的出現降低了“船”分類的分值)。
下邊再舉一個將圖像映射到分類分值的具體例子:

上圖為了便於可視化,假設圖像只有4個像素(都是黑白像素,這里不考慮RGB通道),有3個分類(紅色代表貓,綠色代表狗,藍色代表船,注意,這里的紅、綠和藍3種顏色僅代表分類,和RGB通道沒有關系)。首先將圖像像素拉伸為一個列向量,與W進行矩陣乘,然后得到各個分類的分值。需要注意的是,這個W一點也不好:貓分類的分值非常低。從上圖來看,算法倒是覺得這個圖像是一只狗。
2.2.1 將圖像看做高維度的點
既然圖像被伸展成為了一個高維度的列向量,那么我們可以把圖像看做這個高維度空間中的一個點(即每張圖像是3072維空間中的一個點)。整個數據集就是一個點的集合,每個點都帶有1個分類標簽。
既然定義每個分類類別的分值是權重和圖像的矩陣乘,那么每個分類類別的分數就是這個空間中的一個線性函數的函數值。我們沒辦法可視化3072維空間中的線性函數,但假設把這些維度擠壓到二維,那么就可以看看這些分類器在做什么了:

上圖是圖像空間的示意圖。其中每個圖像是一個點,有3個分類器。以紅色的汽車分類器為例,紅線表示空間中汽車分類分數為0的點的集合,紅色的箭頭表示分值上升的方向。所有紅線右邊的點的分數值均為正,且線性升高。紅線左邊的點分值為負,且線性降低。
從上面可以看到,W的每一行都是一個分類類別的分類器。對於這些數字的幾何解釋是:如果改變其中一行的數字,會看見分類器在空間中對應的直線開始向着不同方向旋轉。而偏差b,則允許分類器對應的直線平移。需要注意的是,如果沒有偏差,無論權重如何,在\(x_{i}=0\)時分類分值始終為0。這樣所有分類器的線都不得不穿過原點。
2.2.2 將線性分類器看做模板匹配
關於權重W的另一個解釋是它的每一行對應着一個分類的模板(有時候也叫作原型)。一張圖像對應不同分類的得分,是通過使用內積(也叫點積)來比較圖像和模板,然后找到和哪個模板最相似。從這個角度來看,線性分類器就是在利用學習到的模板,針對圖像做模板匹配。從另一個角度來看,可以認為還是在高效地使用k-NN,不同的是我們沒有使用所有的訓練集的圖像來比較,而是每個類別只用了一張圖片(這張圖片是我們學習到的,而不是訓練集中的某一張),而且我們會使用(負)內積來計算向量間的距離,而不是使用L1或者L2距離。
2.2.3 圖像數據預處理
在上面的例子中,所有圖像都是使用的原始像素值(從0到255)。在機器學習中,對於輸入的特征做歸一化(normalization)處理是常見的套路。而在圖像分類的例子中,圖像上的每個像素可以看做一個特征。在實踐中,對每個特征減去平均值來中心化數據是非常重要的。在這些圖片的例子中,該步驟意味着根據訓練集中所有的圖像計算出一個平均圖像值,然后每個圖像都減去這個平均值,這樣圖像的像素值就大約分布在[-127, 127]之間了。下一個常見步驟是,讓所有數值分布的區間變為[-1, 1]。零均值的中心化是很重要的,等我們理解了梯度下降后再來詳細解釋。
3 損失函數
在上一節定義了從圖像像素值到所屬類別的評分函數(score function),該函數的參數是權重矩陣W。在函數中,數據\(\left(x_{i}, y_{i}\right)\)是給定的,不能修改。但是我們可以調整權重矩陣這個參數,使得評分函數的結果與訓練數據集中圖像的真實類別一致,即評分函數在正確的分類的位置應當得到最高的評分(score)。
回到之前那張貓的圖像分類例子,它有針對“貓”,“狗”,“船”三個類別的分數。我們看到例子中權重值非常差,因為貓分類的得分非常低(-96.8),而狗(437.9)和船(61.95)比較高。我們將使用損失函數(Loss Function)(有時也叫代價函數Cost Function或目標函數Objective)來衡量我們對結果的不滿意程度。直觀地講,當評分函數輸出結果與真實結果之間差異越大,損失函數輸出越大,反之越小。
3.1 多類支持向量機損失函數
損失函數的具體形式多種多樣。首先,介紹常用的多類支持向量機損失函數(Multiclass Support Vector Machine Loss)。SVM的損失函數想要SVM在正確分類上的得分始終比不正確分類上的得分高出一個邊界值\(\Delta\)。我們可以把損失函數想象成一個人,這位SVM先生(或者女士)對於結果有自己的品位,如果某個結果能使得損失值更低,那么SVM就更加喜歡它。
讓我們更精確一些。回憶一下,第i個數據中包含圖像\(x_{i}\)的像素和代表正確類別的標簽\(y_{i}\)。評分函數輸入像素數據,然后通過公式\(f\left(x_{i}, W\right)\)來計算不同分類類別的分值。這里我們將分值簡寫為s。比如,針對第j個類別的得分就是第j個元素:\(s_{j}=f\left(x_{i}, W\right)_{j}\)。針對第i個數據的多類SVM的損失函數定義如下:
用一個例子演示公式是如何計算的。假設有3個分類,並且得到了分值s=[13,-7,11]。其中第一個類別是正確類別,即\(y_{i}=0\)。同時假設\(\Delta\)是10(后面會詳細介紹該超參數)。上面的公式是將所有不正確分類\(\left(j \neq y_{i}\right)\)加起來,所以我們得到兩個部分:
可以看到第一個部分結果是0,這是因為[-7-13+10]得到的是負數,經過max(0,-)函數處理后得到0。這一對類別分數和標簽的損失值是0,這是因為正確分類的得分13與錯誤分類的得分-7的差為20,高於邊界值10。而SVM只關心差距至少要大於10,更大的差值還是算作損失值為0。第二個部分計算[11-13+10]得到8。雖然正確分類的得分比不正確分類的得分要高(13>11),但是比10的邊界值還是小了,分差只有2,這就是為什么損失值等於8。簡而言之,SVM的損失函數想要正確分類類別\(\mathcal{y}_{i}\)的分數比不正確類別分數高,而且至少要高\(\Delta\)。如果不滿足這點,就開始計算損失值。
那么在這次的模型中,我們面對的是線性評分函數\(\left(f\left(x_{i}, W\right)=W x_{i}\right)\),所以我們可以將損失函數的公式稍微改寫一下:
其中\(w_{j}\)是權重W的第j行,被變形為列向量。然而,一旦開始考慮更復雜的評分函數f公式,這樣做就不是必須的了。
還必須提一下關於0的閥值:\(\max (0,-)\)函數,它常被稱為折葉損失(hinge loss)。有時候會聽到人們使用平方折葉損失SVM(即L2-SVM),它使用的是\(\max (0,-)^{2}\),將更強烈(平方地而不是線性地)地懲罰過界的邊界值。不使用平方是更標准的版本,但是在某些數據集中,平方折葉損失會工作得更好。可以通過交叉驗證來決定到底使用哪個。
3.2 正則化
上面損失函數有一個問題。假設有一個數據集和一個權重集W能夠正確地分類每個數據(即所有的邊界都滿足,對於所有的i都有\(L_{i}=0\))。問題在於這個W並不唯一:可能有很多相似的W都能正確地分類所有的數據。一個簡單的例子:如果W能夠正確分類所有數據,即對於每個數據,損失值都是0。那么當\(\lambda>1\)時,任何數乘\(\lambda \boldsymbol{W}\)都能使得損失值為0,因為這個變化將所有分值的大小都均等地擴大了,所以它們之間的絕對差值也擴大了。舉個例子,如果一個正確分類的分值和舉例它最近的錯誤分類的分值的差距是15,對W乘以2將使得差距變成30。
換句話說,我們希望能向某些特定的權重W添加一些偏好,對其他權重則不添加,以此來消除模糊性。這一點是能夠實現的,方法是向損失函數增加一個正則化懲罰(regularization penalty)R(W)部分。最常用的正則化懲罰是L2范式,L2范式通過對所有參數進行逐元素的平方懲罰來抑制大數值的權重:
上面的表達式中,將W中所有元素平方后求和。注意正則化函數不是數據的函數,僅基於權重。包含正則化懲罰后,就能夠給出完整的多類SVM損失函數了,它由兩個部分組成:數據損失(data loss),即所有樣例的的平均損失\(\boldsymbol{I}_{i}\),以及正則化損失(regularization loss)。完整公式如下所示:
將其展開完整公式是:
其中,N是訓練集的數據量。現在正則化懲罰添加到了損失函數里面,並用超參數\(\lambda\)來計算其權重。該超參數無法簡單確定,需要通過交叉驗證來獲取。
除了上述理由外,引入正則化懲罰還帶來很多良好的性質,這些性質大多會在后續章節介紹。比如引入了L2懲罰后,SVM們就有了最大邊界(max margin)這一良好性質。(如果感興趣,可以查看CS229課程)。
其中最好的性質就是對大數值權重進行懲罰,可以提升其泛化能力,因為這就意味着沒有哪個維度能夠獨自對於整體分值有過大的影響。舉個例子,假設輸入向量\(x=[1,1,1,1]\),兩個權重向量\(w_{1}=[1,0,0,0], \quad w_{2}=[0.25,0.25,0.25,0.25]\)。那么\(w_{1}^{T} x=w_{2}^{T}=1\),兩個權重向量都得到同樣的內積,但是\(w_{1}\)的L2懲罰是1.0,而\(w_{2}\)的L2懲罰是0.25。因此,根據L2懲罰來看,\(w_{2}\)更好,因為它的正則化損失更小。從直觀上來看,這是因為\(w_{2}\)的權重值更小且更分散。既然L2懲罰傾向於更小更分散的權重向量,這就會鼓勵分類器最終將所有維度上的特征都用起來,而不是強烈依賴其中少數幾個維度。在后面的課程中可以看到,這一效果將會提升分類器的泛化能力,並避免過擬合。
需要注意的是,和權重不同,偏差沒有這樣的效果,因為它們並不控制輸入維度上的影響強度。因此通常只對權重W正則化,而不正則化偏差b。在實際操作中,可發現這一操作的影響可忽略不計。最后,因為正則化懲罰的存在,不可能在所有的例子中得到0的損失值,這是因為只有當W=0的特殊情況下,才能得到損失值為0。
3.3 關於SVM loss 的現實考慮
你可能注意到上面的內容對超參數\(\Delta\)及其設置是一筆帶過,那么它應該被設置成什么值?需要通過交叉驗證來求得嗎?現在看來,該超參數在絕大多數情況下設為\(\Delta=1.0\)都是安全的。超參數\(\Delta\)和\(\lambda\)看起來是兩個不同的超參數,但實際上他們一起控制同一個權衡:即損失函數中的數據損失和正則化損失之間的權衡。理解這一點的關鍵是要知道,權重W的大小對於分類分值有直接影響(當然對他們的差異也有直接影響):當我們將W中值縮小,分類分值之間的差異也變小,反之亦然。因此,不同分類分值之間的邊界的具體值(比如\(\Delta=1\)或\(\Delta=100\))從某些角度來看是沒意義的,因為權重自己就可以控制差異變大和縮小。也就是說,真正的權衡是我們允許權重能夠變大到何種程度(通過正則化強度\(\lambda\)來控制)。
你可能對於二元支持向量機有些經驗,它對於第i個數據的損失計算公式是:
其中,C是一個超參數,並且\(y_{i} \in\{-1,1\}\)。可以認為本章節介紹的SVM公式包含了上述公式,上述公式是多類支持向量機公式只有兩個分類類別的特例。也就是說,如果我們要分類的類別只有兩個,那么公式就化為二元SVM公式。這個公式中的C和多類SVM公式中的\(\lambda\)都控制着同樣的權衡,而且它們之間的關系是:\(C \propto \frac{1}{\lambda}\)
注:需要指出的是,本課中展示的多類SVM只是多種SVM公式中的一種。
3.4 Softmax分類器的損失函數
SVM是最常用的兩個分類器之一,而另一個就是Softmax分類器,它的損失函數與SVM的損失函數不同。對於學習過二元邏輯回歸分類器的讀者來說,Softmax分類器就可以理解為邏輯回歸分類器面對多個分類的一般化歸納。SVM將輸出\(f\left(x_{i}, W\right)\)作為每個分類的評分(因為無定標,所以難以直接解釋)。與SVM不同,Softmax的輸出(歸一化的分類概率)更加直觀,並且從概率上可以解釋,這一點后文會討論。在Softmax分類器中,函數映射\(f\left(x_{i} ; W\right)=W x_{i}\)保持不變,但將這些評分值視為每個分類的未歸一化的對數概率,並且將折葉損失(hinge loss)替換為交叉熵損失(cross-entropy loss)。公式如下:
等價於下式:
在上式中,使用\(f_{j}\)來表示分類評分向量\(f\)中的第j個元素。和之前一樣,整個數據集的損失值是數據集中所有樣本數據的損失值\(\boldsymbol{L}_{i}\)的均值與正則化損失\(R(W)\)之和。其中函數\(f_{j}(z)=\frac{e^{z_{j}}}{\sum_{k} e^{z_{k}}}\)被稱作softmax 函數:其輸入值是一個向量,向量中元素為任意實數的評分值(z中的),函數對其進行壓縮,輸出一個向量,其中每個元素值在0到1之間,且所有元素之和為1。所以,包含softmax函數的完整交叉熵損失看起唬人,實際上還是比較容易理解的。
3.4.1 信息論角度的理解
在“真實”分布p和估計分布q之間的交叉熵定義如下:
因此,Softmax分類器所做的就是最小化在估計分類概率(就是上面的\(e^{f_{y_{i}}} / \sum_{j} e^{f_{j}}\))和“真實”分布之間的交叉熵,在這個解釋中,“真實”分布就是所有概率密度都分布在正確的類別上(比如:p=[0,...1,...,0]中在\(y_{i}\)的位置就有一個單獨的1)。還有,既然交叉熵可以寫成熵和相對熵(Kullback-Leibler divergence)\(H(p, q)=H(p)+D_{K L}(p \| q)\),並且delta函數p的熵是0,那么就能等價的看做是對兩個分布之間的相對熵做最小化操作。換句話說,交叉熵損失函數“想要”預測分布的所有概率密度都在正確分類上。
注:Kullback-Leibler差異(Kullback-Leibler Divergence)也叫做相對熵(Relative Entropy),它衡量的是相同事件空間里的兩個概率分布的差異情況。
3.4.2 概率論角度的理解
先看下面的公式:
可以解釋為是給定圖像數據\(x_{i}\),以W為參數,分配給正確分類標簽\(y_{i}\)的歸一化概率。為了理解這點,請回憶一下Softmax分類器將輸出向量f中的評分值解釋為沒有歸一化的對數概率。那么以這些數值做指數函數的冪就得到了沒有歸一化的概率,而除法操作則對數據進行了歸一化處理,使得這些概率的和為1。從概率論的角度來理解,我們就是在最小化正確分類的負對數概率,這可以看做是在進行最大似然估計(MLE)。該解釋的另一個好處是,損失函數中的正則化部分\(R(W)\)可以被看做是權重矩陣W的高斯先驗,這里進行的是最大后驗估計(MAP)而不是最大似然估計。
3.5 關於Softmax的現實考慮
主要是數值穩定問題。編程實現softmax函數計算的時候,中間項\(e^{f_{y_{i}}}\)和\(\sum_{j} e^{f_{j}}\)因為存在指數函數,所以數值可能非常大。除以大數值可能導致數值計算的不穩定,所以學會使用歸一化技巧非常重要。如果在分式的分子和分母都乘以一個常數C,並把它變換到求和之中,就能得到一個從數學上等價的公式:
C的值可自由選擇,不會影響計算結果,通過使用這個技巧可以提高計算中的數值穩定性。通常將C設為logC=-max_jf_j。該技巧簡單地說,就是應該將向量f中的數值進行平移,使得最大值為0。
3.6 關於損失函數命名規則的考慮
精確地說,SVM分類器使用的是折葉損失(hinge loss),有時候又被稱為最大邊界損失(max-margin loss)。Softmax分類器使用的是交叉熵損失(corss-entropy loss)。Softmax分類器的命名是從softmax函數那里得來的,softmax函數將原始分類評分變成正的歸一化數值,所有數值和為1,這樣處理后交叉熵損失才能應用。注意從技術上說“softmax損失(softmax loss)”是沒有意義的,因為softmax只是一個壓縮數值的函數。但是在這個說法常常被用來做簡稱。
3.7 SVM與Softmax的比較
下圖有助於區分這 Softmax和SVM這兩種分類器:

針對一個數據點,SVM和Softmax分類器的不同處理方式的例子。兩個分類器都計算了同樣的分值向量f(本節中是通過矩陣乘來實現)。不同之處在於對f中分值的解釋:SVM分類器將它們看做是分類評分,它的損失函數鼓勵正確的分類(本例中是藍色的類別2)的分值比其他分類的分值高出至少一個邊界值。Softmax分類器將這些數值看做是每個分類沒有歸一化的對數概率,鼓勵正確分類的歸一化的對數概率變高,其余的變低。SVM的最終的損失值是1.58,Softmax的最終的損失值是0.452,但要注意這兩個數值沒有可比性。只在給定同樣數據,在同樣的分類器的損失值計算中,它們才有意義。
SVM的計算是無標定的,而且難以針對所有分類的評分值給出直觀解釋。Softmax分類器則不同,它允許我們計算出對於所有分類標簽的可能性。舉個例子,針對給出的圖像,SVM分類器可能給你的是一個[12.5, 0.6, -23.0]對應分類“貓”,“狗”,“船”。而softmax分類器可以計算出這三個標簽的”可能性“是[0.9, 0.09, 0.01],這就讓你能看出對於不同分類准確性的把握。為什么我們要在”可能性“上面打引號呢?這是因為可能性分布的集中或離散程度是由正則化參數λ直接決定的,λ是你能直接控制的一個輸入參數。舉個例子,假設3個分類的原始分數是[1, -2, 0],那么softmax函數就會計算:
\([1,-2,0] \rightarrow\left[e^{1}, e^{-2}, e^{0}\right]=[2.71,0.14,1] \rightarrow[0.7,0.04,0.26]\)
現在,如果正則化參數λ更大,那么權重W就會被懲罰的更多,然后他的權重數值就會更小。這樣算出來的分數也會更小,假設小了一半吧[0.5, -1, 0],那么softmax函數的計算就是:
\([0.5,-1,0] \rightarrow\left[e^{0.5}, e^{-1}, e^{0}\right]=[1.65,0.73,1] \rightarrow[0.55,0.12,0.33]\)
現在看起來,概率的分布就更加分散了。還有,隨着正則化參數λ不斷增強,權重數值會越來越小,最后輸出的概率會接近於均勻分布。這就是說,softmax分類器算出來的概率最好是看成一種對於分類正確性的自信。和SVM一樣,數字間相互比較得出的大小順序是可以解釋的,但其絕對值則難以直觀解釋。
通常說來,兩種分類器的表現差別很小,不同的人對於哪個分類器更好有不同的看法。相對於Softmax分類器,SVM更加“局部目標化(local objective)”,這既可以看做是一個特性,也可以看做是一個劣勢。考慮一個評分是[10, -2, 3]的數據,其中第一個分類是正確的。那么一個SVM(\(\Delta=1\))會看到正確分類相較於不正確分類,已經得到了比邊界值還要高的分數,它就會認為損失值是0。SVM對於數字個體的細節是不關心的:如果分數是[10, -100, -100]或者[10, 9, 9],對於SVM來說沒設么不同,只要滿足超過邊界值等於1,那么損失值就等於0。
對於softmax分類器,情況則不同。對於[10, 9, 9]來說,計算出的損失值就遠遠高於[10, -100, -100]的。換句話來說,softmax分類器對於分數是永遠不會滿意的:正確分類總能得到更高的可能性,錯誤分類總能得到更低的可能性,損失值總是能夠更小。但是,SVM只要邊界值被滿足了就滿意了,不會超過限制去細微地操作具體分數。這可以被看做是SVM的一種特性。舉例說來,一個汽車的分類器應該把他的大量精力放在如何分辨小轎車和大卡車上,而不應該糾結於如何與青蛙進行區分,因為區分青蛙得到的評分已經足夠低了。