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

在R语言中为核平滑回归寻找最优带宽:基于训练与测试集RMSE的实现方案

没问题!我帮你写一个能自动遍历带宽、计算训练/测试集RMSE并找出最优值的函数,完美适配你现有的核平滑回归代码~

首先,咱们得明确核心逻辑:遍历一系列带宽候选值,对每个带宽用ksmooth拟合训练数据,然后分别计算训练集和测试集的RMSE,最后找出能最小化测试集RMSE的带宽(毕竟我们要的是泛化能力好的模型)。

完整函数代码

# 定义带宽选择函数
find_optimal_bandwidth <- function(train_data, test_data, h_min = 0.1, h_max = 2, h_step = 0.1) {
  # 生成带宽候选序列
  h_candidates <- seq(h_min, h_max, by = h_step)
  
  # 初始化存储RMSE的结果框
  rmse_results <- data.frame(
    bandwidth = h_candidates,
    train_rmse = NA,
    test_rmse = NA
  )
  
  # 遍历每个带宽
  for (i in seq_along(h_candidates)) {
    h <- h_candidates[i]
    
    # 用当前带宽做核平滑回归
    kernel_fit <- ksmooth(train_data$x, train_data$y, kernel = "normal", bandwidth = h)
    
    # 对训练集x值做预测(因为ksmooth返回的是排序后的x,需要用approx匹配原训练集的x)
    train_pred <- approx(kernel_fit$x, kernel_fit$y, xout = train_data$x)$y
    # 计算训练集RMSE
    rmse_results$train_rmse[i] <- sqrt(mean((train_data$y - train_pred)^2))
    
    # 对测试集x值做预测
    test_pred <- approx(kernel_fit$x, kernel_fit$y, xout = test_data$x)$y
    # 计算测试集RMSE
    rmse_results$test_rmse[i] <- sqrt(mean((test_data$y - test_pred)^2))
  }
  
  # 找出测试集RMSE最小的带宽
  optimal_h <- rmse_results$bandwidth[which.min(rmse_results$test_rmse)]
  
  # 返回结果:包含所有RMSE数据和最优带宽
  return(list(
    rmse_table = rmse_results,
    optimal_bandwidth = optimal_h
  ))
}

关键细节解释

  • approx函数的作用:ksmooth返回的是排序后的x和对应的拟合值,但你的训练/测试集x可能是无序的,而且测试集x可能不在训练集的x中。用approx可以根据核平滑的拟合结果,对任意x值做线性插值得到预测值,保证每个样本都能拿到对应的预测结果。
  • 带宽范围调整:函数里的h_min、h_max、h_step是默认值,你可以根据自己的数据分布调整(比如如果你的x范围很小,就把h的范围调小)。
  • 结果返回:函数会返回两个东西:一个是所有带宽对应的RMSE表格,另一个是最优带宽值,方便你后续分析和使用。

使用示例

假设咱们先模拟你说的二元数据(y均值为1/x加噪声),然后拆分训练测试集:

# 模拟数据
set.seed(123) # 设置随机种子保证结果可复现
x <- runif(200, 0.5, 5) # x在0.5到5之间均匀分布
y <- 1/x + rnorm(200, 0, 0.1) # y=1/x加正态噪声

# 拆分训练集和测试集(7:3)
train_idx <- sample(1:length(x), size = 0.7*length(x))
train_points <- data.frame(x = x[train_idx], y = y[train_idx])
test_points <- data.frame(x = x[-train_idx], y = y[-train_idx])

# 调用函数找最优带宽
bandwidth_result <- find_optimal_bandwidth(train_points, test_points, h_min = 0.05, h_max = 1, h_step = 0.05)

# 查看最优带宽
cat("最优带宽值:", bandwidth_result$optimal_bandwidth, "\n")

# 可视化RMSE随带宽的变化
plot(bandwidth_result$rmse_table$bandwidth, bandwidth_result$rmse_table$test_rmse, 
     type = "l", lwd = 2, col = "dodgerblue",
     xlab = "带宽h", ylab = "测试集RMSE", main = "RMSE随带宽变化趋势")
points(bandwidth_result$optimal_bandwidth, 
       bandwidth_result$rmse_table$test_rmse[which.min(bandwidth_result$rmse_table$test_rmse)],
       pch = 19, col = "red", cex = 1.5)
text(bandwidth_result$optimal_bandwidth, 
     bandwidth_result$rmse_table$test_rmse[which.min(bandwidth_result$rmse_table$test_rmse)],
     labels = "最优带宽", pos = 3, col = "red")

# 用最优带宽拟合并画图
optimal_fit <- ksmooth(train_points$x, train_points$y, kernel = "normal", bandwidth = bandwidth_result$optimal_bandwidth)
plot(y~x, train_points, cex = 0.5, col = "dodgerblue", main = "核平滑回归拟合结果(最优带宽)")
lines(optimal_fit, lwd = 2, col = 2)
points(y~x, test_points, cex = 0.5, col = "darkgreen") # 叠加测试集数据

小提示

  • 如果你的测试集RMSE先降后升,说明存在过拟合(带宽太小)和欠拟合(带宽太大)的情况,最优值就在中间的最低点。
  • 你也可以根据训练集RMSE来选带宽,但通常测试集RMSE更能反映模型的泛化能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:37:41