paired_ttest_resample: 重采样配对 t 检验

重采样配对 t 检验过程,用于比较两个模型的性能

from mlxtend.evaluate import paired_ttest_resample

概述

重采样配对 t 检验过程(也称为 k 次留出配对 t 检验)是一种用于比较两个模型(分类器或回归器)性能的常用方法;然而,这种方法有许多缺点,不建议在实践中使用 [1],应改用 paired_ttest_5x2cv 等技术。

为了解释此方法如何工作,让我们考虑估计器(例如,分类器)A 和 B。此外,我们有一个带标签的数据集 D。在常见的留出法中,我们通常将数据集分割成两部分:训练集和测试集。在重采样配对 t 检验过程中,我们重复此分割过程(通常使用 2/3 的训练数据和 1/3 的测试数据) k 次(通常为 30 次)。在每次迭代中,我们在训练集上训练 A 和 B,并在测试集上评估它们的性能。然后,我们计算 A 和 B 在每次迭代中的性能差异,从而获得 k 个差异度量。现在,假设这 k 个差异是独立抽取且近似服从正态分布,我们可以根据 Student's t 检验,在模型 A 和 B 性能相等的零假设下,计算具有 k-1 个自由度的以下 t 统计量:

其中,计算模型性能的差异在第次迭代中,,并且代表分类器性能的平均差异,.

计算出 t 统计量后,我们可以计算 p 值并将其与我们选择的显著性水平进行比较,例如,。如果 p 值小于,则我们拒绝零假设,并接受这两个模型存在显著差异。

程序总结如下:

  1. i := 0
  2. while i < k
  3. 将数据集分割为训练子集和测试子集
  4. 在训练集上拟合模型 A 和 B
  5. 在测试集上计算 A 和 B 的性能
  6. 记录 A 和 B 之间的性能差异
  7. i := i + 1
  8. 计算 t 统计量
  9. 根据具有 k-1 个自由度的 t 统计量计算 p 值
  10. 将 p 值与选定的显著性阈值进行比较

这种方法的问题在于,它违反了 Student's t 检验的假设 [1],这也是不建议在实践中使用它的原因。

  • 模型性能的差异()不服从正态分布,因为不是独立的
  • 这些本身也不是独立的,因为测试集存在重叠;而且,测试集和训练集也存在重叠

参考文献

  • [1] Dietterich TG (1998) Approximate Statistical Tests for Comparing Supervised Classification Learning Algorithms. Neural Comput 10:1895–1923.

示例 1 - 重采样配对 t 检验

假设我们想要比较两种分类算法:逻辑回归和决策树算法

from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from mlxtend.data import iris_data
from sklearn.model_selection import train_test_split


X, y = iris_data()
clf1 = LogisticRegression(random_state=1)
clf2 = DecisionTreeClassifier(random_state=1)

X_train, X_test, y_train, y_test = \
    train_test_split(X, y, test_size=0.25,
                     random_state=123)

score1 = clf1.fit(X_train, y_train).score(X_test, y_test)
score2 = clf2.fit(X_train, y_train).score(X_test, y_test)

print('Logistic regression accuracy: %.2f%%' % (score1*100))
print('Decision tree accuracy: %.2f%%' % (score2*100))
Logistic regression accuracy: 97.37%
Decision tree accuracy: 94.74%

请注意,这些准确率值在配对 t 检验过程中未使用,因为在重采样过程中会生成新的测试/训练分割,上述值仅用于提供直观理解。

现在,假设我们选择的显著性阈值为,用于拒绝零假设(即两个算法在数据集上表现同样好),并进行配对样本 t 检验。

from mlxtend.evaluate import paired_ttest_resampled


t, p = paired_ttest_resampled(estimator1=clf1,
                              estimator2=clf2,
                              X=X, y=y,
                              random_seed=1)

print('t statistic: %.3f' % t)
print('p value: %.3f' % p)
t statistic: -1.809
p value: 0.081

由于,我们无法拒绝零假设,并可能得出结论:两个算法的性能没有显著差异。

虽然通常不建议多次应用统计检验而不进行多重假设检验校正,但让我们看一个示例,其中决策树算法被限制为产生非常简单的决策边界,从而导致相对较差的性能。

clf2 = DecisionTreeClassifier(random_state=1, max_depth=1)

score2 = clf2.fit(X_train, y_train).score(X_test, y_test)
print('Decision tree accuracy: %.2f%%' % (score2*100))


t, p = paired_ttest_resampled(estimator1=clf1,
                              estimator2=clf2,
                              X=X, y=y,
                              random_seed=1)

print('t statistic: %.3f' % t)
print('p value: %.3f' % p)
Decision tree accuracy: 63.16%
t statistic: 39.214
p value: 0.000

假设我们进行此检验时也使用了显著性水平,我们可以拒绝零假设(即两个模型在此数据集上表现同样好),因为 p 值()小于.

API

paired_ttest_resampled(estimator1, estimator2, X, y, num_rounds=30, test_size=0.3, scoring=None, random_seed=None)

实现重采样配对 t 检验过程,用于比较两个模型(也称为 k 次留出配对 t 检验)的性能。

参数

  • estimator1 : scikit-learn 分类器或回归器

  • estimator2 : scikit-learn 分类器或回归器

  • X : {array-like, 稀疏矩阵},形状 = [n_样本数, n_特征数]

    训练向量,其中 n_样本数 是样本数量,n_特征数 是特征数量。

  • y : array-like,形状 = [n_样本数]

    目标值。

  • num_rounds : int (默认值: 30)

    重采样迭代次数(即,训练/测试分割次数)

  • test_size : float 或 int (默认值: 0.3)

    如果为 float,应介于 0.0 和 1.0 之间,表示用于作为测试集的占数据集的比例。如果为 int,表示测试样本的绝对数量。

  • scoring : str, callable, 或 None (默认值: None)

    如果为 None (默认值),则对 scikit-learn 分类器使用 'accuracy',对 scikit-learn 回归器使用 'r2'。如果为 str,则使用 scikit-learn 评分指标字符串标识符,例如分类器的 {accuracy, f1, precision, recall, roc_auc},回归器的 {'mean_absolute_error', 'mean_squared_error'/'neg_mean_squared_error', 'median_absolute_error', 'r2'}。如果提供可调用对象或函数,必须符合 scikit-learn 的签名 scorer(estimator, X, y);有关更多信息,请参阅 https://scikit-learn.cn/stable/modules/generated/sklearn.metrics.make_scorer.html。

  • random_seed : int 或 None (默认值: None)

    用于创建测试/训练分割的随机种子。

返回值

  • t : float

    t 统计量

  • pvalue : float

    双侧 p 值。如果选择的显著性水平大于 p 值,则我们拒绝零假设,并接受两个比较模型之间存在显著差异。

示例

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