Machine-Learning-Mastery-概率教程-二-

126 阅读1小时+

Machine Learning Mastery 概率教程(二)

原文:Machine Learning Mastery

协议:CC BY-NC-SA 4.0

机器学习的离散概率分布

原文:machinelearningmastery.com/discrete-pr…

最后更新于 2020 年 10 月 6 日

离散随机变量的概率可以用离散概率分布来概括。

离散概率分布用于机器学习,最显著的是用于二进制和多类分类问题的建模,但也用于评估二进制分类模型的表现,例如置信区间的计算,以及用于自然语言处理的文本中单词分布的建模。

在选择用于分类任务的深度学习神经网络的输出层中的激活函数和选择适当的损失函数时,也需要离散概率分布的知识。

离散概率分布在应用机器学习中起着重要的作用,从业者必须了解一些分布。

在本教程中,您将发现机器学习中使用的离散概率分布。

完成本教程后,您将知道:

  • 离散随机变量的结果概率可以用离散概率分布来概括。
  • 单个二元结果具有伯努利分布,一系列二元结果具有二项式分布。
  • 单个分类结果具有多项分布,一系列分类结果具有多项分布。

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2020 年 10 月更新:修正了二项式分布描述中的错别字。

Discrete Probability Distributions for Machine Learning

机器学习的离散概率分布 约翰·福勒摄,版权所有。

教程概述

本教程分为五个部分;它们是:

  1. 离散概率分布
  2. 二项分布
  3. 二项分布
  4. 多欧拉分布
  5. 多项分布

离散概率分布

随机变量是随机过程产生的量。

离散随机变量是一个随机变量,它可以有一组有限的特定结果之一。机器学习中最常用的两种离散随机变量是二元和分类变量。

  • 二进制随机变量 : x 在{0,1}中
  • 分类随机变量 : x 在{1,2,…,K}中。

二进制随机变量是一个离散的随机变量,其中有限的结果集在{0,1}中。分类随机变量是一个离散的随机变量,其中有限的结果集在{1,2,…,K}中,其中 K 是唯一结果的总数。

离散随机变量的每个结果或事件都有一个概率。

离散随机变量的事件和它们的概率之间的关系被称为离散概率分布,由概率质量函数(简称 PMF)来概括。

对于可排序的结果,事件等于或小于给定值的概率由累积分布函数(简称 CDF)定义。CDF 的倒数称为百分点函数,它将给出小于或等于概率的离散结果。

  • PMF :概率质量函数,返回给定结果的概率。
  • CDF :累积分布函数,返回小于等于给定结果的概率值。
  • PPF :百分点函数,返回小于等于给定概率的离散值。

有许多常见的离散概率分布。

最常见的是分别针对二元和分类离散随机变量的伯努利分布和多项式分布,以及将每个分布推广到多个独立试验的二项式分布和多项式分布。

  • 二元随机变量:伯努利分布
  • 二元随机变量的序列:二项式分布
  • 分类随机变量:多元线性分布
  • 分类随机变量序列:多项式分布

在接下来的几节中,我们将依次仔细研究这些分布。

您可能还想探索其他离散概率分布,包括泊松分布和离散均匀分布。

二项分布

伯努利分布是一个离散的概率分布,它涵盖了一个事件具有二进制结果为 0 或 1 的情况。

  • {0,1}中的 x

伯努利试验”是一个实验或案例,其结果遵循伯努利分布。该分布和试验以瑞士数学家雅各布·伯努利的名字命名。

伯努利试验的一些常见例子包括:

  • 硬币的单次翻转,可能有正面(0)或反面(1)的结果。
  • 男孩(0)或女孩(1)的单胎。

机器学习中伯努利试验的一个常见示例可能是将单个示例二进制分类为第一类(0)或第二类(1)。

这个分布可以用一个单一的变量 p 来概括,这个变量定义了结果 1 的概率。给定此参数,每个事件的概率可以计算如下:

  • P(x=1) = p
  • p(x = 0)= 1–p

在抛公平硬币的情况下, p 的值将是 0.5,给出每个结果的 50%概率。

二项分布

重复多次独立的伯努利试验被称为伯努利过程

伯努利过程的结果将遵循二项分布。因此,伯努利分布是一个二项分布,只有一次试验。

伯努利过程的一些常见例子包括:

  • 一系列独立的硬币翻转。
  • 一系列独立的出生。

机器学习算法在二进制分类问题上的表现可以被分析为伯努利过程,其中模型对来自测试集的示例的预测是伯努利试验(正确或不正确)。

二项式分布总结了在给定数量的伯努利试验 k 中的成功次数,每个试验都有给定的成功概率 p

我们可以用伯努利过程来证明这一点,其中成功的概率为 30%或 P(x=1) = 0.3,试验总数为 100 (k=100)。

我们可以用随机生成的案例模拟伯努利过程,并计算给定试验次数的成功次数。这可以通过二项式()NumPy 功能来实现。该函数将试验总数和成功概率作为参数,并返回一次模拟试验中成功结果的数量。

# example of simulating a binomial process and counting success
from numpy.random import binomial
# define the parameters of the distribution
p = 0.3
k = 100
# run a single simulation
success = binomial(k, p)
print('Total Success: %d' % success)

我们期望在给定所选参数(k * p 或 100 * 0.3)的情况下,100 个案例中有 30 个会成功。

每次运行代码时都会产生 100 次试验的不同随机序列,因此您的具体结果会有所不同。试着运行这个例子几次。

在这种情况下,我们可以看到我们获得的成功试验略少于预期的 30 个。

Total Success: 28

我们可以使用 binom.stats() SciPy 函数计算这个分布的矩,特别是期望值或平均值和方差。

# calculate moments of a binomial distribution
from scipy.stats import binom
# define the parameters of the distribution
p = 0.3
k = 100
# calculate moments
mean, var, _, _ = binom.stats(k, p, moments='mvsk')
print('Mean=%.3f, Variance=%.3f' % (mean, var))

运行该示例报告了分布的期望值,正如我们所期望的,是 30,以及方差 21,如果我们计算平方根,得到的标准偏差约为 4.5。

Mean=30.000, Variance=21.000

我们可以使用概率质量函数来计算一系列试验的不同成功结果数的可能性,例如 10、20、30 到 100。

我们预计 30 个成功结果的概率最高。

# example of using the pmf for the binomial distribution
from scipy.stats import binom
# define the parameters of the distribution
p = 0.3
k = 100
# define the distribution
dist = binom(k, p)
# calculate the probability of n successes
for n in range(10, 110, 10):
	print('P of %d success: %.3f%%' % (n, dist.pmf(n)*100))

运行该示例定义了二项式分布,并计算了[10,100]中每组 10 个成功结果的概率。

概率乘以 100 给出百分比,我们可以看到 30 个成功结果的概率最高,约为 8.6%。

P of 10 success: 0.000%
P of 20 success: 0.758%
P of 30 success: 8.678%
P of 40 success: 0.849%
P of 50 success: 0.001%
P of 60 success: 0.000%
P of 70 success: 0.000%
P of 80 success: 0.000%
P of 90 success: 0.000%
P of 100 success: 0.000%

鉴于一项试验的成功概率为 30%,我们预计 100 项试验中 50 项或更少成功的概率接近 100%。我们可以用累积分布函数来计算,如下所示。

# example of using the cdf for the binomial distribution
from scipy.stats import binom
# define the parameters of the distribution
p = 0.3
k = 100
# define the distribution
dist = binom(k, p)
# calculate the probability of <=n successes
for n in range(10, 110, 10):
	print('P of %d success: %.3f%%' % (n, dist.cdf(n)*100))

运行该示例会以 10 为一组打印[10,100]中的每一个成功次数,以及在 100 次试验中达到该成功次数或更少的概率。

不出所料,在 50 次或更少的成功之后,涵盖了该分布中 99.999%的预期成功。

P of 10 success: 0.000%
P of 20 success: 1.646%
P of 30 success: 54.912%
P of 40 success: 98.750%
P of 50 success: 99.999%
P of 60 success: 100.000%
P of 70 success: 100.000%
P of 80 success: 100.000%
P of 90 success: 100.000%
P of 100 success: 100.000%

多欧拉分布

多项式分布,也称为分类分布,涵盖了一个事件具有 K 种可能结果之一的情况。

  • {1,2,3,…,K}中的 x

它是伯努利分布从二元变量到分类变量的推广,其中伯努利分布的例数 K 设置为 2, K=2

遵循多项式分布的一个常见例子是:

  • 一卷骰子的结果为{1,2,3,4,5,6},例如 K=6。

机器学习中多类分布的一个常见示例可能是将单个示例多类分类为 K 类之一,例如鸢尾花的三个不同种类之一。

分布可以用从 p1pKK 变量来概括,每个变量定义从 1 到 K 的给定分类结果的概率,其中所有概率的总和为 1.0。

  • P(x=1) = p1
  • P(x=2) = p1
  • P(x=3) = p3
  • P(x=K) = pK

在单卷模具的情况下,每个值的概率将是 1/6,或大约 0.166 或大约 16.6%。

多项分布

多个独立的多项试验的重复将遵循多项式分布。

多项式分布是具有 K 结果的离散变量的二项式分布的推广。

多项式过程的一个例子包括一系列独立的骰子滚动。

多项式分布的一个常见例子是自然语言处理领域的文本文档中单词的出现计数。

多项式分布由具有 K 结果的离散随机变量、从 p1pK 的每个结果的概率和 k 连续试验来概括。

我们可以用一个小例子来证明这一点,3 个类别( K=3 )具有相等的概率( p=33.33% )和 100 个试验。

首先,我们可以使用多项式()NumPy 函数来模拟 100 个独立试验,并总结事件导致每个给定类别的次数。该函数将每个类别的试验次数和概率作为一个列表。

下面列出了完整的示例。

# example of simulating a multinomial process
from numpy.random import multinomial
# define the parameters of the distribution
p = [1.0/3.0, 1.0/3.0, 1.0/3.0]
k = 100
# run a single simulation
cases = multinomial(k, p)
# summarize cases
for i in range(len(cases)):
	print('Case %d: %d' % (i+1, cases[i]))

我们预计每个类别大约有 33 个事件。

运行该示例会报告每个案例和事件的数量。

每次运行代码时都会产生 100 次试验的不同随机序列,因此您的具体结果会有所不同。试着运行这个例子几次。

在这种情况下,我们看到病例的分布高达 37 例,低至 30 例。

Case 1: 37
Case 2: 33
Case 3: 30

我们可能期望 100 个试验的理想化情况分别导致事件 1、2 和 3 的 33、33 和 34 个病例。

我们可以使用概率质量函数或多项式 pmf() SciPy 函数来计算这种特定组合在实践中发生的概率。

下面列出了完整的示例。

# calculate the probability for a given number of events of each type
from scipy.stats import multinomial
# define the parameters of the distribution
p = [1.0/3.0, 1.0/3.0, 1.0/3.0]
k = 100
# define the distribution
dist = multinomial(k, p)
# define a specific number of outcomes from 100 trials
cases = [33, 33, 34]
# calculate the probability for the case
pr = dist.pmf(cases)
# print as a percentage
print('Case=%s, Probability: %.3f%%' % (cases, pr*100))

运行该示例报告了每个事件类型的理想化案例数[33,33,34]小于 1%的概率。

Case=[33, 33, 34], Probability: 0.813%

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

应用程序接口

文章

摘要

在本教程中,您发现了机器学习中使用的离散概率分布。

具体来说,您了解到:

  • 离散随机变量的结果概率可以用离散概率分布来概括。
  • 单个二元结果具有伯努利分布,一系列二元结果具有二项式分布。
  • 单个分类结果具有多项分布,一系列分类结果具有多项分布。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何计算机器学习的 KL 散度

原文:machinelearningmastery.com/divergence-…

最后更新于 2019 年 11 月 1 日

通常希望量化给定随机变量的概率分布之间的差异。

这在机器学习中经常发生,当我们可能对计算实际和观察到的概率分布之间的差异感兴趣时。

这可以使用信息论中的技术来实现,例如库尔巴克-莱布勒散度(KL 散度)或相对熵,以及詹森-香农散度,它提供了 KL 散度的归一化和对称版本。这些评分方法可以作为计算其他广泛使用的方法的捷径,例如互信息用于建模前的特征选择,交叉熵用作许多不同分类器模型的损失函数。

在这篇文章中,你将发现如何计算概率分布之间的散度。

看完这篇文章,你会知道:

  • 统计距离是计算统计对象之间差异的一般思想,例如随机变量的不同概率分布。
  • 库尔巴克-莱布勒散度计算一个分数,用来衡量一个概率分布与另一个概率分布的散度。
  • 詹森-香农散度扩展了 KL 散度来计算一个概率分布与另一个概率分布的对称得分和距离度量。

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2019 年 10 月更新:增加了方程式替代形式的描述(感谢 Ori)。

How to Calculate the Distance Between Probability Distributions

如何计算概率分布之间的距离 图片由帕克森·沃尔伯提供,版权所有。

概观

本教程分为三个部分;它们是:

  1. 统计距离
  2. 库尔巴克-莱布勒散度
  3. 詹森-香农散度

统计距离

在许多情况下,我们可能希望比较两种概率分布。

具体来说,我们可能有一个随机变量和该变量的两个不同的概率分布,例如真实分布和该分布的近似值。

在这种情况下,量化分布之间的差异可能是有用的。通常,这被称为计算两个统计对象之间的统计距离的问题,例如概率分布。

一种方法是计算两个分布之间的距离度量。这可能具有挑战性,因为很难解释这项措施。

相反,更常见的是计算两个概率分布之间的散度。发散就像一种度量,但不是对称的。这意味着散度是一个分布如何不同于另一个分布的评分,其中计算分布 P 和 Q 的散度将给出不同于 Q 和 P 的评分

发散分数是信息论以及更一般的机器学习中许多不同计算的重要基础。例如,它们提供了计算分数的快捷方式,如互信息(信息增益)和交叉熵,用作分类模型的损失函数。

发散分数也直接用作理解复杂建模问题的工具,例如在优化生成对抗网络(GAN)模型时近似目标概率分布。

信息论中两个常用的散度得分是库尔巴克-莱布勒散度和詹森-香农散度。

在下一节中,我们将仔细研究这两个分数。

库尔巴克-莱布勒散度

库尔巴克-莱布勒散度分数,或 KL 散度分数,量化了一个概率分布与另一个概率分布的不同程度。

两个分布 Q 和 P 之间的 KL 散度通常用下面的符号表示:

  • KL(P || Q)

其中“||”运算符表示“散度或与 q 的 Ps 散度。

KL 散度可以计算为 P 中每个事件概率的负和乘以 Q 中事件概率对 P 中事件概率的对数

  • KL(P | | Q)=–X 中 X 的和 P(x) * log(Q(x) / P(x))

总和中的值是给定事件的散度。

这与 P 中每个事件概率的正和乘以 P 中事件概率对 Q 中事件概率的对数相同(例如分数中的项被翻转)。这是实践中使用的更常见的实现。

  • KL(P | | Q)= X 中 X 的和 P(x) * log(P(x) / Q(x))

KL 散度得分的直觉是,当一个事件来自 P 的概率较大,而同一事件在 Q 中的概率较小时,存在较大的散度。当来自 P 的概率小,来自 Q 的概率大时,也有较大的发散,但没有第一种情况大。

它可以用来衡量离散和连续概率分布之间的差异,在后一种情况下,计算的是事件的积分,而不是离散事件的概率之和。

测量两个概率分布 p 和 q 的不相似性的一种方法被称为 kulback-Leibler 散度(KL 散度)或相对熵。

—第 57 页,机器学习:概率视角,2012。

对数可以是以 2 为底的,以“为单位,或者是以“自然对数为底的,以为单位当得分为 0 时,表明两个分布相同,否则得分为正。

重要的是,KL 散度分数是不对称的,例如:

  • KL(P || Q)!= KL(Q || P)

它以方法的两位作者所罗门·库尔巴克和理查德·莱布勒的名字命名,有时被称为“相对熵”

这被称为分布 p(x)和 q(x)之间的相对熵或库尔巴克-莱布勒散度,或 KL 散度。

—第 55 页,模式识别与机器学习,2006。

如果我们试图近似一个未知的概率分布,那么来自数据的目标概率分布是 P,Q 是我们对该分布的近似。

在这种情况下,KL 散度总结了从随机变量表示事件所需的额外位数(即,用以 2 为底的对数计算)。我们的近似越好,需要的额外信息就越少。

……KL 散度是对数据进行编码所需的额外位数的平均值,这是因为我们使用分布 q 对数据进行编码,而不是真正的分布 p。

—第 58 页,机器学习:概率视角,2012。

我们可以用一个实例来具体说明 KL 散度。

考虑一个随机变量,它有三个不同颜色的事件。对于这个变量,我们可能有两种不同的概率分布;例如:

...
# define distributions
events = ['red', 'green', 'blue']
p = [0.10, 0.40, 0.50]
q = [0.80, 0.15, 0.05]

我们可以绘制这些概率的条形图,将它们直接作为概率直方图进行比较。

下面列出了完整的示例。

# plot of distributions
from matplotlib import pyplot
# define distributions
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)))
# plot first distribution
pyplot.subplot(2,1,1)
pyplot.bar(events, p)
# plot second distribution
pyplot.subplot(2,1,2)
pyplot.bar(events, q)
# show the plot
pyplot.show()

运行该示例会为每个概率分布创建一个直方图,从而可以直接比较每个事件的概率。

我们可以看到,分布确实是不同的。

Histogram of Two Different Probability Distributions for the Same Random Variable

同一随机变量两种不同概率分布的直方图

接下来,我们可以开发一个函数来计算两个分布之间的 KL 散度。

我们将使用 log base-2 来确保结果以位为单位。

# calculate the kl divergence
def kl_divergence(p, q):
	return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p)))

然后我们可以用这个函数来计算 P 和 Q 的 KL 散度,以及反过来,P 和 Q 的 KL 散度

# calculate (P || Q)
kl_pq = kl_divergence(p, q)
print('KL(P || Q): %.3f bits' % kl_pq)
# calculate (Q || P)
kl_qp = kl_divergence(q, p)
print('KL(Q || P): %.3f bits' % kl_qp)

将这些结合在一起,完整的示例如下所示。

# example of calculating the kl divergence between two mass functions
from math import log2

# calculate the kl divergence
def kl_divergence(p, q):
	return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p)))

# define distributions
p = [0.10, 0.40, 0.50]
q = [0.80, 0.15, 0.05]
# calculate (P || Q)
kl_pq = kl_divergence(p, q)
print('KL(P || Q): %.3f bits' % kl_pq)
# calculate (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 具有更多的小概率。在第二种情况下,分歧更大。

KL(P || Q): 1.927 bits
KL(Q || P): 2.022 bits

如果我们将 log2() 改为自然对数 log() 函数,结果用 nats 表示,如下所示:

# KL(P || Q): 1.336 nats
# KL(Q || P): 1.401 nats

SciPy 库提供了 kl_div()函数来计算 kl 散度,尽管这里定义了不同的定义。它还提供了计算相对熵的 rel_entr()函数,与这里 KL 散度的定义相匹配。这很奇怪,因为“相对熵经常被用作“ KL 散度的同义词。”

然而,我们可以使用 rel_entr() SciPy 函数计算 KL 散度,并确认我们的手动计算是正确的。

rel_entr() 函数将每个概率分布中所有事件的概率列表作为参数,并返回每个事件的离差列表。这些可以相加得到 KL 散度。计算使用自然对数而不是对数基数-2,因此单位是以 nats 而不是以位为单位。

下面列出了使用 SciPy 为上面使用的相同概率分布计算 KL(P || Q)和 KL(Q || P)的完整示例:

# example of calculating the kl divergence (relative entropy) with scipy
from scipy.special import rel_entr
# define distributions
p = [0.10, 0.40, 0.50]
q = [0.80, 0.15, 0.05]
# calculate (P || Q)
kl_pq = rel_entr(p, q)
print('KL(P || Q): %.3f nats' % sum(kl_pq))
# calculate (Q || P)
kl_qp = rel_entr(q, p)
print('KL(Q || P): %.3f nats' % sum(kl_qp))

运行该示例,我们可以看到计算出的偏差与我们手动计算的 KL(P || Q)和 KL(Q || P)分别约为 1.3 nats 和 1.4 nats 相匹配。

KL(P || Q): 1.336 nats
KL(Q || P): 1.401 nats

詹森-香农散度

詹森-香农散度,简称 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 散度。

当使用以 2 为底的对数时,它作为一种度量更有用,因为它提供了 KL 散度的平滑和归一化版本,分数在 0(相同)和 1(最大差异)之间。

分数的平方根给出了一个量,称为詹森-香农距离,简称 JS 距离。

我们可以用一个工作实例来具体说明 JS 分歧。

首先,我们可以定义一个函数来计算 JS 散度,该函数使用上一节准备的*KL _ diffusion()*函数。

# calculate the kl divergence
def kl_divergence(p, q):
	return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p)))

# calculate the js divergence
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 距离。例如:

...
# calculate 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 发散不同。

...
# calculate 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 距离的完整示例。

# example of calculating the js divergence between two mass functions
from math import log2
from math import sqrt
from numpy import asarray

# calculate the kl divergence
def kl_divergence(p, q):
	return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p)))

# calculate the js divergence
def js_divergence(p, q):
	m = 0.5 * (p + q)
	return 0.5 * kl_divergence(p, m) + 0.5 * kl_divergence(q, m)

# define distributions
p = asarray([0.10, 0.40, 0.50])
q = asarray([0.80, 0.15, 0.05])
# calculate 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))
# calculate 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)相同的分数和距离度量。

JS(P || Q) divergence: 0.420 bits
JS(P || Q) distance: 0.648
JS(Q || P) divergence: 0.420 bits
JS(Q || P) distance: 0.648

SciPy 库通过 jensenshannon()函数提供了 JS 距离的实现。

它将来自每个概率分布的所有事件的概率数组作为参数,并返回 JS 距离分数,而不是散度分数。我们可以使用这个函数来确认我们手动计算的 JS 距离。

下面列出了完整的示例。

# calculate the jensen-shannon distance metric
from scipy.spatial.distance import jensenshannon
from numpy import asarray
# define distributions
p = asarray([0.10, 0.40, 0.50])
q = asarray([0.80, 0.15, 0.05])
# calculate JS(P || Q)
js_pq = jensenshannon(p, q, base=2)
print('JS(P || Q) Distance: %.3f' % js_pq)
# calculate JS(Q || P)
js_qp = jensenshannon(q, p, base=2)
print('JS(Q || P) Distance: %.3f' % js_qp)

运行该示例,我们可以确认距离分数与我们手动计算的 0.648 相匹配,并且距离计算如预期的那样对称。

JS(P || Q) Distance: 0.648
JS(Q || P) Distance: 0.648

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

邮件

蜜蜂

文章

摘要

在这篇文章中,你发现了如何计算概率分布之间的散度。

具体来说,您了解到:

  • 统计距离是计算统计对象之间差异的一般思想,例如随机变量的不同概率分布。
  • 库尔巴克-莱布勒散度计算一个分数,用来衡量一个概率分布与另一个概率分布的散度。
  • 詹森-香农散度扩展了 KL 散度来计算一个概率分布与另一个概率分布的对称得分和距离度量。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何在 Python 中使用经验分布函数

原文:machinelearningmastery.com/empirical-d…

最后更新于 2020 年 8 月 28 日

经验分布函数为不符合标准概率分布的数据样本提供了一种建模和采样累积概率的方法。

因此,它有时被称为经验累积分布函数,简称 ECDF。

在本教程中,您将发现经验概率分布函数。

完成本教程后,您将知道:

  • 有些数据样本无法使用标准分布进行汇总。
  • 经验分布函数提供了一种对数据样本的累积概率建模的方法。
  • 如何使用 statsmodels 库对经验累积分布函数进行建模和采样?

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

How to Use an Empirical Distribution Function in Python

如何在 Python 中使用经验分布函数 图片由 Gigi Griffis 提供,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. 经验分布函数
  2. 双峰数据分布
  3. 采样经验分布

经验分布函数

通常,数据样本的观测值分布符合众所周知的概率分布

例如,人类的身高将符合正态(高斯)概率分布。

情况并非总是如此。有时,收集到的数据样本中的观测值不符合任何已知的概率分布,并且不能通过数据转换或分布函数的参数化而轻易地强制转换为现有的分布。

相反,必须使用经验概率分布。

我们可能需要对两种主要类型的概率分布函数进行采样;它们是:

  • 概率密度函数。
  • 累积分布函数。

PDF 返回观察一个值的预期概率。对于离散数据,PDF 被称为概率质量函数(PMF)。CDF 返回观察到小于或等于给定值的预期概率。

使用非参数密度估计方法,例如核密度估计(KDE) ,可以拟合经验概率密度函数并将其用于数据采样。

经验累积分布函数被称为经验分布函数,简称 EDF。它也被称为经验累积分布函数,或 ECDF。

EDF 的计算方法是对数据样本中的所有唯一观测值进行排序,并计算每个观测值的累积概率,即小于或等于给定观测值的观测值数除以观测值总数。

如下所示:

  • EDF(x) =观测次数< = x / n

像其他累积分布函数一样,概率的总和将从 0.0 到 1.0,因为域中的观测值是从最小到最大枚举的。

为了使经验分布函数具体化,让我们看一个数据集明显不符合已知概率分布的例子。

双峰数据分布

我们可以定义一个明显不符合标准概率分布函数的数据集。

一个常见的例子是当数据具有两个峰值(双峰分布)或多个峰值(多峰分布)时。

我们可以通过组合来自两个不同正态分布的样本来构建双峰分布。具体而言,300 个实例的平均值为 20,标准偏差为 5(较小的峰值),700 个实例的平均值为 40,标准偏差为 5(较大的峰值)。

平均值选择得很接近,以确保组合样本中的分布重叠。

下面列出了创建具有双峰概率分布的样本并绘制直方图的完整示例。

# example of a bimodal data sample
from matplotlib import pyplot
from numpy.random import normal
from numpy import hstack
# generate a sample
sample1 = normal(loc=20, scale=5, size=300)
sample2 = normal(loc=40, scale=5, size=700)
sample = hstack((sample1, sample2))
# plot the histogram
pyplot.hist(sample, bins=50)
pyplot.show()

运行该示例会创建数据样本并绘制直方图。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

平均值为 20 的样本比平均值为 40 的样本要少,这可以在直方图中看到,40 左右的样本密度大于 20 左右的样本密度。

Histogram Plot of Data Sample With a Bimodal Probability Distribution

双峰概率分布数据样本的直方图

根据设计,这种分布的数据不能很好地符合常见的概率分布。

下面是这个数据样本的概率密度函数(PDF)图。

Empirical Probability Density Function for the Bimodal Data Sample

双峰数据样本的经验概率密度函数

这是一个使用经验分布函数的好例子。

计算经验分布函数

经验分布函数可以适用于 Python 中的数据样本。

statmodels Python 库提供了 ECDF 类,用于拟合经验累积分布函数和计算域中特定观测值的累积概率。

通过调用 ECDF()并传入原始数据样本来拟合分布。

...
# fit a cdf
ecdf = ECDF(sample)

一旦拟合,就可以调用该函数来计算给定观测值的累积概率。

...
# get cumulative probability for values
print('P(x<20): %.3f' % ecdf(20))
print('P(x<40): %.3f' % ecdf(40))
print('P(x<60): %.3f' % ecdf(60))

该类还提供了数据中独特观察的有序列表(T0)。x 属性)及其关联概率()。y 属性)。我们可以访问这些属性并直接绘制 CDF 函数。

...
# plot the cdf
pyplot.plot(ecdf.x, ecdf.y)
pyplot.show()

将这些联系在一起,下面是为双峰数据样本拟合经验分布函数的完整示例。

# fit an empirical cdf to a bimodal dataset
from matplotlib import pyplot
from numpy.random import normal
from numpy import hstack
from statsmodels.distributions.empirical_distribution import ECDF
# generate a sample
sample1 = normal(loc=20, scale=5, size=300)
sample2 = normal(loc=40, scale=5, size=700)
sample = hstack((sample1, sample2))
# fit a cdf
ecdf = ECDF(sample)
# get cumulative probability for values
print('P(x<20): %.3f' % ecdf(20))
print('P(x<40): %.3f' % ecdf(40))
print('P(x<60): %.3f' % ecdf(60))
# plot the cdf
pyplot.plot(ecdf.x, ecdf.y)
pyplot.show()

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

运行该示例将经验 CDF 拟合到数据样本,然后打印观察三个值的累积概率。

P(x<20): 0.149
P(x<40): 0.654
P(x<60): 1.000

然后计算整个域的累积概率,并显示为线图。

在这里,我们可以看到大多数累积分布函数的熟悉的 S 形曲线,这里双峰分布的两个峰值的平均值周围有凸起。

Empirical Cumulative Distribution Function for the Bimodal Data Sample

双峰数据样本的经验累积分布函数

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

应用程序接口

文章

摘要

在本教程中,您发现了经验概率分布函数。

具体来说,您了解到:

  • 有些数据样本无法使用标准分布进行汇总。
  • 经验分布函数提供了一种对数据样本的累积概率建模的方法。
  • 如何使用 statsmodels 库对经验累积分布函数进行建模和采样?

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

期望最大化算法的温和介绍

原文:machinelearningmastery.com/expectation…

最后更新于 2020 年 8 月 28 日

最大似然估计是一种通过搜索概率分布及其参数来估计数据集密度的方法。

这是一种通用且有效的方法,是许多机器学习算法的基础,尽管它要求训练数据集是完整的,例如所有相关的交互随机变量都存在。如果存在与数据集中的变量相互作用但被隐藏或未被观察到的变量,即所谓的潜在变量,则最大似然变得难以处理。

期望最大化算法是一种在潜在变量存在的情况下进行最大似然估计的方法。它通过首先估计潜在变量的值,然后优化模型,然后重复这两个步骤,直到收敛。这是一种有效且通用的方法,最常用于缺失数据的密度估计,如高斯混合模型等聚类算法。

在这篇文章中,你将发现期望最大化算法。

看完这篇文章,你会知道:

  • 在存在潜在变量的情况下,最大似然估计对数据具有挑战性。
  • 期望最大化为具有潜在变量的最大似然估计提供了迭代解。
  • 高斯混合模型是一种密度估计方法,其中使用期望最大化算法拟合分布的参数。

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2019 年 11 月更新:修正代码评论错别字(感谢大牛)

A Gentle Introduction to Expectation Maximization (EM Algorithm)

期望最大化(EM 算法) 温和介绍瓦尔克摄,保留部分权利。

概观

本教程分为四个部分;它们是:

  1. 最大似然潜变量问题
  2. 期望最大化算法
  3. 高斯混合模型与电磁算法
  4. 高斯混合模型示例

最大似然潜变量问题

一个常见的建模问题涉及如何估计数据集的联合概率分布。

密度估计包括选择一个概率分布函数和该分布的参数,以最好地解释观测数据的联合概率分布。

有许多技术可以解决这个问题,尽管一种常见的方法被称为最大似然估计,或简称为“最大似然

最大似然估计涉及到将问题作为一个优化或搜索问题来处理,在这个问题中,我们寻找一组参数,这些参数对数据样本的联合概率产生最佳拟合。

最大似然估计的一个限制是,它假设数据集是完整的,或完全观察到的。这并不意味着模型可以访问所有数据;相反,它假设与问题相关的所有变量都存在。

情况并非总是如此。可能有一些数据集,其中只有一些相关变量可以被观察到,而一些不能,尽管它们影响数据集中的其他随机变量,但它们仍然是隐藏的。

更一般地,这些未观察到或隐藏的变量被称为潜在变量

许多现实世界的问题都有隐藏变量(有时称为潜变量),这些变量在可用于学习的数据中是不可观察的。

—第 816 页,人工智能:现代方法,第 3 版,2009 年。

传统的最大似然估计在存在潜在变量的情况下效果不佳。

…如果我们有缺失的数据和/或潜在的变量,那么计算[最大似然]估计就变得困难了。

—第 349 页,机器学习:概率视角,2012。

相反,在存在潜在变量的情况下,需要最大似然的替代公式来搜索适当的模型参数。

期望最大化算法就是这样一种方法。

期望最大化算法

期望最大化算法,简称 EM 算法,是一种在潜在变量存在的情况下进行最大似然估计的方法。

在潜在变量模型中寻找最大似然估计量的一般技术是期望最大化算法。

—第 424 页,模式识别与机器学习,2006。

EM 算法是在两种模式之间循环的迭代方法。第一种模式试图估计缺失或潜在的变量,称为估计步骤或 E 步骤。第二种模式试图优化模型的参数,以最好地解释数据,称为最大化步骤或 M 步骤。

  • 电子步。估计数据集中缺失的变量。
  • M 步。在有数据的情况下最大化模型的参数。

EM 算法可以被非常广泛地应用,尽管它可能在机器学习中最广为人知,用于无监督学习问题,例如密度估计和聚类。

也许讨论最多的 EM 算法的应用是用混合模型进行聚类。

高斯混合模型与电磁算法

混合模型是由多个概率分布函数的未指定组合组成的模型。

使用统计过程或学习算法来估计概率分布的参数,以最佳地拟合给定训练数据集的密度。

高斯混合模型,简称 GMM,是一种混合模型,它使用高斯(正态)概率分布的组合,并要求估计每个概率分布的均值和标准差参数。

虽然最大似然估计可能是最常见的,但是有许多技术可以用来估计 GMM 的参数。

考虑这样一种情况,即一个数据集由许多恰好由两个不同过程生成的点组成。每个过程的点具有高斯概率分布,但是数据被组合,并且分布足够相似,以至于给定点可能属于哪个分布并不明显。

用于生成数据点的过程代表潜在变量,例如过程 0 和过程 1。它影响数据,但不可见。因此,电磁算法是估计分布参数的合适方法。

在 EM 算法中,估计步骤将估计每个数据点的过程潜变量的值,最大化步骤将优化概率分布的参数,以试图最好地捕获数据的密度。重复该过程,直到获得一组良好的潜在值,并获得符合数据的最大似然值。

  • 电子步。估计每个潜在变量的期望值。
  • M 步。使用最大似然法优化分布参数。

我们可以想象这个优化过程如何被约束到仅仅是分布均值,或者被推广到许多不同高斯分布的混合。

高斯混合模型示例

我们可以通过一个实例来具体说明 EM 算法在高斯混合模型中的应用。

首先,让我们设计一个问题,我们有一个数据集,其中点是从两个高斯过程之一生成的。这些点是一维的,第一个分布的平均值是 20,第二个分布的平均值是 40,两个分布的标准偏差都是 5。

我们将从第一个过程中抽取 3000 点,从第二个过程中抽取 7000 点,并将其混合在一起。

...
# generate a sample
X1 = normal(loc=20, scale=5, size=3000)
X2 = normal(loc=40, scale=5, size=7000)
X = hstack((X1, X2))

然后,我们可以绘制点的直方图,为数据集提供直觉。我们期望看到双峰分布,两种分布的平均值各有一个峰值。

下面列出了完整的示例。

# example of a bimodal constructed from two gaussian processes
from numpy import hstack
from numpy.random import normal
from matplotlib import pyplot
# generate a sample
X1 = normal(loc=20, scale=5, size=3000)
X2 = normal(loc=40, scale=5, size=7000)
X = hstack((X1, X2))
# plot the histogram
pyplot.hist(X, bins=50, density=True)
pyplot.show()

运行该示例会创建数据集,然后为数据点创建直方图。

该图清楚地显示了预期的双峰分布,第一过程的峰值在 20 左右,第二过程的峰值在 40 左右。

我们可以看到,对于两个峰值中间的许多点,它们来自哪个分布是不明确的。

Histogram of Dataset Constructed From Two Different Gaussian Processes

由两种不同高斯过程构造的数据集直方图

我们可以使用高斯混合模型来模拟估计该数据集密度的问题。

可以使用高斯混合 Sklearn 类来建模这个问题,并使用期望最大化算法来估计分布的参数。

该类允许我们在定义模型时通过 n_components 参数指定用于生成数据的底层进程的可疑数量。对于这两个过程或分布,我们将把它设置为 2。

如果过程的数量未知,可以测试一系列不同数量的组件,并选择最适合的模型,其中可以使用诸如阿卡克或贝叶斯信息标准(AIC 或 BIC)的分数来评估模型。

我们也有许多方法可以配置模型,以包含我们可能知道的关于数据的其他信息,例如如何估计分布的初始值。在这种情况下,我们将通过将 init_params 参数设置为“随机”来随机猜测初始参数。

...
# fit model
model = GaussianMixture(n_components=2, init_params='random')
model.fit(X)

一旦模型合适,我们就可以通过模型上的参数来访问学习到的参数,例如平均值、协方差、混合权重等等。

更有用的是,我们可以使用拟合模型来估计现有和新数据点的潜在参数。

例如,我们可以为训练数据集中的点估计潜在变量,并且我们期望前 3,000 个点属于一个过程(例如值=1 ),而接下来的 7,000 个数据点属于不同的过程(例如值=0 )。

...
# predict latent values
yhat = model.predict(X)
# check latent value for first few points
print(yhat[:100])
# check latent value for last few points
print(yhat[-100:])

将所有这些结合在一起,下面列出了完整的示例。

# example of fitting a gaussian mixture model with expectation maximization
from numpy import hstack
from numpy.random import normal
from sklearn.mixture import GaussianMixture
# generate a sample
X1 = normal(loc=20, scale=5, size=3000)
X2 = normal(loc=40, scale=5, size=7000)
X = hstack((X1, X2))
# reshape into a table with one column
X = X.reshape((len(X), 1))
# fit model
model = GaussianMixture(n_components=2, init_params='random')
model.fit(X)
# predict latent values
yhat = model.predict(X)
# check latent value for first few points
print(yhat[:100])
# check latent value for last few points
print(yhat[-100:])

运行该示例使用 EM 算法在准备好的数据集上拟合高斯混合模型。拟合后,该模型用于预测训练数据集中示例的潜在变量值。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,至少在数据集中的前几个和最后几个示例中,模型主要预测潜在变量的正确值。这通常是一个具有挑战性的问题,预计分布峰值之间的点将保持不明确,并整体分配给一个或另一个过程。

[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1
 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

应用程序接口

文章

摘要

在这篇文章中,你发现了期望最大化算法。

具体来说,您了解到:

  • 在存在潜在变量的情况下,最大似然估计对数据具有挑战性。
  • 期望最大化为具有潜在变量的最大似然估计提供了迭代解。
  • 高斯混合模型是一种密度估计方法,其中使用期望最大化算法拟合分布的参数。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何开发联合概率、边缘概率和条件概率的直觉

原文:machinelearningmastery.com/how-to-calc…

最后更新于 2019 年 12 月 6 日

单个随机变量的概率是直截了当的,尽管当考虑两个或更多变量时,它会变得复杂。

仅用两个变量,我们可能会对同时发生的两个事件的概率感兴趣,称为联合概率:一个事件给定另一个事件发生的概率称为条件概率,或者仅一个事件的概率而不考虑其他变量,称为边缘概率。

这些类型的概率很容易定义,但是它们背后的直觉可能需要一些时间来理解,需要一些可行的例子来修改。

在本教程中,您将发现计算联合概率、边缘概率和条件概率背后的直觉。

完成本教程后,您将知道:

  • 如何计算独立随机变量的联合概率、边缘概率和条件概率?
  • 如何从联合随机变量中收集观测值并构造联合概率表?
  • 如何从联合概率表中计算联合概率、边缘概率和条件概率?

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2019 年 10 月更新:修复了一些小错别字,感谢 Minel 和 jmy。
  • 2019 年 12 月更新:修正了联合概率表描述中的错别字。

Probabilistic Model Selection Measures AIC, BIC, and MDL

如何培养联合概率、边缘概率和条件概率的直觉 图片由吉尔姆·维尔鲁特提供,版权所有。

教程概述

本教程分为三个部分;它们是:

  1. 联合概率、边缘概率和条件概率
  2. 掷骰子的概率
  3. 两个城市的天气概率

联合概率、边缘概率和条件概率

当使用单个随机变量时,计算概率相对简单。

当考虑两个或更多的随机变量时,它会变得更有趣,就像我们在许多现实世界中经常做的那样。

当处理两个(或更多)随机变量时,我们可能对计算三种主要类型的概率感兴趣。

简而言之,它们是:

  • 联合概率。同时发生事件的概率。
  • 边缘概率。不考虑其他变量的事件概率。
  • 条件概率。给定其他事件出现的概率。

这些不同类型的概率的含义和计算方法因两个随机变量是独立的(更简单)还是相关的(更复杂)而异。

我们将通过实例来探讨如何计算和解释这三种概率。

在下一节中,我们将看两个骰子的独立掷骰子,在下一节中,我们将看两个地理位置相近的城市的天气事件的发生。

掷骰子的概率

探索联合概率和边缘概率的一个好的起点是考虑独立的随机变量,因为计算非常简单。

公平骰子的滚动给出了数字 1 到 6 出现的六分之一(1/6)或 0.166 (16.666%)的概率。

  • p(指数 1=1) = 1/6
  • p(指数 1=2) = 1/6
  • p(指数 1=3) = 1/6
  • p(指数 1=4) = 1/6
  • p(指数 1=5) = 1/6
  • p(指数 1=6) = 1/6

如果我们掷出第二个骰子,我们在那个骰子上得到每个值的概率是相同的。骰子的每个事件都有相等的概率,骰子 1 和骰子 2 的滚动不会相互影响。

  • p(索引 1={1,2,3,4,5,6}) = 1.0
  • p(索引 2={1,2,3,4,5,6}) = 1.0

首先,我们可以将骰子 1 滚动偶数的概率计算为滚动 2、4 或 6 的概率之和,例如:

  • p(索引 1={2,4,6}) = P(索引 1=2) + P(索引 1=4) + P(索引 1=6)
  • p(索引 1={2,4,6}) = 1/6 + 1/6 + 1/6

这是 0.5%或 50%,正如我们可能直观地预期的那样。

现在,我们可以考虑用两个骰子同时掷出偶数的联合概率。独立随机变量的联合概率计算如下:

  • P(A 和 B) = P(A) * P(B)

这是通过 dice1 滚动偶数的概率乘以 dice2 滚动偶数的概率来计算的。第一个事件的概率约束了第二个事件的概率。

  • p(索引 1={2,4,6}和索引 2={2,4,6}) = P(索引 1={2,4,6}) * P(索引 2={2,4,6})

我们知道每个骰子滚动一个偶数的概率是 0.5,因此滚动两个偶数的概率是 3/6 或 0.5。插上它,我们得到:0.5 * 0.5 (0.25)或 25%。

另一种看待这个问题的方法是考虑滚动一个模具给出 6 种组合。将两个骰子滚动在一起,骰子 2 的 6 个组合或(6×6) 36 个组合中的每一个都有 6 个组合。dice1 的 6 个组合中总共有 3 个是偶数,这些组合的 6 个组合中有 3 个是偶数。这给出了 36 个组合中的(3×3) 9 个作为每个管芯的偶数或者(9/36 = 0.25) 25%。

提示:如果你在处理带有离散事件的自变量时,曾经对自己的概率计算有过疑问,那就用组合的方式来思考,事情会再次有意义。

我们可以根据我们对该领域的了解,构建一个联合概率表。下表列出了完整的表格,顶部(x 轴)为 dice1,侧面(y 轴)为 dice2。使用联合概率公式计算给定小区的每个事件的联合概率,例如 0.166 * 0.166 或 0.027 或约 2.777%。

   1      2      3      4      5      6
1  0.027  0.027  0.027  0.027  0.027  0.027
2  0.027  0.027  0.027  0.027  0.027  0.027
3  0.027  0.027  0.027  0.027  0.027  0.027
4  0.027  0.027  0.027  0.027  0.027  0.027
5  0.027  0.027  0.027  0.027  0.027  0.027
6  0.027  0.027  0.027  0.027  0.027  0.027

此表捕获了两个随机变量 dice1 和 dice2 事件的联合概率分布。这很无聊,但我们可以用它来加深我们对自变量联合概率和边缘概率的理解。

例如,用 dice1 滚动 a 2 和用 dice2 滚动 a 2 的联合概率可以直接从表中读出为 2.777%。我们可以探索更复杂的情况,例如用 dice1 滚动 2,用 dice2 滚动奇数。

这可以通过将第二列中用 dice1 滚动 2 的值与用 dice2 滚动奇数的第一、第三和第五行的值相加来读取。

  • p(索引 1=2,索引 2={1,3,5}) = 0.027 + 0.027 + 0.027

这一数字约为 0.083,约为 8.333%。

我们也可以用这个表来计算边缘概率。这被计算为 dice1 的一整列概率或 dice2 的一行概率的总和。

例如,我们可以用 dice2 作为表格最后一行的概率总和来计算滚动 6 的边缘概率。这大约是 0.166 或 16.666%,正如我们可能直观预期的那样。

重要的是,如果我们对表中所有单元格的概率求和,它必须等于 1.0。此外,如果我们对每行的概率求和,那么这些和的总和必须等于 1.0。同样,如果我们对每一列的概率求和,那么这些和的和也必须等于 1.0。这是对联合概率表的要求。

因为事件是独立的,所以计算条件概率没有什么特别的需要。

  • P(给定的 B) = P(A)

例如,无论用 dice1 滚动什么,用 DIC E1 滚动 2 的概率是相同的。

  • p(索引 1=2 给定索引 2=6) = P(索引 1=2)

这样,条件概率对于独立随机变量就没有了有用的意义。

开发一个联合概率表是一个有用的工具,有助于更好地理解如何计算和探索联合概率和边缘概率。

在下一节中,让我们来看一个更复杂的带有因变量的例子。

两个城市的天气概率

我们可以利用两个相依随机变量的事件联合概率表来发展联合概率和边缘概率的直觉。

考虑一下有两个城市的情况,城市城市。这些城市离得很近,一般都会受到相同天气的影响,但它们之间的距离又很远,所以不会受到相同天气的影响。

我们可以考虑这些城市在某一天的离散天气分类,如晴天多云雨天。当城市天气晴朗时,城市天气通常晴朗,但并不总是如此。因此,这两个城市的天气相互依存。

现在,让我们探索不同类型的概率。

数据收集

首先,我们可以记录每个城市二十多天的观测天气。

例如,在第一天,第二天的天气如何,等等。

Day | City1 | City2
1     Sunny   Sunny
2     Sunny   Cloudy
3
...

为了简洁起见,省略了完整的结果表,我们将在后面补充总数。

然后,我们可以计算观察到的配对事件总数的总和。

例如,城市晴天和城市晴天的总次数,城市晴天和城市多云的总次数,等等。

City 1 | City 2 | Total
sunny    sunny    6/20
sunny    cloudy   1/20
sunny    rainy    0/20
...

同样,为了简洁起见,完整的表格被省略了,我们将在后面补充总数。

这些数据为探索这两个城市发生天气事件的概率提供了依据。

联合概率

首先,我们可能对每个城市发生天气事件的概率感兴趣。

我们可以创建一个包含成对或联合天气事件概率的表格。

下表总结了这两个城市的每种离散天气的概率,其中城市定义在顶部(x 轴),城市定义在侧面(y 轴)。

          Sunny | Cloudy | Rainy
Sunny     6/20    2/20     0/20
Cloudy    1/20    5/20     2/20
Rainy     0/20    1/20     3/20

表格中的一个单元格描述了每个城市中事件的联合概率,表格中的概率一起总结了两个城市天气事件的联合概率分布。

表中所有单元格的联合概率之和必须等于 1.0。

我们可以计算出两个城市天气的联合概率。例如,我们预计两个城市同时晴朗的联合概率很高。这可以正式表述为:

  • p(城市=阳光充足,城市=阳光充足)

或者更简洁地说:

  • p(晴天,晴天)

我们可以直接从表格中读出 6/20 或 0.3 或 30%。相对较高的概率。

我们可以更进一步,考虑第一个城市不下雨,第二个城市下雨的概率。我们可以这样说:

  • p(城市=晴天或阴天,城市=雨天)

同样,我们可以直接从表中计算出来。首先,P(晴,雨)为 0/20,P(阴,雨)为 1/20。然后我们可以把这些概率加在一起,得出 1/20 或 0.05 或 5%。这可能发生,但不太可能。

该表还给出了事件边际分布的概念。例如,我们可能对某个城市出现晴天的概率感兴趣,不管这个城市发生了什么。这可以通过对阳光充足的城市的概率求和从表中读出,例如概率的第一列:

  • P(市=晴)= P(市=晴,市=晴)+ P(市=晴,市=多云)+ P(市=晴,市=雨)

或者

  • p(1 =晴天)= 6/20 + 1/20 + 0/20
  • p(1 =晴天)= 7/20

因此,某市晴天的边缘概率为 0.35 或 35%。

我们可以通过连续计算一个事件在部分或全部概率范围内的边缘概率来为 city 做同样的事情。例如,城市中雨天的概率将被计算为沿着表格底部一行的概率之和:

  • p(市=多雨)= 0/20 + 1/20 + 3/20
  • p(市=多雨)= 4/20

因此,城市雨天的边缘概率为 0.2%或 20%。

边缘概率通常是有趣和有用的,更新联合概率表以包括它们是一个好主意;例如:

          Sunny | Cloudy | Rainy | Marginal
Sunny     6/20    2/20     0/20    8/20
Cloudy    1/20    5/20     2/20    8/20
Rainy     0/20    1/20     3/20    4/20
Marginal  7/20    8/20     5/20    20/20

条件概率

鉴于另一个城市发生天气事件,我们可能对天气事件的概率感兴趣。

这被称为条件概率,可以使用联合概率和边缘概率来计算。

  • P(给定的 B) = P(A 和 B) / P(B)

例如,我们可能对某个城市阳光充足的概率感兴趣,因为某个城市阳光充足。

这可以正式表述为:

  • P(1 =阳光充足给定的城市=阳光充足)= P(1 =阳光充足且城市=阳光充足)/ P(城市=阳光充足)

我们可以从上一节的表格中填写联合概率和边缘概率;例如:

  • p(1 =晴天给定的城市=晴天)= 6/20 / 8/20
  • p(1 =阳光充足给定的城市=阳光充足)= 0.3 / 0.4

这个出来是 0.75 或者 75%,很直观。我们预计,如果城市天气晴朗,那么城市大部分时间也应该是晴朗的。

这不同于两个城市在某一天都是晴天的联合概率,后者的概率较低,为 30%。

如果从组合数的角度来考虑更有意义。在这种有条件的情况下,我们有更多的信息,因此我们不必计算所有 20 天的概率。具体来说,我们假设市内是晴天,这就大大减少了天数,从 20 天减少到 8 天。在城市中,总共有 6 天是晴天,在城市中也是晴天,比例为 6/8 或(0.75) 75%。

所有这些都可以从联合概率表中看出。

条件概率经常被误解的一个重要方面是它是不可逆的。

  • p(给定的 B)!= P(给定 A 的 B)

也就是说,假设某个城市是晴天,那么这个城市是晴天的概率与假设某个城市是晴天的概率是不一样的。

  • p(11 =晴天给定的城市=晴天)!= P(城市=阳光充足给定的城市=阳光充足)

在这种情况下,假设某个城市是晴天,那么该城市是晴天的概率计算如下:

  • P(城市=阳光充足给定的城市=阳光充足)= P(城市=阳光充足且城市=阳光充足)/ P(城市=阳光充足)
  • p(city = sunny 给定的 city = sunny)= 6/20/7/20
  • p(city = sunny 给定的 city = sunny)= 0.3/0.35
  • p(city = sunny 给定的 city = sunny)= 0.857

在这种情况下,它更高,约为 85.714%。

我们也可以用条件概率来计算联合概率。

  • P(A 和 B) = P(给定的 B) * P(B)

例如,如果我们只知道给定城市中晴天的条件概率和城市的边缘概率,我们可以将联合概率计算为:

  • P(城=阳光充足,城=阳光充足)= P(城=阳光充足,给定城=阳光充足)* P(城=阳光充足)
  • p(城市=阳光充足,城市=阳光充足)= 0.857 * 0.35
  • p(1 =阳光充足,1 =阳光充足)= 0.3

这给出了我们预期的 0.3%或 30%。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

文章

摘要

在本教程中,您发现了计算联合概率、边缘概率和条件概率背后的直觉。

具体来说,您了解到:

  • 如何计算独立随机变量的联合概率、边缘概率和条件概率?
  • 如何从联合随机变量中收集观测值并构造联合概率表?
  • 如何从联合概率表中计算联合概率、边缘概率和条件概率?

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何通过工作实例开发概率的直觉

原文:machinelearningmastery.com/how-to-deve…

最后更新于 2020 年 12 月 21 日

令人沮丧的是,概率计算是不直观的。

我们的大脑太急于走捷径,得到错误的答案,而不是思考一个问题,正确计算概率。

为了使这个问题变得明显并有助于发展直觉,从应用概率的角度解决经典问题可能是有用的。这些问题,如生日问题、男孩或女孩问题和蒙蒂霍尔问题,用不正确的直观答案欺骗了我们,需要仔细应用边际、条件和联合概率的规则,才能得出正确的答案。

在这篇文章中,你将发现如何通过解决经典的发人深省的问题来培养对概率的直觉。

看完这篇文章,你会知道:

  • 如何用概率相乘来解决生日问题?
  • 如何用条件概率解决男孩或女孩问题?
  • 如何用联合概率求解蒙蒂霍尔问题?

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2020 年 12 月更新:改写了男孩女孩悖论条件概率示例,使其更加清晰。

How to Develop an Intuition for Probability With Worked Examples

如何通过工作实例培养对概率的直觉 图片由伯纳·萨沃里奥提供,保留部分权利。

概观

本教程分为三个部分;它们是:

  1. 生日问题
  2. 男孩还是女孩的问题
  3. 蒙蒂霍尔问题

生日问题

应用概率的一个经典例子是计算两个人生日相同的概率。

这是一个经典的例子,因为结果与我们的直觉不符。因此,它有时被称为生日悖论

这个问题可以概括为:

问题 : 需要多少人才能让组内任意两人生日相同,且至少有 50-50 的几率?

这个问题没有什么诀窍;它包括简单地计算边缘概率。

假设随机选择的人在一年中任何给定的一天(不包括闰年)过生日的概率在一年中的各天均匀分布,例如 1/365 或大约 0.273%。

我们的直觉可能会跳跃到一个答案,并假设我们可能至少需要和一年中的天数一样多的人,例如 365 人。我们的直觉可能会失灵,因为我们在考虑自己和其他人是否与自己的生日相匹配。也就是说,我们在想,和你同一天出生的另一个人需要多少人。这是一个不同的问题。

相反,为了计算解决方案,我们可以考虑比较一个群体中的几对人,以及给定的一对人在同一天出生的概率。这将解锁所需的计算。

一个组内成对比较的次数(不包括每个人与他们自己的比较)计算如下:

  • 比较= n *(n–1)/2

例如,如果我们有一个五人小组,我们将在小组中进行 10 次成对比较,以检查他们是否有相同的生日,这比我们预期的更有可能成功。重要的是,组内比较的次数随着组的大小呈指数增长。

还需要一步。计算问题的逆更容易。即一组中两个人生日不相同的概率。然后,我们可以反转最终结果,以给出所需的概率,例如:

  • p(n 人中有 2 人生日相同)= 1–p(n 人中有 2 人生日不同)

我们可以通过一个小群体的例子来了解为什么计算不匹配生日的概率很容易,在这个例子中,有三个人。

可以一个一个地将人添加到组中。每次将一个人添加到组中,它都会减少一年中没有生日的可用天数,从而将可用天数减少一天。例如 365 天、364 天等。

此外,添加到组中的给定附加人员不匹配的概率必须与之前计算的概率相结合。例如 P(n=2) * P(n=3)等。

这给出了以下结果,计算组大小为 3 的生日不匹配的概率:

  • P(n=3) = 365/365 * 364/365 * 363/365
  • P(n=3) = 99.18%

反转这个给出了三个人中大约 0.820%的匹配生日。

通过这一步,第一个人有一个生日,这将组中其他人的候选天数从 365 天减少到 364 天(即没有生日的天数)。对于第二个人,我们将冲突生日的概率从一年中的 365 天计算为 364 个安全日,或者大约(364/365) 99.72%的概率没有相同的生日。我们现在从可用天数中减去第二个人的生日,得到 363 天。第三个人没有匹配生日的概率然后被给出为 363/365 乘以先验概率,给出大约 99.18%

对于大型组来说,这种计算可能会很繁琐,因此我们可能希望将其自动化。

下面的例子计算了从 2 到 30 的组大小的概率。

# example of the birthday problem
# define group size
n = 30
# number of days in the year
days = 365
# calculate probability for different group sizes
p = 1.0
for i in range(1, n):
	av = days - i
	p *= av / days
	print('n=%d, %d/%d, p=%.3f 1-p=%.3f' % (i+1, av, days, p*100, (1-p)*100))

运行该示例首先打印组大小,然后是可用天数除以一年中的总天数,然后是组中没有匹配生日的概率,接着是补码或组中两个人过生日的概率。

n=2, 364/365, p=99.726 1-p=0.274
n=3, 363/365, p=99.180 1-p=0.820
n=4, 362/365, p=98.364 1-p=1.636
n=5, 361/365, p=97.286 1-p=2.714
n=6, 360/365, p=95.954 1-p=4.046
n=7, 359/365, p=94.376 1-p=5.624
n=8, 358/365, p=92.566 1-p=7.434
n=9, 357/365, p=90.538 1-p=9.462
n=10, 356/365, p=88.305 1-p=11.695
n=11, 355/365, p=85.886 1-p=14.114
n=12, 354/365, p=83.298 1-p=16.702
n=13, 353/365, p=80.559 1-p=19.441
n=14, 352/365, p=77.690 1-p=22.310
n=15, 351/365, p=74.710 1-p=25.290
n=16, 350/365, p=71.640 1-p=28.360
n=17, 349/365, p=68.499 1-p=31.501
n=18, 348/365, p=65.309 1-p=34.691
n=19, 347/365, p=62.088 1-p=37.912
n=20, 346/365, p=58.856 1-p=41.144
n=21, 345/365, p=55.631 1-p=44.369
n=22, 344/365, p=52.430 1-p=47.570
n=23, 343/365, p=49.270 1-p=50.730
n=24, 342/365, p=46.166 1-p=53.834
n=25, 341/365, p=43.130 1-p=56.870
n=26, 340/365, p=40.176 1-p=59.824
n=27, 339/365, p=37.314 1-p=62.686
n=28, 338/365, p=34.554 1-p=65.446
n=29, 337/365, p=31.903 1-p=68.097
n=30, 336/365, p=29.368 1-p=70.632

结果令人惊讶,显示只有 23 个人被要求在同一天给两个人超过 50%的机会过生日。

更令人惊讶的是,有 30 个人,这增加到 70%的概率。这很令人惊讶,因为 20 到 30 人大约是学校的平均班级规模,我们对这些人都有一种直觉(如果我们上过学)。

如果群体规模增加到 60 人左右,那么群体中两个人生日相同的概率在 99%以上!

男孩还是女孩的问题

应用概率的另一个经典例子是计算婴儿是男孩还是女孩的概率。

在没有额外信息的情况下,给定婴儿是男孩还是女孩的概率为 50%。这在现实中可能是真的,也可能不是真的,但让我们假设这是对概率的有用说明。

一旦包含更多的信息,概率计算就会改变,这甚至会让精通数学和概率的人出错。

一个流行的例子是所谓的“两个孩子的问题”,涉及到获得一个有两个孩子的家庭的信息,并估计一个孩子的性别。如果问题表述不准确,会导致误解,进而导致两种不同的概率计算方式。这是使用自然语言代替符号的挑战,在这种情况下被称为“男孩或女孩悖论

让我们看两个精确陈述的例子。

案例 1 : 一个女人有两个孩子,最大的是个男孩。这个女人生两个儿子的概率有多大?

考虑一张无条件概率表。

Younger Child | Older Child | Unconditional Probability
Girl            Boy           1/4
Boy             Boy           1/4
Girl            Girl          1/4
Boy             Girl          1/4

我们的直觉表明,另一个孩子是男孩的概率是 0.5%或 50%。

或者,我们的直觉可能会暗示,对于一个两个孩子的家庭,男孩和女孩的四种可能组合,一个有两个男孩的家庭的概率是 1/4(例如,概率为 0.25)。

我们可以通过列举包含给定信息的所有可能组合来探索这一点:

Younger Child | Older Child | Conditional Probability
Girl            Boy           1/2
Boy             Boy           1/2 (*)
Girl            Girl          0 (impossible)
Boy             Girl          0 (impossible)

直觉告诉我们,额外的信息使某些情况变得不可能。

会有四种结果,但给出的信息将范围缩小到两种可能的结果(较大的孩子是男孩)。

事实上,两种结果中只有一种可以是男孩-男孩,因此概率为 1/2 或(0.5) 50%。

让我们看看第二个非常相似的例子。

案例二 : 一个女人有两个孩子,其中一个是男孩。这个女人生两个儿子的概率有多大?

我们的直觉跳跃到同样的结论。至少我的是这样。

这是不正确的。

例如,1/2 为男孩,第二个孩子为男孩。在所有可能有两个孩子的情况中,男孩男孩的情况可能会有 1/4 的飞跃。

为了找出原因,让我们再次列举所有可能的组合:

Younger Child | Older Child | Conditional Probability
Girl            Boy           1/3
Boy             Boy           1/3 (*)
Boy             Girl          1/3
Girl            Girl          0 (impossible)

同样,直觉告诉我们,额外的信息使得某些情况变得不可能。

会有四种结果,但给出的信息将范围缩小到三种可能的结果(一个孩子是男孩)。三种情况中有一种是男孩-男孩,因此概率为 1/3 或约 33.33%。

我们在案例 1 中有更多的信息,这使我们能够缩小可能结果的范围,并给出符合我们直觉的结果。

案例 2 看起来很相似,但实际上包含的信息较少。我们不知道大一点的孩子还是小一点的孩子是男孩,因此可能的结果范围更大,导致答案不直观。

我们也可以通过计算条件概率来解决这个问题。

案例 1 中,我们可以将问题表述为:假设已知最大的孩子是男孩,那么一个随机家庭有两个男孩(例如男孩-男孩的序列)的概率是多少。

给定一个事件存在另一个事件的概率称为条件概率,可以使用以下公式计算:

  • P(给定的 B) = P(A 和 B) / P(B)

在这里,我们可以把事件 A 看作“2 个男孩”,事件 B 看作“最大的是个男孩”。

  • A =“两个男孩”
  • B =“最大的是个男孩”

然后,我们可以使用我们的术语重申条件概率的计算:

  • P(“2 个男孩”给出“最大的是男孩”)= P(“2 个男孩”和“最大的是男孩”)/ P(“最大的是男孩”)

根据家庭中出生的一系列孩子的具体结果来看待这些事件是有帮助的。

例如,事件可以按照男孩和女孩的顺序来定义,如下所示:

  • “两个男孩”包括{男孩-男孩}
  • “最大的是男孩”包括{男孩-男孩,女孩-男孩}

鉴于给定的信息,即最大的孩子是男孩,事件{女孩-女孩}和{男孩-女孩}是不可能的。

这样来看我们事件的定义,可以看到条件概率计算的分子 P(“2 个男孩”和“最大的是男孩”)包含一些冗余。具体来说,事件“2 个男孩”是事件“最大的是男孩”的子集。

这是条件概率中的一种特殊情况,例如,当事件 A 是事件 B 的子集时,P(A 和 B)

在这种特殊情况下,P(A 和 B)可以简化为 P(A)。

  • P(A 和 B) = P(A),如果事件 A 是事件 B 的子集

这可能会让初学者感到困惑,但我们经常说,如果 A 是 B 的子集,那么 A 意味着 B 的出现,也就是说,如果 A 出现,B 是确定的,或者概率为 1.0。

  • P(A 和 B) = (A * B) = (A * 1.0)

因此,我们可以将分子简化为“2 个男孩”的概率:

  • P(“2 个男孩”和“最大的是男孩”)= P(“2 个男孩”)

我们现在可以使用这种简化来重申条件概率的计算:

  • P(“2 个男孩”给出“最大的是男孩”)= P(“2 个男孩”)/ P(“最大的是男孩”)

我们可以从上面的无条件概率表中得到我们所知道的,并替换这些项。

例如,“2 个男孩”(例如“男孩-男孩”)的概率是 1/4。“最大的是男孩”的概率是“男孩-男孩”的概率是 1/4 加上“女孩-男孩”的概率也是 1/4 等于 2/4。

  • p("两个男孩")= 1/4
  • p(“最大的是男孩”)= (1/4 + 1/4) = 2/4 = 1/2

因此:

  • P(“2 个男孩”给出“最大的是男孩”)= P(“2 个男孩”)/ P(“最大的是男孩”)
  • p(“2 个男孩”给出“最大的是男孩”)= (1/4) / (1/2)
  • p(“2 个男孩”给出“最大的是男孩”)= 1/2

或者用数字代替分数:

  • P(“2 个男孩”给出“最大的是男孩”)= P(“2 个男孩”)/ P(“最大的是男孩”)
  • p(“2 个男孩”给出“最大的是男孩”)= 0.25 / 0.5
  • p(“2 个男孩”给出“最大的是男孩”)= 0.5

案例 2 中,我们可以把问题表述为:一个随机家庭有两个男孩,已知其中一个孩子是男孩的概率是多少。

再次计算条件概率是:

  • P(给定的 B) = P(A 和 B) / P(B)

在这里,我们可以将事件 A 视为“2 个男孩”,将事件 B 视为“至少 1 个男孩”:

  • A =“两个男孩”
  • B =“至少一个男孩”

然后,我们可以使用我们的术语重申条件概率的计算:

  • P("2 个男孩"被给予"至少 1 个男孩")= P("2 个男孩"和"至少 1 个男孩")/ P("至少 1 个男孩")

我们可以在这个计算中看到一些冗余,特别是分子 P(“2 个男孩”和“至少 1 个男孩”)。

事件“至少 1 个男孩”比“2 个男孩”更一般,或者换句话说,“2 个男孩”是事件“至少 1 个男孩”的子集。

  • “两个男孩”包括{男孩-男孩}
  • “至少一个男孩”包括{男孩-男孩、男孩-女孩、女孩-男孩}

给定条件概率规则:

  • P(A 和 B) = P(A),如果事件 A 是事件 B 的子集

我们可以把分子简化为“2 个男孩”。

  • P("两个男孩"和"至少一个男孩")= P("两个男孩")

现在,我们可以重新计算一下。

  • P("2 个男孩"给定"至少 1 个男孩")= P("2 个男孩")/ P("至少 1 个男孩")

然后,上面的无条件概率表可用于在计算中替换特定值。

例如,“2 个男孩”(例如男孩-男孩)的概率是 1/4。“至少 1 个男孩”的概率是“男孩-男孩”的概率加上“男孩-女孩”的概率加上“女孩-男孩”的概率。

  • p("两个男孩")= 1/4
  • p("至少一个男孩")= (1/4 + 1/4 + 1/4) = 3/4

因此:

  • P("2 个男孩"给定"至少 1 个男孩")= P("2 个男孩")/ P("至少 1 个男孩")
  • p("两个男孩"给出"至少一个男孩")= (1/4) / (3/4)
  • p(“两个男孩”给出“至少一个男孩”)= 1 /3

或者用数字代替分数:

  • P("2 个男孩"给定"至少 1 个男孩")= P("2 个男孩")/ P("至少 1 个男孩")
  • P("2 个男孩"给出"至少 1 个男孩")= 0.25 / 0.75
  • p(“2 个男孩”给出“至少 1 个男孩”)= 0.333

注意,概率第 96 页提供了这个计算的一个版本:给热情的初学者

这是一个有用的例子,说明我们如何通过列举可能的情况来克服不正确的直觉并获得正确的答案,以及我们如何通过计算条件概率来获得相同的结果。

蒙蒂霍尔问题

应用概率中的最后一个经典问题叫做游戏展示问题,或称蒙蒂霍尔问题

它基于一个名为“让我们做个交易”的真实游戏节目,并以该节目主持人的名字命名。

这个问题可以概括描述如下:

问题 : 给选手三个门的选择。一辆后面是汽车,另外两辆后面是山羊。一旦选择了一扇门,知道汽车在哪里的主人就会打开另一扇门,里面有一只山羊,并询问参赛者是否希望保留他们的选择或换到另一扇未打开的门。

这是另一个经典问题,因为解决方案不直观,在过去引起了很大的混乱和争论。

对问题的直觉告诉我们,最初有 1/3 或 33%的几率会选车,一旦主人打开车门露出一只山羊,这个几率就变成了 1/2 或 50%。

这是不正确的。

我们可以从列举所有组合和列出无条件概率开始。假设有三扇门,用户随机选择一扇门,例如门 1。

Door 1 | Door 2 | Door 3 | Unconditional Probability
Goat     Goat     Car      1/3
Goat     Car      Goat     1/3
Car      Goat     Goat     1/3

在这个阶段,有 1/3 的概率有车,匹配我们到目前为止的直觉。

然后,主人用一只山羊打开另一扇门,在本例中是第二扇门。

打开的门不是随机选择的;相反,它是用汽车不在哪里的信息选择的。

我们的直觉建议我们从表中删除第二种情况,并将剩余情况的概率更新为 1/2。

这是不正确的,也是错误的原因。

我们可以将这个场景的直观条件概率总结如下:

Door 1 | Door 2 | Door 3 | Uncon. | Cond.
Goat     Goat     Car      1/3      1/2
Goat     Car      Goat     1/3      0
Car      Goat     Goat     1/3      1/2

如果参赛者在主持人开门之前没有做出选择,例如主持人开门是独立的,那么这是正确的。

诀窍来了,因为选手在主持人开门前做了选择,这是有用的信息。这意味着主人不能打开选择的门(门 1)或打开后面有车的门。主持人的选择取决于参赛者的第一选择,然后受到约束。

相反,无论主机打开哪扇门,我们都必须计算切换或不切换的概率。

让我们看一张结果表,给出选择 1 号门和停留或转换。

Door 1 | Door 2 | Door 3 | Stay | Switch
Goat     Goat     Car      Goat   Car
Goat     Car      Goat     Goat   Car
Car      Goat     Goat     Car    Goat

我们可以看到 2/3 的切换情况会导致赢得一辆车(前两排),如果我们留下来,1/3 会给车(最后一排)。

如果选手换车,则有 2/3 或 66.66%的概率获胜。

他们应该一直切换。

我们已经通过列举和计算解决了这个问题。

解决这个问题的另一种方法是计算主机开门的联合概率,以测试两种情况下的停留与切换决策,从而最大化期望结果的概率。

例如,假设参赛者选择了门 1,如果门 1 有车,我们可以计算主人打开门 3 的概率如下:

  • p(车门 1 =汽车,车门 3 =打开)= 1/3 * 1/2
  • = 0.333 * 0.5
  • = 0.166

然后,我们可以计算车门 2 让汽车和主机打开车门 3 的联合概率。这是不同的,因为如果门 2 包含汽车,主机只能打开门 3;它有 1.0 的概率,一个确定性。

  • p(车门 2 =汽车,车门 3 =打开)= 1/3 * 1
  • = 0.333 * 1.0
  • = 0.333

选择了门 1 和主机打开门 3 后,汽车在门 2 后面的概率(约 33%)高于门 1(约 16%)。我们应该换一下。

在这种情况下,我们应该切换到 2 号门。

或者,我们可以模拟主机打开门 2 的选择,它具有相同的概率结构:

  • p(车门 1 =汽车,车门 2 =打开)= 0.166
  • p(车门 3 =汽车,车门 2 =打开)= 0.333

同样,选择门 1 和主机打开门 2 后,汽车在门 3 后面的概率(约 33%)高于门 1(约 16%)。我们应该换一下。

如果我们寻求最大化这些概率,那么最好的策略是转换。

同样,在这个例子中,我们已经看到了如何克服我们错误的直觉,并通过列举案例和使用条件概率来解决问题。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

文章

摘要

在这篇文章中,你发现了如何通过解决经典的发人深省的问题来培养对概率的直觉。

具体来说,您了解到:

  • 如何用概率相乘来解决生日问题?
  • 如何用条件概率解决男孩或女孩问题?
  • 如何用联合概率求解蒙蒂霍尔问题?

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何利用概率开发和评估朴素分类器策略

原文:machinelearningmastery.com/how-to-deve…

最后更新于 2019 年 9 月 25 日

朴素分类器是一个简单的分类模型,它对问题的假设很少甚至没有,它的表现提供了一个基线,通过这个基线可以比较数据集上评估的所有其他模型。

有不同的策略可以用于朴素分类器,有些策略比其他策略更好,这取决于数据集和表现度量的选择。最常见的表现度量是分类准确率和常见的朴素分类策略,包括随机猜测类标签、从训练数据集中随机选择标签以及使用多数类标签。

开发一个小概率框架来计算给定朴素分类策略的预期表现,并进行实验来证实理论预期是有用的。这些练习为一般的朴素分类算法的行为以及为分类任务建立表现基线的重要性提供了直觉。

在本教程中,您将发现如何为机器学习开发和评估朴素分类策略。

完成本教程后,您将知道:

  • 朴素分类模型的表现提供了一个基线,通过这个基线,所有其他模型都可以被认为是熟练的或不熟练的。
  • 多数类分类器比其他朴素分类器模型(如随机猜测和预测随机选择的观察类标签)获得更好的准确性。
  • 朴素分类器策略可以通过 Sklearn 库中的 DummyClassifier 类用于预测建模项目。

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

How to Develop and Evaluate Naive Classifier Strategies Using Probability

如何使用概率开发和评估朴素分类器策略 图片由理查德·伦纳德提供,版权所有。

教程概述

本教程分为五个部分;它们是:

  1. 朴素分类器
  2. 预测随机猜测
  3. 预测随机选择的班级
  4. 预测多数阶级
  5. Sklearn 中的朴素分类器

朴素分类器

分类预测建模问题涉及预测给定模型输入的类别标签。

分类模型适用于训练数据集,并在测试数据集上进行评估,表现通常被报告为正确预测数与所做预测总数之比的一小部分,称为准确性。

给定一个分类模型,如何知道模型有没有技巧?

这是每个分类预测建模项目中常见的问题。答案是将给定分类器模型的结果与基线或原始分类器模型进行比较。

一个简单的分类器模型是一个不使用任何复杂程度来进行预测的模型,通常进行随机或恒定的预测。这种模型是幼稚的,因为它们没有使用任何关于该领域的知识或任何学习来进行预测。

分类任务中基线分类器的表现提供了问题中所有其他模型的预期表现的下限。例如,如果一个分类模型比一个简单的分类器表现得更好,那么它就有一些技巧。如果一个分类器模型的表现比朴素分类器差,那么它就没有任何技能。

幼稚分类器应该用什么分类器?

这是初学者常见的困惑领域,采用了不同的幼稚分类器。

一些常见的选择包括:

  • 预测一个随机类。
  • 从训练数据集中预测一个随机选择的类。
  • 从训练数据集中预测多数类。

问题是,并不是所有的幼稚分类器都是平等的,有些分类器的表现比其他分类器更好。因此,我们应该在所有的分类预测建模项目中使用表现最好的朴素分类器。

我们可以使用简单概率来评估不同朴素分类器模型的表现,并确定应该始终用作原生分类器的策略。

在我们开始评估不同的策略之前,让我们定义一个人为的两类分类问题。为了使其有趣,我们将假设每个类的观察数不相等(例如问题是不平衡的),0 类有 25 个例子,1 类有 75 个例子。

我们可以用下面列出的 Python 中的一个小例子来具体说明这一点。

# summarize a test dataset
# define dataset
class0 = [0 for _ in range(25)]
class1 = [1 for _ in range(75)]
y = class0 + class1
# summarize distribution
print('Class 0: %.3f' % (len(class0) / len(y) * 100))
print('Class 1: %.3f' % (len(class1) / len(y) * 100))

运行该示例会创建数据集,并汇总属于每个类的示例的分数,显示类 0 和类 1 的 25%和 75%,正如我们可能直观预期的那样。

Class 0: 25.000
Class 1: 75.000

最后,我们可以定义一个评估朴素分类策略的概率模型。

在这种情况下,我们感兴趣的是计算给定二分类模型的分类准确率。

  • P(yhat = y)

这可以计算为模型预测每个类别值的概率乘以观察每个类别出现的概率。

  • p(yhat = y)= p(yhat = 0)* p(y = 0)+p(yhat = 1)* p(y = 1)

这将计算模型在数据集上的预期表现。它提供了一个非常简单的概率模型,我们可以用它来计算一个简单分类器模型的预期表现。

接下来,我们将使用这个人为的预测问题来探索一个朴素分类器的不同策略。

预测随机猜测

也许最简单的策略是随机猜测每个所需预测的可用类别之一。

我们称之为随机猜测策略。

使用我们的概率模型,我们可以计算出这个模型在我们设计的数据集上的平均表现。

每个类的随机猜测是每个可能的类标签上的均匀概率分布,或者在两类问题的情况下,每个类的概率为 0.5。同样,我们知道数据集的类 0 和类 1 的值的预期概率,因为我们设计了这个问题;分别为 0.25 和 0.75。因此,我们计算该策略的平均表现如下:

  • p(yhat = y)= p(yhat = 0)* p(y = 0)+p(yhat = 1)* p(y = 1)
  • P(yhat = y) = 0.5 * 0.25 + 0.5 * 0.75
  • P(yhat = y) = 0.125 + 0.375
  • P(yhat = y) = 0.5

该计算表明,在我们设计的问题上预测一致随机类标签的表现是 0.5%或 50%的分类准确率。

这可能会令人惊讶,但这很好,因为它强调了系统地计算一个幼稚策略的预期表现的好处。

我们可以用一个小实验来证实这个估计是正确的。

该策略可以实现为一个函数,为每个所需的预测随机选择 0 或 1。

# guess random class
def random_guess():
	if random() < 0.5:
		return 0
	return 1

然后可以为数据集中所需的每个预测调用这个函数,并可以评估准确率

...
yhat = [random_guess() for _ in range(len(y))]
acc = accuracy_score(y, yhat)

这只是一次试验,但每次使用该策略的准确性都会有所不同。

为了解决这个问题,我们可以重复实验 1000 次,并报告策略的平均表现。我们希望平均表现与上面计算的预期表现相匹配。

下面列出了完整的示例。

# example of a random guess naive classifier
from numpy import mean
from numpy.random import random
from sklearn.metrics import accuracy_score

# guess random class
def random_guess():
	if random() < 0.5:
		return 0
	return 1

# define dataset
class0 = [0 for _ in range(25)]
class1 = [1 for _ in range(75)]
y = class0 + class1
# average performance over many repeats
results = list()
for _ in range(1000):
	yhat = [random_guess() for _ in range(len(y))]
	acc = accuracy_score(y, yhat)
	results.append(acc)
print('Mean: %.3f' % mean(results))

运行该示例执行了我们实验的 1000 次试验,并报告了策略的平均准确性。

鉴于算法的随机性,您的具体结果会有所不同。

在这种情况下,我们可以看到预期表现与计算表现非常接近。假设大数定律,我们进行的实验越多,我们的估计就越接近我们计算的理论值。

Mean: 0.499

这是一个很好的开始,但是如果我们在策略中使用一些关于训练数据集组成的基本信息呢。接下来我们将探讨这一点。

预测随机选择的班级

另一种简单的分类方法是以某种方式利用训练数据集。

也许最简单的方法是将训练数据集中的观察结果用作预测。具体来说,我们可以在训练集中随机选择观察值,并为每个请求的预测返回它们。

这是有意义的,我们可能期望训练数据集的这种原始使用会产生比随机猜测稍好的原始准确性。

我们可以通过使用我们的概率框架计算该方法的预期表现来找出答案。

如果我们从具有均匀概率分布的训练数据集中选择示例,我们将从每个类中抽取示例,它们在训练数据集中出现的概率相同。也就是说,我们将绘制概率为 25%的类-0 和概率为 75%的类-1 的示例。这也是模型独立预测的概率。

有了这些知识,我们可以将这些值插入概率模型。

  • p(yhat = y)= p(yhat = 0)* p(y = 0)+p(yhat = 1)* p(y = 1)
  • P(yhat = y) = 0.25 * 0.25 + 0.75 * 0.75
  • P(yhat = y) = 0.0625 + 0.5625
  • P(yhat = y) = 0.625

结果表明,使用从训练数据集中均匀随机选择的类作为预测比简单地在该数据集中预测均匀随机类产生更好的朴素分类器,显示 62.5%而不是 50%,或者 12.2%的提升。

还不错!

让我们用一个小模拟再次确认我们的计算。

下面的 random_class() 函数通过从训练数据集中选择并返回一个随机的类标签来实现这个朴素的分类器策略。

# predict a randomly selected class
def random_class(y):
	return y[randint(len(y))]

然后,我们可以使用上一节中的相同框架来评估模型 1000 次,并报告这些试验的平均分类准确率。我们希望这个经验估计值与我们的期望值相匹配,或者非常接近。

下面列出了完整的示例。

# example of selecting a random class naive classifier
from numpy import mean
from numpy.random import randint
from sklearn.metrics import accuracy_score

# predict a randomly selected class
def random_class(y):
	return y[randint(len(y))]

# define dataset
class0 = [0 for _ in range(25)]
class1 = [1 for _ in range(75)]
y = class0 + class1
# average over many repeats
results = list()
for _ in range(1000):
	yhat = [random_class(y) for _ in range(len(y))]
	acc = accuracy_score(y, yhat)
	results.append(acc)
print('Mean: %.3f' % mean(results))

运行该示例执行了我们实验的 1000 次试验,并报告了策略的平均准确性。

鉴于算法的随机性,您的具体结果会有所不同。

在这种情况下,我们可以看到预期表现再次与计算表现非常接近:模拟中为 62.4%,而我们上面计算的是 62.5%。

Mean: 0.624

在预测类别标签时,也许我们可以做得比均匀分布更好。我们将在下一节探讨这一点。

预测多数阶级

在前一节中,我们探索了一种策略,该策略基于训练数据集中观察到的标签的均匀概率分布来选择类别标签。

这使得预测的概率分布与观察到的每个类的概率分布相匹配,并且比类标签的均匀分布有所改进。尤其是这种不平衡数据集的一个缺点是,一个类在更大程度上被期望高于另一个类,并且随机预测类,甚至以有偏见的方式,导致太多不正确的预测。

相反,我们可以预测多数类,并确保达到至少与训练数据集中多数类的组成一样高的准确率。

也就是说,如果训练集中 75%的示例是类 1,并且我们为所有示例预测了类 1,那么我们知道我们至少会达到 75%的准确率,这比我们在上一节中随机选择的类有所提高。

我们可以通过使用我们的概率模型计算该方法的预期表现来证实这一点。

这种天真的分类策略预测类别 0 的概率是 0.0(不可能),预测类别 1 的概率是 1.0(确定)。因此:

  • p(yhat = y)= p(yhat = 0)* p(y = 0)+p(yhat = 1)* p(y = 1)
  • P(yhat = y) = 0.0 * 0.25 + 1.0 * 0.75
  • P(yhat = y) = 0.0 + 0.75
  • P(yhat = y) = 0.75

这证实了我们的预期,并表明在此特定数据集上,该策略将比以前的策略进一步提升 12.5%。

同样,我们可以通过模拟来证实这种方法。

多数类可以使用模式进行统计计算;也就是分布中最常见的观察。

可以使用模式()SciPy 功能。它返回两个值,第一个是我们可以返回的模式。下面的*more _ class()*函数实现了这个朴素的分类器。

# predict the majority class
def majority_class(y):
	return mode(y)[0]

然后,我们可以在设计好的数据集上评估策略。我们不需要重复多次实验,因为策略中没有随机成分,算法每次在相同的数据集上会给出相同的表现。

下面列出了完整的示例。

# example of a majority class naive classifier
from scipy.stats import mode
from sklearn.metrics import accuracy_score

# predict the majority class
def majority_class(y):
	return mode(y)[0]

# define dataset
class0 = [0 for _ in range(25)]
class1 = [1 for _ in range(75)]
y = class0 + class1
# make predictions
yhat = [majority_class(y) for _ in range(len(y))]
# calculate accuracy
accuracy = accuracy_score(y, yhat)
print('Accuracy: %.3f' % accuracy)

运行该示例会报告数据集上多数类朴素分类器的准确性。

准确性与 75%的概率框架计算的期望值和训练数据集的组成相匹配。

Accuracy: 0.750

这个多数类朴素分类器是应该用来计算分类预测建模问题的基线表现的方法。

它同样适用于具有相同数量的类别标签的数据集,以及具有两个以上类别标签的问题,例如多类别分类问题。

现在我们已经发现了表现最好的朴素分类器模型,我们可以看到如何在下一个项目中使用它。

Sklearn 中的朴素分类器

Sklearn 机器学习库提供了多数类朴素分类算法的实现,您可以在下一个分类预测建模项目中使用它。

它是作为dummy 分类器类的一部分提供的。

要使用朴素分类器,必须定义类,并将“策略”参数设置为“最频繁,以确保预测多数类。然后,该类可以适合训练数据集,并用于对测试数据集或其他重采样模型评估策略进行预测。

...
# define model
model = DummyClassifier(strategy='most_frequent')
# fit model
model.fit(X, y)
# make predictions
yhat = model.predict(X)

事实上,dummy 分类器是灵活的,允许使用另外两个朴素的分类器。

具体来说,将“策略”设置为“制服”将执行我们首先测试的随机猜测策略,将“策略”设置为“分层”将执行我们其次测试的随机选择类策略。

  • 随机猜测:将“战略论证设置为“制服”。
  • 选择随机类:将“策略参数设置为“分层”。
  • 多数类:将“战略论证设置为“最 _ 频繁”。

通过在我们设计的数据集上进行测试,我们可以确认 DummyClassifier 在多数类朴素分类策略下的表现符合预期。

下面列出了完整的示例。

# example of the majority class naive classifier in Sklearn
from numpy import asarray
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score
# define dataset
X = asarray([0 for _ in range(100)])
class0 = [0 for _ in range(25)]
class1 = [1 for _ in range(75)]
y = asarray(class0 + class1)
# reshape data for sklearn
X = X.reshape((len(X), 1))
# define model
model = DummyClassifier(strategy='most_frequent')
# fit model
model.fit(X, y)
# make predictions
yhat = model.predict(X)
# calculate accuracy
accuracy = accuracy_score(y, yhat)
print('Accuracy: %.3f' % accuracy)

运行该示例准备数据集,然后使用多数类策略在数据集上定义并拟合 DummyClassifier。

评估来自模型的预测的分类准确性证实了模型的表现如预期的那样,获得了 75%的分数。

Accuracy: 0.750

这个例子提供了一个起点,用于计算将来您自己的分类预测建模项目的朴素分类器基线表现。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

摘要

在本教程中,您发现了如何为机器学习开发和评估幼稚的分类策略。

具体来说,您了解到:

  • 朴素分类模型的表现提供了一个基线,通过这个基线,所有其他模型都可以被认为是熟练的或不熟练的。
  • 多数类分类器获得了比其他朴素分类器模型更好的准确性,例如随机猜测和预测随机选择的观察类标签。
  • 朴素分类器策略可以通过 Sklearn 库中的 DummyClassifier 类用于预测建模项目。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

机器学习的信息增益和互信息

原文:machinelearningmastery.com/information…

最后更新于 2020 年 12 月 10 日

信息增益计算通过某种方式转换数据集所带来的熵减少或惊喜。

它通常用于从训练数据集中构建决策树,方法是评估每个变量的信息增益,并选择最大化信息增益的变量,从而最小化熵,并最好地将数据集分成组以进行有效分类。

通过在目标变量的上下文中评估每个变量的增益,信息增益也可以用于特征选择。在这种略有不同的用法中,计算被称为两个随机变量之间的相互信息。

在这篇文章中,你将发现机器学习中的信息增益和互信息。

看完这篇文章,你会知道:

  • 信息增益是通过转换数据集来减少熵或惊喜,通常用于训练决策树。
  • 通过比较变换前后数据集的熵来计算信息增益。
  • 互信息计算两个变量之间的统计相关性,是应用于变量选择时信息增益的名称。

用我的新书机器学习概率启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2019 年 11 月更新:改进了信息/熵基础的描述(感谢 HR)。
  • 更新 2020 年 8 月:方程增加了漏括号(感谢大卫)

What is Information Gain and Mutual Information for Machine Learning

什么是机器学习的信息增益和互信息 摄影:朱塞佩·米洛,版权所有。

概观

本教程分为五个部分;它们是:

  1. 什么是信息增益?
  2. 计算信息增益的实例
  3. 机器学习中的信息获取示例
  4. 什么是相互信息?
  5. 信息获取和相互信息是如何相关的?

什么是信息增益?

信息增益(简称 IG)通过根据随机变量的给定值分割数据集来衡量熵的减少或惊喜。

较大的信息增益意味着较低的熵组或样本组,因此不那么令人惊讶。

你可能还记得信息用比特来量化一个事件有多令人惊讶。低概率事件信息多,高概率事件信息少。量化随机变量中有多少信息,或者更具体地说,它的概率分布。偏斜分布的熵较低,而事件概率相等的分布熵较大。

在信息论中,我们喜欢描述一个事件的“惊喜”。低概率事件更令人惊讶,因此具有更大的信息量。而事件具有相同可能性的概率分布更令人惊讶,并且具有更大的熵。

  • 偏斜概率分布 ( 不出所料):低熵。
  • 均衡概率分布 ( 惊人):高熵。

有关信息和熵的基础知识的更多信息,请参见教程:

现在,让我们考虑数据集的熵。

我们可以根据属于一个或另一个类别的数据集中的观测值的概率分布来考虑数据集的熵,例如在二进制类别数据集的情况下是两个类别。

信息论对熵的一种解释是,它规定了对 S 的任意成员(即以均匀概率随机抽取的 S 成员)的分类进行编码所需的最小信息位数。

—第 58 页,机器学习,1997。

例如,在二分类问题(两类)中,我们可以计算数据样本的熵,如下所示:

  • 熵= -(p(0) * log(P(0)) + p(1) * log(P(1)))

对于两个类,样本分割为 50/50 的数据集的最大熵(最大惊喜)为 1 位,而分割为 10/90 的不平衡数据集的熵较小,因为从数据集中随机抽取的示例的惊喜较小。

我们可以用 Python 中计算这个不平衡数据集熵的例子来演示这一点。下面列出了完整的示例。

# calculate the entropy for a dataset
from math import log2
# proportion of examples in each class
class0 = 10/100
class1 = 90/100
# calculate entropy
entropy = -(class0 * log2(class0) + class1 * log2(class1))
# print the result
print('entropy: %.3f bits' % entropy)

运行该示例,我们可以看到用于二进制分类的数据集的熵小于 1 位。也就是说,对数据集中任意示例的类标签进行编码所需的信息不到一位。

entropy: 0.469 bits

以这种方式,熵可以用作数据集纯度的计算,例如,类的分布碰巧有多平衡。

0 位的熵表示数据集包含一个类;1 位或更多位的熵表示平衡数据集的最大熵(取决于类的数量),介于两者之间的值表示这两个极端之间的级别。

信息增益提供了一种使用熵来计算数据集变化如何影响数据集纯度的方法,例如类的分布。较小的熵意味着更高的纯度或更少的惊喜。

……信息增益,简单来说就是根据这个属性对示例进行划分所导致的熵的预期减少。

—第 57 页,机器学习,1997。

例如,我们可能希望通过将数据集 S 拆分为一个具有一系列值的随机变量来评估对纯度的影响。

这可以计算如下:

  • IG(S,a)= H(S)–H(S | a)

其中 IG(S,a) 是数据集的信息 S 是随机变量 a 的信息, H(S) 是数据集在任何变化之前的熵(如上所述) H(S | a) 是给定变量 a 的数据集的条件熵。

该计算描述了变量 a 在数据集 S 中的增益,是转换数据集时保存的位数。

条件熵的计算方法是,针对 a 的每个观测值将数据集分成多个组,并计算整个数据集的每个组中的示例比率之和乘以每个组的熵。

  • H(S | a)= a Sa(v)中的和 v/S * H(Sa(v))

其中 Sa(v)/S 是数据集中样本数与变量 a 取值 v 的比值, H(Sa(v)) 是变量 a 取值 v 的样本组熵。

这听起来可能有点混乱。

我们可以用一个实例来具体说明信息增益的计算。

计算信息增益的实例

在本节中,我们将通过一个实例来具体说明信息增益的计算。

我们可以定义一个函数,根据属于类别 0 和类别 1 的样本的比率来计算一组样本的熵。

# calculate the entropy for the split in the dataset
def entropy(class0, class1):
	return -(class0 * log2(class0) + class1 * log2(class1))

现在,考虑一个包含 20 个示例的数据集,13 个用于类 0,7 个用于类 1。我们可以计算这个数据集的熵,它将少于 1 位。

...
# split of the main dataset
class0 = 13 / 20
class1 = 7 / 20
# calculate entropy before the change
s_entropy = entropy(class0, class1)
print('Dataset Entropy: %.3f bits' % s_entropy)

现在考虑数据集中的一个变量有两个唯一的值,比如“值 1 ”和“值 2 ”我们感兴趣的是计算这个变量的信息增益。

让我们假设,如果我们按值 1 分割数据集,我们有一组八个样本,七个用于类 0,一个用于类 1。然后我们可以计算这组样本的熵。

...
# split 1 (split via value1)
s1_class0 = 7 / 8
s1_class1 = 1 / 8
# calculate the entropy of the first group
s1_entropy = entropy(s1_class0, s1_class1)
print('Group1 Entropy: %.3f bits' % s1_entropy)

现在,让我们假设我们按值 2 分割数据集;我们有一组 12 个样本,每组 6 个。我们希望这个组的熵为 1。

...
# split 2  (split via value2)
s2_class0 = 6 / 12
s2_class1 = 6 / 12
# calculate the entropy of the second group
s2_entropy = entropy(s2_class0, s2_class1)
print('Group2 Entropy: %.3f bits' % s2_entropy)

最后,我们可以根据为变量的每个值创建的组和计算出的熵来计算这个变量的信息增益。

第一个变量产生了一组来自数据集的八个示例,第二组具有数据集中剩余的 12 个样本。因此,我们拥有计算信息增益所需的一切。

在这种情况下,信息增益可以计算为:

  • 熵(数据集)–(计数(组 1) /计数(数据集)*熵(组 1) +计数(组 2) /计数(数据集)*熵(组 2))

或者:

  • 熵(13/20,7/20)–(8/20 *熵(7/8,1/8) + 12/20 *熵(6/12,6/12))

或者用代码:

...
# calculate the information gain
gain = s_entropy - (8/20 * s1_entropy + 12/20 * s2_entropy)
print('Information Gain: %.3f bits' % gain)

将这些结合在一起,完整的示例如下所示。

# calculate the information gain
from math import log2

# calculate the entropy for the split in the dataset
def entropy(class0, class1):
	return -(class0 * log2(class0) + class1 * log2(class1))

# split of the main dataset
class0 = 13 / 20
class1 = 7 / 20
# calculate entropy before the change
s_entropy = entropy(class0, class1)
print('Dataset Entropy: %.3f bits' % s_entropy)

# split 1 (split via value1)
s1_class0 = 7 / 8
s1_class1 = 1 / 8
# calculate the entropy of the first group
s1_entropy = entropy(s1_class0, s1_class1)
print('Group1 Entropy: %.3f bits' % s1_entropy)

# split 2  (split via value2)
s2_class0 = 6 / 12
s2_class1 = 6 / 12
# calculate the entropy of the second group
s2_entropy = entropy(s2_class0, s2_class1)
print('Group2 Entropy: %.3f bits' % s2_entropy)

# calculate the information gain
gain = s_entropy - (8/20 * s1_entropy + 12/20 * s2_entropy)
print('Information Gain: %.3f bits' % gain)

首先,数据集的熵计算在略低于 1 位。然后,第一和第二组的熵分别在大约 0.5 和 1 比特处计算。

最后,变量的信息增益计算为 0.117 位。也就是说,通过所选变量拆分数据集获得的增益为 0.117 位。

Dataset Entropy: 0.934 bits
Group1 Entropy: 0.544 bits
Group2 Entropy: 1.000 bits
Information Gain: 0.117 bits

机器学习中的信息获取示例

也许在机器学习中,信息增益最常用的是在决策树中。

一个例子是迭代二分器 3 算法,简称 ID3,用于构建决策树。

信息增益正是 ID3 在树生长的每一步选择最佳属性时使用的度量。

—第 58 页,机器学习,1997。

为数据集中的每个变量计算信息增益。选择具有最大信息增益的变量来分割数据集。通常,较大的增益表示较小的熵或较小的惊喜。

请注意,最小化熵相当于最大化信息增益…

—第 547 页,机器学习:概率视角,2012。

然后对每个创建的组重复该过程,排除已经选择的变量。一旦到达所需的决策树深度或不可能再进行拆分,此操作就会停止。

现在为每个非终端后代节点重复选择新属性和划分训练示例的过程,这次仅使用与该节点相关联的训练示例。排除了树中较高的属性,因此任何给定的属性在树中的任何路径上最多只能出现一次。

—第 60 页,机器学习,1997。

在决策树的大多数现代实现中,信息增益可以用作拆分标准,例如在用于分类的决策树分类器类中的 Sklearn Python 机器学习库中实现分类和回归树(CART)算法。

这可以通过在配置模型时将标准参数设置为“”来实现;例如:

# example of a decision tree trained with information gain
from sklearn.tree import DecisionTreeClassifier
model = sklearn.tree.DecisionTreeClassifier(criterion='entropy')
...

信息增益也可用于建模前的特征选择。

它包括计算目标变量和训练数据集中每个输入变量之间的信息增益。 Weka 机器学习工作台通过信息增益属性评估类为特征选择提供信息增益的实现。

在这个特征选择的上下文中,信息增益可以被称为“互信息”,并计算两个变量之间的统计相关性。使用信息增益(互信息)进行特征选择的一个例子是互信息类函数

什么是相互信息?

互信息是在两个变量之间计算出来的,测量一个变量给定另一个变量的已知值时不确定性的减少。

一个叫做互信息的量衡量一个人从一个随机变量中获得的信息量。

—第 310 页,数据挖掘:实用机器学习工具与技术,2016 年第 4 版。

两个随机变量 XY 之间的相互信息可以正式表述如下:

  • 一(X;Y)= H(X)–H(X | Y)

其中I(X;Y)XY 的互信息, H(X) 是给定 YXH(X | Y) 的条件熵。结果有位的单位。

互信息是对两个随机变量之间的依赖或“T0”相互依赖的度量。因此,度量是对称的,意味着我(X;Y)= I(Y;X)

它衡量学习 y 的值所导致的 x 的不确定性的平均减少;反之亦然,x 传递的关于 y 的平均信息量。

—第 139 页,信息论、推理和学习算法,2003。

Kullback-Leibler,或 KL,散度是计算两个概率分布之间差异的度量。

互信息也可以计算为联合概率分布和每个变量的边缘概率乘积之间的 KL 散度。

如果变量不是独立的,我们可以通过考虑联合分布和边际的乘积之间的 kulback-Leibler 散度来获得关于它们是否“接近”独立的一些想法,这被称为变量之间的互信息

—第 57 页,模式识别与机器学习,2006。

这可以正式表述如下:

  • 一(X;Y) = KL(p(X,Y) || p(X) * p(Y))

互信息总是大于或等于零,其中值越大,两个变量之间的关系越大。如果计算结果为零,那么变量是独立的。

互信息通常用作相关系数的一般形式,例如随机变量之间相关性的度量。

它也被用作一些机器学习算法的一个方面。一个常见的例子是独立成分分析,简称独立成分分析,它提供数据集统计独立成分的投影。

信息获取和相互信息是如何关联的?

互信息和信息增益是同一件事,尽管措施的上下文或用法通常会产生不同的名称。

例如:

  • 转换到数据集(决策树)的效果:信息增益。
  • 变量之间的依赖(特征选择):互信息。

注意计算互信息的方式和计算信息增益的方式的相似性;它们是等价的:

  • 一(X;Y)= H(X)–H(X | Y)

  • IG(S,a)= H(S)–H(S | a)

因此,相互信息有时被用作信息增益的同义词。从技术上讲,如果应用于相同的数据,它们计算的数量是相同的。

我们可以把两者之间的关系理解为联合概率分布和边缘概率分布(互信息)的差异越大,信息的增益(信息增益)越大。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

应用程序接口

文章

摘要

在这篇文章中,你发现了机器学习中的信息增益和互信息。

具体来说,您了解到:

  • 信息增益是通过转换数据集来减少熵或惊喜,通常用于训练决策树。
  • 通过比较变换前后数据集的熵来计算信息增益。
  • 互信息计算两个变量之间的统计相关性,是应用于变量选择时信息增益的名称。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。