proportion_difference: 分类器的比例差异检验。
用于分类器性能比较的比例差异检验。
from mlxtend.evaluate import proportion_difference
概述
在实践中,有几种不同的统计假设检验框架用于比较分类模型的性能,包括常见的双比例差异法(这里,比例是测试集估计的泛化准确率),我们可以基于在第一部分中介绍的二项分布正态近似概念构建 95% 置信区间。
对两个总体比例进行 z 分数检验无疑是比较模型的***最直接***方法(但绝不是最好的方法!):简而言之,如果两个模型的准确率的 95% 置信区间不重叠,我们可以拒绝原假设,即两个分类器的性能在某个置信水平下是相同的。(或 5% 的概率)。撇开违反假设的情况不谈(例如测试集样本不是独立的),正如 Thomas Dietterich 在一项模拟研究 [1] 中基于经验结果所指出的那样,这项检验往往具有较高的假阳性率(在此处:错误地检测到差异,而实际上没有差异),这是不建议在实践中使用该检验的原因之一。
尽管如此,为了完整性,并且由于它在实践中是一种常用方法,下面概述了通用步骤(这也适用于后面介绍的不同假设检验)
- 制定要检验的假设(例如,原假设陈述比例相同;因此,如果我们使用双侧检验,则备择假设是比例不同);
- 确定显著性阈值(例如,如果观察到比实际观察到的更极端的差异的概率大于 5%,则我们计划拒绝原假设);
- 分析数据,计算检验统计量(此处:z 分数),并将其相关的 p 值(概率)与预先确定的显著性阈值进行比较;
- 根据 p 值和显著性阈值,在给定的置信水平下接受或拒绝原假设,并解释结果。
z 分数的计算方法是观察到的差异除以它们组合方差的平方根
其中是一个模型的准确率,而是从测试集估计的第二个模型的准确率。回想一下,我们在第一部分中计算了估计准确率的方差为
在第一部分中,然后计算了置信区间(正态近似区间)为其中用于 95% 置信区间。比较两个准确率估计的置信区间并检查它们是否重叠,类似于计算的比例差异值,并将概率(p 值)与选定的显著性阈值进行比较。因此,要直接计算两个比例差异的 z 分数,和,我们将这些比例合并(假设和是在大小为和的两个独立测试集上估计的两个模型的性能),
并计算标准差为
这样我们就可以计算 z 分数了,
由于使用相同的测试集(并违反独立性假设),我们有,因此我们可以将 z 分数的计算简化为
其中很简单就是.
第二步,根据计算出的值(这假设测试误差是独立的,但在实践中通常会违反,因为我们使用相同的测试集),我们可以在水平下拒绝原假设,即一对模型的性能相等(这里以“分类准确率”衡量),如果大于 1.96。或者如果我们想做额外的工作,我们可以计算标准正态累积分布在 z 分数阈值下的面积。如果我们发现这个 p 值小于我们在进行检验之前设定的显著性水平,那么我们可以在给定的显著性水平下拒绝原假设。
然而,这项检验的问题在于我们使用相同的测试集来计算两个分类器的准确率;因此,最好使用配对检验,例如配对样本 t 检验,但更稳健的替代方案是 McNemar 检验。
参考文献
- [1] Dietterich, Thomas G. "Approximate statistical tests for comparing supervised classification learning algorithms." Neural computation 10, no. 7 (1998): 1895-1923.
示例 1 - 比例差异
作为应用此检验的示例,考虑以下 2 个模型的预测结果
import numpy as np
## 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])
假设测试准确率如下所示
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
现在,设置显著性阈值为并进行检验
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)
计算比例差异检验的检验统计量和 p 值。
参数
-
proportion_1
: float第一个比例
-
proportion_2
: float第二个比例
-
n_1
: int第一个测试样本的样本大小
-
n_2
: int 或 None (默认值=None)第二个测试样本的样本大小。如果为
None
,则n_1
=n_2
。
返回值
-
z, p
: float 或 None, float返回 z 分数和 p 值
示例
有关使用示例,请参阅 https://mlxtend.cn/mlxtend/user_guide/evaluate/proportion_difference/