对于给定的随机变量,我们通常希望量化概率分布之间的差异。
这在机器学习中经常发生,我们可能对计算实际概率分布与观测概率分布之间的差异感兴趣。
这可以通过信息论中的技术来实现,例如库尔贝克-莱布勒散度(KL 散度)或相对熵,以及提供 KL 散度的归一化和对称版本的詹森-香农散度。这些评分方法可以作为计算其他广泛使用方法的捷径,例如在建模前用于特征选择的互信息,以及用作许多不同分类器模型损失函数的交叉熵。
在这篇文章中,您将了解如何计算概率分布之间的散度。
阅读本文后,你将了解:
- 统计距离是计算统计对象(如随机变量的不同概率分布)之间差异的一般概念。
- 库尔贝克-莱布勒散度计算一个分数,该分数衡量一个概率分布与另一个概率分布的散度。
- 詹森-香农散度扩展了 KL 散度,以计算一个对称的分数和距离度量,用于衡量一个概率分布与另一个概率分布的差异。
用我的新书《机器学习概率》来启动您的项目,其中包括所有示例的分步教程和 Python 源代码文件。
让我们开始吧。
- 更新于 2019 年 10 月:添加了对替代方程形式的描述(感谢 Ori)。

如何计算概率分布之间的距离
照片由 Paxson Woelber 拍摄,保留部分权利。
概述
本教程分为三个部分;它们是:
- 统计距离
- 库尔贝克-莱布勒散度
- 詹森-香农散度
统计距离
在许多情况下,我们可能希望比较两个概率分布。
具体来说,我们可能有一个单一的随机变量和该变量的两个不同概率分布,例如一个真实分布和一个该分布的近似值。
在这种情况下,量化分布之间的差异会很有用。通常,这被称为计算两个统计对象(例如概率分布)之间的统计距离问题。
一种方法是计算两个分布之间的距离度量。但这可能具有挑战性,因为度量可能难以解释。
相反,计算两个概率分布之间的散度更为常见。散度类似于度量,但不对称。这意味着散度是衡量一个分布与另一个分布差异的评分,其中计算分布 P 和 Q 的散度与计算 Q 和 P 的散度会得到不同的分数。
散度分数是信息论以及更广泛的机器学习中许多不同计算的重要基础。例如,它们为计算诸如互信息(信息增益)和用作分类模型损失函数的交叉熵等分数提供了捷径。
散度分数也直接用作理解复杂建模问题的工具,例如在优化生成对抗网络 (GAN) 模型时近似目标概率分布。
信息论中两个常用的散度分数是库尔贝克-莱布勒散度和詹森-香农散度。
我们将在下一节中更详细地研究这两个分数。
想学习机器学习概率吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
库尔贝克-莱布勒散度
库尔贝克-莱布勒散度分数,或称 KL 散度分数,量化了一个概率分布与另一个概率分布的差异程度。
两个分布 Q 和 P 之间的 KL 散度通常用以下表示法表示
- KL(P || Q)
其中“||”运算符表示“散度”或 P 相对于 Q 的散度。
KL 散度可以计算为 P 中每个事件的概率乘以 Q 中事件概率与 P 中事件概率之比的对数的负总和。
- KL(P || Q) = – sum x in X P(x) * log(Q(x) / P(x))
求和内的值是给定事件的散度。
这与 P 中每个事件的概率乘以 P 中事件概率与 Q 中事件概率之比的对数的正总和相同(例如,分数中的项被翻转)。这是实践中更常见的实现方式。
- KL(P || Q) = sum x in X P(x) * log(P(x) / Q(x))
KL 散度分数的直观理解是,当 P 中某个事件的概率很大,而 Q 中同一事件的概率很小时,散度就很大。当 P 的概率小而 Q 的概率大时,散度也很大,但不如第一种情况大。
它可以用来衡量离散和连续概率分布之间的散度,在后一种情况下,计算的是事件的积分而不是离散事件概率的总和。
衡量两个概率分布 p 和 q 差异的一种方法是库尔贝克-莱布勒散度(KL 散度)或相对熵。
— 第 57 页,《机器学习:概率视角》,2012年。
对数可以以 2 为底,单位为“比特”,或者以自然对数 e 为底,单位为“奈特”。当分数为 0 时,表示两个分布相同,否则分数为正。
重要的是,KL 散度分数是非对称的,例如
- KL(P || Q) != KL(Q || P)
它以该方法的两位作者 Solomon Kullback 和 Richard Leibler 的名字命名,有时也被称为“相对熵”。
这被称为分布 p(x) 和 q(x) 之间的相对熵或库尔贝克-莱布勒散度,或 KL 散度。
— 第 55 页,《模式识别与机器学习》,2006年。
如果我们试图近似一个未知的概率分布,那么来自数据的目标概率分布是 P,而 Q 是我们对该分布的近似。
在这种情况下,KL 散度概括了表示来自随机变量的事件所需的额外比特数(即使用以 2 为底的对数计算)。我们的近似越好,所需的额外信息就越少。
...KL 散度是编码数据所需的平均额外比特数,这是因为我们使用了分布 q 而不是真实分布 p 来编码数据。
— 第 58 页,《机器学习:概率视角》,2012年。
我们可以通过一个具体的例子来理解 KL 散度。
考虑一个具有三个事件(不同颜色)的随机变量。我们可能对这个变量有两个不同的概率分布;例如
1 2 3 4 5 |
... # 定义分布 events = ['red', 'green', 'blue'] p = [0.10, 0.40, 0.50] q = [0.80, 0.15, 0.05] |
我们可以绘制这些概率的条形图,将它们作为概率直方图直接进行比较。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 分布图 from matplotlib import pyplot # 定义分布 events = ['red', 'green', 'blue'] p = [0.10, 0.40, 0.50] q = [0.80, 0.15, 0.05] print('P=%.3f Q=%.3f' % (sum(p), sum(q))) # 绘制第一个分布 pyplot.subplot(2,1,1) pyplot.bar(events, p) # 绘制第二个分布 pyplot.subplot(2,1,2) pyplot.bar(events, q) # 显示绘图 pyplot.show() |
运行该示例会为每个概率分布创建一个直方图,从而可以直接比较每个事件的概率。
我们可以看到这两个分布确实是不同的。

同一随机变量的两个不同概率分布的直方图
接下来,我们可以开发一个函数来计算两个分布之间的 KL 散度。
我们将使用以 2 为底的对数,以确保结果的单位是比特。
1 2 3 |
# 计算 kl 散度 def kl_divergence(p, q): return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p))) |
然后,我们可以使用这个函数来计算 P 相对于 Q 的 KL 散度,以及反过来 Q 相对于 P 的 KL 散度。
1 2 3 4 5 6 |
# 计算 (P || Q) kl_pq = kl_divergence(p, q) print('KL(P || Q): %.3f bits' % kl_pq) # 计算 (Q || P) kl_qp = kl_divergence(q, p) print('KL(Q || P): %.3f bits' % kl_qp) |
将所有这些结合起来,完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 计算两个质量函数之间 kl 散度的示例 from math import log2 # 计算 kl 散度 def kl_divergence(p, q): return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p))) # 定义分布 p = [0.10, 0.40, 0.50] q = [0.80, 0.15, 0.05] # 计算 (P || Q) kl_pq = kl_divergence(p, q) print('KL(P || Q): %.3f bits' % kl_pq) # 计算 (Q || P) kl_qp = kl_divergence(q, p) print('KL(Q || P): %.3f bits' % kl_qp) |
运行该示例,首先计算出 P 相对于 Q 的散度略低于 2 比特,然后计算出 Q 相对于 P 的散度略高于 2 比特。
如果我们考虑到当 Q 的概率小时 P 的概率大,那么 P 的散度就比 Q 相对于 P 的散度小,因为当 P 的概率大时 Q 有更多的小概率,这是很直观的。在第二种情况下,散度更大。
1 2 |
KL(P || Q): 1.927 比特 KL(Q || P): 2.022 比特 |
如果我们将 log2() 更改为自然对数函数 log(),结果将以奈特为单位,如下所示:
1 2 |
# KL(P || Q): 1.336 奈特 # KL(Q || P): 1.401 奈特 |
SciPy 库提供了 kl_div() 函数 用于计算 KL 散度,尽管其定义与此处不同。它还提供了 rel_entr() 函数 用于计算相对熵,这与此处的 KL 散度定义相匹配。这很奇怪,因为“相对熵”通常用作“KL 散度”的同义词。
尽管如此,我们可以使用 rel_entr() SciPy 函数计算 KL 散度,并确认我们的手动计算是正确的。
rel_entr() 函数接受来自每个概率分布的所有事件的概率列表作为参数,并返回每个事件的散度列表。将这些散度相加即可得到 KL 散度。该计算使用自然对数而不是以 2 为底的对数,因此单位是奈特而不是比特。
下面列出了使用 SciPy 计算 KL(P || Q) 和 KL(Q || P) 的完整示例,其中使用了与上面相同的概率分布
1 2 3 4 5 6 7 8 9 10 11 |
# 使用 scipy 计算 kl 散度(相对熵)的示例 from scipy.special import rel_entr # 定义分布 p = [0.10, 0.40, 0.50] q = [0.80, 0.15, 0.05] # 计算 (P || Q) kl_pq = rel_entr(p, q) print('KL(P || Q): %.3f nats' % sum(kl_pq)) # 计算 (Q || P) kl_qp = rel_entr(q, p) print('KL(Q || P): %.3f nats' % sum(kl_qp)) |
运行该示例,我们可以看到计算出的散度与我们手动计算的 KL(P || Q) 约 1.3 奈特和 KL(Q || P) 约 1.4 奈特相匹配。
1 2 |
KL(P || Q): 1.336 奈特 KL(Q || P): 1.401 奈特 |
詹森-香农散度
詹森-香农散度(简称 JS 散度)是量化两个概率分布之间差异(或相似性)的另一种方法。
它使用 KL 散度来计算一个对称的归一化分数。这意味着 P 相对于 Q 的散度与 Q 相对于 P 的散度相同,或者用公式表示为:
- JS(P || Q) == JS(Q || P)
JS 散度的计算方法如下:
- JS(P || Q) = 1/2 * KL(P || M) + 1/2 * KL(Q || M)
其中 M 的计算方法为:
- M = 1/2 * (P + Q)
其中 KL() 的计算方式为上一节中描述的 KL 散度。
它作为一种度量更有用,因为它提供了 KL 散度的平滑和归一化版本,当使用以 2 为底的对数时,得分在 0(相同)和 1(最大不同)之间。
分数的平方根得到一个被称为詹森-香农距离(简称 JS 距离)的量。
我们可以通过一个具体的例子来理解 JS 散度。
首先,我们可以定义一个计算 JS 散度的函数,该函数使用上一节中准备的 kl_divergence() 函数。
1 2 3 4 5 6 7 8 |
# 计算 kl 散度 def kl_divergence(p, q): return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p))) # 计算 js 散度 def js_divergence(p, q): m = 0.5 * (p + q) return 0.5 * kl_divergence(p, m) + 0.5 * kl_divergence(q, m) |
然后我们可以使用上一节中使用的相同概率分布来测试这个函数。
首先,我们将计算分布的 JS 散度得分,然后计算该得分的平方根,以得到分布之间的 JS 距离。例如:
1 2 3 4 5 |
... # 计算 JS(P || Q) js_pq = js_divergence(p, q) print('JS(P || Q) divergence: %.3f bits' % js_pq) print('JS(P || Q) distance: %.3f' % sqrt(js_pq)) |
然后可以对反向情况重复此操作,以表明散度是对称的,这与 KL 散度不同。
1 2 3 4 5 |
... # 计算 JS(Q || P) js_qp = js_divergence(q, p) print('JS(Q || P) divergence: %.3f bits' % js_qp) print('JS(Q || P) distance: %.3f' % sqrt(js_qp)) |
将这些内容结合起来,下面列出了计算 JS 散度和 JS 距离的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# 计算两个质量函数之间 js 散度的示例 from math import log2 from math import sqrt from numpy import asarray # 计算 kl 散度 def kl_divergence(p, q): return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p))) # 计算 js 散度 def js_divergence(p, q): m = 0.5 * (p + q) return 0.5 * kl_divergence(p, m) + 0.5 * kl_divergence(q, m) # 定义分布 p = asarray([0.10, 0.40, 0.50]) q = asarray([0.80, 0.15, 0.05]) # 计算 JS(P || Q) js_pq = js_divergence(p, q) print('JS(P || Q) divergence: %.3f bits' % js_pq) print('JS(P || Q) distance: %.3f' % sqrt(js_pq)) # 计算 JS(Q || P) js_qp = js_divergence(q, p) print('JS(Q || P) divergence: %.3f bits' % js_qp) print('JS(Q || P) distance: %.3f' % sqrt(js_qp)) |
运行该示例表明,分布之间的 JS 散度约为 0.4 比特,距离约为 0.6。
我们可以看到计算是对称的,JS(P || Q) 和 JS(Q || P) 得到相同的分数和距离度量。
1 2 3 4 |
JS(P || Q) 散度: 0.420 比特 JS(P || Q) 距离: 0.648 JS(Q || P) 散度: 0.420 比特 JS(Q || P) 距离: 0.648 |
SciPy 库通过 jensenshannon() 函数 提供了 JS 距离的实现。
它将来自每个概率分布的所有事件的概率数组作为参数,并返回 JS 距离分数,而不是散度分数。我们可以使用这个函数来验证我们手动计算的 JS 距离。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 计算詹森-香农距离度量 from scipy.spatial.distance import jensenshannon from numpy import asarray # 定义分布 p = asarray([0.10, 0.40, 0.50]) q = asarray([0.80, 0.15, 0.05]) # 计算 JS(P || Q) js_pq = jensenshannon(p, q, base=2) print('JS(P || Q) Distance: %.3f' % js_pq) # 计算 JS(Q || P) js_qp = jensenshannon(q, p, base=2) print('JS(Q || P) Distance: %.3f' % js_qp) |
运行该示例,我们可以确认距离分数与我们手动计算的 0.648 相匹配,并且距离计算如预期一样是对称的。
1 2 |
JS(P || Q) 距离: 0.648 JS(Q || P) 距离: 0.648 |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
书籍
文章
API
文章
总结
在这篇文章中,您了解了如何计算概率分布之间的散度。
具体来说,你学到了:
- 统计距离是计算统计对象(如随机变量的不同概率分布)之间差异的一般概念。
- 库尔贝克-莱布勒散度计算一个分数,该分数衡量一个概率分布与另一个概率分布的散度。
- 詹森-香农散度扩展了 KL 散度,以计算一个对称的分数和距离度量,用于衡量一个概率分布与另一个概率分布的差异。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason,您在公式中提到是负和,但在代码中是正和。
对!
我们也可以使用另一种形式:KL(P || Q) = sum x in X P(x) * log(P(x) / Q(x))
这是我们在实践中实现的版本。
我已经更新了文章,谢谢!
嗨,Jason,
这个问题可能在你的博客里已经回答过了,但我还是没搞明白。假设一开始给了你两个样本的直方图。有了这些信息,我应该如何计算这两个数据集的 KL 散度?
您需要数据,直方图(图表)是不够的。
你好 Jason,
您是否写过一篇关于“分类数据以及数值/连续数据的相关系数计算”的文章?
有时候这对我来说似乎有误导性,当数据同时包含分类特征和连续特征时,我对于计算相关系数的正确方法感到困惑。
如果有的话,请提供博客的链接。
谢谢您,
Saurabh
是的,我会安排一篇关于跨类型相关性主题的文章。
感谢您的建议。
嗨,Jason,
如果给定的分布是连续概率分布,您能提供 KL 和 JS 散度的代码吗?
感谢您的建议。
嗨,Jason,
使用 zip 方法而不是 range(len()) 会更符合 Python 风格。
[pi * np.log2(qi/pi) for pi, qi in zip(p,q)]
例如,请看这里
https://docs.quantifiedcode.com/python-anti-patterns/readability/not_using_zip_to_iterate_over_a_pair_of_lists.html
是的,谢谢!
嗨,Jason,您是否知道这两个指标是否存在一个阈值,该阈值对应于一个分布对另一个分布的可接受近似?我觉得所有概率指标最终都非常主观。谢谢!
当分布包含确定概率(0 和 1)时,KL 散度将与交叉熵匹配,因为分布的熵将为零。
这有帮助吗?
我不认为它们是主观的,它们测量的是真实数据。
嗨,Jason,感谢您的文章!我想问一下以下做法是否有意义:
我使用高斯混合模型方法对几张图片进行了无监督聚类,我想找出两张图片之间的相似度,其中每张图片都来自不同的簇。
通过将两张图片视为不同的分布,并使用这两张图片计算詹森-香农距离来衡量它们之间的相似性,这样做有意义吗?(https://docs.scipy.org.cn/doc/scipy/reference/generated/scipy.spatial.distance.jensenshannon.html)
谢谢你。
或许可以试试看它是否适合您的数据。
我相信图像相似性是一个庞大的研究领域,我建议您查阅文献,看看哪些方法通常效果好。
我正在处理一个和我问的问题类似的问题。我有一个数据样本,它的直方图遵循某种随机的、不常见的分布。由于计算 KL 散度需要概率,我尝试使用核非参数估计(我在您关于概率密度的博客中读到过)来估计一个密度函数。然后使用这个密度函数,我得到了 KL 散度。
所以我的担忧是我是否做错了什么。
您的方法听起来是合理的。
你好,
在多变量数据集中,是否可以为因变量的概率分布找到KL散度?如果可以,如何操作?请举例说明。这里的因变量依赖于多个自变量。
谢谢你
抱歉,我不太明白,您能详细说明一下您的意思吗?
你好,
我的意思是,如果数据集是多变量的,我们如何计算 KL 散度?假设每个实例的形式都是 (x,y),其中 x={x1,x,2,...xn},即 x 属性(自变量)的数量,而 y 依赖于这些 x 值。对于这种类型的多变量数据集,如何计算 KL 散度?
据我所知,该方法是通用的,您可以计算单变量和多变量概率分布之间的散度。
也许这会有帮助。
https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence#Multivariate_normal_distributions
好的,谢谢
你好,
您的帖子很棒!但是您写的 kl_divergence(p, q) 函数,这只适用于离散变量,对吗?对于连续变量该怎么办?
谢谢。
我为离散变量描述了它,但你也可以用于连续变量。
好的,还有一件事,我知道 p 或 q 中的值需要在 0-1 之间。但是 p 的所有值之和必须是 1 吗?
另外,使用 rel_entr() 函数,我在尝试的一个例子中得到了负值,这可能吗?如果是,那是什么意思?
所有事件的概率之和必须为一。
P 和 Q 是事件的分布。P 的所有事件总和必须为 1。Q 的所有事件总和必须为 1。
我不理解负的kl散度,抱歉。
非常感谢您的回复。在查阅了许多资料后,我在一个地方发现KL散度的值不能为负。我的数据中可能存在一些KL散度不接受的事实,这就是为什么会产生负值。谢谢。
很高兴听到这个消息。
嗨,Jason,
当只有来自 P 的蒙特卡洛样本,而 Q 是已知的正态分布,比如 N(0,1) 时,您有估算 KL(P(x) || Q(x)) 的想法吗?
谢谢!
只要您在每个分布中对相同事件有概率,我认为您就可以继续了。
也许您需要对一些样本进行插值。
问题是对于 P 分布,我只有样本,所以我不知道如何计算概率。除非我将分布离散化,使用每个区间内样本的归一化频率作为概率值,但这会因离散化而引入额外的估计误差。
一种方法可能是使用经验分布函数。
https://machinelearning.org.cn/empirical-distribution-function-in-python/
嗨 Jason
您有关于如何近似两个 GMM 之间 KL 散度的教程吗?
抱歉,我没有。
嗨,Jason,好文章!
在我的项目中,我有 10 个离散概率分布。我计算了每对分布的 KL 散度,并创建了一个 KL 散度得分矩阵 [10X10]。然后,我利用这个矩阵应用层次聚类来聚类相似的分布。
我的问题是:KL 散度分数有什么方法可以用来理解一对分布的相似程度吗?我知道 0 表示相同,KL 值可以达到无穷大。例如,KL 值为 0.5 代表什么?这能等同于分布之间某种 90% 或 80% 的相似度吗?
问题基本上是确定两个概率分布之间的一个 KL 相似度得分阈值,以了解它们是否可以被聚类。这个阈值可能取决于我们试图解决的业务问题,但我们如何证明任何 KL 散度得分阈值的合理性?
如果使用以 2 为底的对数,你可以用比特来解释结果。
例如,一个事件分布相对于另一个事件分布包含了多少额外的信息或意外性。
非常感谢 Jason!
不客气。
我们如何用比特来解释结果,也就是说,我们如何为这种方法找到一个理想的阈值?
嗨 Nandana… 以下资源可能对您有帮助
https://towardsdatascience.com/light-on-math-machine-learning-intuitive-guide-to-understanding-kl-divergence-2b382ca2b2a8
这是一篇很棒的文章,Jason!谢谢!
一个问题——如果 JS 可以用来计算两个分布之间的“距离”,您能解释一下什么时候我应该使用这个距离度量,而不是使用像余弦距离这样的度量吗?
我已经使用余弦距离有一段时间了,我想了解在什么特定情况下使用 JS 比余弦更合适。
再次感谢!
NIkhil
余弦距离是两个向量之间的距离。上述方法是用于两个分布之间的距离。
我有四个(非线性的、基于树的)模型在生产中使用,并将它们的平均值作为提供的预测。我们能立即获得真实数据。
在训练过程中,优化的候选模型表现非常相似,所以我决定部署所有模型,取其平均值作为预测。意图是稍后找出哪个模型真正最好。
那个稍后的时刻到来了。
在这四个模型中,有两个似乎与真实数据分布拟合得很好,至少通过检查预测值的 KDE 图与真实数据分布的对比可以看出来。
我最初考虑进行成对的双样本 KS 检验(每个模型与真实数据对比),看模型的预测值是否与真实数据来自同一分布。
但我后来打消了这个念头。主要是因为我有超过 50,000 个预测,我想这么大的样本量无论如何都会导致很小的 p 值。
然后我将注意力转向了 KL 散度。这是我以前从未使用过的东西。
比较每个模型预测与真实数据之间的 KL 散度,是评估模型拟合度的 好方法吗?
如果是这样,我该如何操作?scipy.stats.kl_div 输出一个数组,其中包含(我假设)预测值与真实值之间的散度。
我是否只需将数组求和,然后称其为模型与真实数据之间的散度?
希望我听起来不疯狂,也不太像不知道自己在做什么或说什么。因为我确实有点不知道,但又不是完全不知道。
谢谢你
是的,也许可以试试看。
您需要对每个预测的散度求平均值。
这会给你一些思路
https://machinelearning.org.cn/cross-entropy-for-machine-learning/
嗨 Jason!感谢回复。我还有另一个版本的问题。
使用 KL 散度来衡量回归问题中预测值与真实值之间的差异是否有意义?
我已经调整了四个模型,并在生产环境中提供平均值作为预测。
我绘制了每个模型预测值与真实值的 ecdf 和 kde 图,我想用一个数字来捕捉分布的接近程度,以便长期跟踪。
我使用 MAE 作为评估性能的指标,但我也想用一个单一的数字来捕捉预测和真实数据分布形状的相似或不同程度。
嗯,好问题。
谨慎地说,我会说是的,但请仔细查阅文献,看是否有更合适的散度度量。
嗨,Jason,感谢这篇精彩的文章!
一个问题——您能否更详细地解释一下 LK 散度在两种情况下(p 到 q 和 q 到 p)为何不同?换句话说,我无法理解下面的直观解释(引用部分);每个事件的概率之差无论方向如何(p 到 q 或 q 到 p)都是相同的。
“如果我们认为当 Q 的概率较小时 P 的概率较大,那么 P 的散度比 Q 相对于 P 的散度要小,因为当 P 的概率较大时 Q 有更多的小概率,这是很直观的。”
可以把它看作是“相对熵”,即第一个分布相对于第二个分布。如果顺序改变,相对熵也必须改变。
谢谢 Jason!现在清楚多了。
不客气。
嗨,Jason,
如果 p 和 q 是多维的,比如形状是 (32,50),那我们该如何计算 kl 散度呢?
抱歉,不太明白你的意思。
p 和 q 是事件的概率分布。
嗨,Jason,文章写得很好。我只是对 KL 散度有一个评论。当你在示例中计算它时,你得到了
KL(P || Q): 1.927 比特
根据定义,结果应该是负数,您是使用绝对值来推断比特数的吗?
好问题,请注意我们使用的是在实践中更常见的替代正向计算方法,这在标题为“库尔贝克-莱布勒散度”的部分有讨论。
嗨,Jason,
感谢您的文章!
您写道 KL 不是对称的,“例如……”。从数学上讲,非对称恰恰意味着 KL(P,Q) = KL(Q, P) 并不总是成立,所以恕我直言,最好将“例如”替换为“也就是说,等式……不总是成立”或“也就是说,通常 KL(P,Q) != KL(Q,P)”。
感谢您的建议。
你好 Jason,
如果我想用 KL 来评估我的 GAN,并计算真实分布和生成分布之间的 KL 散度,我该怎么做?
我使用了您的脚本,将 P 设为真实分布,Q 设为生成分布,但返回了 nan 值。
所以,您能帮我吗?
我不确定它是否是评估 GAN 的合适指标。
相反,我推荐这里列出的指标
https://machinelearning.org.cn/how-to-evaluate-generative-adversarial-networks/
是的,我读过了,谢谢。
我读过关于 GAN 的论文,他们使用 KL 作为评估指标,例如 MAD-GAN。
https://openaccess.thecvf.com/content_cvpr_2018/papers/Ghosh_Multi-Agent_Diverse_Generative_CVPR_2018_paper.pdf
有意思。感谢分享。
嘿,您能谈谈如何将这个扩展到马尔可夫过程吗?
感谢您的建议。
嗨,Jason,
感谢这篇精彩的文章。如果 p(k)=0(除以零)或 q(k)(log 为 0),是否有首选的计算 KL 的方法?
通常在实际编码时,我们会给参数添加很小的值以避免零。
你好,我正在思考这个陈述。
* KL(P || Q) = sum x in X P(x) * log(P(x) / Q(x))
KL 散度分数的直观理解是,当 P 中某个事件的概率很大,而 Q 中同一事件的概率很小时,散度就很大。当 P 的概率小而 Q 的概率大时,散度也很大,但不如第一种情况大。
似乎,如果 P(p) 很小,而同一事件的 P(q) 很大,那么对数中的分数将小于 1。这会得到一个负结果,因此,它不应该实际上抵消掉一些散度吗?前提是我们没有对求和的项取绝对值。
因此,是的,如果 P 很大而 Q 很小,则散度很大,但在相反的情况下,实际上存在“负”散度。
我有什么遗漏的地方吗?
感谢这篇文章,非常有用,只是想澄清一下关于这一点的困惑。
也许你可以用一些具体的例子/真实数字来检验你的直觉。
你好,我正在思考这个陈述。
* KL(P || Q) = sum x in X P(x) * log(P(x) / Q(x))
KL 散度分数的直观理解是,当 P 中某个事件的概率很大,而 Q 中同一事件的概率很小时,散度就很大。当 P 的概率小而 Q 的概率大时,散度也很大,但不如第一种情况大。
在第二种情况下,散度难道不是负的吗,这意味着它会与 P > Q 的其他情况有所抵消?为什么我们不取所有求和项的绝对值呢?
用真实数据算算看。
我不确定为什么我的kl值是NAN。y_train是y的0.7,y_val是y的0.3。
p = y_train
q = y_val
kl_pq = rel_entr(p, q)
print('KL(P || Q): %.3f nats' % sum(kl_pq))
kl_qp = rel_entr(q, p)
print('KL(Q || P): %.3f nats' % sum(kl_qp))
结果
KL(P || Q): nan nats
KL(Q || P): nan nats
y 本身没有任何 nan。
p 和 q 都必须全部非负,否则你的 rel_entr 会给你 nan。然后 sum 也会是 nan。
嗨,Jason,
我不确定为什么我的一个 KL 值为负。我为您提供了 p 和 q 数组(我已将它们转换为 numpy 数组)。
p: [6.33527306 0.17195741 0.01810078 0.01810078]
q: [7.36958404 0.09665028 0.02416257 0.02416257]
KL(p, q): -1.2543610466991473
KL(q, p): 1.547671142537377
JS(P || Q) 距离: 0.042
JS(Q || P) 距离: 0.042
KL 公式涉及对数,而对数可以返回负值。
如何找到生成对抗网络中的收敛性?
嗨,Dipnakar... 以下资源可能有助于解决您关于 GANs 的许多疑问。
https://machinelearning.org.cn/resources-for-getting-started-with-generative-adversarial-networks/
你好,
如果我们有相同类型的数据(PDFs 值),并且需要使用随机森林和 KL 散度进行分类。有什么方法可以检查哪一个表现更好吗?
或者我只需要尝试两种方法,然后检查哪一个表现更好?
嗨 Wesam…以下内容可能有助于比较机器学习模型的性能。
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
嗨,我想了解如何解释詹森-香农距离,例如,JSD = 0.5 的值是否意味着两个分布重叠了 50%?判断数据漂移是否显著的 JS 距离阈值是多少?谢谢。