mcnemar:用于分类器比较的 McNemar 检验
用于配对名义数据的 McNemar 检验
from mlxtend.evaluate import mcnemar
概述
McNemar 检验 [1](有时也称为“组内卡方检验”)是用于配对名义数据的统计检验。在机器学习(或统计)模型的背景下,我们可以使用 McNemar 检验来比较两个模型的预测准确率。McNemar 检验基于两个模型预测结果的 2x2 列联表。
McNemar 检验统计量
在 McNemar 检验中,我们提出零假设,即概率和相同,或者简单地说:两个模型中没有任何一个比另一个表现更好。因此,备择假设是两个模型的表现不相等。
McNemar 检验统计量(“卡方”)可以按如下方式计算
如果单元格 c 和 b 的总和足够大,则值遵循具有一个自由度的卡方分布。在设定显著性阈值(例如,)后,我们可以计算 p 值——假设零假设为真,p 值是观察到这个经验卡方值(或更大值)的概率。如果 p 值低于我们选择的显著性水平,我们可以拒绝两个模型表现相等的零假设。
连续性校正
在 Quinn McNemar 发表 McNemar 检验 [1] 大约一年后,Edwards [2] 提出了一个连续性校正版本,这是当今更常用的变体。
精确 p 值
如前所述,对于小样本量 ([3]),建议使用精确二项检验,因为卡方值可能无法很好地通过卡方分布来近似。精确 p 值可以按如下方式计算
其中,以及因子用于计算双侧 p 值。
示例
例如,给定两个模型具有 99.7% 和 99.6% 的准确率,一个 2x2 列联表可以为模型选择提供进一步的见解。
在子图 A 和 B 中,两个模型的预测准确率如下:
- 模型 1 准确率:9,960 / 10,000 = 99.6%
- 模型 2 准确率:9,970 / 10,000 = 99.7%
现在,在子图 A 中,我们可以看到模型 2 正确预测了模型 1 预测错误的 11 个样本。反之,模型 1 正确预测了模型 2 预测错误的 1 个样本。因此,基于 11:1 的比例,我们可能会得出结论,模型 2 表现明显优于模型 1。然而,在子图 B 中,比例是 25:15,这对于选择哪个模型更好没有那么明确的结论。
在下面的代码示例中,我们将使用这两个场景 A 和 B 来说明 McNemar 检验。
参考文献
- [1] McNemar, Quinn, 1947. "Note on the sampling error of the difference between correlated proportions or percentages". Psychometrika. 12 (2): 153–157.
- [2] Edwards AL: Note on the “correction for continuity” in testing the significance of the difference between correlated proportions. Psychometrika. 1948, 13 (3): 185-187. 10.1007/BF02289261.
- [3] https://en.wikipedia.org/wiki/McNemar%27s_test
示例 1 - 创建 2x2 列联表
mcnemar
函数期望一个 2x2 列联表作为 NumPy 数组,其格式如下
这样的列联矩阵可以使用 mlxtend.evaluate
中的 mcnemar_table
函数创建。例如
import numpy as np
from mlxtend.evaluate import mcnemar_table
# The correct target (class) labels
y_target = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
# Class labels predicted by model 1
y_model1 = np.array([0, 1, 0, 0, 0, 1, 1, 0, 0, 0])
# Class labels predicted by model 2
y_model2 = np.array([0, 0, 1, 1, 0, 1, 1, 0, 0, 0])
tb = mcnemar_table(y_target=y_target,
y_model1=y_model1,
y_model2=y_model2)
print(tb)
[[4 1]
[2 3]]
示例 2 - 场景 B 的 McNemar 检验
现在,让我们继续概述部分中提到的示例,并假设我们已经计算了 2x2 列联表
import numpy as np
tb_b = np.array([[9945, 25],
[15, 15]])
为了检验两个模型的预测性能相等的零假设(使用显著性水平为),我们可以进行校正后的 McNemar 检验来计算卡方值和 p 值,如下所示
from mlxtend.evaluate import mcnemar
chi2, p = mcnemar(ary=tb_b, corrected=True)
print('chi-squared:', chi2)
print('p-value:', p)
chi-squared: 2.025
p-value: 0.154728923485
由于 p 值大于我们假定的显著性阈值(),我们无法拒绝零假设,并假设两个预测模型之间没有显著差异。
示例 3 - 场景 A 的 McNemar 检验
与场景 B(示例 2)相反,场景 A 中的样本量相对较小 (b + c = 11 + 1 = 12),小于推荐的 25 [3],无法很好地通过卡方分布近似计算出的卡方值。
在这种情况下,我们需要从二项分布计算精确 p 值
from mlxtend.evaluate import mcnemar
import numpy as np
tb_a = np.array([[9959, 11],
[1, 29]])
chi2, p = mcnemar(ary=tb_a, exact=True)
print('chi-squared:', chi2)
print('p-value:', p)
chi-squared: None
p-value: 0.005859375
假设我们也以显著性水平为进行此检验,我们可以拒绝两个模型在该数据集上表现一样好的零假设,因为 p 值()小于.
API
mcnemar(ary, corrected=True, exact=False)
用于配对名义数据的 McNemar 检验
参数
-
ary
: array-like, shape=[2, 2]2 x 2 列联表(由 evaluate.mcnemar_table 返回),其中 a: ary[0, 0]: 两个模型都正确预测的样本数 b: ary[0, 1]: 模型 1 正确但模型 2 预测错误的样本数 c: ary[1, 0]: 模型 2 正确但模型 1 预测错误的样本数 d: aryCell [1, 1]: 两个模型都预测错误的样本数
-
corrected
: array-like, shape=[n_samples] (默认值: True)如果为
True
,则使用 Edward 的连续性校正计算卡方值 -
exact
: bool, (默认值: False)如果为
True
,则使用精确二项检验,将 b 与参数 n = b + c 且 p = 0.5 的二项分布进行比较。强烈建议在样本量小于 25 时使用exact=True
,因为卡方值无法很好地通过卡方分布来近似!
返回值
-
chi2, p
: float 或 None, float返回卡方值和 p 值;如果
exact=True
(默认值:False
),则chi2
为None
示例
For usage examples, please see
[https://mlxtend.cn/mlxtend/user_guide/evaluate/mcnemar/](https://mlxtend.cn/mlxtend/user_guide/evaluate/mcnemar/)
Python