线性回归的留一法交叉验证实现

我在cafe数据集上构建了一个线性回归模型,并希望通过计算留一法交叉验证来验证结果。

我为此编写了自己的函数,如果我使用lm()对所有数据进行拟合,它可以正常工作,但是当我使用列的子集(来自逐步回归)时,我会得到一个错误。请考虑以下代码:

cafe <- read.table("C:/.../cafedata.txt", header=T)cafe$Date <- as.Date(cafe$Date, format="%d/%m/%Y")#删除第34行cafe <- cafe[-c(34), ]#不需要日期cafe <- cafe[,-1]library(DAAG)#中心化数据cafe.c <- data.frame(lapply(cafe[,2:15], function(x) scale(x, center = FALSE, scale = max(x, na.rm = TRUE))))cafe.c$Day.of.Week <- cafe$Day.of.Weekcafe.c$Sales <- cafe$Sales#留一法交叉验证函数LOOCV <- function(fit, dataset){  # 属性:  #------------------------------  # fit: 模型拟合  # dataset: 使用的数据集  # -----------------------------  # 返回每个折叠的平方误差均值 - MSE  MSEP_=c()  for (idx in 1:nrow(dataset)){    train <- dataset[-c(idx),]    test <- dataset[idx,]    MSEP_[idx]<-(predict(fit, newdata = test) -  dataset[idx,]$Sales)^2  }  return(mean(MSEP_))}

然后当我拟合简单的线性模型并调用函数时,它可以工作:

#----------------使用所有属性的简单线性回归-----------------fit.all.c <- lm(cafe.c$Sales ~., data=cafe.c)#MSE:258LOOCV(fit.all.c, cafe.c)

然而,当我仅使用列的子集拟合相同的lm()时,我得到了一个错误:

#-------------------------逐步线性回归--------------------------step <- stepAIC(fit.all.c, direction="both")fit.step <- lm(cafe.c$Sales ~ cafe.c$Bread.Sand.Sold + cafe.c$Bread.Sand.Waste               + cafe.c$Wraps.Waste + cafe.c$Muffins.Sold                + cafe.c$Muffins.Waste + cafe.c$Fruit.Cup.Sold                + cafe.c$Chips + cafe.c$Sodas + cafe.c$Coffees                + cafe.c$Day.of.Week,data=cafe.c)LOOCV(fit.step, cafe.c)

5495.069

有50个或更多的警告(使用warnings()查看前50个)

如果我仔细查看:

idx <- 1train <- cafe.c[-c(idx)]test <- cafe.c[idx](predict(fit.step, newdata = test) -cafe.c[idx]$Sales)^2

我得到了所有行的MSE和一个错误:

警告信息:’newdata’有1行,但找到的变量有47行

编辑

我找到了这个问题,关于这个错误,它说当我给列取不同的名字时会发生这种错误,但这不是我的情况。


回答:

请像以下这样修改你的代码:

fit.step <- lm(Sales ~ Bread.Sand.Sold + Bread.Sand.Waste               + Wraps.Waste + Muffins.Sold                + Muffins.Waste + Fruit.Cup.Sold                + Chips + Sodas + Coffees                + Day.of.Week,data=cafe.c)LOOCV(fit.step, cafe.c)# [1] 278.8984idx <- 1train <- cafe.c[-c(idx),]test <- cafe.c[idx,] # 需要选择行,而不是列(predict(fit.step, newdata = test) -cafe.c[idx,]$Sales)^2#    1 # 51.8022 

另外,你的LOOCV实现是不正确的。你必须在每次留一法折叠时在训练数据集上拟合一个新模型。现在你是在整个数据集上训练一次模型,并使用同一个单一模型来计算每个留一法折叠的保留测试数据集上的MSE,但理想情况下,你应该在不同的训练数据集上训练不同的模型。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注