应用机器学习中的一个常见问题是确定输入特征是否与要预测的结果相关。
这就是特征选择的问题。
在分类问题中,当输入变量也是分类变量时,我们可以使用统计检验来确定输出变量是否与输入变量相关或独立。如果独立,那么输入变量就是可能与问题无关并应从数据集中移除的特征的候选。
Pearson 的卡方统计假设检验是检验分类变量之间独立性的一个例子。
在本教程中,您将了解用于量化成对分类变量独立性的卡方统计假设检验。
完成本教程后,您将了解:
- 成对的分类变量可以使用列联表进行汇总。
- 卡方检验可以比较观测到的列联表和期望的列联表,并确定分类变量是否独立。
- 如何在 Python 中计算和解释分类变量的卡方检验。
立即开始您的项目,阅读我的新书 机器学习统计学,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。
- 更新 2018 年 6 月:修订了对检验临界值解释中的小笔误(感谢 Andrew)。
- 更新 2019 年 10 月:修正了关于因子/水平的语言(感谢 Marc)。

机器学习卡方检验简明入门
照片作者:NC Wetlands,部分权利保留
教程概述
本教程分为3个部分;它们是
- 列联表
- Pearson 卡方检验
- 卡方检验示例
需要机器学习统计学方面的帮助吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
列联表
分类变量是可能取一组标签中的一个的变量。
一个例子是性别,可以概括为男性或女性。在这种情况下,变量或因子是‘性别’,变量的标签或水平是‘男性’和‘女性’。
我们可能希望查看分类变量相对于另一个分类变量的汇总。例如,性别和兴趣,其中兴趣可能具有‘科学’、‘数学’或‘艺术’等标签。我们可以收集关于这两个分类变量的观察结果;例如
1 2 3 4 5 6 |
性别,兴趣 男,艺术 女,数学 男,科学 男,数学 ... |
我们可以将收集到的观察结果汇总到一个表中,其中一个变量对应列,另一个变量对应行。表中的每个单元格对应于属于行和列类别的观察次数或频率。
历史上,这种形式的两个分类变量的表格汇总被称为列联表。
例如,以性别=行和兴趣=列的表格,包含人为的计数,可能如下所示:
1 2 3 |
科学,数学,艺术 男 20, 30, 15 女 20, 15, 30 |
该表由 Karl Pearson 命名为列联表,因为目的是帮助确定一个变量是否依赖于另一个变量。例如,对数学或科学的兴趣是否取决于性别,还是它们是独立的?
仅从表格中确定这一点具有挑战性;相反,我们可以使用一种称为 Pearson 卡方检验的统计方法。
Pearson 卡方检验
Pearson 卡方检验,或简称为卡方检验,以 Karl Pearson 命名,尽管该检验有变种。
卡方检验是一种统计假设检验,它假设(零假设)一个分类变量的观测频率与该分类变量的期望频率相匹配。该检验计算一个具有卡方分布的统计量,该分布以希腊字母 Chi(X)命名,发音为“ki”,如 kite。
以上面的性别/兴趣为例,一个类别的观察数量(例如男性和女性)可能相同,也可能不同。尽管如此,我们可以计算每个兴趣组中观察的期望频率,并查看按性别划分的兴趣是否导致相似或不同的频率。
卡方检验对列联表进行此操作,首先计算组的期望频率,然后确定组的划分(称为观测频率)是否与期望频率匹配。
检验的结果是一个具有卡方分布的检验统计量,可以解释为拒绝或不拒绝观测频率与期望频率相同的假设或零假设。
当观测频率与期望频率相差很大时,和中的相应项很大;当两者接近时,该项很小。X^2 的大值表示观测频率和期望频率相差很大。X^2 的小值则相反:观测频率接近期望频率。因此,X^2 确实测量了观测频率和期望频率之间的距离。
— 第 525 页,统计学,第四版,2007 年。
当观测频率和期望频率相似时,变量被认为是独立的,这意味着变量的水平不相互作用,也不依赖。
卡方独立性检验通过比较您收集到的分类编码数据(称为观测频率)与您期望仅凭偶然性在表格的每个单元格中获得的频率(称为期望频率)来进行。
— 第 162 页,通俗统计学,第三版,2010 年。
我们可以根据具有所需自由度的卡方分布来解释检验统计量,如下所示:
- 如果统计量 >= 临界值:结果显著,拒绝零假设(H0),表明相关。
- 如果统计量 < 临界值:结果不显著,不拒绝零假设(H0),表明独立。
卡方分布的自由度是根据列联表的大小计算的:
1 |
自由度:(行数 - 1) * (列数 - 1) |
就 p 值和选定的显著性水平(alpha)而言,该检验可以解释为:
- 如果 p 值 <= alpha:结果显著,拒绝零假设(H0),表明相关。
- 如果 p 值 > alpha:结果不显著,不拒绝零假设(H0),表明独立。
为了使检验有效,列联表中的每个单元格至少需要有五个观察值。
接下来,让我们看看如何计算卡方检验。
卡方检验示例
可以使用 Python 中的 chi2_contingency() SciPy 函数来计算 Pearson 的卡方独立性检验。
该函数接受一个数组作为输入,表示两个分类变量的列联表。它返回计算出的统计量和 p 值以供解释,以及计算出的自由度和期望频率表。
1 |
stat, p, dof, expected = chi2_contingency(table) |
我们可以通过从卡方分布中检索概率和自由度数量对应的临界值来解释统计量。
例如,可以使用 95% 的概率,这表明检验结果在测试变量独立的假设下是很有可能的。如果统计量小于或等于临界值,我们可以不拒绝此假设,否则可以拒绝。
1 2 3 4 5 6 7 |
# 解释检验统计量 prob = 0.95 critical = chi2.ppf(prob, dof) if abs(stat) >= critical: print('相关 (拒绝 H0)') else: print('独立 (不拒绝 H0)') |
我们还可以通过将 p 值与选择的显著性水平进行比较来解释 p 值,该水平将是 5%,这是通过反转临界值解释中使用的 95% 概率计算得出的。
1 2 3 4 5 6 |
# 解释 p 值 alpha = 1.0 - prob if p <= alpha: print('相关 (拒绝 H0)') else: print('独立 (不拒绝 H0)') |
我们可以将所有这些内容结合起来,并使用一个人为的列联表来演示卡方显著性检验。
下面定义了一个列联表,该表为每个总体(行)提供了不同数量的观察值,但跨每个组(列)的比例相似。鉴于比例相似,我们期望检验发现组是相似的,并且变量是独立的(不拒绝零假设,即 H0)。
1 2 |
table = [ [10, 20, 30], [6, 9, 17]] |
完整的示例如下所示。
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 |
# 具有相似比例的卡方检验 from scipy.stats import chi2_contingency from scipy.stats import chi2 # 列联表 table = [ [10, 20, 30], [6, 9, 17]] print(table) stat, p, dof, expected = chi2_contingency(table) print('dof=%d' % dof) print(expected) # 解释检验统计量 prob = 0.95 critical = chi2.ppf(prob, dof) print('probability=%.3f, critical=%.3f, stat=%.3f' % (prob, critical, stat)) if abs(stat) >= critical: print('相关 (拒绝 H0)') else: print('独立 (不拒绝 H0)') # 解释 p 值 alpha = 1.0 - prob print('significance=%.3f, p=%.3f' % (alpha, p)) if p <= alpha: print('相关 (拒绝 H0)') else: print('独立 (不拒绝 H0)') |
运行示例首先打印列联表。计算检验,并报告自由度(dof)为 2,这在
1 2 3 4 |
自由度:(行数 - 1) * (列数 - 1) 自由度:(2 - 1) * (3 - 1) 自由度:1 * 2 自由度:2 |
接下来,打印计算出的期望频率表,我们可以看到,通过目测检查数字,观测列联表确实与之匹配。
计算并解释了临界值,发现变量确实是独立的(不拒绝 H0)。p 值的解释也得出了相同的结论。
1 2 3 4 5 6 7 8 9 10 11 12 |
[[10, 20, 30], [6, 9, 17]] dof=2 [[10.43478261 18.91304348 30.65217391] [ 5.56521739 10.08695652 16.34782609]] probability=0.950, critical=5.991, stat=0.272 独立(不拒绝 H0) significance=0.050, p=0.873 独立(不拒绝 H0) |
扩展
本节列出了一些您可能希望探索的扩展本教程的想法。
- 更新卡方检验以使用您自己的列联表。
- 编写一个函数来报告给定两个分类变量的观测值的独立性。
- 加载包含分类变量的标准机器学习数据集,并报告每个变量的独立性。
如果您探索了这些扩展中的任何一个,我很想知道。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
书籍
API
文章
总结
在本教程中,您了解了用于量化成对分类变量独立性的卡方统计假设检验。
具体来说,你学到了:
- 成对的分类变量可以使用列联表进行汇总。
- 卡方检验可以比较观测到的列联表和期望的列联表,并确定分类变量是否独立。
- 如何在 Python 中计算和解释分类变量的卡方检验。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason,
感谢这篇很棒的文章。
应该使用哪种统计检验来检验连续变量对分类变量的依赖性(例如:体重和性别)?
祝好,
Elie
好问题。我没见过可以直接做到这一点的检验。
通常,将连续变量离散化/序数化,然后使用卡方检验。它会给出结果,但我不确定这在统计学上是否有效。
有没有办法只获取所有输入特征之间的相关性,但使用二进制值,即 0 和 1(从 true 和 false 转换而来)?
也许可以将输入特征转换为名义变量,例如离散的桶?
这是离散变量,例如:
df = pd.DataFrame({
‘y1’: [1,1,1,1,1,1,1,1,0,1,0,0],
‘y2’: [1,1,1,1,1,1,1,1,0,1,1,0],
y3: [0,1,0,0,0,1,0,0,0,1,1,0],
y4: [0,1,1,1,0,0,1,1,0,0,1,0],
})
这里 y1 和 y2 之间应该有很强的相关性。
这些都是特征(独立/输入变量)。没有一个目标变量。
有什么方法可以用来查找相关性吗?
请帮忙。
卡方检验可能是一个不错的起点。
卡方检验是关于输入和输出的,对吗?余弦相似度呢?我认为它会起作用。
卡方检验只关注两个分类变量。它们可以是模型输入或输出,也可以不是。
余弦相似度具体是指什么?
余弦相似度可以给出两个不同向量的相似度。在我上面的例子中,它会说 y1 和 y2 的相关性超过 95%。
详情请见:
https://en.wikipedia.org/wiki/Cosine_similarity
你好 Elie,
你可以试试分箱技术。请参阅下方:
http://www.saedsayad.com/binning.htm
希望有帮助:)
方差分析将适用于此。
2 样本 KS 检验(https://docs.scipy.org.cn/doc/scipy-0.14.0/reference/generated/scipy.stats.ks_2samp.html)
太棒了!
独立双样本 t 检验
https://en.wikipedia.org/wiki/Correlation_ratio
Jason,很棒的文章!一个小问题:上面的说法是否应该是:“如果统计量 > 临界值,则结果显著”和“如果统计量 <= 临界值,则结果不显著”?统计量的值和 p 值应该是成反比的。
是的,谢谢。那是说明中的一个笔误。已修复。
嗨,
如何在一个步骤中循环进行卡方检验,以检查目标变量与其他所有变量的关系?
并且会告诉我任何组合与目标的 p 值、dof 等信息?
我试过了,但没成功……
谢谢!
也许可以写一个 for 循环来检查所有变量?
我们如何进行卡方检验来找到与每个类别最相关的项?
也许可以计算每个项的检验,然后对结果进行排序?
非常有帮助,易于理解。非常感谢。
谢谢,很高兴对您有帮助。
写得真好!谢谢您的时间和文章!
谢谢,很高兴对您有帮助。
嗨,
我的数据集中有 3 个分类变量。
幸福感、收入和学历。
我需要找出以下内容:
进行了一项针对 2800 名客户的调查,涵盖了多项人口统计特征。其中捕获了劳动状况、性别、年龄、年龄组、种族、幸福感、子女数量、婚姻状况、教育程度、收入组等。(数据集:sample_survey.csv)。
a. 劳动状况与婚姻状况之间是否存在任何关系? b. 您认为教育程度在某种程度上控制着婚姻状况吗? c. 幸福感是由收入还是婚姻状况驱动的?
也许可以试试卡方检验?
如何在 python 中创建列联表?
看这里
https://statsmodels.cn/stable/contingency_tables.html
您也可以查看 pandas crosstab 函数 ~ https://pandas.ac.cn/pandas-docs/stable/reference/api/pandas.crosstab.html
感谢 Patrick 的提示。
很棒的内容!谢谢!
疑问
- 如果我理解正确,通过这个卡方检验,你可以说组别之间是否存在显著差异,但如果存在,如何找出具体是哪些组别?
例如:假设您设法拒绝了零假设。如何找出是哪个组别有显著差异?
我们是否必须对每个类别之间的多对 2x2 列联表应用 Fisher 精确检验?
谢谢!
您说的组别是指某个变量的类别吗?
例如:在您的示例中,您有 3 个被检验的类别:科学、数学和艺术。假设您的结果表明您有足够的证据拒绝零假设(变量是相关的)。但是,您如何知道是哪个(或所有)造成了这种结果?
让我们考虑另一个例子,您有 34 个类别(自由度 = 33)。您也设法拒绝了零假设。那么,您如何知道那 34 个类别中的哪些导致了最终结果(p <= alpha)?
是的,这是一个具有 3 种状态或事件的离散随机变量。
测试是对随机变量的评论,而不是对状态的评论。
这有帮助吗?
有人能为以下 4 个分类变量提供 Python 代码吗??
该表显示了婚姻状况与教育程度的列联表。使用卡方检验来检验同质性。婚姻状况与教育程度的列联表。
通过执行以下 Python 命令查看表格
from prettytable import PrettyTable
t = PrettyTable([‘婚姻状况’,’小学’, ‘中学’,’本科’,’硕士’,’博士’])
t.add_row([‘单身’,18,36,21,9,6])
t.add_row([‘已婚’,12,36,45,36,21])
t.add_row([‘离异’,6,9,9,3,3])
t.add_row([‘丧偶’,3,9,9,6,3])
print (t)
exit()
假设
零假设:从婚姻状况来看,教育水平类型之间的分布没有差异。
备择假设:存在差异
编码
1.从 scipy.stats 包导入 chi2_contingency 和 chi2。
2.使用婚姻状况与教育程度列联表中的值声明一个二维数组。
3.计算并打印以下值:
– 卡方统计量
– 自由度
– P 值
– 提示:使用 chi2_contigency() 函数
4.假设 alpha 值为 0.05
5.将 P 值与 alpha 进行比较,决定是否拒绝零假设。
– 如果拒绝,则打印“拒绝零假设”
– 否则,打印“未能拒绝零假设”
示例输出 2.33 4.5 8.9 拒绝零假设
看起来像是家庭作业。也许可以试试发到 Stack Overflow?
from scipy.stats import chi2_contingency
from scipy.stats import chi2
table= [ [18,31,21,9,6],[12,36,45,36,21], [6,9,9,3,3],[3,9,9,6,3] ]
stat,p,dof,expected = chi2_contingency(table)
prob = 0.95
critical = chi2.ppf(prob, dof)
if abs(p) <= 0.05
print(stat, dof ,p ,'Reject the Null Hypothesis')
else
print(stat, dof ,p ,'Failed to reject the Null Hypothesis')
输出
21.032858435297882 12 0.0499013559023993 拒绝零假设
需要帮助:请告诉我为什么输出不正确
我有一些建议可能会有所帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
你的表格显示“单身”行值为 18,36,21,9,6
而你的代码中是 18,*31*,21…
那个 31 应该是 36
感谢分享。
感谢您清晰的解释。
在文本中你说:“变量是‘性别’,该变量的标签或因子在这种情况下是‘男性’和‘女性’。”
你不是指:“变量或因子是‘性别’,变量的标签或水平在这种情况下是‘男性’和‘女性’”
参考:https://stattrek.com/statistics/dictionary.aspx?definition=factor
是的,你说得对。已修复,谢谢。
谢谢 Jason。这是一篇好文章。
不客气。
很棒的教程,谢谢!
我想知道如何进行卡方检验,其中调查受访者可以选择多个答案。
例如:您使用什么操作系统? A) Windows B) Linux C) Mac
结果:1000 人参加了调查,500 人说 Windows,400 人说 Mac,200 人说 Linux。总数大于受访者人数。
我可以通过创建以下列联表并运行检验来比较 Windows 和 Mac 吗?
操作系统,非操作系统
Mac 400, 600
Windows 500, 500
好问题,我一时之间不确定如何处理多选答案。这会扰乱列联表。
你可能需要查阅书籍或咨询统计学家/在 CrossValidated 上发帖。
嗨,Jason,
非常好的文章,清晰地解释了卡方检验。我有一个问题。当阅读 scikit-learn 特征选择使用卡方检验时(链接:https://scikit-learn.cn/stable/modules/feature_selection.html),我被这个例子搞糊涂了,在这个例子中,Iris 数据集被用来演示对非分类数据的卡方检验,它甚至不是频率或计数。这是否错误?
可能。
一篇写得非常清晰的文章。
谢谢!
嗨,Jason,
对于不平衡数据中坏账率仅为 1% 的自变量,卡方检验是否效果好?
我认为该检验要求列联表中每个单元格至少有 20 个样本。
谢谢。这是一个非常重要且非常实际的问题。你能提供更多见解吗?
我没有更多见解可给,也许可以查看“进一步阅读”部分的一些参考资料。
你好,Jason。
很棒的文章。我有一个问题。如果我们对样本数据集进行了卡方检验,并且两个分类变量之间的结果是相关的。那么这种“相关性”也可以说适用于总体吗?
是的,也否。这是一个统计估计。一个具有一定置信度的概率猜测。
谢谢 Jason,这是一篇好文章,信息量很大。
有时我会混淆卡方拟合优度检验和卡方独立性检验。我们是否可以将这两个术语互换使用,还是它们彼此不同?
我相信是相同的,只是用例不同。
谢谢 Jason 的澄清。
在 scipy 中,有两个不同的卡方函数:
1) scipy.stats.chisquare
2) scipy.stats.chi2_contingency
您介意告诉我每个函数分别用于什么用例吗?
也许可以查看 API 文档,看看哪个符合您的要求。
你好 JB,
你有没有探索过为什么 scikit-learn 的 chi2 在统计量和 p 值上给出与手工计算或使用 scipy 的 chi2_contingence 不同的值?
我找不到令人满意的答案,希望这位好医生(你)能提供一些见解。
谢谢
我没有。
嗨,
我刚开始接触这个领域。
我有 x_1、x_2 和 y。我该如何查看 y 对 x_1 和 x_2 的依赖性?
x=[[1,0],[1,0],[0,1],[1,1],[1,0],[1,0],[1,0],[1,1],[0,1],[0,1]]
y=[0,0,1,1,0,0,0,1,1,1]
为什么不使用上面的教程来计算依赖性呢?
你好!我是数据科学新手。想了解一下,在 A/B 测试中,我们如何决定使用哪种检验(卡方检验、单样本 t 检验、独立样本 t 检验、配对样本 t 检验)?
好问题,请看这个
https://machinelearning.org.cn/statistical-hypothesis-tests-in-python-cheat-sheet/
我不太明白为什么当分子很大时,我们会拒绝零假设。这意味着期望频率和观察频率之间存在巨大差异,但这并不意味着两个分类变量是相关的。提前感谢。
你好 Daniele,
在执行假设检验后,只有两种可能的结果。
当你的 p 值小于或等于你的显著性水平时,你拒绝零假设。数据支持备择假设。
当你的 p 值大于你的显著性水平时,你未能拒绝零假设。
以下内容应该能提供更多清晰的说明
https://www.statisticshowto.com/probability-and-statistics/hypothesis-testing/support-or-reject-null-hypothesis/
你好,感谢这篇精彩的文章。
chi2_contingency
的输入需要是包含出现次数/计数的表格,对吗?而不是频率百分比表格,对吗?
谢谢
你好 Makaros…以下内容可能有助于进一步阐明
https://towardsdatascience.com/chi-square-test-for-feature-selection-in-machine-learning-206b1f0b8223
嗨 James,
如何用 Python 代码报告卡方检验的效果量?
你好 Francisco…这个资源可能会对你有帮助
https://www.askpython.com/python/examples/chi-square-test
你好,
关于分类变量检验的一个问题,
我有一个用一些数据训练的模型,其中有一个分类变量,例如
purpose = [‘radio_television’, ‘new_car’, ‘furniture_equipment’, ‘used_car’, ‘business’]
在重新训练时,新数据在 purpose 列中有一个新值“education”
purpose = [‘radio_television’, ‘new_car’, ‘furniture_equipment’, ‘used_car’, ‘business’, ‘education’]
我应该进行什么检验来判断数据没有相同的分布,即数据发生了漂移?
提前感谢
你好,
对于二元分类模型,
旧模型和数据,用于用新数据重新训练相同的模型,
在数值字段上
例如:Salary 列,我们可以对旧数据和新数据之间的 Salary 列进行假设检验,以检查分布。
请问在旧数据和新数据的分类列(例如“Purpose”列)上应该进行什么检验?
非常感谢
嗨,Jason,
请问如果“观察列联表和期望列联表相同”,是否意味着变量是独立的?