GLM、GAM及逐步回归模型计算MSE出现NaN值的问题求助
R语言GLM、GAM及逐步回归模型MSE计算返回NaN的问题排查
核心错误点
1. RMSE计算引用不存在的目标变量列
你在计算RMSE时使用了test$target_variable,但目标变量实际是Salary,测试集test中并无target_variable这一列,导致实际值为NA,最终RMSE返回NaN。正确写法应为test$Salary。
2. 模型拟合未用处理过缺失值的数据
你先拟合了model_glm、gam_model和model_step,之后才对Hitters的缺失值进行填充。这意味着模型基于带缺失值的原始数据训练(glm和gam会自动删除含NA的行),但后续测试集用的是填充后的数据,两者样本量或数据分布可能不一致,引发预测异常。需先处理缺失值,再拟合模型。
3. 逐步回归模型未保存训练结果
你运行了step()函数但未将结果赋值给model_step,导致model_step仍是初始的截距模型lm(Salary ~ 1)。后续用该模型预测时,所有预测值都是Salary的均值,完全不符合需求。正确写法:
model_step <- step(model_glm, direction = "forward", scope = formula(model_glm), trace = 0)
4. 训练/测试集划分逻辑混乱
你先后用两种方式划分数据集:先通过sample()创建train和valid,又用createDataPartition()创建test,且两个过程数据源不一致(train/valid用标准化后的x,test用填充后的原始Hitters)。这种混乱会导致模型训练与预测的数据不匹配,建议统一划分逻辑,确保训练集和测试集的预处理(缺失值填充、标准化)一致。
5. 标准化操作未同步到模型与测试集
你对训练用的x做了标准化,但模型拟合用的是原始未标准化数据,后续测试集也未做标准化。若要使用标准化特征,需先对训练集做标准化,拟合模型后,测试集用训练集的均值和标准差进行标准化,避免特征尺度不一致导致的预测偏差。
修正后的示例代码片段
# 先处理缺失值 data(Hitters) Hitters[sapply(Hitters, is.numeric)] <- lapply(Hitters[sapply(Hitters, is.numeric)], function(x) { x[is.na(x)] <- mean(x, na.rm = TRUE) x}) # 划分数据集 set.seed(79511) library(caret) index <- createDataPartition(Hitters$Salary, p = 0.6, list = FALSE) train_data <- Hitters[index, ] temp <- Hitters[-index, ] index_val <- createDataPartition(temp$Salary, p = 0.5, list = FALSE) valid_data <- temp[index_val, ] test_data <- temp[-index_val, ] # 拟合GLM模型 vars <- c("AtBat", "Hits", "HmRun", "Runs", "RBI", "Walks", "Years", "CAtBat", "CHits", "CHmRun", "CRuns", "CRBI", "CWalks", "PutOuts", "Assists", "Errors", "Salary") model_glm <- glm(Salary ~ ., data = train_data[, vars], family = gaussian()) # 拟合GAM模型 library(mgcv) gam_model <- gam(Salary ~ s(AtBat) + s(Hits) + s(HmRun) + s(Runs) + s(RBI) + s(Walks) + s(Years) + s(CAtBat) + s(CHits) + s(CHmRun) + s(CRuns) + s(CRBI) + s(CWalks) + s(PutOuts) + s(Assists) + s(Errors), data = train_data, family = gaussian) # 拟合逐步回归模型 model_step_init <- lm(Salary ~ 1, data = train_data) model_step <- step(model_step_init, direction = "forward", scope = formula(model_glm), trace = 0) # 计算测试集RMSE mse_glm_test <- caret::RMSE(predict(model_glm, newdata = test_data), test_data$Salary) mse_gam_test <- caret::RMSE(predict(gam_model, newdata = test_data), test_data$Salary) mse_model_step_test <- caret::RMSE(predict(model_step, newdata = test_data), test_data$Salary)
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

