使用 caret 包和 R 绘制学习曲线

Posted

技术标签:

【中文标题】使用 caret 包和 R 绘制学习曲线【英文标题】:Plot learning curves with caret package and R 【发布时间】:2013-12-20 16:07:06 【问题描述】:

我想研究模型调整的偏差/方差之间的最佳权衡。我在 R 中使用插入符号,它允许我根据模型的超参数(mtry、lambda 等)绘制性能指标(AUC、准确度...)并自动选择最大值。这通常会返回一个好的模型,但如果我想进一步挖掘并选择不同的偏差/方差权衡,我需要一个学习曲线,而不是性能曲线。

为了简单起见,假设我的模型是一个随机森林,它只有一个超参数“mtry”

我想绘制训练集和测试集的学习曲线。像这样的:

(红色曲线为测试集)

在 y 轴上,我放置了一个错误度量(错误分类示例的数量或类似的东西);在 x 轴“mtry”或训练集大小上。

问题:

    是否具有插入符号以根据不同大小的训练集折叠迭代训练模型的功能?如果我必须手动编码,我该怎么做?

    如果我想将超参数放在 x 轴上,我需要使用 caret::train 训练的所有模型,而不仅仅是最终模型(在 CV 之后获得最大性能的模型)。这些“废弃”的模型在训练后是否仍然可用?

【问题讨论】:

见:topepo.github.io/caret/… 【参考方案1】:

这是我在使用Caret 包训练您的模型时如何处理在R 中绘制学习曲线的问题的代码。我在 R 中使用 Motor Trend Car Road Tests 进行说明。首先,我将mtcars 数据集随机化并拆分为训练集和测试集。 21 条训练记录和 13 条测试集记录。在此示例中,响应功能为 mpg

# set seed for reproducibility
set.seed(7)

# randomize mtcars
mtcars <- mtcars[sample(nrow(mtcars)),]

# split iris data into training and test sets
mtcarsIndex <- createDataPartition(mtcars$mpg, p = .625, list = F)
mtcarsTrain <- mtcars[mtcarsIndex,]
mtcarsTest <- mtcars[-mtcarsIndex,]

# create empty data frame 
learnCurve <- data.frame(m = integer(21),
                     trainRMSE = integer(21),
                     cvRMSE = integer(21))

# test data response feature
testY <- mtcarsTest$mpg

# Run algorithms using 10-fold cross validation with 3 repeats
trainControl <- trainControl(method="repeatedcv", number=10, repeats=3)
metric <- "RMSE"

# loop over training examples
for (i in 3:21) 
    learnCurve$m[i] <- i
    
    # train learning algorithm with size i
    fit.lm <- train(mpg~., data=mtcarsTrain[1:i,], method="lm", metric=metric,
             preProc=c("center", "scale"), trControl=trainControl)        
    learnCurve$trainRMSE[i] <- fit.lm$results$RMSE
    
    # use trained parameters to predict on test data
    prediction <- predict(fit.lm, newdata = mtcarsTest[,-1])
    rmse <- postResample(prediction, testY)
    learnCurve$cvRMSE[i] <- rmse[1]


pdf("LinearRegressionLearningCurve.pdf", width = 7, height = 7, pointsize=12)

# plot learning curves of training set size vs. error measure
# for training set and test set
plot(log(learnCurve$trainRMSE),type = "o",col = "red", xlab = "Training set size",
          ylab = "Error (RMSE)", main = "Linear Model Learning Curve")
lines(log(learnCurve$cvRMSE), type = "o", col = "blue")
legend('topright', c("Train error", "Test error"), lty = c(1,1), lwd = c(2.5, 2.5),
       col = c("red", "blue"))

dev.off()

输出图如下图:

【讨论】:

谢谢!!这正是我想要的。【参考方案2】:

可能在提出这个问题之后,插入符号包添加了 learning_curve_dat 函数,该函数有助于评估模型在一系列训练集大小上的性能。

这是函数文档中的示例:

library(caret)
set.seed(1412)
class_dat <- twoClassSim(1000)

set.seed(29510)
lda_data <- learning_curve_dat(dat = class_dat, 
                               outcome = "Class",
                               test_prop = 1/4, 
                               ## `train` arguments:
                               method = "lda", 
                               metric = "ROC",
                               trControl = trainControl(classProbs = TRUE, 
                                                        summaryFunction = twoClassSummary))

ggplot(lda_data, aes(x = Training_Size, y = ROC, color = Data)) + 
  geom_smooth(method = loess, span = .8)

针对每个 Training_Size 找到性能指标,并与数据变量(“重采样”、“训练”和可选的“测试”)一起保存在 lda_data 中。

这里是函数文档的链接:https://rdrr.io/cran/caret/man/learning_curve_dat.html

需要明确的是,这回答了问题的第一部分,而不是第二部分。

注意 至少在 2020 年 8 月之前,插入符号包代码和文档中存在拼写错误。在更正为 learning_curve_dat 之前,函数调用是 learing_curve_dat。我已经更新了我的答案以反映这一变化。确保您使用的是最新版本的 caret 包。

【讨论】:

我一直在摸索为什么这个函数不起作用,我注意到插入符包中有一个错字,拼写为learing_curve_dat(),而不是learning_curve_dat() 好地方!我已经更新了我的答案。感谢您的评论。 拼写错误现已修正。 @SimonWoodward 感谢更新 learing_curve_dat 拼写修复。【参考方案3】:

    如果您设置 trainControl() 函数和参数(例如 mtry)使用 tuneGrid()。 然后将这两个作为控制选项传递给train() 功能。 tuneGrid 参数的细节(例如 mtry、ntree)对于每个参数都会有所不同 模型类型。

    是的,最终的 trainFit 模型将包含 CV 所有折叠的错误率(无论您如何指定)。

所以你可以指定例如10 倍 CV 乘以具有 10 个 mtry 值的网格 - 这将是 100 次迭代。你可能想去喝杯茶或午餐。

如果这听起来很复杂...there is a very good example here - caret 是最好的文档包之一。

【讨论】:

Tnx 为您解答,但我仍有疑问。我需要的是 不是 迭代训练 CV 的不同折叠(boostrap,...),而是用训练集的不同子集模拟整个 train() 过程(包括 CV 等)( 10%、20%...100%)。基本上,我想估计更多的训练集大小是否会降低我的高方差。对于 2.,我需要改变超参数 mtry 的错误率,但如果我理解你的意思,trainFit 将计算不同 CV 折叠的错误率(而最后一个是所有的平均值,我想)跨度> 如果你想进行训练前拆分,然后使用createDataPartition 来创建几个不同的平衡训练集,例如train10、train20、train100,然后运行train,每个矩阵都有tuneGrid 选项.您甚至可能需要重复几次不同的抽奖 train10a、train10b、train10c 等。 据我所知,使用 tuneGrid 我可以指定要测试的每个超参数的范围。这很棒。然后,我将使用 createDataPartition 预拆分数据并使用循环(或类似的方法)调用 train() n 次。那么,只需要解决最后一个问题:如何获得变参数的错误率? @StephenHenderson 该链接已删除。我相信这就是 Max Kuhn 所指的the Caret package documentation @EkabaBisong 谢谢我已经编辑了原始答案以使用您建议的新链接。

以上是关于使用 caret 包和 R 绘制学习曲线的主要内容,如果未能解决你的问题,请参考以下文章

如何绘制从使用 R 中的“caret”包创建的随机森林中选择的树

在 R 中绘制由 caret 包训练的 SVM 线性模型

如何在 R(party-package)中绘制 cForest 的学习曲线?

R语言自定义变成进行决策曲线分析DCA曲线绘制(Decision Curve Analysis)

R语言使用caret包对GBM模型参数调优(自定义调优的评估指标,例如ROC指标):抽取预测标签及类概率抽样ROC的指标并绘制密度图

R语言绘制生存曲线95%区间