mcnemar: McNemar检验用于分类器比较

McNemar检验用于配对名义数据

> `from mlxtend.evaluate import mcnemar`

概述

麦克尼马尔检验 [1](有时也称为“组内卡方检验”)是一种用于配对名义数据的统计检验。在机器学习(或统计)模型的背景下,我们可以使用麦克尼马尔检验来比较两个模型的预测准确性。麦克尼马尔检验基于两个模型预测的 2×2 列联表。

McNemar的检验统计量

在McNemar检验中,我们提出零假设,即概率$p(b)$和$p(c)$是相同的,简而言之:两个模型的表现没有一个比另一个更好。因此,备择假设是两个模型的表现不相等。

McNemar检验统计量("卡方")可以按如下方式计算:

$$\chi^2 = \frac{(b - c)^2}{(b + c)},$$

如果单元格 c 和 b 的和足够大,则 $\chi^2$ 值遵循自由度为 1 的卡方分布。在设定显著性阈值,例如 $\alpha=0.05$ 后,我们可以计算 p 值——假设原假设为真,p 值是观察到这个经验(或更大)卡方值的概率。如果 p 值低于我们选择的显著性水平,我们可以拒绝原假设,即两个模型的性能相等。

连续性校正

在奎因·迈克尼马尔发表迈克尼马尔检验约1年后,爱德华兹提出了一种连续性校正版本,这也是今天更常用的变体:

$$\chi^2 = \frac{( \mid b - c \mid - 1)^2}{(b + c)}.$$

精确p值

如前所述,对于小样本量($b + c < 25$),建议使用精确的二项检验 [3],因为卡方值可能无法很好地被卡方分布所近似。精确的p值可以按如下方式计算:

$$p = 2 \sum^{n}_{i=b} \binom{n}{i} 0.5^i (1 - 0.5)^{n-i},$$

其中$n = b + c$,因子$2$用于计算双侧p值。

示例

例如,给定两种模型的准确率分别为99.7%和99.6%,一个2x2列联表可以提供更多关于模型选择的见解。

在子图A和B中,两个模型的预测准确率如下:

现在,在子图A中,我们可以看到模型2正确预测了11个模型1预测错误的情况。反之,模型2有1个预测正确,而模型1预测错误。因此,基于这个11:1的比率,我们可以得出结论,模型2的表现明显优于模型1。然而,在子图B中,比例为25:15,这对哪种模型是更好的选择不那么明确。

在接下来的代码示例中,我们将使用这两种情况A和B来说明McNemar检验。

参考文献

示例 1 - 创建 2x2 列联表

mcnemar 函数期望一个 2x2 的列联表,格式为 NumPy 数组,如下所示:

这样的列联矩阵可以通过使用 mlxtend.evaluate 中的 mcnemar_table 函数来创建。例如:

import numpy as np
from mlxtend.evaluate import mcnemar_table

# 正确的目标(类别)标签
y_target = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])

# 模型1预测的类别标签
y_model1 = np.array([0, 1, 0, 0, 0, 1, 1, 0, 0, 0])

# 模型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 - McNemar 检验用于情景 B

不,让我们继续概述部分提到的示例,并假设我们已经计算出了2x2列联表:

import numpy as np

tb_b = np.array([[9945, 25],
                 [15, 15]])

为了检验两个模型的预测性能是否相等(使用显著性水平 $\alpha=0.05$),我们可以进行校正的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值大于我们假设的显著性阈值($\alpha=0.05$),我们无法拒绝我们的零假设,假设这两个预测模型之间没有显著差异。

示例 3 - McNemar检验用于场景A

与场景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

假设我们以显著性水平 $\alpha=0.05$ 进行此测试,我们可以拒绝原假设,即这两个模型在该数据集上的表现相同,因为 p 值 ($p \approx 0.006$) 小于 $\alpha$。

API

mcnemar(ary, corrected=True, exact=False)

McNemar test for paired nominal data

Parameters

Returns

Examples

For usage examples, please see
[https://rasbt.github.io/mlxtend/user_guide/evaluate/mcnemar/](https://rasbt.github.io/mlxtend/user_guide/evaluate/mcnemar/)

ython