1. KL散度的定义
散度(Kullback-Leibler divergence) 是指两个概率分布 和 差别的度量。 散度是用来度量基于 的分布来编码服从 的分布的样本所需要的额外的平均比特数。典型情况下P表示数据的真实分布, 表示数据的理论分布、估计的模型分布、或者 的近似分布。
问题1:我们要怎么理解上面所描述的
散度?
例如:对于给定的数据集,数据对应的真实数据的标签分布为
,通过模型预测得到的标签分布为
。那么
散度就是用来计算真实数据的标签分布P和预测得到的标签分布
这两个分布的距离。
问题2: 那么为什么KL散度可以度量两个分布的距离
在解决这个问题之前,我们首先来看一下KL散度的具体计算公式定义。
对于离散的随机变量而言,概率分布 和概率分布 的定义可以按照以下的公式定义为
上述公式等价于
根据上述的公式的定义,进一步推导得到以用分布
来编码真实分布
的
散度为
那么上述公式可以理解 散度是在近似分布 上表示实际分布 所需要的额外的数据信息,当上述公式底数为 时信息的单位为 。那么 散度表示的含义为通过分布 编码真实分布 的时候所需要的额外 数,当所需要的额外信息越多,两个部分的距离越远,因此将 散度用来描述两个分布的距离。
2. KL散度的性质
- 性质1: 散度的值大于等于 ,当且仅当分布 的时候
上述性质可以理解为:当通过一个分布 去编码另外一个不同于 的分布 的时候必然需要引入额外的信息。因此我们称 散度具有非负性。
散度的非负性证明(吉布斯不等式的推导过程):
已知 当且仅当 的时候等号成立
根据上述公式可以证明
- 性质2: 通过分布Q编码分布P和通过分布P编码分布Q所需要引入的额外信息不相等,即
如何理解 的不对称性:
- 从计算公式上看
根据上述公式,可以看出两个公式公式不具有对称性,具体的数值证明可以通过选择两个相等的分布 和分布 去计算两个分布的距离。 - 从直观理解上看
表示用分布 去编码分布 所需要的额外信息量, 表示用分布 去编码分布 所需要的额外信息量,这两个过程不是逆过程,所需要的额外信息不相等。
3 KL散度在计算文本距离上的使用
在上述两个章节介绍完 散度的具体定义和相关性质后,本小节介绍一下 散度在实际生成中使用的一个小的例子。在下述例子中,通过 散度度量文本之间的相似度。我们给出了10个视频的关键字以及关键字对应的权重,如以下给出的表中的例子。
视频 | 关键词级权重 |
---|---|
视频1 | 萌娃们,0.33749074;棒棒糖,0.53786916;妈妈,0.16444901;看到,0.16505052;生气,0.21418166;萌娃,0.23613926;献上,0.29948534;棒棒糖,0.53786916 |
视频2 | 小宝宝,0.31487281;想吃,0.27792542;棒棒糖,0.94127103;妈妈,0.19185718;棒棒糖,0.94127103;最喜欢,0.28808985;棒棒糖,0.94127103 |
视频3 | 少儿,0.18663512;亲子,0.17464393;萝莉,0.20129519;哭泣,0.23701418;想吃,0.20844407;棒棒糖,0.47063551;妈妈,0.14389288;棒棒糖,0.47063551 |
视频4 | 美女,0.15522329;直播,0.22456859;彩色,0.26547745;棒棒糖,0.62751402;棒棒糖,0.62751402;童年,0.26974450;向往的生活 |
视频5 | 美女,0.14328304;直播,0.20729408;棒棒糖,0.57924371;神器,0.24123205;彩色,0.24505611;棒棒糖,0.57924371;看着,0.20298627;向往的生活 |
视频6 | 小萝莉,0.28599448;哥哥,0.21002553;姐姐,0.21028452;唱歌,0.21416910;跳舞,0.21271410;品尝,0.29246684;棒棒糖,0.57924371;美味,0.21848880;棒棒糖,0.57924371 |
视频7 | 知道,0.14769089;白雪,0.24709617;最喜欢,0.21606739;棒棒糖,0.47063551;棒棒糖,0.47063551;破坏,0.21554974 |
视频8 | 美女,0.15522329;直播,0.22456859;彩色,0.26547745;棒棒糖,0.62751402;西瓜,0.28019999;棒棒糖,0.62751402;童年,0.26974450;生活,0.20752392 |
视频9 | 爷爷,0.19108679;帮助,0.18984625;佩奇,0.21293892;棒棒糖,0.47063551;小朋友们,0.23485655;棒棒糖,0.47063551 |
视频10 | 佩奇,0.28391857;一家,0.25900229;棒棒糖,0.62751402;还有,0.22019583;棒棒糖,0.62751402;准备,0.22930146;分给,0.37381181;小朋友,0.25053489 |
根据上述章节中公式的定义两个视频之间 散度的计算公式如下
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import codecs
import math
class VideoMeta(object):
#解析词汇的权重
def _parse(self, keywords):
keywords_dict = dict()
sum_weight = 0.0
for keyword in keywords.strip().split(";"):
res = keyword.split(",")
k = res[0]
w = float(res[1])
if k in keywords_dict.keys():
keywords_dict[k] += w
else:
keywords_dict[k] = w
sum_weight += w
for k in keywords_dict.keys():
keywords_dict[k] = keywords_dict[k] / sum_weight
return keywords_dict
def __init__(self, keywords):
self._keywords = self._parse(keywords)
# 计算两个文本的KL散度,值得注意的是在计算过程中以当前文本为基准文本
def kullback_leibler_divergence(self, video_meta):
keywords2 = video_meta.get_keyword_weight()
kl_divergence = 0
infinity = 10000000
accretion = infinity
for k1 in self._keywords:
if self._keywords[k1] == 0:
continue
for k2 in keywords2:
if k1 == k2 and keywords2[k2] != 0:
accretion = self._keywords[k1] * math.log(keywords2[k2] / self._keywords[k1])
# 更新KL散度的距离
kl_divergence += accretion
accretion = infinity
return kl_divergence
def get_keyword_weight(self):
return self._keywords
if __name__=="__main__":
video_list = list()
for i, keywords in enumerate(codecs.open("a.txt",
mode="r", encoding="utf-8")):
video_meta = VideoMeta(keywords)
video_list.append(video_meta)
for video1 in video_list:
for video2 in video_list:
print(video1.kullback_leibler_divergence(video2))
在上述代码对应的a.txt文件中具体的格式如下。
萌娃们,0.33749074;棒棒糖,0.53786916;妈妈,0.16444901;看到,0.16505052;生气,0.21418166;萌娃,0.23613926;献上,0.29948534;棒棒糖,0.53786916
小宝宝,0.31487281;想吃,0.27792542;棒棒糖,0.94127103;妈妈,0.19185718;棒棒糖,0.94127103;最喜欢,0.28808985;棒棒糖,0.94127103
少儿,0.18663512;亲子,0.17464393;萝莉,0.20129519;哭泣,0.23701418;想吃,0.20844407;棒棒糖,0.47063551;妈妈,0.14389288;棒棒糖,0.47063551
美女,0.15522329;直播,0.22456859;彩色,0.26547745;棒棒糖,0.62751402;棒棒糖,0.62751402;童年,0.26974450;向往的生活,0.34335
美女,0.14328304;直播,0.20729408;棒棒糖,0.57924371;神器,0.24123205;彩色,0.24505611;棒棒糖,0.57924371;看着,0.20298627;向往的生活,0.342453
小萝莉,0.28599448;哥哥,0.21002553;姐姐,0.21028452;唱歌,0.21416910;跳舞,0.21271410;品尝,0.29246684;棒棒糖,0.57924371;美味,0.21848880;棒棒糖,0.57924371
知道,0.14769089;白雪,0.24709617;最喜欢,0.21606739;棒棒糖,0.47063551;棒棒糖,0.47063551;破坏,0.21554974
美女,0.15522329;直播,0.22456859;彩色,0.26547745;棒棒糖,0.62751402;西瓜,0.28019999;棒棒糖,0.62751402;童年,0.26974450;生活,0.20752392
爷爷,0.19108679;帮助,0.18984625;佩奇,0.21293892;棒棒糖,0.47063551;小朋友们,0.23485655;棒棒糖,0.47063551
佩奇,0.28391857;一家,0.25900229;棒棒糖,0.62751402;还有,0.22019583;棒棒糖,0.62751402;准备,0.22930146;分给,0.37381181;小朋友,0.25053489
在下表中根据代码的计算结果,我们挑选了前五个视频的计算结果列出了视频两两之间的 散度。
KL散度 | 视频1 | 视频2 | 视频3 | 视频4 | 视频5 |
---|---|---|---|---|---|
视频1 | 0.0 | 50000000.204377 | 50000000.02043807 | 60000000.062932596 | 60000000.023707926 |
视频2 | 29999999.638809167 | 0.0 | 19999999.694402423 | 39999999.73007338 | 39999999.66420929 |
视频3 | 49999999.97870493 | 40000000.1584195 | 0.0 | 60000000.047100134 | 60000000.0062307 |
视频4 | 49999999.92718792 | 50000000.18598768 | 49999999.94769892 | 0.0 | 9999999.92944586 |
视频5 | 59999999.97495331 | 60000000.21126917 | 59999999.99368237 | 20000000.064559713 | 0.0 |
根据表中给出的数据结果可以很明显的发现以下几个问题:
- 以视频1为基准计算得到的视频1和视频2的 散度与以视频2为基准计算得到的视频2和视频1的 散度不相同,如何评估根据 散度来评估两个文本之间的距离?
- 在具有相同词汇的情况下 散度明显地受到词汇权重的影响,如何理解权重对 散度的影响?
- 对于两个分布而言如果 的值和 的差距非常大,如何理解分布 和分布 的关系?(针对这个问题,参考【6】中知乎给出了相对应的讨论)
4 相关思考
- 由于 散度的不对称性,我们在计算相似度的时候需要采用以哪一个分布为基准计算得到的结果?如何解释这个结果表示的相似度关系?
- 散度的受到权重的影响使得 散度具有哪些特性?如何理解这种特性?
-
在一次京东推荐的相关分享上,京东在
阶段排序后的物品做
的时候使用了
散度和
得分结合贪心算法做多样性控制,这样做如何带来多样性的收益?
5 参考内容
【1】如何理解K-L散度(相对熵)
【2】维基百科 相对熵
【3】相对熵(relative entropy或 Kullback-Leibler divergence,KL距离)的java实现(一)
【4】相对熵(relative entropy或 Kullback-Leibler divergence,KL距离)的java实现(二)
【5】相对熵(relative entropy或 Kullback-Leibler divergence,KL距离)的java实现(三)
【6】KL散度不对称。如果分布P和Q,KL(P||Q)很大而KL(Q||P)很小表示什么现象?
【7】京东电商推荐系统实践