轉(zhuǎn)自 http://baike.renwuyi.com/2016-12/18582.html
交叉熵(Cross Entropy)是Loss函數(shù)的一種(也稱為損失函數(shù)或代價函數(shù)),用于描述模型預(yù)測值與真實值的差距大小,常見的Loss函數(shù)就是均方平方差(Mean Squared Error),定義如下。
? 平方差很好理解,預(yù)測值與真實值直接相減,為了避免得到負(fù)數(shù)取絕對值或者平方,再做平均就是均方平方差。注意這里預(yù)測值需要經(jīng)過sigmoid激活函數(shù),得到取值范圍在0到1之間的預(yù)測值。
平方差可以表達(dá)預(yù)測值與真實值的差異,但在分類問題種效果并不如交叉熵好。
上面的文章也介紹了交叉熵可以作為Loss函數(shù)的原因,首先是交叉熵得到的值一定是正數(shù),其次是預(yù)測結(jié)果越準(zhǔn)確值越小,注意這里用于計算的“a”也是經(jīng)過sigmoid激活的,取值范圍在0到1。如果label是1,預(yù)測值也是1的話,前面一項y * ln(a)就是1 * ln(1)等于0,后一項(1 - y) * ln(1 - a)也就是0 * ln(0)等于0,Loss函數(shù)為0,反之Loss函數(shù)為無限大非常符合我們對Loss函數(shù)的定義。
這里多次強調(diào)sigmoid激活函數(shù),是因為在多目標(biāo)或者多分類的問題下有些函數(shù)是不可用的,而TensorFlow本身也提供了多種交叉熵算法的實現(xiàn)。
TensorFlow的交叉熵函數(shù)
TensorFlow針對分類問題,實現(xiàn)了四個交叉熵函數(shù),分別是
sigmoid_cross_entropy_with_logits詳解
我們先看sigmoid_cross_entropy_with_logits,為什么呢,因為它的實現(xiàn)和前面的交叉熵算法定義是一樣的,也是TensorFlow最早實現(xiàn)的交叉熵算法。這個函數(shù)的輸入是logits和targets,logits就是神經(jīng)網(wǎng)絡(luò)模型中的 W * X矩陣,注意不需要經(jīng)過sigmoid,而targets的shape和logits相同,就是正確的label值,例如這個模型一次要判斷100張圖是否包含10種動物,這兩個輸入的shape都是[100, 10]。注釋中還提到這10個分類之間是獨立的、不要求是互斥,這種問題我們成為多目標(biāo),例如判斷圖片中是否包含10種動物,label值可以包含多個1或0個1,還有一種問題是多分類問題,例如我們對年齡特征分為5段,只允許5個值有且只有1個值為1,這種問題可以直接用這個函數(shù)嗎?答案是不可以,我們先來看看sigmoid_cross_entropy_with_logits的代碼實現(xiàn)吧。
可以看到這就是標(biāo)準(zhǔn)的Cross Entropy算法實現(xiàn),對W * X得到的值進行sigmoid激活,保證取值在0到1之間,然后放在交叉熵的函數(shù)中計算Loss。對于二分類問題這樣做沒問題,但對于前面提到的多分類,例如年輕取值范圍在04,目標(biāo)值也在04,這里如果經(jīng)過sigmoid后預(yù)測值就限制在0到1之間,而且公式中的1 - z就會出現(xiàn)負(fù)數(shù),仔細(xì)想一下0到4之間還不存在線性關(guān)系,如果直接把label值帶入計算肯定會有非常大的誤差。因此對于多分類問題是不能直接代入的,那其實我們可以靈活變通,把5個年齡段的預(yù)測用onehot encoding變成5維的label,訓(xùn)練時當(dāng)做5個不同的目標(biāo)來訓(xùn)練即可,但不保證只有一個為1,對于這類問題TensorFlow又提供了基于Softmax的交叉熵函數(shù)。
softmax_cross_entropy_with_logits詳解
Softmax本身的算法很簡單,就是把所有值用e的n次方計算出來,求和后算每個值占的比率,保證總和為1,一般我們可以認(rèn)為Softmax出來的就是confidence也就是概率,算法實現(xiàn)如下。
?softmax_cross_entropy_with_logits和sigmoid_cross_entropy_with_logits很不一樣,輸入是類似的logits和lables的shape一樣,但這里要求分類的結(jié)果是互斥的,保證只有一個字段有值,例如CIFAR-10中圖片只能分一類而不像前面判斷是否包含多類動物。想一下問什么會有這樣的限制?在函數(shù)頭的注釋中我們看到,這個函數(shù)傳入的logits是unscaled的,既不做sigmoid也不做softmax,因為函數(shù)實現(xiàn)會在內(nèi)部更高效得使用softmax,對于任意的輸入經(jīng)過softmax都會變成和為1的概率預(yù)測值,這個值就可以代入變形的Cross Entroy算法- y * ln(a) - (1 - y) * ln(1 - a)算法中,得到有意義的Loss值了。如果是多目標(biāo)問題,經(jīng)過softmax就不會得到多個和為1的概率,而且label有多個1也無法計算交叉熵,因此這個函數(shù)只適合單目標(biāo)的二分類或者多分類問題,TensorFlow函數(shù)定義如下。
再補充一點,對于多分類問題,例如我們的年齡分為5類,并且人工編碼為0、1、2、3、4,因為輸出值是5維的特征,因此我們需要人工做onehot encoding分別編碼為00001、00010、00100、01000、10000,才可以作為這個函數(shù)的輸入。理論上我們不做onehot encoding也可以,做成和為1的概率分布也可以,但需要保證是和為1,和不為1的實際含義不明確,TensorFlow的C++代碼實現(xiàn)計劃檢查這些參數(shù),可以提前提醒用戶避免誤用。
sparse_softmax_cross_entropy_with_logits詳解
sparse_softmax_cross_entropy_with_logits是softmax_cross_entropy_with_logits的易用版本,除了輸入?yún)?shù)不同,作用和算法實現(xiàn)都是一樣的。前面提到softmax_cross_entropy_with_logits的輸入必須是類似onehot encoding的多維特征,但CIFAR-10、ImageNet和大部分分類場景都只有一個分類目標(biāo),label值都是從0編碼的整數(shù),每次轉(zhuǎn)成onehot encoding比較麻煩,有沒有更好的方法呢?答案就是用sparse_softmax_cross_entropy_with_logits,它的第一個參數(shù)logits和前面一樣,shape是[batch_size, num_classes],而第二個參數(shù)labels以前也必須是[batch_size, num_classes]否則無法做Cross Entropy,這個函數(shù)改為限制更強的[batch_size],而值必須是從0開始編碼的int32或int64,而且值范圍是[0, num_class),如果我們從1開始編碼或者步長大于1,會導(dǎo)致某些label值超過這個范圍,代碼會直接報錯退出。這也很好理解,TensorFlow通過這樣的限制才能知道用戶傳入的3、6或者9對應(yīng)是哪個class,最后可以在內(nèi)部高效實現(xiàn)類似的onehot encoding,這只是簡化用戶的輸入而已,如果用戶已經(jīng)做了onehot encoding那可以直接使用不帶“sparse”的softmax_cross_entropy_with_logits函數(shù)。
weighted_sigmoid_cross_entropy_with_logits詳解
weighted_sigmoid_cross_entropy_with_logits是sigmoid_cross_entropy_with_logits的拓展版,輸入?yún)?shù)和實現(xiàn)和后者差不多,可以多支持一個pos_weight參數(shù),目的是可以增加或者減小正樣本在算Cross Entropy時的Loss。實現(xiàn)原理很簡單,在傳統(tǒng)基于sigmoid的交叉熵算法上,正樣本算出的值乘以某個系數(shù)接口,算法實現(xiàn)如下。
?總結(jié)
這就是TensorFlow目前提供的有關(guān)Cross Entropy的函數(shù)實現(xiàn),用戶需要理解多目標(biāo)和多分類的場景,根據(jù)業(yè)務(wù)需求(分類目標(biāo)是否獨立和互斥)來選擇基于sigmoid或者softmax的實現(xiàn),如果使用sigmoid目前還支持加權(quán)的實現(xiàn),如果使用softmax我們可以自己做onehot coding或者使用更易用的sparse_softmax_cross_entropy_with_logits函數(shù)。
TensorFlow提供的Cross Entropy函數(shù)基本cover了多目標(biāo)和多分類的問題,但如果同時是多目標(biāo)多分類的場景,肯定是無法使用softmax_cross_entropy_with_logits,如果使用sigmoid_cross_entropy_with_logits我們就把多分類的特征都認(rèn)為是獨立的特征,而實際上他們有且只有一個為1的非獨立特征,計算Loss時不如Softmax有效。這里可以預(yù)測下,未來TensorFlow社區(qū)將會實現(xiàn)更多的op解決類似的問題,我們也期待更多人參與TensorFlow貢獻算法和代碼