深度学习中的信息论——交叉熵
信息量
可以說就信息量是在將信息量化。首先信息的相對多少是有切實體會的,有的人一句話能包含很多信息,有的人說了等于沒說。我們還可以直觀地感覺到信息的多少和概率是有關的,概率大的信息也相對低一些。為了量化信息,一個做法就是找到一個單位,比如說拋硬幣就是一個基本單位,或者說我們使用01編碼。先看等概率的情況,種類數越多,那么需要編碼的長度就越大,每個碼字(編碼的每一位)獨立分布,所以當每個碼字的取值為時,可以表示的種類為,所以。因為是等概,所以概率和種類數目就是倒數的關系,。那么,不等概的情況呢,比如把骰子的2改為1,那么轉到1那一面的概率為,我們以“”轉到1的一面“”這件事件為單位對概率1重新劃分,因為概率總和為1,那么所有的類的數目就是1/p。
現在我們知道信息量中log取2為底和概率取導數的真正含義了。那么熵是什么呢?既然信息量是衡量一件事的不確定程度,那么熵就是衡量一個系統的混亂程度。它綜合了所有可能發生類別的不確定性,其實就是信息量的期望。從編碼的角度,熵指的是對隨機變量編碼所需的最小比特數。有一種編碼的種類就叫作熵編碼,屬于無損編碼。因為熵就是平均信息量,而信息量是以01編碼進行量化的,那么為了不損失信息,我們最少也需要這么多的bit進行編碼。同時可以看到,概率越小出現的符號,允許使用更長的編碼,這樣整體的編碼效率才更高。
交叉熵
對于兩個信源,分別求熵可以得到各自平均每個字符對應的最小的編碼長度。那么如果兩個信源互換編碼方式呢?平均每個字符所需的最小bit位如何計算呢。從公式上看,變化就是取對數的對象換成了編碼對象的概率分布,而加權所使用的概率仍然是自己的概率??梢灶A見,互換編碼方式之后求出的“熵”會增大。因為兩個位置的概率不統一,所以被稱作交叉熵。
交叉熵用于評估兩個分布的差異,常用于分類任務。而分類中常用的激活函數是softmax,我們看看在代碼上有什么需要注意的地方。https://blog.csdn.net/weixin_40476348/article/details/94570666
import torch import torch.nn.functional as F import torch.nn as nntorch.manual_seed(2019)output = torch.randn(2, 3) # 網絡輸出 target = torch.ones(2, dtype=torch.long).random_(3) # 真實標簽 print('output:\n{}'.format(output)) print('target:\n{}\n'.format(target))# 第一步,對output進行log_softmax運算 log_softmax = F.log_softmax(output, dim=1) print('log_softmax:\n{}\n'.format(log_softmax)) # 第二步,將計算結果和target輸入nll_loss損失函數計算交叉熵 nll_loss = F.nll_loss(log_softmax, target) print('nll_loss:{}'.format(nll_loss))# 直接使用cross_entropy損失函數計算output與target的交叉熵 cross_entropy_loss = F.cross_entropy(output, target) print('cross_entropy_loss:{}'.format(cross_entropy_loss))# 實例化類 criterion = nn.CrossEntropyLoss() loss = criterion(output, target) print('loss:{}'.format(loss))""" output: tensor([[-0.1187, 0.2110, 0.7463],[-0.6136, -0.1186, 1.5565]]) target: tensor([2, 0])log_softmax: tensor([[-1.5614, -1.2317, -0.6964],[-2.4335, -1.9386, -0.2635]])nll_loss:1.564985990524292 cross_entropy_loss:1.564985990524292 loss:1.564985990524292 """當使用torch中的cross_entropy函數時,輸入可以直接是全連接的輸出和標簽值,而不需要添加softmax。原因是在cross_entropy內部自動計算softmax得到概率,并且最終輸出交叉熵。
按照公式,交叉熵的計算可以分為三步:先計算輸出的判決概率;再取對數;再以先驗概率加權求和,并取負號。第一步由torch.softmax完成(原理細節可以參考之前的博客);第二步就是簡單的取對數:torch.log;第三步在torch有函數F.nll_loss。而第一第二步又可以合并為一步:torch.Logsoftmax()
注意n.softmax在計算概率的時候要指定好維度,從而保證不同互斥類別的概率之和為1.
KL散度,相對熵
剛才提到,熵的一個重要意義是編碼對應的最短碼字。注意看公式值權重的概率和log中的概率是相對應的。權重的概率表示先驗的分布,當log中概率變為q,權重仍然為p時,表示依靠舊的先驗分布去cover另外一個未知的情況,那么這時再計算出的值肯定會比原來的最短碼長長。他們的差值就是相對熵,寫成公式為:
注意權重概率都是p,p對應時更短,所以放在減號右邊,經過變換,寫成比例關系時位于分子的位置。當然是長的減短的,所以取值范圍就是0~正無窮。經過恒等變換,就可以得到我們最常見的KL散度的表達式。這就經常被用來衡量兩個信源,或者說兩個分布的差異性,因為差異越大,編碼的適用性越差,編碼長度變化量也越大。需要注意的是該“距離”不具有對稱性。
既然KL散度可以衡量兩個分布的差異,而機器學習/深度學習的目的就是讓模型在訓練集和測試集中得分的分布盡可能接近,所以KL散度就可以用來作損失函數。但為什么常見的是交叉熵呢?這是因為KL散度的一部分是恒定不變的,所以交叉熵和相對熵其實是同等變化的。交叉熵作為損失函數還有一個好處是使用sigmoid函數在梯度下降時能避免均方誤差損失函數學習速率降低的問題,因為學習速率可以被輸出的誤差所控制。
再深究一點,其實最小化交叉熵和最大似然估計也是等價的。因為最大似然的目的其實是最小化取負對數,取對數的目的是防止連乘過程中的溢出。這就造成了二者首先在格式上是相似的。最大似然是求取模型的參數分布,使得輸出的值是已知樣本的概率最大,本質上也是讓二者的分布最接近。
在決策樹中,除了使用基于熵的信息增益,常見的還有基尼不純度。從名字上看,不純度和熵的混亂程度是類似的;實際上,二者確實也是類似的,基尼不純度其實是熵的近似值(log泰勒展開,忽略高階項)?;诮坪蟮玫降男鹿?#xff0c;也可以有新的解釋:一個隨機事件變成它的對立事件的概率/分錯的概率。
在網上的資料中提到,熵與基尼不純度還有一個區別是熵到達峰值的過程相對慢一些,并且由此造成熵對于混亂程度的判罰要重一些。這里我不太明白,基尼不純度是通過舍棄高階項來近似熵,所以基尼不純度是要比熵值低一些的,二者都是在等概時取最大值,所以二者的關系是熵的曲線段在不純度上方,二者端點相同。因為熵值更大,所以作為損失函數時的懲罰力度更大。
scipy中實現了KL散度的計算,當參數中只有一個序列時,計算的是熵,并且可以指定以e為底還是以2為底:
>>>entropy([1/2, 1/2], base=2) 1.0當有兩個序列時,以第一個序列為先驗分布計算二者的KL散度:
>>>entropy([1/2, 1/2], qk=[9/10, 1/10]) 0.5108256237659907而我在這里計算的時候返回的值是inf,即便輸入的是兩個完全一致的序列也是這樣,問題出在哪里呢?我這里犯了一個錯,輸入的序列應該是各個事件發生的概率,即應該是一個離散的概率密度序列,而不能直接輸入兩個取值的集合。尤其是取值可能出現負數,這樣把它當做概率進行求對數,就會出錯,返回inf。
對應做法是利用scipy中的norm.pdf估計概率密度。還有就是手動統計兩個序列在各個區間內數值的頻率。比如可以利用np.percentile得到四分位數。
Reference:
https://zhuanlan.zhihu.com/p/59550047
https://www.zhihu.com/question/65288314
https://zhuanlan.zhihu.com/p/40024110
https://www.cnblogs.com/arkenstone/p/10524720.html
https://zhuanlan.zhihu.com/p/76667156
近似https://blog.csdn.net/yingwei13mei/article/details/75452526?utm_source=blogxgwz7
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的深度学习中的信息论——交叉熵的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++程序从源代码到可执行程序的流程
- 下一篇: 【每日SQL打卡】