H2O AutoML 留一法的性能比 10 折交叉验证好得多

H2O AutoML leave-one-out performs too much better than 10-folds cross-validation

我有一个机器学习问题:88 个实例,2 个 classes("FR" class 的 40 个实例,"RF" class 的 48 个实例).我自己尝试了几种不同的算法,通过交叉验证和留一法评估结果,我无法达到超过 0.6 的准确度。这是 csv 格式的数据集的 link:https://drive.google.com/open?id=1lhCOP3Aywk4kGDEStAwL6Uq1H3twSJWS

尝试使用 10 折交叉验证的 H2O AutoML 我得到了大致相同的结果:cross-validation-leaderbord。 但是当我尝试留一法时,我出乎意料地得到了更好的结果:leave-one-out-leaderboard

我通过 fold_column 参数执行留一法验证,为每个实例分配不同的折叠,代码如下:

train <- read.csv("training_set.csv", header = TRUE)
train$ID <- seq.int(nrow(train))

# Identify predictors and response
y <- "class"
x <- setdiff(setdiff(names(train), y), "ID")

# For binary classification, response should be a factor
train[,y] <- as.factor(train[,y])

# Run AutoML for 20 base models 
aml <- h2o.automl(x = x, y = y,
                  fold_column = "ID",
                  keep_cross_validation_predictions = TRUE,
                  keep_cross_validation_fold_assignment = TRUE,
                  sort_metric = "logloss",
                  training_frame = as.h2o(train),
                  max_models = 20,
                  seed = 1)

# View the AutoML Leaderboard
lb <- aml@leaderboard
print(lb, n = nrow(lb))

首先,我不知道这是否是执行留一法的正确方法,我也尝试将 n_folds 设置为 88,但我得到的结果大致相同。 这里的信息在 aml@leader@model[["cross_validation_metrics"]]:

H2OBinomialMetrics: stackedensemble
** Reported on cross-validation data. **
** 88-fold cross-validation on training data (Metrics computed for combined holdout predictions) **

MSE:  0.1248958
RMSE:  0.353406
LogLoss:  0.4083967
Mean Per-Class Error:  0.075
AUC:  0.8635417
pr_auc:  0.7441933
Gini:  0.7270833

Confusion Matrix (vertical: actual; across: predicted) for F1-optimal threshold:
       FR RF    Error   Rate
FR     34  6 0.150000  =6/40
RF      0 48 0.000000  =0/48
Totals 34 54 0.068182  =6/88

Maximum Metrics: Maximum metrics at their respective thresholds
                        metric threshold    value idx
1                       max f1  0.712894 0.941176  53
2                       max f2  0.712894 0.975610  53
3                 max f0point5  0.712894 0.909091  53
4                 max accuracy  0.712894 0.931818  53
5                max precision  0.712894 0.888889  53
6                   max recall  0.712894 1.000000  53
7              max specificity  0.739201 0.975000   0
8             max absolute_mcc  0.712894 0.869227  53
9   max min_per_class_accuracy  0.715842 0.850000  46
10 max mean_per_class_accuracy  0.712894 0.925000  53

虽然这些信息看起来是一致的,但另一个让我觉得有问题的地方是上面的混淆矩阵和h2o.confusionMatrix(aml@leader)得到的混淆矩阵的区别:

Confusion Matrix (vertical: actual; across: predicted)  for max f1 @ threshold = 0.117307738035598:
       FR RF    Error    Rate
FR     18 22 0.550000  =22/40
RF      3 45 0.062500   =3/48
Totals 21 67 0.284091  =25/88

为什么两个混淆矩阵不同?他们不应该找到相同的 F1 最优阈值吗?

有什么不对吗?还是 Stacked Ensemble 更好?

  • 只有 88 个数据实例,存在过度拟合的风险。为确保您不会过度拟合,您应该将数据样本作为 holdout/test(model/training 不会看到)然后使用其余的进行训练和交叉验证。然后,您可以使用 holdout 数据查看它的性能是否与您从验证中发现的相似,并查看 LOO 是否更好。

针对您的问题:为什么这两个混淆矩阵不同?他们不应该找到相同的 F1 最优阈值吗?

  • 两个混淆矩阵都使用最大 F1 阈值。不同的可能是dataset是用来计算F1的。您可以在 table "Maximum Metrics: Maximum metrics at their respective thresholds."

  • 的第一行看到阈值
  • aml@leader@model[["cross_validation_metrics"]] 看起来正在使用验证数据,而 h2o.confusionMatrix(aml@leader) 正在使用训练数据。你可以尝试 aml@leader@model[["training_metrics"]] 看看它是否匹配 h2o.confusionMatrix(aml@leader).

这里发生了很多事情(我同意 Neema 关于过度拟合的评论)。正如他还提到的,您看到的主要问题是您正在将交叉验证指标与培训指标进行比较。 h2o.confusionMatrix() 函数(以及所有指标效用函数)默认 return 训练误差。

但是,我认为 h2o.confusionMatrix() 函数存在错误,因为它不允许 xval = TRUE 参数(通常 return 任何 H2O 指标中的 CV 指标功能)。我提交了错误报告 here