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] Snedecor, George W. 和 Cochran, William G. (1989), Statistical Methods, 第八版, 爱荷华州立大学出版社。
- [2] Looney, Stephen W. "比较多个分类器准确性的统计技术。" 模式识别字母 8, no. 1 (1988): 5-9。
- [3] Kuncheva, Ludmila I. Combining pattern classifiers: methods and algorithms. 约翰·威利父子公司, 2004。
示例 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
-
y_target
: array-like, shape=[n_samples]True class labels as 1D NumPy array.
-
*y_model_predictions
: array-likes, shape=[n_samples]Variable number of 2 or more arrays that contain the predicted class labels from models as 1D NumPy array.
Returns
-
f, p
: float or None, floatReturns the F-value and the p-value
Examples
For usage examples, please see https://rasbt.github.io/mlxtend/user_guide/evaluate/ftest/