KL 散度(相對熵)


KL 散度又叫 相對熵,是衡量 兩個概率分布 匹配程度的指標,KL 散度越大,分布差異越大,匹配度越低 

計算公式如下

 

或者

 

 

其中 p是 目標分布,或者叫被匹配的分布,或者叫模板分布,q 是去匹配的分布;

試想,p 是真實值,q 是預測值,豈不是 個 loss function

 

性質

如果 兩個分布 完全匹配,Dkl=0;

KL 散度是非對稱的,即 D(p||q) 不一定等於 D(q||p);

KL 散度 取值范圍 大於等於 0;        【參考資料2有證明,有個 傑森不等式】

 

直觀解釋

KL 散度左邊是個 概率,右邊是個 log(p/q);

先看下右邊的 log,如果 p > q,log 為正,如果 p < q,log 為負,如果 p = q,log 為 0;

為了使 KL 是個期望值,加入了權重 p,也就是說,p 使得 高概率的匹配區域 比 低概率的匹配區域 更加重要

p(xi) 大,說明 xi 對應的 占比大,占比大的 是不是該 重視一下呢,而 乘以 p(xi) 剛好可以使得其 權重增大,代表 重視了

直觀而言,優先正確匹配近似分布中真正高可能性的事件是有實際價值的。
從數學上講,這能讓你自動忽略落在真實分布的支集(支集(support)是指分布使用的 X 軸的全長度)之外的分布區域。
另外,這還能避免計算 log(0) 的情況——如果你試圖計算落在真實分布的支集之外的任意區域的這個對數項,就可能出現這種情況。

 

Python 實現

import numpy as np
import scipy.stats      # 不能只 import scipy

# 隨機生成兩個離散型分布
x = [np.random.randint(1, 11) for i in range(10)]
px = x / np.sum(x)
print(px)
y = [np.random.randint(1, 11) for i in range(10)]
py = y / np.sum(y)
print(py)


##### scipy API進行計算
# scipy計算函數可以處理非歸一化情況,因此這里使用
# scipy.stats.entropy(x, y)或scipy.stats.entropy(px, py)均可
KL = scipy.stats.entropy(x, y)
print(KL)           # 0.14931583282835742


##### 手動實現
KL = 0.0
for i in range(10):
    KL += px[i] * np.log(px[i] / py[i])
print(KL)           # 0.14931583282835742

 

Pytorch 中 KL 計算出現負值

需加個 log

import torch

KL_criterion = torch.nn.KLDivLoss(size_average=False)
a = torch.tensor([0.2, 0.1, 0.3, 0.4])
b = torch.tensor([0.1, 0.2, 0.3, 0.4])

loss1 = KL_criterion(a.log(), b)
print(loss1)        # tensor(0.0693)    加 log 正確
loss2 = KL_criterion(a, b)
print(loss2)        # tensor(-1.5699)   不加 log 為 負數,錯誤

注意:分布的結果相加需要為1

 

 

 

 

參考資料:

https://www.jianshu.com/p/7b7c0777f74d  直觀解讀KL散度的數學概念    講得比較好,主要參考,里面還有其他內容,可以看看

https://zhuanlan.zhihu.com/p/39682125  KL散度理解

https://www.cnblogs.com/hxsyl/p/4910218.html  淺談KL散度

https://www.zhihu.com/question/384982085/answer/1856014994  pytorch KL散度為負數?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM