作者 | PARAS DAHAL
譯者 | zzq
出品 | 人工智慧頭條(公眾號ID:AI_Thinker)
【導讀】如果你稍微了解一點深度學習的知識或者看過深度學習的在線課程,你就一定知道最基礎的多分類問題。當中,老師一定會告訴你在全連接層後面應該加上 Softmax 函數,如果正常情況下(不正常情況指的是類別超級多的時候)用交叉熵函數作為損失函數,你就一定可以得到一個讓你基本滿意的結果。而且,現在很多開源的深度學習框架,直接就把各種損失函數寫好了(甚至在 Pytorch中 CrossEntropyLoss 已經把 Softmax函數集合進去了),你根本不用操心怎麼去實現他們,但是你真的理解為什麼要這麼做嗎?這篇小文就將告訴你:Softmax 是如何把 CNN 的輸出轉變成概率,以及交叉熵是如何為優化過程提供度量。為了讓讀者能夠深入理解,我們將會用 Python 一一實現他們。
▌Softmax函數Softmax 函數接收一個 這N維向量作為輸入,然後把每一維的值轉換成(0,1)之間的一個實數,它的公式如下面所示:
正如它的名字一樣,Softmax 函數是一個「軟」的最大值函數,它不是直接取輸出的最大值那一類作為分類結果,同時也會考慮到其它相對來說較小的一類的輸出。
說白了,Softmax 可以將全連接層的輸出映射成一個概率的分布,我們訓練的目標就是讓屬於第k類的樣本經過 Softmax 以後,第 k 類的概率越大越好。這就使得分類問題能更好的用統計學方法去解釋了。
使用 Python,我們可以這麼去實現 Softmax 函數:
我們需要注意的是,在 numpy 中浮點類型是有數值上的限制的,對於float64,它的上限是 。對於指數函數來說,這個限制很容易就會被打破,如果這種情況發生了 python 便會返回 nan。
為了讓 Softmax 函數在數值計算層面更加穩定,避免它的輸出出現 nan這種情況,一個很簡單的方法就是對輸入向量做一步歸一化操作,僅僅需要在分子和分母上同乘一個常數 C,如下面的式子所示
理論上來說,我們可以選擇任意一個值作為,但是一般我們會選擇
,通過這種方法就使得原本非常大的指數結果變成0,避免出現 nan的情況。
同樣使用 Python,改進以後的 Softmax 函數可以這樣寫:
通過上文我們了解到,Softmax 函數可以將樣本的輸出轉變成概率密度函數,由於這一很好的特性,我們就可以把它加裝在神經網絡的最後一層,隨著迭代過程的不斷深入,它最理想的輸出就是樣本類別的 One-hot 表示形式。進一步我們來了解一下如何去計算 Softmax 函數的梯度(雖然有了深度學習框架這些都不需要你去一步步推導,但為了將來能設計出新的層,理解反向傳播的原理還是很重要的),對 Softmax 的參數求導:
根據商的求導法則,對於 其導數為 。對於我們來說
。在 中, 一直都是 ,但是在 中,若且唯若 的時候, 才為。具體的過程,我們看一下下面的步驟:
如果 ,
如果
所以 Softmax 函數的導數如下面所示:
▌交叉熵損失函數下面我們來看一下對模型優化真正起到作用的損失函數——交叉熵損失函數。交叉熵函數體現了模型輸出的概率分布和真實樣本的概率分布的相似程度。它的定義式就是這樣:
在分類問題中,交叉熵函數已經大範圍的代替了均方誤差函數。也就是說,在輸出為概率分布的情況下,就可以使用交叉熵函數作為理想與現實的度量。這也就是為什麼它可以作為有 Softmax 函數激活的神經網絡的損失函數。
我們來看一下,在 Python 中是如何實現交叉熵函數的:
就像我們之前所說的,Softmax 函數和交叉熵損失函數是一對好兄弟,我們用上之前推導 Softmax 函數導數的結論,配合求導交叉熵函數的導數:
加上 Softmax 函數的導數:
y 代表標籤的 One-hot 編碼,因此 ,並且 。因此我們就可以得到:
可以看到,這個結果真的太簡單了,不得不佩服發明它的大神們!最後,我們把它轉換成代碼:
▌小結需要注意的是,正如我之前提到過的,在許多開源的深度學習框架中,Softmax 函數被集成到所謂的 CrossEntropyLoss 函數中。比如 Pytorch 的說明文檔,就明確地告訴讀者 CrossEntropyLoss 這個損失函數是 Log-Softmax 函數和負對數似然函數(NLLoss)的組合,也就是說當你使用它的時候,沒有必要再在全連接層後面加入 Softmax 函數。還有許多文章中會提到 SoftmaxLoss,其實它就是 Softmax 函數和交叉熵函數的組合,跟我們說的 CrossEntropyLoss 函數是一個意思,這點需要讀者自行分辨即可。
原文連結:https://deepnotes.io/softmax-crossentropy
GitHub 地址:
https://github.com/parasdahal/deepnet
參考連結:The Softmax function and its derivative
Bendersky, E., 2016.
https://eli.thegreenplace.net/2016/the-softmax-function-and-its-derivative/
CS231n Convolutional Neural Networks for Visual Recognition
Andrej Karpathy, A.K., 2016.
http://cs231n.github.io/convolutional-networks/