[我已经发现了一个奇特的效果,即与sample
软件包和caret
功能一起使用的训练集相比,测试集的RMSE更低。
我的代码对训练和测试集进行了常见划分:
set.seed(seed)
training.index <- createDataPartition(dataset[[target_label]], p = 0.8, list = FALSE)
training.set <- dataset[training.index, ]
testing.set <- dataset[-training.index, ]
例如给出测试集0.651
的RMSE,它高于训练集RMSE 0.575
-如预期。
遵循许多资料来源的建议,例如here,应将数据重新排序,因此我在进行上述拆分之前就已经这样做:
# shuffle data - short version:
set.seed(17)
dataset <- data %>% nrow %>% sample %>% data[.,]
[洗牌后,测试集RMSE 0.528
比训练集RMSE 0.575
低!这一发现在包括lm, glm, knn, kknn, rf, gbm, svmLinear, svmRadial
等在内的多种算法中都是一致的。
据我所知,sample()的默认值为replace = FALSE
,因此不会有任何数据泄漏到测试集中。尽管createDataPartition
进行分层,但在分类(准确性和kappa)中也会出现相同的观察结果,因此应处理任何数据不平衡的情况。
我不使用任何特殊配置,仅使用普通的交叉验证:
training.configuration <- trainControl( method = "repeatedcv", number = 10 , repeats = CV.REPEATS , savePredictions = "final", # , returnResamp = "all" )
我在这里想念什么?
-
我检查了数据分布,并发现了所描述效果的潜在提示。
训练集分配:
. Freq prop 1 1 124 13.581599 2 2 581 63.636364 3 3 194 21.248631 4 4 14 1.533406
测试集分布无
随机播放:
. Freq prop 1 1 42 18.502203 2 2 134 59.030837 3 3 45 19.823789 4 4 6 2.643172
测试集分布with
随机播放:
. Freq prop 1 1 37 16.299559 2 2 139 61.233480 3 3 45 19.823789 4 4 6 2.643172
[如果我们查看模式(最频繁的值),则它在带有随机
61.2%
的测试集中的比例要比不带有随机63.6%
的训练集比例59.0%
更近。我不知道如何用基本理论从统计学上解释这一点-有人可以吗?
[我的直觉是,改组使测试集分布(由createDataPartition()
隐式执行)的分层更加“分层”-我的意思是“更接近训练集分布”。这可能会导致数据向相反方向泄漏的影响-进入测试集。
library(caret) library(tidyverse) library(magrittr) library(mlbench) data(BostonHousing) seed <- 171 # shuffled <- TRUE shuffled <- FALSE if (shuffled) { dataset <- BostonHousing %>% nrow %>% sample %>% BostonHousing[., ] } else { dataset <- BostonHousing %>% as_tibble() } target_label <- "medv" features_labels <- dataset %>% select_if(is.numeric) %>% select(-target_label) %>% names %T>% print # define ml algorithms to train algorithm_list <- c( "lm" , "glmnet" , "knn" , "gbm" , "rf" ) # repeated cv training_configuration <- trainControl( method = "repeatedcv", number = 10 , repeats = 10 , savePredictions = "final", # , returnResamp = "all" ) # preprocess by standardization within each k-fold preprocess_configuration = c("center", "scale") # select variables dataset %<>% select(target_label, features_labels) %>% na.omit # dataset subsetting for tibble: [[ set.seed(seed) training.index <- createDataPartition(dataset[[target_label]], p = 0.8, list = FALSE) training.set <- dataset[training.index, ] testing.set <- testing.set <- dataset[-training.index, ] ######################################## # 3.2: Select the target & features ######################################## target <- training.set[[target_label]] features <- training.set %>% select(features_labels) %>% as.data.frame ######################################## # 3.3: Train the models ######################################## models.list <- list() models.list <- algorithm_list %>% map(function(algorithm_label) { model <- train( x = features, y = target, method = algorithm_label, preProcess = preprocess_configuration, trControl = training_configuration ) return(model) } ) %>% setNames(algorithm_list)
更新:用于计算测试集性能的代码
observed <- testing.set[[target_label]] models.list %>% predict(testing.set) %>% map_df(function(predicted) { sqrt(mean((observed - predicted)^2)) }) %>% t %>% as_tibble(rownames = "model") %>% rename(RMSE.testing = V1) %>% arrange(RMSE.testing) %>% as.data.frame
在
shuffled = FALSE
上同时为shuffled = TRUE
和testing.set
运行此代码将给出:
model RMSE.testing RMSE.testing.shuffled
1 gbm 3.436164 2.355525
2 glmnet 4.516441 3.785895
3 knn 3.175147 3.340218
4 lm 4.501077 3.843405
5 rf 3.366466 2.092024
效果可再现!
我已经发现了一个奇特的效果,即测试集的RMSE低于带有插入符号包的带有样本功能的训练集的RMSE。我的代码对训练和...
之所以获得不同的测试RMSE,是因为您拥有不同的测试集。您正在整理数据,然后每次都使用相同的training.index
,因此没有理由相信每次测试集都将相同。
在您的原始比较中,您需要将改组后的测试数据的RMSE与改组后的训练数据(而不是原始训练数据)的RMSE进行比较。
我完全同意强尼·菲尔普斯(Jonny Phelps)的回答。根据您的代码和插入符号功能代码,对混洗后的数据使用createDataPartition
时,没有理由怀疑任何类型的数据泄漏。因此,性能差异必须归因于不同的训练/测试拆分。