我进行了一些测试,看起来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)
library(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
现在平均超过折叠更乐观
因此,一种方法并不总是更乐观。