R:glmnet 的 caret::train 函数可以在固定的 alpha 和 lambda 交叉验证 AUC 吗?

Posted

技术标签:

【中文标题】R:glmnet 的 caret::train 函数可以在固定的 alpha 和 lambda 交叉验证 AUC 吗?【英文标题】:R: can caret::train function for glmnet cross-validate AUC at fixed alpha and lambda? 【发布时间】:2021-04-25 02:56:33 【问题描述】:

我想使用 caret::train 计算具有最佳 alpha 和 lambda 的弹性网络回归模型的 10 倍交叉验证 AUC

https://stats.stackexchange.com/questions/69638/does-caret-train-function-for-glmnet-cross-validate-for-both-alpha-and-lambda/69651 解释了如何使用caret::train 交叉验证 alpha 和 lambda

我关于 Cross Validated 的问题已结束,因为它已被归类为编程问题:https://stats.stackexchange.com/questions/505865/r-calculate-the-10-fold-crossvalidated-auc-with-glmnet-and-given-alpha-and-lamb?noredirect=1#comment934491_505865

我有什么

数据集:

library(tidyverse)
library(caret)
library(glmnet)
library(mlbench)

# example data
data(PimaIndiansDiabetes, package="mlbench")

# make a training set
set.seed(2323)
train.data <- PimaIndiansDiabetes

我的模特:

# build a model using the training set
set.seed(2323)
model <- train(
  diabetes ~., data = train.data, method = "glmnet",
  trControl = trainControl("cv",
                           number = 10,
                           classProbs = TRUE,
                           savePredictions = TRUE),
  tuneLength = 10,
  metric="ROC"
)

这里我得到了错误:

Warning message:
In train.default(x, y, weights = w, ...) :
  The metric "ROC" was not in the result set. Accuracy will be used instead.

如果我忽略错误,最好的 alpha 和 lambda 将是:

model$bestTune
   alpha      lambda
11   0.2 0.002926378

现在我想使用具有最佳 alpha 和 lambda 以及训练数据的模型获得 10 倍交叉验证的 AUC。

我尝试了什么

我的方法是这样的,但是,我得到了错误:Something is wrong; all the Accuracy metric values are missing:

model <- train(
  diabetes ~., data = train.data, method = "glmnet",
  trControl = trainControl("cv",
                           number = 10,
                           classProbs = TRUE,
                           savePredictions = TRUE),
  alpha=model$bestTune$alpha,
  lambda=model$bestTune$lambda,
  tuneLength = 10,
  metric="ROC"
)

如何使用最佳 alpha 和 lambda 以及训练数据计算交叉验证的 AUC?

我仍然不确定如何交叉验证 AUC 而不是准确性。

感谢您的帮助。

【问题讨论】:

如果从最后一段代码中删除tuneLength = 10 会发生什么? 谢谢。如果我删除它,我会收到警告消息:1: In train.default(x, y, weights = w, ...) : The metric "ROC" was not in the result set. Accuracy will be used instead. 2: model fit failed for Fold01: alpha=0.10, lambda=0.04967 Error in (function (x, y, family = c("gaussian", "binomial", "poisson", : formal argument "alpha" matched by multiple actual arguments 设置tuneGrid = data.frame(alpha = model$bestTune$alpha, lambda = model$bestTune$lambda),而不是tuneLength。但是这不是必需的,因为这些参数的 AUC 已经包含在您调整 alpha 和 lambda 的第一个调用中 - 请参阅model$results 谢谢。我误解了。我没有意识到,如果我针对 alpha 和 lambda 进行调整,并且如果我使用固定的 alpha 和 lambda 进行交叉验证,我实际上会得到相同的结果。最后一个问题,我刚刚意识到我选择的是准确度而不是 ROC 的最佳模型,因为我实际上打算这样做。我能以某种方式解决这个问题吗? 【参考方案1】:

您打算使用“ROC” - ROC 曲线下的区域来选择最佳调整参数,但您没有指定拥有此指标的twoClassSummary()。这就是警告的内容 通知你

Warning message:
In train.default(x, y, weights = w, ...) :
  The metric "ROC" was not in the result set. Accuracy will be used instead.

进行车削:

library(tidyverse)
library(caret)
library(glmnet)
library(mlbench)

data(PimaIndiansDiabetes, package="mlbench")

set.seed(2323)
train.data <- PimaIndiansDiabetes

set.seed(2323)
model <- train(
  diabetes ~., data = train.data, method = "glmnet",
  trControl = trainControl("cv",
                           number = 10,
                           classProbs = TRUE,
                           savePredictions = TRUE,
                           summaryFunction = twoClassSummary),
  tuneLength = 10,
  metric="ROC" #ROC metric is in twoClassSummary
)

由于您指定了classProbs = TRUEsavePredictions = TRUE,因此您可以根据预测计算任何指标。 计算精度:

model$pred %>%
  filter(alpha == model$bestTune$alpha,   #filter predictions for best tuning parameters
         lambda == model$bestTune$lambda) %>%
  group_by(Resample) %>% #group by fold
  summarise(acc = sum(pred == obs)/n()) #calculate metric
#output
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 2
   Resample   acc
   <chr>    <dbl>
 1 Fold01   0.740
 2 Fold02   0.753
 3 Fold03   0.818
 4 Fold04   0.776
 5 Fold05   0.779
 6 Fold06   0.753
 7 Fold07   0.766
 8 Fold08   0.792
 9 Fold09   0.727
10 Fold10   0.789

这为您提供了每折叠指标。获得平均性能

model$pred %>%
  filter(alpha == model$bestTune$alpha,
         lambda == model$bestTune$lambda) %>%
  group_by(Resample) %>%
  summarise(acc = sum(pred == obs)/n()) %>%
  pull(acc) %>%
  mean
#output
0.769566

当 ROC 用作选择指标时,超参数会针对所有决策阈值进行优化。在许多情况下,使用默认决策阈值 0.5 时,所选模型会表现不佳。

Caret 有一个函数thresholder()

它将根据超过指定决策阈值的重采样数据计算许多指标。

thresholder(model, seq(0, 1, length.out = 10)) #in reality I would use length.out = 100

#输出

alpha     lambda prob_threshold Sensitivity Specificity Pos Pred Value Neg Pred Value Precision Recall        F1 Prevalence Detection Rate Detection Prevalence Balanced Accuracy  Accuracy
1    0.1 0.03607775      0.0000000       1.000  0.00000000      0.6510595            NaN 0.6510595  1.000 0.7886514  0.6510595      0.6510595            1.0000000         0.5000000 0.6510595
2    0.1 0.03607775      0.1111111       0.994  0.02621083      0.6557464      0.7380952 0.6557464  0.994 0.7901580  0.6510595      0.6471463            0.9869617         0.5101054 0.6562714
3    0.1 0.03607775      0.2222222       0.986  0.15270655      0.6850874      0.8711111 0.6850874  0.986 0.8082906  0.6510595      0.6419344            0.9375256         0.5693533 0.6952837
4    0.1 0.03607775      0.3333333       0.964  0.32421652      0.7278778      0.8406807 0.7278778  0.964 0.8290127  0.6510595      0.6276316            0.8633459         0.6441083 0.7408578
5    0.1 0.03607775      0.4444444       0.928  0.47364672      0.7674158      0.7903159 0.7674158  0.928 0.8395895  0.6510595      0.6041866            0.7877990         0.7008234 0.7695147
6    0.1 0.03607775      0.5555556       0.862  0.59002849      0.7970454      0.7053968 0.7970454  0.862 0.8274687  0.6510595      0.5611928            0.7043575         0.7260142 0.7669686
7    0.1 0.03607775      0.6666667       0.742  0.75740741      0.8521972      0.6114289 0.8521972  0.742 0.7926993  0.6510595      0.4830827            0.5677204         0.7497037 0.7473855
8    0.1 0.03607775      0.7777778       0.536  0.90284900      0.9156149      0.5113452 0.9156149  0.536 0.6739140  0.6510595      0.3489918            0.3828606         0.7194245 0.6640636
9    0.1 0.03607775      0.8888889       0.198  0.98119658      0.9573810      0.3967404 0.9573810  0.198 0.3231917  0.6510595      0.1289474            0.1354751         0.5895983 0.4713602
10   0.1 0.03607775      1.0000000       0.000  1.00000000            NaN      0.3489405       NaN  0.000       NaN  0.6510595      0.0000000            0.0000000         0.5000000 0.3489405
       Kappa          J      Dist
1  0.0000000 0.00000000 1.0000000
2  0.0258717 0.02021083 0.9738516
3  0.1699809 0.13870655 0.8475624
4  0.3337322 0.28821652 0.6774055
5  0.4417759 0.40164672 0.5329805
6  0.4692998 0.45202849 0.4363768
7  0.4727251 0.49940741 0.3580090
8  0.3726156 0.43884900 0.4785352
9  0.1342372 0.17919658 0.8026597
10 0.0000000 0.00000000 1.0000000

现在根据您所需的指标选择一个阈值并使用它。通常用于不平衡数据的指标Cohen's Kappa、Youden's J 或Matthews correlation coefficient (MCC)。这是一个不错的paper。

请注意,由于此数据用于寻找最佳阈值,因此以这种方式获得的性能将存在乐观偏差。为了评估选择的决策阈值的性能,最好使用几个独立的测试集。换句话说,我建议使用嵌套重采样,您可以使用内部折叠优化参数和阈值并评估外部折叠。

Here is an explanation 关于如何使用带有插入符号的嵌套重采样和回归。需要进行一些修改以使其适用于具有优化阈值的分类。

请注意,这不是选择最佳决策阈值的唯一方法。另一种方法是先验地选择所需的度量(例如 MCC)并将决策阈值视为一个超参数,该超参数将与所有其他超参数一起调整。我相信插入符号不支持创建自定义模型。

【讨论】:

感谢您的回答。我有一些问题:您提出的调整没有选择给出最高 AUC 的模型参数(alpha 和 lambda),对吗?这有可能吗?如果是,我可以只计算每折的 AUC(就像你对 acc 所做的那样)并将平均值作为交叉验证的 AUC,对吗? 我建议的调整确实选择了产生最高 AUC 的 alpha 和 lambda。如果您计算每次折叠的 AUC 并对它们进行平均,您将获得与返回的 train 对象中插入符号相同的结果。 再次感谢您的回答。不幸的是,我仍在为嵌套重采样而苦苦挣扎。如果你有时间看看我的follow-up question,我将非常感谢!

以上是关于R:glmnet 的 caret::train 函数可以在固定的 alpha 和 lambda 交叉验证 AUC 吗?的主要内容,如果未能解决你的问题,请参考以下文章

R 理解来自 kernlab 的 caret train(tuneLength = ) 和 SVM 方法

caret::train:指定模型生成参数

R - Caret train()“错误:停止”,“并非在新数据中找到的对象中使用的所有变量名称”

运行 caret::train() 以开发 kknn 模型时的性能预期

Caret train 方法抱怨出问题了;缺少所有 RMSE 度量值

在 R 中加载 Lime 包时出现错误“对象‘coef.cv.glmnet’不是由‘namespace:glmnet’导出”-