R语言交叉验证及CV绘图失败,Lasso模型预测出错求助
汽车价格预测模型问题排查与解决方案
一、交叉验证CV Errors全为NaN问题
原因分析
- 循环内判断条件
sum(best.fit$which[i, ]) > 0逻辑错误:best.fit$which的行对应不同变量数的模型,列对应变量,该条件无法正确判断模型是否有效,导致大量循环未执行,cv.errors矩阵始终为NA。 - 数据集存在NA值:
scaled_train_df中的缺失值会导致模型拟合或预测失败,生成NaN。 - 哑变量不匹配:训练集和验证集的分类变量水平不一致,导致
predict.regsubsets函数生成的预测值为NA。
解决方案
修正循环判断逻辑
替换错误的判断条件,直接检查对应变量数的模型是否有系数:k <- 10 set.seed(42) folds <- sample(1:k, nrow(scaled_train_df), replace = TRUE) cv.errors <- matrix(NA, k, 10, dimnames = list(NULL, paste(1:10))) for (j in 1:k) { best.fit <- regsubsets(Pris ~ ., data = scaled_train_df[folds != j, ], nvmax = 10) for (i in 1:10) { # 检查对应变量数的模型是否存在有效系数 coef_i <- coef(best.fit, id = i) if (!is.null(coef_i)) { pred <- predict(best.fit, scaled_train_df[folds == j, ], id = i) actual <- scaled_train_df$Pris[folds == j] cv.errors[j, i] <- mean((actual - pred)^2, na.rm = TRUE) } } }清理数据集缺失值
移除或填充NA值,确保模型拟合正常:# 方式1:直接移除含NA的行 scaled_train_df <- na.omit(scaled_train_df) # 方式2:按变量类型填充NA(数值变量用均值,分类变量用众数) scaled_train_df$Miltal[is.na(scaled_train_df$Miltal)] <- mean(scaled_train_df$Miltal, na.rm = TRUE) scaled_train_df$Bränsle[is.na(scaled_train_df$Bränsle)] <- names(which.max(table(scaled_train_df$Bränsle)))同步分类变量水平
确保验证集的分类变量水平与训练集一致:# 同步所有分类变量的水平 for(col in c("Bränsle", "Växellåda", "Biltyp", "Drivning")){ scaled_train_df[[col]] <- as.factor(scaled_train_df[[col]]) # 若验证集是scaled_train_df的子集可跳过,否则需同步外部测试集 # scaled_test_df[[col]] <- factor(scaled_test_df[[col]], levels = levels(scaled_train_df[[col]])) }
二、Lasso模型预测变量数不匹配问题
原因分析
- 训练集与测试集的变量数不一致:训练Lasso时的
x矩阵和测试集x_test的变量数不同,通常是因为分类变量生成的哑变量数量不一致(比如训练集某分类变量有3个水平,测试集只有2个)。 model.matrix生成的矩阵未对齐:训练和测试的特征矩阵没有统一变量列,导致维度不匹配。
解决方案
统一特征矩阵生成方式
基于训练集的变量列生成测试集的特征矩阵,确保维度一致:# 生成训练集特征矩阵(去掉截距列) x_train <- model.matrix(Pris ~ ., data = scaled_train_df)[, -1] y_train <- scaled_train_df$Pris # 同步测试集分类变量水平 for(col in c("Bränsle", "Växellåda", "Biltyp", "Drivning")){ scaled_test_df[[col]] <- factor(scaled_test_df[[col]], levels = levels(scaled_train_df[[col]])) } # 生成测试集特征矩阵,仅保留训练集存在的变量 x_test <- model.matrix(Pris ~ ., data = scaled_test_df)[, colnames(x_train)] # 重新训练Lasso并预测 grid <- 10^seq(10, -2, length = 100) lasso.mod <- glmnet(x_train, y_train, alpha = 1, lambda = grid) set.seed(42) cv.out <- cv.glmnet(x_train, y_train, alpha = 1) bestlam <- cv.out$lambda.min lasso.pred <- predict(lasso.mod, newx = x_test, s = bestlam)解决绘图警告
collapsing to unique 'x' values是因为lambda值重复,生成唯一的lambda序列即可:grid <- unique(10^seq(10, -2, length = 100)) # 去重lambda值 lasso.mod <- glmnet(x_train, y_train, alpha = 1, lambda = grid) plot(lasso.mod)修复均方误差计算
确保预测值生成后再执行逆缩放:# 逆缩放计算真实均方误差 pred <- lasso.pred * pris_scale_factor + pris_scale actual <- scaled_test_df$Pris * pris_scale_factor + pris_scale mean_error <- mean((actual - pred)^2) print(mean_error)
内容的提问来源于stack exchange,提问作者l_b
相关产品推荐
相关产品推荐

