資訊量、熵和交叉熵
資訊量、熵和交叉熵
總結
- 資訊量利用概率倒數的對數對事件的稀缺性進行衡量
- 熵是一個隨機系統資訊量的期望
- 交叉熵用於衡量兩個概率分佈之間的差異
資訊量:
資訊量是對事件發生概率的度量,一個事件發生的概率越低,則這個事件包含的資訊量越大,這跟我們直觀上的認知也是吻合的,越稀奇新聞包含的資訊量越大,因為這種新聞出現的概率低。夏農提出了一個定量衡量資訊量的公式:
熵
熵是一種對不確定性的方法,對於存在不確定性的系統,熵越大表示該系統的不確定性越大,熵為0表示沒有任何不確定性。熵的定義如下:
從這個公式可以看出,熵其實就是隨機系統各個事件的夏農資訊量的期望,或者叫均值。如果這個隨機系統只包含兩種可能,如拋硬幣的結果,正面概率為p,反面結果為1-p,那麼這個系統的熵就是:
當隨機系統中各個事件概率相等的時候,系統的熵最大,也就是不確定性最大,而隨著某個事件的概率逐漸增大,對立事件概率越來越小,這種情況下系統的不確定性越來越小,最終趨向於0,也就是成為一個沒有隨機因素的系統。這個結論可以通過對熵計算極值的方法求證,對上面熵的公式進行求導,使其導數為0:
可以看出,當p=1/2的時候熵取最大值,也就是系統不確定性最大。
上面給出的計算是基於拋硬幣系統進行的,這個系統只有正面或反面兩種事件,推廣到包含多個事件的隨機系統結論也是成立的。也就是說,對於包含N個事件的隨機系統,在沒有任何先驗知識的前提下,當這N個事件等概率的時候,系統熵最大,最混亂。
在統計學習方法中,有個最大熵模型,最大熵模型認為使得一個隨機系統的熵最大(最混亂)的模型是最好的模型,這是最大熵模型的大前提。主觀上理解,在沒有任何先驗知識的情況下,假設各個事件是等概率的,這是合理的。在這個前提或者叫準則下,最大熵模型的任務就是使得隨機系統在滿足約束條件的前提下,達到最大的熵。
最大熵模型的計算分三種情況:
-
不存在任何約束
這種情況下只有一個隱形的等式約束,就是各個事件概率之和為1。直接令熵的導數=0求解即可,結論上面已經給出,當N個事件等概率的時候熵最大,可以通過拉格朗日乘子法進行證明 -
只存在等式約束
這時同樣需要使用拉格朗日函乘子將約束條件加入到目標函式中進行求解。下面給出一個使用拉格朗日乘子求解帶等式約束的最大化問題:
-
存在不等式約束
存在不等式約束的最優化問題求解同樣使用拉格朗日運算元進行計算,使目標函式滿足KKT條件,進行求解,此處不再推導。
交叉熵
交叉熵用來衡量預測概率分佈和真實概率分佈之間差異的度量,計算公式如下,其中Pi是真實分佈,Qi是預測分佈:
預測分佈越接近真實的分佈,交叉熵越小,當預測分佈等於真實分佈時,交叉熵最小,此時交叉熵的值等同於熵。所以,交叉熵提供了一種衡量兩個分佈之間差異大小的方式,常用來作為神經網路的損失函式。當神經網路的預測分佈跟真實分佈(人工標註結果)相差很大時,交叉熵就大;當神經網路隨著訓練的進行預測分佈越來越接近真實分佈時,交叉熵就逐漸減小。
交叉熵和均方誤差的區別
交叉熵和均方誤差都可以作為神經網路的損失函式,他們的區別在於:
- 交叉熵適用於分類問題,結果是離散的類別(如圖片分類),而均方誤差適用於迴歸問題,結果是一個連續的數值(如雨量預測)【實際上均方誤差也可以用於分類問題】
- 在使用sigmod啟用函式時,如果使用均方誤差作為損失函式,反向傳播的導數(直接影響學習速度)會包含sigmod函式的梯度,這個梯度隨著變數的增大會趨向於0,導致學習速度迅速降低;而如果使用交叉熵作為損失函式,就不存在這個問題,反向傳播的導數包含sigmod函式,而不包含sigmod函式的導數。
tf.nn.softmax_cross_entropy_with_logits實現交叉熵和損失的計算
import tensorflow as tf
logits = tf.constant([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]])
y_ = tf.constant([[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]])
# softmax_cross_entropy_with_logits計算後,矩陣的每一行資料計算出一個交叉熵,三行資料共計算出三個交叉熵
cross_entropy_lst = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_)
# 通過reduce_sum進行累加,計算出一個batch的交叉熵
cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_))
# 將batch裡每條記錄的交叉熵求均值,作為損失
cross_entropy_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_))
# 手動分解上面的計算,過程如下
logits_softmax = tf.nn.softmax(logits)
cross_entropy_2 = -tf.reduce_sum(y_ * tf.log(logits_softmax)) # batch所有資料求和
cross_entropy_lst_2 = -tf.reduce_sum(y_ * tf.log(logits_softmax), 1) # batch每行資料求和
cross_entropy_2_loss = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(logits_softmax), 1)) # batch每行資料求和後,再求均值
with tf.Session() as sess:
print sess.run(cross_entropy_lst)
print sess.run(cross_entropy)
print sess.run(cross_entropy_loss)
print sess.run(cross_entropy_lst_2)
print sess.run(cross_entropy_2)
print sess.run(cross_entropy_2_loss)
輸出:
[ 0.40760595 0.40760595 0.40760595]
1.22282
0.407606
[ 0.40760601 0.40760601 0.40760598]
1.22282
0.407606