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

如何在R中对LASSO与KNN回归做标准化并对比输出?

问题分析与解决方案

核心问题拆解

  • 标准化逻辑错误:你在KNN代码中误将目标变量Salary也做了标准化,但LASSO的standardize=TRUE仅标准化自变量,目标变量保留原始尺度,导致两者预测值不在同一量级,MSE无法直接对比。
  • 模型特性误解:KNN是基于距离的非参数模型,不存在类似LASSO的回归系数(beta),因此没有“对比系数”的基础,这是思路上的误区。

修正方案

一、统一标准化流程(确保MSE可对比)

无论使用LASSO还是KNN,标准化都应仅处理自变量,目标变量保留原始值;且测试集必须使用训练集的均值和标准差进行标准化(禁止用测试集自身统计量,避免数据泄露)。

1. 修正后的KNN代码

library(caret)

fn.split <- function(d,p=0.2) {
  aux     <- 1:length(d[,1])
  id.test <- sort(sample(aux,size=floor(p*length(aux)),
                         replace=FALSE))
  d.test  <- d[id.test,]
  d.train <- d[-id.test,]
  return(list(train=d.train,test=d.test))
}

set.seed(34064064)

hitters.na<-na.omit(Hitters)
split.data<-fn.split(d=hitters.na,p=0.3)
train<-split.data$train
test<-split.data$test

# 分离自变量与目标变量,仅对自变量做标准化
train_x <- train[, !names(train) %in% "Salary"]
train_y <- train$Salary
test_x <- test[, !names(test) %in% "Salary"]
test_y <- test$Salary

# 记录训练集自变量的均值、标准差(用于测试集标准化)
norm_params <- lapply(train_x, function(col) {
  if(is.numeric(col)) list(mean = mean(col), sd = sd(col))
  else NULL
})

# 标准化训练集自变量
for (col in names(train_x)) {
  if(is.numeric(train_x[[col]])) {
    train_x[[col]] <- (train_x[[col]] - norm_params[[col]]$mean) / norm_params[[col]]$sd
  }
}

# 用训练集参数标准化测试集自变量(关键步骤)
for (col in names(test_x)) {
  if(is.numeric(test_x[[col]])) {
    test_x[[col]] <- (test_x[[col]] - norm_params[[col]]$mean) / norm_params[[col]]$sd
  }
}

# 生成哑变量
train_x$League<-ifelse(train_x$League=="N",1,0)
train_x$NewLeague<-ifelse(train_x$NewLeague=="N",1,0)
train_x$Division<-ifelse(train_x$Division=="W",1,0)
test_x$League<-ifelse(test_x$League=="N",1,0)
test_x$NewLeague<-ifelse(test_x$NewLeague=="N",1,0)
test_x$Division<-ifelse(test_x$Division=="W",1,0)

# 合并数据并训练KNN
train_processed <- cbind(train_x, Salary = train_y)
knn.reg<-knnreg(Salary~.,data=train_processed,k=20)

# 预测并计算原始尺度下的MSE
pred <- predict(knn.reg, newdata = test_x)
mse<- mean((test_y - pred)^2)
print(mse)

2. LASSO代码验证

你的LASSO代码逻辑正确:glmnet的standardize=TRUE会自动标准化自变量,预测时将结果还原为目标变量的原始尺度,计算的MSE是原始Salary量级下的值,现在可与修正后的KNN的MSE直接对比。

二、关于“系数对比”的说明

KNN是非参数模型,不学习线性回归式的系数,仅通过样本间距离加权预测,因此不存在可与LASSO的beta系数对比的参数。若需对比特征重要性:

  • LASSO可通过非零系数直接判断特征是否被选中;
  • KNN可通过“移除某特征后MSE的变化幅度”评估该特征的贡献度。

三、额外优化建议

  • 用caret的preProcess功能替代手动标准化,更简洁且避免错误:
preProc <- preProcess(train_x, method = c("center", "scale", "dummy"))
train_x_processed <- predict(preProc, train_x)
test_x_processed <- predict(preProc, test_x)
  • LASSO交叉验证可直接使用默认lambda序列,无需手动指定,通常效果更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:23:21