ftest: 分类器比较的F检验

用于比较多个分类器性能的F检验。

> `from mlxtend.evaluate import ftest`

概述

在评估机器学习模型的背景下,George W. Snedecor 的 F 检验 [1] 可以视为类似于 Cochran 的 Q 检验,后者可以用于评估多个分类器(即,它们在测试集上估计的准确性是否存在差异),如 Looney 所述 [2][3]。

更正式地,假设任务是检验原假设,即分类准确性之间没有差异 [1]:

$$p_i: H_0 = p_1 = p_2 = \cdots = p_L.$$

令 ${C_1, \dots , C_M}$ 为一组分类器,这些分类器都已在同一数据集上进行测试。如果这 $M$ 个分类器的表现没有差异,则 F 统计量服从自由度为 $(M-1)$ 和 $(M-1)\times n$ 的 F 分布,其中 $n$ 是测试集中的示例数量。F 统计量的计算由几个组成部分构成,具体如下(引用自 [2])。

我们首先定义 $ACC_{avg}$ 为不同模型的准确率平均值:

$$ACC_{avg} = \frac{1}{M}\sum_{j=1}^M ACC_j.$$

随后,分类器的平方和计算为:

$$ SSA = n \sum_{j=1}^{M} (G_j)^2 -n \cdot M \cdot ACC_{avg}, $$

其中 $G_j$ 是分类器 $j$ 正确分类的 $n$ 个示例的比例。

对象的平方和计算如下:

$$ SSB= \frac{1}{M} \sum_{j=1}^n (M_j)^2 - M\cdot n \cdot ACC_{avg}^2. $$

这里,$M_j$ 是在 $M$ 个分类器中正确分类对象 $\mathbf{x}j \in \mathbf{X}{n}$ 的分类器数量,其中 $$\mathbf{X}{n} = {\mathbf{x}_1, ... \mathbf{x}{n}}$$ 是对分类器进行测试的测试数据集。

最后,我们计算平方和的总和:

$$ SST = M\cdot n \cdot ACC_{avg} (1 - ACC_{avg}), $$

然后可以计算分类与对象交互的平方和:

$$ SSAB = SST - SSA - SSB. $$

为了计算 F 统计量,我们接下来计算平均 SSA 和平均 SSAB 值:

$$ MSA = \frac{SSA}{M-1}, $$

以及

$$ MSAB = \frac{SSAB}{(M-1) (n-1)}. $$

从 MSA 和 MSAB,我们可以计算 F 值:

$$ F = \frac{MSA}{MSAB}. $$

在计算出 F 值后,我们可以查找对应自由度的 F 分布表中的 p 值,或从累积分布 F 函数中计算得出。在实践中,如果我们在先前选择的显著性阈值下成功拒绝了原假设,我们可以进行多次事后成对检验——例如,使用 Bonferroni 校正的 McNemar 检验——以确定哪些对的总体比例不同。

参考文献

示例 1 - F 检验

import numpy as np
from mlxtend.evaluate import ftest

# #数据集:

# 测试数据集的地面实况标签:

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])


# 3个分类器(`y_model_1`、`y_model_2` 和 `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])

假设显著性水平 $\alpha=0.05$,我们可以进行Cochran的Q检验,如下所示,以检验原假设不存在分类准确率的差异,即 $p_i: H_0 = p_1 = p_2 = \cdots = p_L$:

f, p_value = ftest(y_true, 
                   y_model_1, 
                   y_model_2, 
                   y_model_3)

print('F: %.3f' % f)
print('p-value: %.3f' % p_value)

F: 3.873
p-value: 0.022

因为p值小于$\alpha$,我们可以拒绝原假设,并得出分类准确性之间存在差异的结论。如前面引言中提到的,我们现在可以进行多次事后成对检验——例如,进行带有Bonferroni校正的McNemar检验——以确定哪些对具有不同的总体比例。

API

ftest(y_target, y_model_predictions)*

F-Test test to compare 2 or more models.

Parameters

Returns

Examples

For usage examples, please see https://rasbt.github.io/mlxtend/user_guide/evaluate/ftest/