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

R语言构建循环对比神经网络与逻辑回归的Bootstrap MSE问题

我明白你现在的困境——想用Bootstrap对比神经网络和逻辑回归的MSE,但自定义统计量让boot函数卡壳,而且对神经网络的循环实现有点懵。刚好我对Günther & Fritsch (2010)的模拟框架很熟悉,咱们一步步解决这个问题:

解决Bootstrap MSE对比的问题:神经网络 vs 逻辑回归

首先明确核心问题:boot包要求自定义统计量函数必须接受数据和Bootstrap索引两个参数,很多时候出错就是因为没正确处理索引提取样本。另外神经网络的拟合需要注意收敛参数,避免中途报错。

1. 准备模拟数据(贴合Günther & Fritsch 2010的风格)

先生成非线性的回归/分类数据,这里先做回归场景(分类场景我后面会补充):

# 加载必备包
library(boot)
library(nnet)

set.seed(123) # 固定随机种子保证可复现
n <- 200
x1 <- runif(n, -pi, pi)
x2 <- runif(n, -pi, pi)
# 生成非线性响应变量
y <- sin(x1) + cos(x2) + rnorm(n, 0, 0.3)
data <- data.frame(x1, x2, y)

2. 定义Bootstrap统计量函数

这是关键!统计量函数必须接受data和indices两个参数,用indices从原数据中抽取Bootstrap样本,再拟合模型计算MSE。

线性/逻辑回归的统计量函数

如果是回归问题(你提到的逻辑回归可能是笔误?如果是分类我后面补),先写线性回归的:

boot_lm_mse <- function(data, indices) {
  # 提取Bootstrap样本
  boot_sample <- data[indices, ]
  # 拟合模型
  lm_model <- lm(y ~ x1 + x2, data = boot_sample)
  # 计算MSE
  pred <- predict(lm_model, newdata = boot_sample)
  mse <- mean((boot_sample$y - pred)^2)
  return(mse)
}

如果是分类问题(逻辑回归),调整数据和函数:

# 生成二分类数据
y_prob <- plogis(sin(x1) + cos(x2))
y_bin <- rbinom(n, 1, y_prob)
data_bin <- data.frame(x1, x2, y_bin)

# 逻辑回归的MSE统计量(预测概率与实际标签的均方误差)
boot_glm_mse <- function(data, indices) {
  boot_sample <- data[indices, ]
  glm_model <- glm(y_bin ~ x1 + x2, data = boot_sample, family = binomial)
  pred_prob <- predict(glm_model, newdata = boot_sample, type = "response")
  mse <- mean((boot_sample$y_bin - pred_prob)^2)
  return(mse)
}

神经网络的统计量函数

神经网络拟合要注意设置足够的迭代次数(maxit)避免收敛失败,关闭trace减少冗余输出:

# 回归神经网络的统计量函数
boot_nnet_mse <- function(data, indices) {
  boot_sample <- data[indices, ]
  # 1个隐藏层节点,迭代1000次,关闭训练日志
  nnet_model <- nnet(y ~ x1 + x2, data = boot_sample, size = 1, maxit = 1000, trace = FALSE)
  pred <- predict(nnet_model, newdata = boot_sample)
  mse <- mean((boot_sample$y - pred)^2)
  return(mse)
}

# 分类神经网络的统计量函数
boot_nnet_bin_mse <- function(data, indices) {
  boot_sample <- data[indices, ]
  # 加entropy=TRUE用交叉熵损失,适合分类
  nnet_model <- nnet(y_bin ~ x1 + x2, data = boot_sample, size = 1, maxit = 1000, trace = FALSE, entropy = TRUE)
  pred_prob <- predict(nnet_model, newdata = boot_sample, type = "raw")
  mse <- mean((boot_sample$y_bin - pred_prob)^2)
  return(mse)
}

3. 运行Bootstrap并对比结果

用boot包快速运行,或者用你熟悉的for循环实现:

用boot包实现

B <- 1000 # Bootstrap次数

# 回归场景
boot_lm_results <- boot(data = data, statistic = boot_lm_mse, R = B)
boot_nnet_results <- boot(data = data, statistic = boot_nnet_mse, R = B)

# 查看结果
cat("线性回归Bootstrap MSE均值:", mean(boot_lm_results$t), "\n")
cat("神经网络Bootstrap MSE均值:", mean(boot_nnet_results$t), "\n")

# 可视化分布
par(mfrow = c(1,2))
hist(boot_lm_results$t, main = "线性回归MSE分布", xlab = "MSE", col = "lightblue")
hist(boot_nnet_results$t, main = "神经网络MSE分布", xlab = "MSE", col = "lightgreen")
par(mfrow = c(1,1))

用for循环实现(你提到的传统循环方式)

如果你更习惯手动写循环,这样做:

B <- 1000
mse_lm <- numeric(B)
mse_nnet <- numeric(B)

set.seed(123)
for (i in 1:B) {
  # 抽取Bootstrap样本(有放回抽样)
  boot_indices <- sample(1:nrow(data), nrow(data), replace = TRUE)
  boot_sample <- data[boot_indices, ]
  
  # 拟合线性回归并计算MSE
  lm_model <- lm(y ~ x1 + x2, data = boot_sample)
  mse_lm[i] <- mean((boot_sample$y - predict(lm_model, boot_sample))^2)
  
  # 拟合神经网络并计算MSE
  nnet_model <- nnet(y ~ x1 + x2, data = boot_sample, size = 1, maxit = 1000, trace = FALSE)
  mse_nnet[i] <- mean((boot_sample$y - predict(nnet_model, boot_sample))^2)
}

# 结果汇总
cat("线性回归MSE均值(循环版):", mean(mse_lm), "\n")
cat("神经网络MSE均值(循环版):", mean(mse_nnet), "\n")

常见坑点提醒

  • 统计量函数参数:必须包含data和indices,不能直接用全局数据,否则boot函数无法正确抽样;
  • 神经网络收敛:一定要设置maxit(比如1000),默认迭代次数太少容易导致拟合失败;
  • 分类问题注意事项:神经网络要加entropy=TRUE,预测时用type="raw"获取概率值,否则会得到分类标签,MSE计算就没意义了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 06:43:39