梯度提升机器精度随着迭代次数的增加而降低

机器算法验证 机器学习 插入符号 助推
2022-02-07 00:32:24

我正在通过caretR 中的包试验梯度提升机算法。

使用一个小型大学招生数据集,我运行了以下代码:

library(caret)

### Load admissions dataset. ###
mydata <- read.csv("http://www.ats.ucla.edu/stat/data/binary.csv")

### Create yes/no levels for admission. ### 
mydata$admit_factor[mydata$admit==0] <- "no"
mydata$admit_factor[mydata$admit==1] <- "yes"             

### Gradient boosting machine algorithm. ###
set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(5000,1000000,5000), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

令我惊讶的是,随着提升迭代次数的增加,模型的交叉验证准确度下降而不是增加,在约 450,000 次迭代时达到约 0.59 的最小准确度。

在此处输入图像描述

我是否错误地实现了 GBM 算法?

编辑:按照 Underminer 的建议,我重新运行了上面的caret代码,但专注于运行 100 到 5,000 次增强迭代:

set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(100,5000,100), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

结果图显示,准确度实际上在约 1,800 次迭代时达到接近 0.705 的峰值:

在此处输入图像描述

奇怪的是,准确度并没有稳定在 0.70 左右,而是在 5,000 次迭代后下降。

4个回答

您所展示的是过度拟合的经典示例。错误的小幅上升来自交叉验证数据集的验证部分的较差性能。更多的迭代几乎总是可以改善训练集的错误,但对于验证/测试集则相反。

一般来说,提升误差会随着迭代次数的增加而增加,特别是当数据有噪声时(例如错误标记的情况)。在不了解您的数据的情况下,我无法说这是否是您的问题

基本上,提升可以“专注于”正确预测包含错误信息的案例,并在此过程中降低其他更具实质性的案例的平均表现。

此链接(Boosting and Noise)显示了比我能提供的问题更好的描述。

Long 和 Servedio 的这篇论文(随机分类噪声)提供了该问题的更多技术细节。

重现类似结果的代码,无需网格搜索,

mod = gbm(admit ~ .,
      data = mydata[,-5],
      n.trees=100000,
      shrinkage=0.001,
      interaction.depth=2,
      n.minobsinnode=10,
      cv.folds=5,
      verbose=TRUE,
      n.cores=2)

best.iter <- gbm.perf(mod, method="OOB", plot.it=TRUE, oobag.curve=TRUE, overlay=TRUE)
print(best.iter)
[1] 1487
pred = as.integer(predict(mod, newdata=mydata[,-5], n.trees=best.iter) > 0)
y = mydata[,1]
sum(pred == y)/length(y)
[1] 0.7225

gbm 包具有估计最佳迭代次数(= 树数或基函数数)的功能,

gbm.perf(mod, method="OOB", plot.it=TRUE, oobag=TRUE, overlay=TRUE)

你不需要插入符号的火车。