KL散度与JS散度

  • KL散度(Kullback-Leibler divergence)
  • KL散度的计算公式
  • KL散度的基本性质
  • JS散度(Jensen-Shannon divergence)
  • JS散度的数学公式
  • 不同于KL的主要两方面


KL散度(Kullback-Leibler divergence)

又称KL距离,相对熵。KL散度是描述两个概率分布P和Q之间差异的一种方法。直观地说,可以用来衡量给定任意分布偏离真实分布的程度,如果两个分布完全匹配,那么KL(p||q)=0,否则它的取值应该是0~∞(inf)之间。KL散度越小,真实分布与近视分布之间的匹配程度就越好。

KL散度的计算公式

离散概率分布的KL散度计算公式:
js散度kl散度代码pytorch kl散度公式推导_深度学习
连续概率分布的KL散度计算公式:
js散度kl散度代码pytorch kl散度公式推导_算法_02

KL散度的基本性质

  • 非负性
    KL散度的结果是非负的,简单证明如下:
    js散度kl散度代码pytorch kl散度公式推导_深度学习_03
    由于对数函数是一个上凸函数,所以有:
    js散度kl散度代码pytorch kl散度公式推导_深度学习_04
  • 不对称性
    js散度kl散度代码pytorch kl散度公式推导_KL散度_05

JS散度(Jensen-Shannon divergence)

JS散度也称JS距离,是KL散度的一种变形。

JS散度的数学公式

js散度kl散度代码pytorch kl散度公式推导_算法_06

不同于KL的主要两方面

  • 值域范围
    JS散度的值域范围是[0,1],相同为0,相反则为1。相比较于KL,对相似度的判别更准确了。
  • 对称性
    js散度kl散度代码pytorch kl散度公式推导_KL散度_07,而对称能让散度度量更准确。下面用一段代码展示这其中的道理:
import numpy as np
import math
# 离散随机变量的KL散度和JS散度的计算方法
def KL(p,q):
    #p,q为两个list,里面存着对应的取值的概率,整个list相加为1
    if 0 in q:
        raise ValueError
    return sum(_p * math.log(_p/_q) for (_p,_q) in zip(p,q) if _p != 0)

def JS(p,q):
    M = [0.5 * (_p + _q) for (_p,_q) in zip(p,q)]
    return 0.5 * (KL(p,M) + KL(q,M))

def exp(a,b):
    a = np.array(a,dtype=np.float32)
    b = np.array(b,dtype=np.float32)
    a /= a.sum()
    b /= b.sum()
    print(a)
    print(b)
    print(KL(a,b))
    print(JS(a,b))
# exp 1
exp([1,2,3,4,5],[5,4,3,2,1])

[0.06666667 0.13333334 0.2        0.26666668 0.33333334]
[0.33333334 0.26666668 0.2        0.13333334 0.06666667]
0.5216030835963031
0.11968758856917597

# exp 2
#把公式中的第二个分布做修改,假设这个分布中有某个值的取值非常小,就有可能增加两个分布的散度值
exp([1,2,3,4,5],[1e-12,4,3,2,1])
exp([1,2,3,4,5],[5,4,3,2,1e-12])

[0.06666667 0.13333334 0.2        0.26666668 0.33333334]
[1.e-13 4.e-01 3.e-01 2.e-01 1.e-01]
2.065502018456509
0.0985487692550548
[0.06666667 0.13333334 0.2        0.26666668 0.33333334]
[3.5714287e-01 2.8571430e-01 2.1428572e-01 1.4285715e-01 7.1428574e-14]
9.662950847122168
0.19399530008415986

# exp 3
exp([1e-12,2,3,4,5],[5,4,3,2,1])
exp([1,2,3,4,1e-12],[5,4,3,2,1])

[7.1428574e-14 1.4285715e-01 2.1428572e-01 2.8571430e-01 3.5714287e-01]
[0.33333334 0.26666668 0.2        0.13333334 0.06666667]
0.7428131560123377
0.19399530008415986
[1.e-01 2.e-01 3.e-01 4.e-01 1.e-13]
[0.33333334 0.26666668 0.2        0.13333334 0.06666667]
0.38315075574389773
0.0985487692550548

将第一个实验与第二个实验做对比,可以看出KL散度的波动比较大,而JS的波动相对小。
如果将第二个实验和第三个实验做对比,可以发现KL散度在衡量两个分布的差异时具有很大的不对称性。如果后面的分布在某一个值上缺失,就回得到很大的散度值;但是如果前面的分布在某一个值上缺失,最终的KL散度并没有太大的波动。这个demo可以清楚地看出KL不对称性带来的一些小问题,而JS具有对称性,所以第二个实验和第三个实验的JS散度实际上是距离相等的分布组。