开发者社区> 问答> 正文

通过sample()进行的数据改组将RMSE在testset中的值降到比trainingset低的值

我发现了一个奇特的效果,即测试集的RMSE低于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" ) 更新1:预告有关数据泄漏到测试集中 我检查了数据分布,并发现了所描述效果的潜在提示。

训练集分布:

. 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 使用洗牌测试集分布:

. 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())的分层更加“分层”-我的意思是“更接近训练集分布”。这可能会导致数据泄漏到相反方向的影响-进入测试集。

更新2:可复制代码 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 效果可重现!

展开
收起
被纵养的懒猫 2019-10-08 17:00:07 693 0
0 条回答
写回答
取消 提交回答
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载