You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

关键修复说明

  1. 解决变量缺失问题:构造临时数据框temp_train和temp_test,将目标变量与变换后的特征绑定,保证模型训练和预测时变量一致。
  2. 修复语法错误:补全transformations_table的括号,正确生成所有90个特征的名称(X1到X90)。
  3. 保证分箱一致性:分箱类变换复用训练集的断点规则处理测试集,同时处理分位数重复的问题避免报错。
  4. 提升代码鲁棒性:对log、sqrt、inv等变换添加非正值/零值处理,对exp变换先做缩放避免数值溢出。
  5. 优化代码结构:预先初始化结果向量提升循环效率,减少全局变量依赖,函数参数更清晰。

内容的提问来源于stack exchange,提问作者Nina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 05:53:19