YearPredictionMSD数据集特征变换代码报错:遍历特征部分异常求助
问题排查与代码修复
核心错误点分析
- 预测时变量缺失:原函数训练模型时用的是局部变量
transformed_predictor,但测试集里没有这个列,导致predict函数无法找到对应变量直接报错。 - 语法错误:创建
transformations_table时括号未闭合,且预测变量名称生成逻辑错误,没有覆盖所有特征。 - 分箱变换不一致:
interval_binning和quantile_binning在测试集应用时未复用训练集的分箱规则,会出现因子水平不匹配的问题,导致预测失败。 - 全局变量依赖:函数内依赖全局的
Year变量,代码耦合性高,容易引发意外错误。
修复后的完整代码
data <- read.delim("YearPredictionMSD.txt", header = FALSE, sep = ",") # 加载依赖包 library(mlr) library(dplyr) # 设置随机种子保证结果可复现 set.seed(123) # 按数据集官方规则划分训练/测试集 train_data <- data[1:463715, ] test_data <- data[463716:nrow(data), ] # 定义所有候选变换类型 transforms <- c("none", "log", "exp", "inv", "square", "sqrt", "center_scale", "range", "interval_binning", "quantile_binning") # 定义单特征最优变换选择函数 determine_best_transform <- function(predictor_col, train_data, test_data, transforms) { rmse_values <- numeric(length(transforms)) names(rmse_values) <- transforms # 提取目标变量 train_target <- train_data[, 1] test_target <- test_data[, 1] # 遍历每个变换类型 for (transform in transforms) { # 对训练集特征应用变换,并同步处理测试集 if (transform == "none") { train_transformed <- train_data[, predictor_col] test_transformed <- test_data[, predictor_col] } else if (transform == "log") { # 处理非正值避免报错 min_pos_val <- min(train_data[, predictor_col][train_data[, predictor_col] > 0]) train_transformed <- log(pmax(train_data[, predictor_col], min_pos_val)) test_transformed <- log(pmax(test_data[, predictor_col], min_pos_val)) } else if (transform == "exp") { # 先缩放避免数值溢出 train_scaled <- scale(train_data[, predictor_col]) train_transformed <- exp(train_scaled) test_scaled <- scale(test_data[, predictor_col], center = attr(train_scaled, "scaled:center"), scale = attr(train_scaled, "scaled:scale")) test_transformed <- exp(test_scaled) } else if (transform == "inv") { # 处理0值避免除以0报错 train_transformed <- 1 / pmax(train_data[, predictor_col], 1e-6) test_transformed <- 1 / pmax(test_data[, predictor_col], 1e-6) } else if (transform == "square") { train_transformed <- train_data[, predictor_col]^2 test_transformed <- test_data[, predictor_col]^2 } else if (transform == "sqrt") { # 处理负值避免报错 train_transformed <- sqrt(pmax(train_data[, predictor_col], 0)) test_transformed <- sqrt(pmax(test_data[, predictor_col], 0)) } else if (transform == "center_scale") { train_transformed <- scale(train_data[, predictor_col]) test_transformed <- scale(test_data[, predictor_col], center = attr(train_transformed, "scaled:center"), scale = attr(train_transformed, "scaled:scale")) } else if (transform == "range") { train_min <- min(train_data[, predictor_col]) train_range <- max(train_data[, predictor_col]) - train_min train_transformed <- (train_data[, predictor_col] - train_min) / train_range test_transformed <- (test_data[, predictor_col] - train_min) / train_range } else if (transform == "interval_binning") { breaks <- c(-Inf, 0, 10, 100, 1000, Inf) train_transformed <- cut(train_data[, predictor_col], breaks = breaks, labels = c("A", "B", "C", "D", "E")) test_transformed <- cut(test_data[, predictor_col], breaks = breaks, labels = c("A", "B", "C", "D", "E")) } else if (transform == "quantile_binning") { # 复用训练集分位数断点,处理重复断点避免报错 breaks <- unique(quantile(train_data[, predictor_col], na.rm = TRUE)) train_transformed <- cut(train_data[, predictor_col], breaks = breaks, include.lowest = TRUE) test_transformed <- cut(test_data[, predictor_col], breaks = breaks, include.lowest = TRUE) } # 构造临时数据集用于模型训练和预测 temp_train <- data.frame(target = train_target, feat = train_transformed) temp_test <- data.frame(target = test_target, feat = test_transformed) # 训练线性模型并计算RMSE model <- lm(target ~ feat, data = temp_train) predictions <- predict(model, newdata = temp_test) rmse_values[transform] <- sqrt(mean((predictions - temp_test$target)^2, na.rm = TRUE)) } # 返回RMSE最小的变换类型 return(names(which.min(rmse_values))) } # 遍历所有预测变量(第2列到最后一列) transformations <- character(ncol(train_data) - 1) names(transformations) <- paste0("X", 1:(ncol(train_data)-1)) for (i in 2:ncol(train_data)) { transformations[i-1] <- determine_best_transform(predictor_col = i, train_data = train_data, test_data = test_data, transforms = transforms) } # 生成特征-最优变换对照表 transformations_table <- data.frame( Predictor = names(transformations), Best_Transformation = transformations, stringsAsFactors = FALSE ) # 生成变换使用次数汇总表 summary_table <- table(transformations) # 输出结果 print("特征最优变换对照表:") print(transformations_table) print("\n变换使用次数汇总:") print(summary_table)
关键修复说明
- 解决变量缺失问题:构造临时数据框
temp_train和temp_test,将目标变量与变换后的特征绑定,保证模型训练和预测时变量一致。 - 修复语法错误:补全
transformations_table的括号,正确生成所有90个特征的名称(X1到X90)。 - 保证分箱一致性:分箱类变换复用训练集的断点规则处理测试集,同时处理分位数重复的问题避免报错。
- 提升代码鲁棒性:对
log、sqrt、inv等变换添加非正值/零值处理,对exp变换先做缩放避免数值溢出。 - 优化代码结构:预先初始化结果向量提升循环效率,减少全局变量依赖,函数参数更清晰。
内容的提问来源于stack exchange,提问作者Nina
相关产品推荐
相关产品推荐

