【问题标题】:Linear regression with LOOCV split in R returns ErrorR 中 LOOCV 拆分的线性回归返回错误
【发布时间】:2019-11-19 14:39:37
【问题描述】:

我尝试使用 Leave one out 交叉验证拆分来拟合线性模型。

我使用了这个DATASET,数据集有 517 行和 13 列(其中两个是分类变量)。因变量是“面积”。

我想建立一个有和没有分类变量的模型。然后是计算系数均值。当我删除分类变量时,代码运行良好,但是当我保留它们时,出现以下错误 " Error in estcoef[i, ]

我的代码如下

wdbc<- read.csv("forestfires.csv") ## upload the dataset
wdbc<-wdbc[-(3:4)] ## If I want to build the model without the catogrical variables
#####################################

fitted_value <- rep(0,nrow(wdbc))
estcoef<-matrix(0,nrow=nrow(wdbc),ncol=ncol(wdbc)) #estimation coefficients

# LOOCV split leave one out cross validation 
for(i in 1:nrow(wdbc)){
  validation<-wdbc[i,]
  training<-wdbc[-i,]
  model1<-lm(area ~ ., data = training)
  fitted_value[i] <- predict(model1, newdata = validation) 
  estcoef[i,]<-coef(model1) 
}

meancoef<-colMeans(estcoef) #coefficent means

有人可以帮我解决这个问题吗?

我很乐意提供任何其他附加信息。

更新

我包含了前 10 行数据

  X Y month day FFMC   DMC    DC  ISI temp RH wind rain area
1  7 5   mar fri 86.2  26.2  94.3  5.1  8.2 51  6.7  0.0    0
2  7 4   oct tue 90.6  35.4 669.1  6.7 18.0 33  0.9  0.0    0
3  7 4   oct sat 90.6  43.7 686.9  6.7 14.6 33  1.3  0.0    0
4  8 6   mar fri 91.7  33.3  77.5  9.0  8.3 97  4.0  0.2    0
5  8 6   mar sun 89.3  51.3 102.2  9.6 11.4 99  1.8  0.0    0
6  8 6   aug sun 92.3  85.3 488.0 14.7 22.2 29  5.4  0.0    0
7  8 6   aug mon 92.3  88.9 495.6  8.5 24.1 27  3.1  0.0    0
8  8 6   aug mon 91.5 145.4 608.2 10.7  8.0 86  2.2  0.0    0
9  8 6   sep tue 91.0 129.5 692.6  7.0 13.1 63  5.4  0.0    0
10 7 5   sep sat 92.5  88.0 698.6  7.1 22.8 40  4.0  0.0    0

我还包括了最后 10 行,这表明我们只有一行月份 = Nov(最后一行),即使提供的答案也会返回错误。

> tail(wdbc,10)
    X Y month day FFMC   DMC    DC  ISI temp RH wind rain  area
508 2 4   aug fri 91.0 166.9 752.6  7.1 25.9 41  3.6  0.0  0.00
509 1 2   aug fri 91.0 166.9 752.6  7.1 25.9 41  3.6  0.0  0.00
510 5 4   aug fri 91.0 166.9 752.6  7.1 21.1 71  7.6  1.4  2.17
511 6 5   aug fri 91.0 166.9 752.6  7.1 18.2 62  5.4  0.0  0.43
512 8 6   aug sun 81.6  56.7 665.6  1.9 27.8 35  2.7  0.0  0.00
513 4 3   aug sun 81.6  56.7 665.6  1.9 27.8 32  2.7  0.0  6.44
514 2 4   aug sun 81.6  56.7 665.6  1.9 21.9 71  5.8  0.0 54.29
515 7 4   aug sun 81.6  56.7 665.6  1.9 21.2 70  6.7  0.0 11.16
516 1 4   aug sat 94.4 146.0 614.7 11.3 25.6 42  4.0  0.0  0.00
517 6 3   nov tue 79.5   3.0 106.7  1.1 11.8 31  4.5  0.0  0.00

【问题讨论】:

  • 你看过coef(model1)length(coef(model1))吗?您似乎假设系数的数量与列的数量相同,但事实并非如此。因为我没有你的数据,所以我无法检查有什么不同。但是coef(model1) 应该是一个很好命名的向量,它可以阐明问题......
  • 如果其中一个回归变量是具有n 级别的分类变量,则您可能有更多系数,n - 1 仅用于此变量。加上其他回归量。
  • @Gregor,我提供了问题中数据的链接。
  • @Rui Barradas,那么我应该怎么做才能使我的代码在没有分类变量的情况下工作。
  • 完成,看我的回答。

标签: r machine-learning regression linear-regression cross-validation


【解决方案1】:

如果不是创建一个矩阵来存储系数,而是将它们存储在list 中,那么这个问题很容易解决。像这样不会有任何物品可以更换,以后会处理所有的事情。

在下面的代码中,我使用内置数据集iris,将响应的名称更改为area

wdbc <- iris
names(wdbc)[1] <- "area"

fitted_value <- rep(0, nrow(wdbc))
estcoef <- vector("list", length = nrow(wdbc))

# LOOCV split leave one out cross validation 
for(i in 1:nrow(wdbc)){
  validation <- wdbc[i,]
  training <- wdbc[-i, ]
  model1 <- lm(area ~ ., data = training)
  fitted_value[i] <- predict(model1, newdata = validation) 
  estcoef[[i]] <- coef(model1) 
}

estcoef <- do.call(rbind, estcoef)
meancoef <- colMeans(estcoef) # coefficent means

编辑。

Op 抱怨一个错误:

model.frame.default 中的错误(术语,newdata,na.action = na.action,xlev = object$xlevels):
因子月有新的水平 nov

这是因为数据集只有一行包含 month == "nov",因此在拟合模型时,省略了这一行,validation 数据集在 month 列中的值不存在于training 数据集和 predict 不知道如何处理它。

解决方法是使用tryCatch 来捕获错误并让代码继续运行。下面的函数是上面代码的重复,调用tryCatch。它返回系数均值和拟合值。当predict 给出错误时,返回值为NaN。随意更改。

fitModelLOOCV <- function(DF){

  fitted_value <- rep(0, nrow(DF))
  estcoef <- vector("list", length = nrow(DF))

  # LOOCV split leave one out cross validation 
  for(i in 1:nrow(DF)){
    validation <- DF[i,]
    training <- DF[-i, ]
    model1 <- lm(area ~ ., data = training)
    fitted_value[i] <- tryCatch(predict(model1, newdata = validation),
                                error = function(e) {print(e); NaN})
    estcoef[[i]] <- coef(model1) 
  }

  estcoef <- do.call(rbind, estcoef)
  meancoef <- colMeans(estcoef) # coefficent means
  list(meancoef = meancoef, fitted = fitted_value)
}

fitModelLOOCV(wdbc)

另一种方法是在运行函数之前删除问题值。 (也许只有一个数据点并不那么重要。)

wdbc2 <- wdbc[-which(wdbc$month == "nov"), ]
fitModelLOOCV(wdbc2)

【讨论】:

  • 谢谢,但是当我在我的数据上运行代码时,我得到了“model.frame.default 错误(Terms, newdata, na.action = na.action, xlev = object$xlevels):因素月有新的等级 nov'
  • @jeza 错误出现在对predict 的调用中。这是因为month == "nov" 只有一行。因此,当它从训练数据中更新时,拟合模型没有nov。然后您尝试使用新级别进行预测,而 predict 不知道如何处理该值。
  • @jeza 查看编辑。也许添加的代码可以解决问题。
  • 我明白了。好的,这个问题有什么解决办法吗?
  • 非常感谢,除非我们得到其他人的回答,否则我会将其视为解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
  • 2010-11-13
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2013-02-11
相关资源
最近更新 更多