cross_entropy-----交叉熵是深度學(xué)習(xí)中常用的一個概念,一般用來求目標(biāo)與預(yù)測值之間的差距。
在介紹softmax_cross_entropy,binary_cross_entropy、sigmoid_cross_entropy之前,先來回顧一下信息量、熵、交叉熵等基本概念。
---------------------
信息論
交叉熵是信息論中的一個概念,要想了解交叉熵的本質(zhì),需要先從最基本的概念講起。
一、信息量
首先是信息量。假設(shè)我們聽到了兩件事,分別如下:
事件A:巴西隊進(jìn)入了2018世界杯決賽圈。
事件B:中國隊進(jìn)入了2018世界杯決賽圈。
僅憑直覺來說,顯而易見事件B的信息量比事件A的信息量要大。究其原因,是因為事件A發(fā)生的概率很大,事件B發(fā)生的概率很小。所以當(dāng)越不可能的事件發(fā)生了,我們獲取到的信息量就越大。越可能發(fā)生的事件發(fā)生了,我們獲取到的信息量就越小。那么信息量應(yīng)該和事件發(fā)生的概率有關(guān)。
二、什么是熵
熵
對于某個事件,有n種可能性,每一種可能性都有一個概率p(xi)
這樣就可以計算出某一種可能性的信息量。舉一個例子,假設(shè)你拿出了你的電腦,按下開關(guān),會有三種可能性,下表列出了每一種可能的概率及其對應(yīng)的信息量
注:文中的對數(shù)均為自然對數(shù)
我們現(xiàn)在有了信息量的定義,而熵用來表示所有信息量的期望,即:
其中n代表所有的n種可能性,所以上面的問題結(jié)果就是
二、 相對熵(KL散度)
相對熵又稱KL散度,如果我們對于同一個隨機變量 x 有兩個單獨的概率分布 P(x) 和 Q(x),我們可以使用 KL 散度(Kullback-Leibler (KL) divergence)來衡量這兩個分布的差異
在機器學(xué)習(xí)中,P往往用來表示樣本的真實分布,比如[1,0,0]表示當(dāng)前樣本屬于第一類。Q用來表示模型所預(yù)測的分布,比如[0.7,0.2,0.1]
KL散度的計算公式:
三、什么是交叉熵
交叉熵
對式3.1變形可以得到:
其中p代表label或者叫g(shù)roundtruth,q代表預(yù)測值
在機器學(xué)習(xí)中,我們需要評估label和predicts之間的差距,使用KL散度剛剛好,即
由于KL散度中的前一部分恰巧就是p的熵,p代表label或者叫g(shù)roundtruth,故?H(p(x))不變,故在優(yōu)化過程中,只需要關(guān)注交叉熵就可以了,所以一般在機器學(xué)習(xí)中直接用用交叉熵做loss,評估模型。
交叉熵:
四、softmax_cross_entropy
以tensorflow中函數(shù)softmax_cross_entropy_with_logits為例,在二分類或者類別相互排斥多分類問題,計算 logits 和 labels 之間的 softmax 交叉熵。
數(shù)據(jù)必須經(jīng)過 One-Hot Encoding 編碼
tf.one_hot
用 mnist 數(shù)據(jù)舉例,如果是目標(biāo)值是3,那么 label 就是[0,0,0,1,0,0,0,0,0,0],除了第4個值為1,其他全為0。
該函數(shù)把一個維度上的 labels 作為一個整體判斷,結(jié)果給出整個維度的損失值。
這個函數(shù)傳入的 logits 是 unscaled 的,既不做 sigmoid 也不做 softmax ,因為函數(shù)實現(xiàn)會在內(nèi)部更高效得使用 softmax 。
softmax_cross_entropy_with_logits計算過程
1、對輸入進(jìn)行softmax
舉個例子:假設(shè)你的輸入S=[1,2,3],那么經(jīng)過softmax層后就會得到[0.09,0.24,0.67],這三個數(shù)字表示這個樣本屬于第1,2,3類的概率分別是0.09,0.24,0.67。
2、計算交叉熵
L是損失,Sj是softmax的輸出向量S的第j個值,前面已經(jīng)介紹過了,表示的是這個樣本屬于第j個類別的概率。yj前面有個求和符號,j的范圍也是1到類別數(shù)T,因此label——y是一個1*T的向量,里面的T個值,而且只有1個值是1,其他T-1個值都是0。真實標(biāo)簽對應(yīng)的位置的那個值是1,其他都是0。所以這個公式其實有一個更簡單的形式:
來舉個例子吧。假設(shè)一個5分類問題,然后一個樣本I的標(biāo)簽y=[0,0,0,1,0],也就是說樣本I的真實標(biāo)簽是4,假設(shè)模型預(yù)測的結(jié)果概率(softmax的輸出)p=[0.1,0.15,0.05,0.6,0.1],可以看出這個預(yù)測是對的,那么對應(yīng)的損失L=-log(0.6),也就是當(dāng)這個樣本經(jīng)過這樣的網(wǎng)絡(luò)參數(shù)產(chǎn)生這樣的預(yù)測p時,它的損失是-log(0.6)。那么假設(shè)p=[0.15,0.2,0.4,0.1,0.15],這個預(yù)測結(jié)果就很離譜了,因為真實標(biāo)簽是4,而你覺得這個樣本是4的概率只有0.1(遠(yuǎn)不如其他概率高,如果是在測試階段,那么模型就會預(yù)測該樣本屬于類別3),對應(yīng)損失L=-log(0.1)。
補充:sparse_softmax_cross_entropy_with_logits
sparse_softmax_cross_entropy_with_logits 是 softmax_cross_entropy_with_logits 的易用版本,除了輸入?yún)?shù)不同,作用和算法實現(xiàn)都是一樣的。
區(qū)別是:softmax_cross_entropy_with_logits 要求傳入的 labels 是經(jīng)過 one_hot encoding 的數(shù)據(jù),而 sparse_softmax_cross_entropy_with_logits 不需要。
五、binary_cross_entropy
binary_cross_entropy是二分類的交叉熵,實際是多分類softmax_cross_entropy的一種特殊情況,當(dāng)多分類中,類別只有兩類時,即0或者1,即為二分類,二分類也是一個邏輯回歸問題,也可以套用邏輯回歸的損失函數(shù)。
1、利用softmax_cross_entropy_with_logits來計算二分類的交叉熵
來舉個例子,假設(shè)一個2分類問題,假如一個batch包含兩個樣本,那么標(biāo)簽要制成二維,形如
y=[ [1, 0],[0, 1] ],
模型預(yù)測輸出也為二維,形如
p=[ [0.8,0.2],[0.4,0.6] ]? #(softmax的輸出)
那么對應(yīng)的損失
L=( -log(0.8) - log(0.6) ) / 2
實際在計算中若采用softmax_cross_entropy_with_logits函數(shù),不要事先做softmax處理。
2、套用邏輯回歸代價損失函數(shù)來計算二分類的交叉熵
邏輯回歸的損失函數(shù)如下:
來舉個例子,假設(shè)一個2分類問題,假如一個batch包含兩個樣本,那么標(biāo)簽要制成一維,形如
y=[0,1 ],
模型預(yù)測輸出也為一維,形如
p=[ 0.2,0.6 ]? #sigmoid的輸出,這里一定要預(yù)先用sigmod處理,將預(yù)測結(jié)果限定在0~1之間,
那么對應(yīng)的損失
L=( - 0*log(0.2) - (1 - 0)*log(1- 0.2) - log(0.6) - (1 -1)*log(1 - 0.6) ) / 2 = ( -log(0.8) - log(0.6) ) / 2
六、sigmoid_cross_entropy
以tensorflow中函數(shù)sigmoid_cross_entropy_with_logits為例說明
sigmoid_cross_entropy_with_logits函數(shù),測量每個類別獨立且不相互排斥的離散分類任務(wù)中的概率。(可以執(zhí)行多標(biāo)簽分類,其中圖片可以同時包含大象和狗。)
import tensorflow as tf
_logits = [[0.5, 0.7, 0.3], [0.8, 0.2, 0.9]]
_one_labels = tf.ones_like(_logits)
# [[1 1 1]? ?
#? [1 1 1]]? ?
_zero_labels = tf.zeros_like(_logits)
# [[0 0 0]? ?
#? [0 0 0]]? ?
with tf.Session() as sess:
? ? ? ? loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=_logits, labels=_one_labels)
? ? ? ? print(sess.run(loss))
? ? ? ? # [[0.47407699? 0.40318602? 0.5543552]? ?
? ? ? ? #? [0.37110069? 0.59813887? 0.34115386]]? ?
? ? ? ? loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=_logits, labels=_zero_labels)
? ? ? ? print(sess.run(loss))
? ? ? ? ? # [[0.97407699? 1.10318601? 0.85435522]? ?
? ? ? ? ? #? [1.17110074? 0.79813886? 1.24115384]]
看看sigmoid_cross_entropy_with_logits函數(shù)定義
def sigmoid_cross_entropy_with_logits(_sentinel=None,? labels=None, logits=None,? name=None):
#為了描述簡潔,規(guī)定 x = logits,z = labels,那么 Logistic 損失值為:
? ? ? z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x))
? ? ? = z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
? ? ? = z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
? ? ? = z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
? ? ? = (1 - z) * x + log(1 + exp(-x))
? ? ? = x - x * z + log(1 + exp(-x))
該函數(shù)與 softmax_cross_entropy_with_logits的區(qū)別在于:softmax_cross_entropy_with_logits中的labels 中每一維只能包含一個 1,而sigmoid_cross_entropy_with_logits中的labels 中每一維可以包含多個 1。
softmax_cross_entropy_with_logits函數(shù)把一個維度上的 labels 作為一個整體判斷,結(jié)果給出整個維度的損失值,而 sigmoid_cross_entropy_with_logits 是每一個元素都有一個損失值,都是一個二分類(binary_cross_entropy)問題。