进行交叉验证时如何计算 R 平方值?

机器算法验证 回归 多重回归 交叉验证 r平方
2022-03-21 16:13:17

我正在使用具有 72 个变量的数据集的多元线性回归,并使用 5 折交叉验证来评估模型。

我不确定我需要查看哪些值才能理解模型的验证。与原始数据集的 R 平方值相比,是 5 个模型的平均 R 平方值吗?据我了解,采样数据的平均 R 平方值需要在原始数据集中 R 平方值的 2% 以内。是对的吗?或者还有其他我应该看的结果吗?

2个回答

他们都不是。计算每组的均方误差和方差,并使用公式 为每个折叠获得 R^2。报告样本外 R^2 的均值和标准误差。R2=1E(yy^)2V(y)

也请看看这个讨论网上有很多例子,特别是 R 代码,其中是通过将交叉验证折叠的结果叠加在一起并在该嵌合向量和观察到的结果变量之间来计算的。然而,上述讨论和Kvålseth 的这篇论文中的答案和评论早于交叉验证技术的广泛采用,强烈建议使用公式 在一般情况下。R2R2yR2=1E(yy^)2V(y)

(1)堆叠和(2)关联预测的实践可能会出现几件事。

1.y考虑测试集中的观测值:c(1,2,3,4)和预测:c(8, 6, 4, 2)显然,预测与观察值是反相关的,但您将报告完全相关R2=1.0

2.考虑一个预测器,它返回一个向量,该向量是 的训练点的复制平均值y现在假设您y在拆分为交叉验证 (CV) 折叠之前进行了排序。您无需改组即可拆分,例如,在 16 个样本的 4 倍 CV 中,您具有以下排序的折叠 ID 标签y

foldid = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4)
y = c(0.09, 0.2, 0.22, 0.24, 0.34, 0.42, 0.44, 0.45, 0.45, 0.47, 0.55, 0.63, 0.78, 0.85, 0.92, 1)

当您拆分排序y点时,训练集的平均值将与测试集的平均值反相关,因此您会得到一个较低的负 Pearson现在你计算一个堆积的并且你得到一个相当高的值,尽管你的预测器只是噪声并且预测是基于所见的平均值10倍CV见下图RR2y

模拟:

更新:重新审视我的“年轻”答案,我同意,这种拼接方法不是计算 R 平方度量的正确方法。缝合可能有助于目视检查残差。正如其他答案中提到的那样,我保持原样回答。

@是 5 个模型的平均 R 平方值吗?

- 不,它的计算如下所示。您预测 k-fold 观察值,将它们拼接成一个有序向量,其中 obs#1 是第一个,obs#last 是最后一个。然后计算这个 k 折预测向量与响应向量 (y) 的平方 pearson 积矩相关性 (R²)。与响应 (y) 的 CV 相关性低于直接 MLR 拟合。在下面的示例中,R²(CV) = .63 和 R²(直接拟合)=.82。这表明这里的简单 MLR 稍微过拟合,如果这让您感到困扰,您可以尝试使用 PLS、岭回归或 PCR 做得更好。我没有听说过任何 2% 规则。

 library(foreach)
 obs=250
 vars=72
 nfolds=5

 #a test data set
 X = data.frame(replicate(vars,rnorm(obs)))
 true.coefs = runif(vars,-1,1)
 y_signal = apply(t(t(X) * true.coefs),1,sum)
 y_noise = rnorm(obs,sd=sd(y_signal)*0.5)
 y = y_signal + y_noise

 #split obs randomly in nfold partitions
 folds = split(sample(obs),1:nfolds)
 #run nfold loops, train, predict..
 #use cbind to stich together predictions of each test set to one
 test.preds = foreach(i = folds,.combine=cbind) %do% {
   Data.train = data.frame(X=X[-i,],y=y[-i])
   Data.test  = data.frame(X=X[i ,],y=y[ i])
   lmf = lm(y~.,Data.train)  
   test.pred = rep(0,obs)
   test.pred[i] = predict(lmf,Data.test)
   return(test.pred)
 }
 CVpreds = apply(test.preds,1,sum)

 cat(nfolds,"-fold CV, pearson R^2=",cor(CVpreds,y)^2,sep="")
 cat("simple MLR fit, pearson R^2=",cor(lm(y~.,data.frame(y,X))$fit,y)^2,sep="")