python实现:KL距离、jensen-shannon距离



Kullback–Leibler divergence:KL距离,是从信息熵的角度出发,也叫相对熵,衡量相同事件空间里的两个概率分布之间的差异情况。

计算公式:
     D_{\mathrm {KL} }(P\|Q)=\sum _{i}P(i)\,\log {\frac {P(i)}{Q(i)}}.    


=p、q的交叉熵 -  p的信息熵                          

性质:(1)kl(P||Q) >= 0,无最大值     (2)不对称 KL(P||Q) != KL(Q||P)      (3)不满足三角不等式


问题来了:概率分布中p、q为0的情况如何处理?“log of zero”报错在python中如何解决?
一个简单的办法,给概率分布都加一个极小的值,使概率值不为0,而对概率分布又没有什么影响。
matlab中有esp表示最小值,python中的numpy库有spacing函数表示最小值,

</pre><pre name="code" class="python">import numpy as np
from math import log
def KLD(p,q):
    p,q=zip(*filter(lambda (x,y): x!=0 or y!=0, zip(p,q))) #去掉二者都是0的概率值
    p=p+np.spacing(1)
    q=q+np.spacing(1)
    print p,q
    return sum([_p * log(_p/_q,2) for (_p,_q) in zip(p,q)])
p=np.ones(5)/5.0
q=[0,0,0.5,0.2,0.3]
print KLD(p,q)
结果:19.489850642923379
<span style="font-family: Arial, Helvetica, sans-serif; color: rgb(255, 0, 0); background-color: rgb(255, 255, 255);"><strong>
</strong></span>
<span style="font-family: Arial, Helvetica, sans-serif; color: rgb(255, 0, 0); background-color: rgb(255, 255, 255);"><strong>改进</strong></span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">:由于它的不对称性,不能完全表示两个分布之间的单向关系,因此有人提出了Jensen-Shannon距离,计算每个分布与平均分布的KL距离再去均值。</span>
M=(P+Q)/2
JSD=1/2*KL(P||M) +1/2*KL(Q||M)
当log的底数为2时,JSD的取值范围【0,1】
当log的底数为e时,JSD的取值范围【0,log(e,2)】

应用举例:计算两个字符串的字母分布距离。
如: ‘absfjowswls’ 和 ‘ahoafbaqqq’ 中每个字母出现的概率的分布有何差异?
import string
from math import log
import numpy as np
KLD=lambda p,q:sum([_p * log(_p,2)-_p * log(_q,2) for (_p,_q) in zip(p,q)])


def JSD_core(p,q):
    p,q=zip(*filter(lambda (x,y): x!=0 or y!=0, zip(p,q))) #去掉二者都是0的概率值
    M = [0.5*(_p+_q) for _p,_q in zip(p,q)]
    p=p+np.spacing(1)
    q=q+np.spacing(1)
    M=M+np.spacing(1)
#     print p,q,M
    return 0.5*KLD(p,M)+0.5*KLD(q,M)


reg=lambda x:[x.count(i) for i in string.lowercase]  #频数分布
rate=lambda y:[round(i*1.0/sum(reg(y)),4) for i in reg(y)]  #概率分布
s1='ahaebssa'
s2='awohwsess'
print JSD_core(rate(s1),rate(s2))
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值