cochrans_q: Cochran's Q 检验,用于比较多个分类器

Cochran's Q 检验,用于比较多个分类器的性能。

from mlxtend.evaluate import cochrans_q

概览

Cochran's Q 检验可以视为 McNemar 检验的广义版本,可用于评估多个分类器。从某种意义上说,Cochran's Q 检验类似于 ANOVA 用于二元结果。

要比较两个以上的分类器,我们可以使用 Cochran's Q 检验,其检验统计量近似遵循(类似于 McNemar 检验)卡方分布,自由度为,其中 L 是我们评估的模型数量(因为对于 McNemar 检验,McNemar 检验统计量近似遵循自由度为 1 的卡方分布)。更为正式地,Cochran's Q 检验检验的假设是分类准确率之间没有差异 [1]

是一组分类器,它们都在相同的数据集上进行了测试。如果这 L 个分类器的表现没有差异,则以下 Q 统计量近似遵循自由度为的“卡方”分布此处,

是模型个对象中正确分类的对象数量。; 个分类器中正确分类对象的分类器数量,其中是用于测试分类器的测试数据集;并且个分类器中正确分类票数的总数 [2]

为了执行 Cochran's Q 检验,我们通常将分类器预测组织成一个二元矩阵。如果分类器错误分类了数据示例(向量),则此矩阵的条目为 0;否则为 1(如果分类器正确预测了类别标签)[2]。以下示例取自 [2],说明了如何组织分类结果。例如,假设我们有测试数据集的真实标签 y_true 以及 3 个分类器(y_model_1y_model_2y_model_3)的以下预测结果:

然后,正确 (1) 和不正确 (0) 分类的表格可能如下所示:

y_true = np.array([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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0])

y_model_1 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 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, 0, 0,
                      0, 0])

y_model_2 = np.array([1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      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, 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])

y_model_3 = np.array([1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      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, 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,
                      1, 1])

正确 (1) 和 错误 (0) 分类 的 表格 可能 会 如下 所示

(模型 1) (模型 2) (模型 3) 出现次数
1 1 1 80
1 1 0 2
1 0 1 0
1 0 0 2
0 1 1 9
0 1 0 1
0 0 1 3
0 0 0 3
准确率 84/100*100% = 84% 92/100*100% = 92% 92/100*100% = 92%

将相应的值代入前面的等式,我们得到以下值 [2]

(注意,[2] 中的值由于排印错误列为 3.7647,与作者讨论后,正确值为 7.5294。)

现在,Q 值(近似于)对应于近似 0.023 的 p 值,假设分布为自由度。假设我们选择的显著性水平为,我们将拒绝所有分类器表现相同的零假设,因为.

在实践中,如果我们成功拒绝了零假设,我们可以执行多个事后成对检验——例如,使用 Bonferroni 校正的 McNemar 检验——以确定哪些对的总体比例不同。

参考文献

  • [1] Fleiss, Joseph L., Bruce Levin, and Myunghee Cho Paik. Statistical methods for rates and proportions. John Wiley & Sons, 2013.
  • [2] Kuncheva, Ludmila I. Combining pattern classifiers: methods and algorithms. John Wiley & Sons, 2004.

示例 1 - Cochran's Q 检验

import numpy as np
from mlxtend.evaluate import cochrans_q
from mlxtend.evaluate import mcnemar_table
from mlxtend.evaluate import mcnemar

## Dataset:

# ground truth labels of the test dataset:

y_true = np.array([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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0])


# predictions by 3 classifiers (`y_model_1`, `y_model_2`, and `y_model_3`):

y_model_1 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 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, 0, 0,
                      0, 0])

y_model_2 = np.array([1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      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, 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])

y_model_3 = np.array([1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                      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, 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,
                      1, 1])

假设显著性水平,我们可以如下进行 Cochran's Q 检验,以检验分类准确率没有差异的零假设,:

q, p_value = cochrans_q(y_true, 
                        y_model_1, 
                        y_model_2, 
                        y_model_3)

print('Q: %.3f' % q)
print('p-value: %.3f' % p_value)
Q: 7.529
p-value: 0.023

由于 p 值小于,我们可以拒绝零假设并得出结论:分类准确率之间存在差异。正如引言中提到的,我们现在可以执行多个事后成对检验——例如,使用 Bonferroni 校正的 McNemar 检验——以确定哪些对的总体比例不同。

最后,让我们说明 Cochran's Q 检验确实只是 McNemar 检验的一个广义版本

chi2, p_value = cochrans_q(y_true, 
                           y_model_1, 
                           y_model_2)

print('Cochran\'s Q Chi^2: %.3f' % chi2)
print('Cochran\'s Q p-value: %.3f' % p_value)
Cochran's Q Chi^2: 5.333
Cochran's Q p-value: 0.021
chi2, p_value = mcnemar(mcnemar_table(y_true, 
                                      y_model_1, 
                                      y_model_2),
                        corrected=False)

print('McNemar\'s Chi^2: %.3f' % chi2)
print('McNemar\'s p-value: %.3f' % p_value)
McNemar's Chi^2: 5.333
McNemar's p-value: 0.021

API

cochrans_q(y_target, *y_model_predictions)

Cochran's Q 检验,用于比较 2 个或更多模型。

参数

  • y_target : array-like, shape=[n_samples]

    作为 1D NumPy 数组的真实类别标签。

  • *y_model_predictions : array-likes, shape=[n_samples]

    可变数量的 2 个或更多数组,包含模型预测的类别标签,作为 1D NumPy 数组。

返回值

  • q, p : float 或 None, float

    返回 Q (chi-squared) 值和 p 值

示例

有关使用示例,请参阅 https://mlxtend.cn/mlxtend/user_guide/evaluate/cochrans_q/