比例差异:分类器的比例差异检验。
分类器性能比较的比例差异检验。
> `from mlxtend.evaluate import proportion_difference`
概述
有几种不同的统计假设检验框架在实际中用于比较分类模型的性能,包括常用的方法如两个比例的差异(这里,比例是从测试集中估计的泛化准确度),我们可以基于第一部分中介绍的关于正态近似二项分布的概念构造95%的置信区间。
对于两个总体比例进行z-score检验无疑是比较模型最简单的方法(但绝对不是最佳的方法!):简单来说,如果两个模型的准确度的95%置信区间不重叠,我们可以在置信水平为$\alpha=0.05$(或5%的概率)时拒绝两个分类器性能相等的原假设。撇开假设违反不谈(例如测试集样本不独立),正如Thomas Dietterich根据模拟研究中的经验结果指出的[1],该检验往往具有较高的假阳性率(即在没有差异的情况下错误地检测到差异),这也是它在实践中不推荐使用的原因之一。
尽管如此,出于完整性的考虑,并且因为它在实际中是常用的方法,下面概述了基本的步骤(这也一般适用于后面提出的不同假设检验):
- 制定待检验的假设(例如,原假设指出比例相同;因此,如果我们使用双尾检验,则替代假设为比例不同);
- 决定显著性阈值(例如,如果观察到的差异比观察到的更极端的概率超过5%,那么我们计划拒绝原假设);
- 分析数据,计算检验统计量(这里是z-score),并将其相关的p值(概率)与先前确定的显著性阈值进行比较;
- 根据p值和显著性阈值,在给定的置信水平下接受或拒绝原假设,并解释结果。
z-score的计算公式为观察到的差异除以其合并方差的平方根:
$$ z = \frac{ACC_1 - ACC_2}{\sqrt{\sigma_{1}^2 + \sigma_{2}^2}}, $$ 其中$ACC_1$是一个模型的准确度,$ACC_2$是从测试集中估算的第二个模型的准确度。回想一下,我们计算估计准确度的方差为:
$$ \sigma^2 = \frac{ACC(1-ACC)}{n} $$
在第一部分中,然后计算置信区间(正态近似区间)为:
$$ ACC \pm z \times \sigma, $$ 其中$z=1.96$对应于95%的置信区间。比较两个准确度估计的置信区间并检查它们是否重叠则类似于计算两个比例差异的$z$值并将概率(p值)与所选显著性阈值进行比较。因此,为了直接计算两个比例的差异$ACC_1$和$ACC_2$的z-score,我们将这些比例进行汇总(假设$ACC_1$和$ACC_2$是从两个独立测试集大小为$n_1$和$n_2$估计的两个模型的性能),
$$ ACC_{1, 2} = \frac{ACC_1 \times n_1 + ACC_2 \times n_2}{n_1 + n_2}, $$
并计算标准差为
$$ \sigma_{1,2} = \sqrt{\frac{ACC_{1, 2} (1 - ACC_{1, 2})}{n_1 + n_2}}, $$
这样我们就可以计算z-score为:
$$ z = \frac{ACC_1 - ACC_2}{\sigma_{1,2}}. $$ 由于使用同一测试集(并违反独立性假设),我们有$n_1 = n_2 = n$,因此我们可以简化z-score计算为:
$$ z = \frac{ACC_1 - ACC_2}{\sqrt{2\sigma^2}} = \frac{ACC_1 - ACC_2}{\sqrt{2\cdot ACC_{1,2}(1-ACC_{1,2})/n}}. $$
其中$ACC_{1, 2}$就是$(ACC_1 + ACC_2)/2$。
在第二步中,基于计算得到的$z$值(这假设检验误差是独立的,通常在实际中是违反的,因为我们使用相同的测试集),如果$z$大于1.96,我们可以拒绝这对模型具有相等性能的原假设(这里是以“分类准确度”来衡量)在$\alpha=0.05$水平下。或者如果我们想做额外的工作,可以计算在z-score阈值下的标准正态累积分布的面积。如果我们发现这个p值小于我们在进行检验前设定的显著性水平,那么我们可以在给定的显著性水平下拒绝原假设。
但这个检验的问题在于我们使用相同的测试集来计算两个分类器的准确度;因此,使用配对检验如配对样本t检验可能会更好,但更稳健的替代方案是McNemar检验。
参考文献
- [1] Dietterich, Thomas G. "用于比较监督分类学习算法的近似统计检验。" 神经计算 10, no. 7 (1998): 1895-1923.
示例 1 - 比例的差异
作为应用此测试的一个示例,请考虑以下两个模型预测:
import numpy as np
# #数据集:
# 测试数据集的地面实况标签:
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])
假设测试准确率如下:
acc_1 = np.sum(y_true == y_model_1) / y_true.shape[0]
acc_2 = np.sum(y_true == y_model_2) / y_true.shape[0]
print('Accuracy Model 1:', acc_1)
print('Accuracy Model 2:', acc_2)
Accuracy Model 1: 0.84
Accuracy Model 2: 0.92
现在,设置显著性阈值为 $\alpha=0.05$ 并进行检验。
from mlxtend.evaluate import proportion_difference
z, p_value = proportion_difference(acc_1, acc_2, n_1=y_true.shape[0])
print('z: %.3f' % z)
print('p-value: %.3f' % p_value)
z: -1.754
p-value: 0.040
我们发现模型表现之间存在统计学上显著的差异。然而,值得强调的是,由于使用相同测试集的典型独立性违反以及其较高的假阳性率,因此在实践中不推荐使用此测试。
API
proportion_difference(proportion_1, proportion_2, n_1, n_2=None)
Computes the test statistic and p-value for a difference of proportions test.
Parameters
-
proportion_1
: floatThe first proportion
-
proportion_2
: floatThe second proportion
-
n_1
: intThe sample size of the first test sample
-
n_2
: int or None (default=None)The sample size of the second test sample. If
None
,n_1
=n_2
.
Returns
-
z, p
: float or None, floatReturns the z-score and the p-value
Examples
For usage examples, please see https://rasbt.github.io/mlxtend/user_guide/evaluate/proportion_difference/