波士顿房价数据集:调优后Neuralnet的RMSE远超线性模型,如何构建?
波士顿房价数据集:正确构建调优神经网络模型
基于波士顿房价(Boston Housing)数据集的实验中,线性模型表现正常,但调优后的神经网络训练集RMSE远高于线性模型,核心问题出在参数设置和数据索引上,以下是修复方案:
原始问题复现
线性模型代码(正常运行):
library(e1071) # for tune.nnet library(MASS) # for the Boston housing data set library(Metrics) # to calculate RMSE library(nnet) df <- MASS::Boston train <- df[1:100, ] test <- df[101:505, ] Boston_lm <- lm(medv ~ ., data = train) lm_rmse <- Metrics::rmse(actual = train$medv, predicted = Boston_lm$fitted.values) #RMSE = 2.037201
神经网络代码(存在问题):
Boston_tune_nnet <- e1071::tune.nnet(x = train[, 1:ncol(train)-1], y = train$medv, size = 1) nnet_tune_rmse <- Metrics::rmse(actual = train$medv, predicted = Boston_tune_nnet$best.model$fitted.values) #RMSE = 22.11024
问题诊断
- 数据索引错误:
1:ncol(train)-1的运算顺序错误,R中会先计算ncol(train)-1,再生成序列,导致出现0索引(列索引不能为0),正确写法应为1:(ncol(train)-1)。 - 回归任务未指定:
tune.nnet默认是分类任务,会用sigmoid激活函数将输出压缩到0-1区间,完全不适合房价(medv范围5-50)的回归场景,必须添加linout = TRUE启用线性输出。 - 调优参数单一:仅设置
size=1,未调整权重衰减(decay)等关键参数,模型容易欠拟合或训练不稳定。 - 训练数据划分不合理:固定选取前100条数据,不如随机划分更具代表性。
正确调优神经网络的完整代码
library(e1071) library(MASS) library(Metrics) library(nnet) # 加载数据并随机划分训练/测试集 df <- MASS::Boston set.seed(123) # 固定随机种子保证可复现 train_idx <- sample(nrow(df), 100) train <- df[train_idx, ] test <- df[-train_idx, ] # 线性模型基准 Boston_lm <- lm(medv ~ ., data = train) lm_train_rmse <- Metrics::rmse(train$medv, Boston_lm$fitted.values) lm_test_rmse <- Metrics::rmse(test$medv, predict(Boston_lm, test)) cat("线性模型训练RMSE:", round(lm_train_rmse, 4), "\n") cat("线性模型测试RMSE:", round(lm_test_rmse, 4), "\n") # 设置调优参数网格:尝试不同隐藏层神经元数和权重衰减值 tune_grid <- expand.grid( size = c(1, 3, 5), decay = c(0, 0.001, 0.01) ) # 执行5折交叉验证调优,指定回归任务 Boston_tune_nnet <- e1071::tune.nnet( x = train[, 1:(ncol(train)-1)], # 修正索引 y = train$medv, linout = TRUE, # 关键:启用线性输出适配回归 size = tune_grid$size, decay = tune_grid$decay, maxit = 1000, # 增加迭代次数确保模型收敛 trace = FALSE, # 关闭训练过程输出 tunecontrol = tune.control(sampling = "cross", cross = 5) ) # 提取最优模型并计算RMSE best_nnet <- Boston_tune_nnet$best.model nnet_train_rmse <- Metrics::rmse(train$medv, best_nnet$fitted.values) nnet_test_rmse <- Metrics::rmse(test$medv, predict(best_nnet, test)) cat("\n最优神经网络训练RMSE:", round(nnet_train_rmse, 4), "\n") cat("最优神经网络测试RMSE:", round(nnet_test_rmse, 4), "\n")
核心优化点说明
linout = TRUE:这是回归任务的必要设置,确保输出层使用线性激活函数,避免数值被错误压缩。- 交叉验证调优:通过5折交叉验证选择最优参数组合,比单一参数测试更可靠。
- 随机数据划分:避免固定前N条数据带来的分布偏差,提升模型泛化性。
- 参数网格扩展:同时调整隐藏层神经元数和权重衰减,平衡模型拟合能力与过拟合风险。
内容的提问来源于stack exchange,提问作者Russ Conte
相关产品推荐
相关产品推荐

