【问题标题】:Is there a simple command to do leave-one-out cross validation with the lm() function?是否有一个简单的命令可以使用 lm() 函数进行留一交叉验证?
【发布时间】:2018-04-12 09:29:03
【问题描述】:

是否有一个简单的命令可以使用 R 中的 lm() 函数进行留一交叉验证?

下面的代码是否有一个简单的命令?

x <- rnorm(1000,3,2)
y <- 2*x + rnorm(1000)

pred_error_sq <- c(0)
for(i in 1:1000) {
  x_i <- x[-i]
  y_i <- y[-i]
  mdl <- lm(y_i ~ x_i) # leave i'th observation out
  y_pred <- predict(mdl, data.frame(x_i = x[i])) # predict i'th observation
  pred_error_sq <- pred_error_sq + (y[i] - y_pred)^2 # cumulate squared prediction errors
}

y_squared <- sum((y-mean(y))^2)/100 # Variation of the data

R_squared <- 1 - (pred_error_sq/y_squared) # Measure for goodness of fit

【问题讨论】:

    标签: r cross-validation lm


    【解决方案1】:

    只需编写您自己的代码,使用索引变量来标记一个超出样本的观察值。用插入符号针对最高票数测试此方法。尽管插入符号简单易用,但我的粗暴方法花费的时间更少。 (我用的是LDA而不是lm,但差别不大)

    for (index in 1:dim(df)[1]){
       # here write your lm function
    }
    

    【讨论】:

      【解决方案2】:

      https://www.rdocumentation.org/packages/boot/versions/1.3-20/topics/cv.glm 中的cv.glm 默认执行 LOOCV,并且只需要数据和 lmglm 函数。

      【讨论】:

        【解决方案3】:

        您可以使用自定义函数,使用统计技巧避免实际计算所有 N 个模型:

        loocv=function(fit){
          h=lm.influence(fit)$h
          mean((residuals(fit)/(1-h))^2)
        }
        

        这里有解释:https://gerardnico.com/wiki/lang/r/cross_validation 它仅适用于线性模型 我猜你可能想在公式中的平均值后面加上一个平方根。

        【讨论】:

          【解决方案4】:

          另一种解决方案是使用caret

          library(caret)
          
          data <- data.frame(x = rnorm(1000, 3, 2), y = 2*x + rnorm(1000))
          
          train(y ~ x, method = "lm", data = data, trControl = trainControl(method = "LOOCV"))
          

          线性回归

          1000 个样本 1 个预测器

          无预处理重采样:留一法交叉验证摘要 样本量:999, 999, 999, 999, 999, 999, ... 结果:

          RMSE Rsquared MAE
          1.050268 0.940619 0.836808

          调整参数 'intercept' 保持恒定值 TRUE

          【讨论】:

            【解决方案5】:

            你可以试试 DAAG 包中的cv.lm

            cv.lm(data = DAAG::houseprices, form.lm = formula(sale.price ~ area),
                          m = 3, dots = FALSE, seed = 29, plotit = c("Observed","Residual"),
                          main="Small symbols show cross-validation predicted values",
                          legend.pos="topleft", printit = TRUE)
            
            Arguments
            
            data        a data frame
            form.lm,    a formula or lm call or lm object
            m           the number of folds
            dots        uses pch=16 for the plotting character
            seed        random number generator seed
            plotit      This can be one of the text strings "Observed", "Residual", or a logical value. The logical TRUE is equivalent to "Observed", while FALSE is equivalent to "" (no plot)
            main        main title for graph
            legend.pos      position of legend: one of "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right", "center".
            printit     if TRUE, output is printed to the screen
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-11-27
              • 2020-07-06
              • 2014-09-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-27
              相关资源
              最近更新 更多