现有的答案非常好,但这里有更多细节。在他发明随机森林的论文中,Breiman 吹捧袋外计算作为交叉验证的替代方案:
因此,使用袋外误差估计消除了对预留测试集的需要。
在同一篇论文中,他加倍强调,OOB 比 CV 更可取:
...与存在偏差但程度未知的交叉验证不同,袋外估计是无偏的
这是一个更具体的例子。让我们根据来自 Kaggle的数据集训练一个随机森林。
library(conflicted)
library(tidyverse)
library(tidymodels)
library(ranger)
col_factor <- readr::col_factor
telco_raw <- read_csv(
"archive.zip",
col_types = cols(
Churn = col_factor(levels = c("Yes",
"No")),
Dependents = col_factor(levels = c("Yes",
"No")),
PaperlessBilling = col_factor(levels = c("Yes",
"No")),
Partner = col_factor(levels = c("Yes",
"No")),
PhoneService = col_factor(levels = c("Yes",
"No")),
SeniorCitizen = col_factor(levels = c("0",
"1")),
customerID = col_skip(),
gender = col_factor(levels = c("Female",
"Male"))
)
) %>%
na.omit()
telco <- initial_split(telco_raw, prop = 0.8, strata = Churn)
telco_train <- training(telco)
# Since we're only running this once, we can combine testing and assessment
telco_test <- rbind(testing(telco), assessment(telco))
model_ranger <- ranger(Churn ~ ., data = telco_train)
袋外数据的准确性如何?换句话说,使用从每棵树的训练中排除的数据的模型的准确性是多少?
# OOB accuracy
1 - model_ranger$prediction.error
#0.7965168
80%左右。
模型在整个训练数据集上的准确性如何?
# Training data accuracy
accuracy_vec(truth = telco_train$Churn, estimate = model_ranger$predictions)
#0.7965168
完全一样!好的,但是最重要的交叉验证的准确性呢?
# CV accuracy
accuracy_vec(truth = telco_test$Churn, predict(model_ranger, data = telco_test)$predictions)
#0.7921708
它稍微低一点,但与我们在训练数据中看到的非常接近。
如果您只训练一次模型而不尝试对其进行调整,则可以使用所有数据来训练随机森林。当我在工作时,我仍然使用 CV 有以下三个原因:
- 我以特定于训练数据的方式调整模型。
- 通常,我正在对较旧的数据进行培训,并希望我的模型能够处理将来生成的数据。我拿出最新的数据点进行测试。例如,我可能会使用 3 到 24 个月前的数据进行训练,并使用最后两个月进行测试/验证。在这种情况下,我想说明坚持数据中“存在偏差但其程度未知”的事实。
- 我喜欢能够逐个比较模型,所以我对我制作的每个模型都使用相同的保留数据和相同的测试。很高兴能够在所有模型类型中获得完全相同的指标。