перемешивание данных при выборке () уменьшает среднеквадратичное среднеквадратичное отклонение до более низкого значения в тестовом наборе, чем в обучающем наборе - PullRequest
1 голос
/ 28 сентября 2019

Я обнаружил своеобразный эффект, что RMSE становится меньше для тестового набора, чем для обучающего набора с функцией sample с пакетом caret.

Мой код выполняет общее разделение набора обучения и тестирования:

  set.seed(seed)
  training.index <- createDataPartition(dataset[[target_label]], p = 0.8, list = FALSE)
  training.set <- dataset[training.index, ]
  testing.set <- dataset[-training.index, ]

Это, например, дает RMSE для набора тестирования 0.651, который выше, чем обучающий набор RMSE 0.575 - какожидается.

В соответствии с рекомендациями многих источников, например здесь , данные должны быть перетасованы, поэтому я делаю это до разделения выше:

  # 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 выполняет стратификацию, поэтому любой дисбаланс данных следует обрабатывать.

Я не использую какую-либо необычную конфигурацию, просто обычную перекрестную проверку:

  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

Распределение испытательного набора без shuffle:

  . Freq      prop
1 1   42 18.502203
2 2  134 59.030837
3 3   45 19.823789
4 4    6  2.643172

ПроверкаРаспределение набора с shuffle:

  . Freq      prop
1 1   37 16.299559
2 2  139 61.233480
3 3   45 19.823789
4 4    6  2.643172

Если мы посмотрим на режим (наиболее частое значение), его доля в тестовом наборе с shuffle 61.2% ближе к пропорции обучающего набора63.6% чем без перемешивания 59.0%.

Я не знаю, как статистически интерпретировать это с помощью лежащей в основе теории - кто-нибудь может?

Моя интуиция заключается в том, что перетасовка делает стратификацию распределения тестового набора (неявно выполняемую createDataPartition()) «более стратифицированный» - под этим я подразумеваю «ближе к распределению учебных наборов».Это может вызвать эффект утечки данных в противоположном направлении - в набор для тестирования.

Обновление 2: Воспроизводимый код

library(caret)
library(tidyverse)
library(magrittr)

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)

Запуск этого кода для 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

Эффект воспроизводим!

...