R语言绘制岭回归MSE误差图时遇变量数不匹配错误的解决方法
错误原因及解决方法
错误根源
出现这个错误是因为你训练岭回归模型时用的是16个指定的数值变量,但计算验证集MSE时,model.matrix(Salary ~ ., data = valid)[,-1]会生成包含所有变量(包括分类变量生成的哑变量)的矩阵,变量数量远超过16个,导致模型无法匹配输入维度。此外,你还存在数据泄露问题:直接对整个数据集做了标准化,而正确的做法应该是用训练集的标准化参数去处理验证集。
完整修正步骤
1. 预处理数据(清理缺失值+拆分训练/验证集)
首先清理Hitters数据中的缺失值,再拆分训练集和验证集:
library(glmnet) library(caret) data(Hitters, package = "ISLR") # 移除Salary列有缺失值的行 Hitters_clean <- na.omit(Hitters) # 随机拆分训练集(70%)和验证集(30%) set.seed(123) # 保证结果可复现 train_idx <- sample(nrow(Hitters_clean), 0.7 * nrow(Hitters_clean)) train <- Hitters_clean[train_idx, ] valid <- Hitters_clean[-train_idx, ]
2. 选择一致的16个变量并标准化
确保训练集和验证集使用完全相同的16个变量,且仅用训练集的标准化参数处理验证集:
# 定义要使用的16个变量 feature_cols <- c("AtBat", "Hits", "HmRun", "Runs", "RBI", "Walks", "Years", "CAtBat", "CHits", "CHmRun", "CRuns", "CRBI", "CWalks", "PutOuts", "Assists", "Errors") # 提取训练集特征和标签 x_train <- train[, feature_cols] y_train <- train$Salary # 提取验证集特征和标签 x_valid <- valid[, feature_cols] y_valid <- valid$Salary # 对训练集做标准化,并保存标准化参数(均值、标准差) scaled_x_train <- scale(x_train) mean_train <- attr(scaled_x_train, "scaled:center") sd_train <- attr(scaled_x_train, "scaled:scale") # 用训练集的标准化参数处理验证集 scaled_x_valid <- scale(x_valid, center = mean_train, scale = sd_train)
3. 重新训练最优岭回归模型
基于标准化后的训练集重新训练模型:
lambda_seq <- 10^seq(10, -2, length = 100) # 交叉验证选择最优lambda cv_ridge <- cv.glmnet(scaled_x_train, y_train, alpha = 0, lambda = lambda_seq) lambda_optimal <- cv_ridge$lambda.min # 训练最优模型 ridge_model_optimal <- glmnet(scaled_x_train, y_train, alpha = 0, lambda = lambda_optimal)
4. 计算验证集MSE
现在可以正常计算验证集的MSE(或RMSE):
# 生成验证集预测结果 pred_ridge <- predict(ridge_model_optimal, newx = scaled_x_valid) # 计算MSE(均方误差) mse_ridge <- mean((pred_ridge - y_valid)^2) # 若需要RMSE(均方根误差),用caret包: rmse_ridge <- caret::RMSE(pred_ridge, y_valid) print(paste("验证集MSE:", round(mse_ridge, 2))) print(paste("验证集RMSE:", round(rmse_ridge, 2)))
5. 绘制MSE柱状图(示例)
如果要对比不同模型的MSE,可按以下方式绘制柱状图:
# 假设你还有其他模型的MSE结果,比如普通线性回归 lm_model <- lm(Salary ~ ., data = train[, c(feature_cols, "Salary")]) pred_lm <- predict(lm_model, newdata = valid) mse_lm <- mean((pred_lm - y_valid)^2) # 构建数据框 mse_df <- data.frame( Model = c("岭回归", "普通线性回归"), MSE = c(mse_ridge, mse_lm) ) # 绘制柱状图 barplot(mse_df$MSE, names.arg = mse_df$Model, col = c("#1f77b4", "#ff7f0e"), ylab = "均方误差(MSE)", main = "不同模型的验证集MSE对比")
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

