为何train()函数在for循环中无法运行?出现未定义列选择错误
解决caret::train()在for循环中报错及拟合指标图异常的问题
Hey,我来帮你搞定这个问题!你碰到的两个问题——循环报错和ggplot出直线,根源其实是同一个:公式里的循环变量d没有被正确解析。
先复现下你的问题场景:
你运行这段多项式回归调参代码时:
library(ISLR) attach(Wage) library(caret) set.seed(1) inTraining = createDataPartition(Wage$age, p = .75, list = FALSE) training = Wage[ inTraining,] testing = Wage[-inTraining,] fitControl <- trainControl(## 10-fold CV method = "repeatedcv", number = 10, repeats = 10) set.seed(2) degree = 1:10 RSquared = rep(0,10) RMSE = rep(0,10) for ( d in degree) { LinearRegressor <- train(wage ~ poly(age,d),data=training, method = "lm", trControl = fitControl) RSquared[d] <- LinearRegressor$results$Rsquared RMSE[d]<- LinearRegressor$results$RMSE } library(ggplot2) Degree.RegParams = data.frame(degree,RSquared,RMSE) ggplot(aes(x = degree,y = RSquared),data = Degree.RegParams) + geom_line() ggplot(aes(x = degree,y = RMSE),data = Degree.RegParams) + geom_line()
会弹出错误:
Error in `[.data.frame`(data, , all.vars(Terms), drop = FALSE) : undefined columns selected
而且最后画出来的R²和RMSE图都是直线,这是因为train()根本没正常完成拟合,RSquared和RMSE一直是初始的0值。
问题原因
当你在train()的公式里写poly(age,d)时,caret的公式解析器会把d当成training数据框里的列名来查找,但你的Wage数据里根本没有叫d的列,所以就会报“未定义列”的错误。同时,拟合过程异常中断,导致你记录的RSquared和RMSE都是初始的0,自然画出来是直线。
解决方案
我们需要动态生成公式,让循环变量d被解析成当前的数值,而不是列名。这里有两种简单的实现方式:
方式1:用reformulate()创建动态公式
for ( d in degree) { # 动态构建公式:wage ~ poly(age, 当前d值) fit_formula <- reformulate(paste0("poly(age, ", d, ")"), response = "wage") LinearRegressor <- train(fit_formula, data=training, method = "lm", trControl = fitControl) RSquared[d] <- LinearRegressor$results$Rsquared RMSE[d]<- LinearRegressor$results$RMSE }
方式2:拼接字符串后转成公式
for ( d in degree) { # 先把公式拼成字符串,再转成formula对象 formula_str <- paste0("wage ~ poly(age, ", d, ")") LinearRegressor <- train(as.formula(formula_str), data=training, method = "lm", trControl = fitControl) RSquared[d] <- LinearRegressor$results$Rsquared RMSE[d]<- LinearRegressor$results$RMSE }
验证效果
修复后重新运行代码,循环不会再报错,RSquared和RMSE会正确记录每个多项式阶数的交叉验证结果,最后用ggplot画出来的图会是符合预期的曲线(比如R²随阶数上升先提升后趋于平稳,RMSE先下降后平稳)。
内容的提问来源于stack exchange,提问作者nicholas heimpel
相关产品推荐
相关产品推荐

