R:插入符号包预测导致无意义的预测的训练

问题描述

我在插入符号包predict.train函数中遇到了问题,该函数为我的“正控制”模型提供了一些随机预测(即应该给出相对较好的预测)。该问题在不同算法(“ glmnet”和“ rf”)中仍然存在。但是,当我使用最终的glmnet模型系数手动计算预测时,预测效果很好。

在这里,我做了一个例子:

模型设置:

## Define fitControl object
fitControl = trainControl(method = "cv",number = 5)
   
## Define tuneGrid
glmnet.tuneGrid = expand.grid(alpha = seq(from = 0,to = 1,by = 0.2),lambda = seq(from = 0,by = 0.2))

## Run inner CV
glmnet.fit = train(x = train[,x],y = train[,y],method = "glmnet",metric = "RMSE",trControl = fitControl,tuneGrid = glmnet.tuneGrid)

使用predict.train函数提取预测,并使用最佳模型系数进行手动计算:

## Predict in itest set
glmnet.preds = predict(glmnet.fit,newdata = test)
            
## Compute manual predictions
glmnet.coefs = coef(glmnet.fit$finalModel,s = glmnet.fit$bestTune$lambda)
manual.preds = as.vector(
glmnet.coefs[1,] + 
glmnet.coefs[2,]*test$t0_bdi_std + 
glmnet.coefs[3,]*test$sex_std + 
glmnet.coefs[4,]*test$age_std + 
glmnet.coefs[5,]*test$BMI_std)

如果我评估这些预测,则会得到不同的值:

> glmnet.preds
       3        6        7       17       20       23       27       37       38       47       54 
21.07649 18.32825 18.30302 19.02607 21.18579 21.91725 18.84951 21.46324 18.64773 21.30349 22.01814 
      56       66       67       69       74       77       88       89       92       98      104 
21.52209 21.44642 18.65614 21.18579 19.54734 19.67345 21.86680 20.96719 18.79066 21.03445 20.81586 
     108 
19.19422 
> manual.preds
 [1] 20.97291 17.80435 17.77912 15.64083 13.21352 17.52165 20.47162 18.85598 22.05817 15.11957 21.91455
[12] 18.55717 16.69316 17.05924 25.01654 27.60745 22.36856 18.54421 16.21393 19.69743 18.06953 18.56627
[23] 23.32000

我也获得了拟合指数和预测指数的差异。火车输出看起来是相对随机的,而手动预测则表现出预期:

> postResample(test[,glmnet.preds)
        RMSE     Rsquared          MAE 
13.665491040  0.004892648 11.756136481 
> postResample(test[,manual.preds)
      RMSE   Rsquared        MAE 
11.7743854  0.4606725 10.0398907 

一个有趣的旁注:我试图用模拟数据创建一个完全可重现的示例,但随后predict.train得出了相同的结果。

如果有人知道导致这些结果的原因以及解决方法,我会很好奇(非常感谢)。

系统信息:

  • R 版本:4.0.2
  • 插入符号版本:6.0-86

解决方法

由于未提供数据,所以无法知道计算是否正确。下面我使用一个示例数据集:

library(mlbench)
library(caret)

data(BostonHousing)
#exclude one factor column
tr_dat = BostonHousing[1:300,-4]
test_dat = BostonHousing[301:nrow(BostonHousing),-4]

fitControl = trainControl(method = "cv",number = 5)
   
glmnet.tuneGrid = expand.grid(alpha = seq(from = 0,to = 1,by = 0.2),lambda = seq(from = 0,by = 0.2))

glmnet.fit = train(x = tr_dat[,-ncol(tr_dat)],y = tr_dat[,ncol(tr_dat)],method = "glmnet",etric = "RMSE",trControl = fitControl,tuneGrid = glmnet.tuneGrid)

关卡预测:

pred_caret = predict(glmnet.fit,newdata=test_dat)

我们进行手动预测,因此您可以通过在系数和预测变量矩阵之间进行矩阵乘法%*%来获得它:

predictor = cbind(Intercept=1,as.matrix(test_dat[,-ncol(test_dat)]))
coef_m = as.matrix(coef(glmnet.fit$finalModel,s=glmnet.fit$bestTune$lambda))
pred_manual = predictor %*% coef_m

table(pred_manual == pred_caret)

TRUE 
 206 

您完全恢复原状