交叉验证的实现

机器算法验证 r 交叉验证
2022-03-26 12:48:28

我正在参加计算统计课程,这应该是一门应用课程。我们研究不同的方法,这些方法在“现实”中很重要。这些主题之一是交叉验证。我面临来自家庭作业的以下问题。给定一个数据集,假设模型的形式为 ,即非参数回归。我们想使用留一法交叉验证分数来计算广义误差。这应该通过使用核估计器、局部多项式和平滑样条来完成。我的第一个问题非常笼统:给定数据,我如何通过肉眼为内核估计器选择合理的带宽?例如见下图:

Yi=m(Xi)+ϵi
ksmooth

在此处输入图像描述

由于这些数据看起来相当“狂野”,因此我不清楚如何选择带宽。我的第一次尝试只是用不同的带宽运行 ksmooth。但正如我所说,这里的数据是狂野的,所以(对我来说)很难确定一个合理的带宽。

第二个问题是关于上述问题的更具体的问题。到目前为止,我有以下代码:

   cv <- function(data,used.function)
{
  n <- nrow(data)
  cv.value <- rep(0,length(n))
  for (i in 1:n){
      new.data <- data[-i,]
      cv.value[i] <- used.function(new.data[,1],new.data[,2],data[i,1])
  }
  ## MSE
  return(1/n*sum((new.data[,2]-cv.value)^2))
}


### kernel estimator usind nadaraya-watson:
fcn1 <- function(reg.x, reg.y, x){
  return(ksmooth(reg.x, reg.y, x.point = x, kernel = "normal", bandwidth = h)$y)
}
### CV-score for kernel estimator:
(cv.nw <- cv(real.data, fcn1))

函数 cv 应该是通用的,这样我也可以应用局部多项式和平滑样条曲线。变量 real.data 包含数据。它是一个矩阵,存储所有值和值。在 cv 的函数体中,我执行了遗漏交叉验证。但是,使用此代码为 cv.nw 提供了 NA。我的代码有什么问题?我非常感谢你的帮助。n×2xy

1个回答

我现在意识到这是一个更老的问题,但也许这可以阐明一些问题。您的代码有几处问题。

  1. 目前的代码是不可重现的。任何时候都没有h定义您希望调整的确切参数。
  2. 您不会在不同的带宽上进行迭代。如果您使用交叉验证来比较不同的模型,则需要不同的模型(即不同的参数)。

修改您的代码并利用cars数据集,这是一个可重复的带宽留一法交叉验证示例,您可以通过不同带宽的“网格”来调整模型。

cv <- function(data, used.function, bandwidth.grid)
{
  n <- nrow(data)
  mse <- matrix(, nrow=length(bandwidth.grid), ncol=2)
  for (b in 1:length(bandwidth.grid)){
    cv.value <- rep(0, n-1)
    for (i in 1:(n-1)){
      new.data <- data[-i,]
      funcargs <- list(reg.x=new.data[,1],reg.y=new.data[,2],x=data[i,1], h = bandwidth.grid[b])
      cv.value[i] <- do.call(used.function, funcargs)
    }
    mse[b,] <- c(bandwidth.grid[b], 1/n*sum((new.data[,2]-cv.value)^2))
  }

  ## MSE
  colnames(mse) <- c("bandwidth", "mse")
  return(mse)
}

### kernel estimator usind nadaraya-watson:
fcn1 <- function(reg.x, reg.y, x, h){
  return(ksmooth(reg.x, reg.y, x.point = x, kernel = "normal", bandwidth = h)$y)
}

attach(cars)
### CV-score for kernel estimator:
cv(cbind(speed, dist), fcn1, seq(10))
> cv(cbind(speed, dist), fcn1, seq(10))
      bandwidth      mse
 [1,]         1 261.9555
 [2,]         2 223.3542
 [3,]         3 217.8303
 [4,]         4 214.0923
 [5,]         5 211.1874
 [6,]         6 211.4104
 [7,]         7 214.6941
 [8,]         8 220.1501
 [9,]         9 227.2262
[10,]        10 235.5479

在这里我们可以看到 abandwidth = 5是最好的。