我正在使用Mevik的pls R包进行偏最小二乘回归(2007)。 具有10倍交叉验证的模型如下:
left join
之后,我可以使用以下方法打印出精度,例如R2或RMSE:
group by
其中xcomp是最佳组件数。 例如,R2的结果如下所示:
pls.fa <- plsr(FA ~ ., ncomp = xcomp,scale = TRUE, validation = "CV", segments = 10,jackknife =TRUE, data=train)
我的问题是:这种交叉验证产生的R2是10倍的平均值?
由于
答案 0 :(得分:2)
我执行了一些测试,R2
和RMSE
返回的pls::R2
和pls::RMSEP
似乎不是10倍的平均值。通过从所有10个CV折叠中提取预测,并将它们与观察到的结果进行比较,一次性使用所有保留样本计算它们:
以下是一个例子:
library(pls)
使用内置纱线数据集拟合模型:
data(yarn)
pls.fa <- plsr(density ~ NIR,
data = yarn,
ncomp = 6,
scale = TRUE,
validation = "CV",
segments = 10,
jackknife = TRUE)
我将使用等效的caret
函数进行比较
以下代码返回使用前1:6组件获得的RMSE:
pls::RMSEP(pls.fa, ncomp = 1:6, estimate = "CV", intercept = FALSE)
#output
1 comps 2 comps 3 comps 4 comps 5 comps 6 comps
8.4692 2.5553 1.9430 1.0151 0.7399 0.5801
以数字向量的形式提取RMSE:
unlist(lapply(1:6, function(x) pls::RMSEP(pls.fa,
ncomp = 1:6,
estimate = "CV",
intercept = FALSE)$val[,,x]))
让我们使用所有数据将输出与caret::RMSE
进行比较:
all.equal(
unlist(lapply(1:6, function(x) caret::RMSE(pls.fa$validation$pred[,,x],
yarn$density))),
unlist(lapply(1:6, function(x) pls::RMSEP(pls.fa,
ncomp = 1:6,
estimate = "CV",
intercept = FALSE)$val[,,x])))
#output
TRUE
因此RMSEP
是使用所有保留预测计算的。
等同于R2
:
all.equal(
unlist(lapply(1:6, function(x) caret::R2(pls.fa$validation$pred[,,x],
yarn$density,
form = "traditional"))),
unlist(lapply(1:6, function(x) pls::R2(pls.fa,
ncomp = 1:6,
estimate = "CV",
intercept = FALSE)$val[,,x])))
#output
TRUE
编辑:回答评论中的问题:
哪种方式更适合在折叠上平均RMSE,或者从折叠中提取所有预测并计算一个RMSE:
在我看来,无论哪种方式都是好的,在比较模型时,只需要在计算中加入。请考虑以下示例:
set.seed(1)
true <- rnorm(100)
fold <- sample(1:10, size = 100, replace = T)
pred <- rnorm(100)
z <- data.frame(true, pred, fold)
库(tidyverse)
z %>%
group_by(fold) %>%
summarise(rmse = caret::RMSE(true, pred)) %>%
pull(rmse) %>%
mean
#ouput
1.479923
z %>%
summarise(rmse = caret::RMSE(true, pred)) %>%
pull(rmse)
#ouput
1.441471
与拉动所有预测和计算RMSE相比,这里对折叠的平均值给出了更悲观的结果。
使用与set.seed(2)相同的代码:
平均折叠:1.442483 拉全部:1.500432
现在平均折叠更为乐观
所以一种方式并不总是更乐观。