經過神經網絡解決多分類問題時,最經常使用的一種方式就是在最後一層設置n個輸出節點,不管在淺層神經網絡仍是在CNN中都是如此,好比,在AlexNet中最後的輸出層有1000個節點:
而即使是ResNet取消了全鏈接層,也會在最後有一個1000個節點的輸出層:
git
通常狀況下,最後一個輸出層的節點個數與分類任務的目標數相等。假設最後的節點數爲N,那麼對於每個樣例,神經網絡能夠獲得一個N維的數組做爲輸出結果,數組中每個維度會對應一個類別。在最理想的狀況下,若是一個樣本屬於k,那麼這個類別所對應的的輸出節點的輸出值應該爲1,而其餘節點的輸出都爲0,即[0,0,1,0,….0,0],這個數組也就是樣本的Label,是神經網絡最指望的輸出結果,交叉熵就是用來斷定實際的輸出與指望的輸出的接近程度!數組
神經網絡的原始輸出不是一個機率值,實質上只是輸入的數值作了複雜的加權和與非線性處理以後的一個值而已,那麼如何將這個輸出變爲機率分佈?
這就是Softmax層的做用,假設神經網絡的原始輸出爲y1,y2,….,yn,那麼通過Softmax迴歸處理以後的輸出爲:
很顯然的是:
而單個節點的輸出變成的一個機率值,通過Softmax處理後結果做爲神經網絡最後的輸出。網絡
交叉熵刻畫的是實際輸出(機率)與指望輸出(機率)的距離,也就是交叉熵的值越小,兩個機率分佈就越接近。假設機率分佈p爲指望輸出,機率分佈q爲實際輸出,H(p,q)爲交叉熵,則:函數
這個公式如何表徵距離呢,舉個例子:
假設N=3,指望輸出爲p=(1,0,0),實際輸出q1=(0.5,0.2,0.3),q2=(0.8,0.1,0.1),那麼:spa
很顯然,q2與p更爲接近,它的交叉熵也更小。
除此以外,交叉熵還有另外一種表達形式,仍是使用上面的假設條件:3d
其結果爲:code
以上的全部說明針對的都是單個樣例的狀況,而在實際的使用訓練過程當中,數據每每是組合成爲一個batch來使用,因此對用的神經網絡的輸出應該是一個m*n的二維矩陣,其中m爲batch的個數,n爲分類數目,而對應的Label也是一個二維矩陣,仍是拿上面的數據,組合成一個batch=2的矩陣:blog
因此交叉熵的結果應該是一個列向量(根據第一種方法):
而對於一個batch,最後取平均爲0.2。圖片
在TensorFlow能夠採用這種形式:ip
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
其中y_表示指望的輸出,y表示實際的輸出(機率值),*爲矩陣元素間相乘,而不是矩陣乘。
上述代碼實現了第一種形式的交叉熵計算,須要說明的是,計算的過程其實和上面提到的公式有些區別,按照上面的步驟,平均交叉熵應該是先計算batch中每個樣本的交叉熵後取平均計算獲得的,而利用tf.reduce_mean函數其實計算的是整個矩陣的平均值,這樣作的結果會有差別,可是並不改變實際意義。
除了tf.reduce_mean函數,tf.clip_by_value函數是爲了限制輸出的大小,爲了不log0爲負無窮的狀況,將輸出的值限定在(1e-10, 1.0)之間,其實1.0的限制是沒有意義的,由於機率怎麼會超過1呢。
因爲在神經網絡中,交叉熵經常與Sorfmax函數組合使用,因此TensorFlow對其進行了封裝,即:
cross_entropy = tf.nn.sorfmax_cross_entropy_with_logits(y_ ,y)
與第一個代碼的區別在於,這裏的y用神經網絡最後一層的原始輸出就行了。