Интервалы прогнозирования из лесов Квантильной регрессии имеют более высокий охват, чем ожидалось?

#r #random-forest #tidymodels #quantile-regression #r-ranger

Вопрос:

Вопрос:

Какие факторы могут привести к тому, что интервал прогнозирования будет иметь более широкий охват, чем можно было бы ожидать? Особенно в отношении лесов квантильной регрессии с пакетом ranger?

Конкретный контекст РЕПРЕКС:

Я использую леса квантильной регрессии через пастернак и набор пакетов ranger tidymodels для генерации интервалов прогнозирования. Я рассматривал пример с использованием ames данных о жилье и был удивлен, увидев в приведенном ниже примере, что мои 90%-ные интервалы прогнозирования имели эмпирическое покрытие ~97% при оценке по набору данных с задержкой (охват обучающих данных был еще выше).

Это было еще более удивительно, учитывая, что производительность моей модели значительно хуже в режиме ожидания, чем в режиме обучения, поэтому я бы предположил, что охват был бы меньше, чем ожидалось, а не больше, чем ожидалось?

Загрузка библиотек, данных, разделение настроек:

 ```{r}
library(tidyverse)
library(tidymodels)
library(AmesHousing)

ames <- make_ames() %>% 
  mutate(Years_Old = Year_Sold - Year_Built,
         Years_Old = ifelse(Years_Old < 0, 0, Years_Old))

set.seed(4595)
data_split <- initial_split(ames, strata = "Sale_Price", p = 0.75)

ames_train <- training(data_split)
ames_test  <- testing(data_split)
```
 

Укажите рабочий процесс модели:

 ```{r}
rf_recipe <- 
  recipe(
    Sale_Price ~ Lot_Area   Neighborhood    Years_Old   Gr_Liv_Area   Overall_Qual   Total_Bsmt_SF   Garage_Area, 
    data = ames_train
  ) %>%
  step_log(Sale_Price, base = 10) %>%
  step_other(Neighborhood, Overall_Qual, threshold = 50) %>% 
  step_novel(Neighborhood, Overall_Qual) %>% 
  step_dummy(Neighborhood, Overall_Qual) 

rf_mod <- rand_forest() %>% 
  set_engine("ranger", importance = "impurity", seed = 63233, quantreg = TRUE) %>% 
  set_mode("regression")

set.seed(63233)
rf_wf <- workflows::workflow() %>% 
  add_model(rf_mod) %>% 
  add_recipe(rf_recipe) %>% 
  fit(ames_train)
```
 

Make predictions on training and hold-out datasets:

 ```{r}
rf_preds_train <- predict(
  rf_wf$fit$fit$fit, 
  workflows::pull_workflow_prepped_recipe(rf_wf) %>% bake(ames_train),
  type = "quantiles",
  quantiles = c(0.05, 0.50, 0.95)
  ) %>% 
  with(predictions) %>% 
  as_tibble() %>% 
  set_names(paste0(".pred", c("_lower", "", "_upper"))) %>% 
  mutate(across(contains(".pred"), ~10^.x)) %>% 
  bind_cols(ames_train)

rf_preds_test <- predict(
  rf_wf$fit$fit$fit, 
  workflows::pull_workflow_prepped_recipe(rf_wf) %>% bake(ames_test),
  type = "quantiles",
  quantiles = c(0.05, 0.50, 0.95)
  ) %>% 
  with(predictions) %>% 
  as_tibble() %>% 
  set_names(paste0(".pred", c("_lower", "", "_upper"))) %>% 
  mutate(across(contains(".pred"), ~10^.x)) %>% 
  bind_cols(ames_test)
```
 

Покажите, что коэффициент охвата намного выше как для данных обучения, так и для данных о задержке, чем ожидалось на 90% (эмпирически кажется, что он составляет ~98% и ~97% соответственно).:

 ```{r}
rf_preds_train %>%
  mutate(covered = ifelse(Sale_Price >= .pred_lower amp; Sale_Price <= .pred_upper, 1, 0)) %>% 
  summarise(n = n(),
            n_covered = sum(
              covered
            ),
            covered_prop = n_covered / n,
            stderror = sd(covered) / sqrt(n)) %>% 
  mutate(min_coverage = covered_prop - 2 * stderror,
         max_coverage = covered_prop   2 * stderror)
# # A tibble: 1 x 6
#       n n_covered covered_prop stderror min_coverage max_coverage
#   <int>     <dbl>        <dbl>    <dbl>        <dbl>        <dbl>
# 1  2199      2159        0.982  0.00285        0.976        0.988

rf_preds_test %>%
  mutate(covered = ifelse(Sale_Price >= .pred_lower amp; Sale_Price <= .pred_upper, 1, 0)) %>% 
  summarise(n = n(),
            n_covered = sum(
              covered
            ),
            covered_prop = n_covered / n,
            stderror = sd(covered) / sqrt(n)) %>% 
  mutate(min_coverage = covered_prop - 2 * stderror,
         max_coverage = covered_prop   2 * stderror)
# # A tibble: 1 x 6
#       n n_covered covered_prop stderror min_coverage max_coverage
#   <int>     <dbl>        <dbl>    <dbl>        <dbl>        <dbl>
# 1   731       706        0.966  0.00673        0.952        0.979
```
 

Догадки:

  • Что-то в ranger пакете или лесах квантильной регрессии чрезмерно экстремально в том, как они оценивают квантили, или я каким-то образом перестраиваюсь в «крайнем» направлении, что приводит к моим очень консервативным интервалам прогнозирования
  • Это особенность, характерная для данного набора данных / модели
  • Я что-то упускаю или что-то неправильно настраиваю

Комментарии:


1. Вытекает из соответствующего сообщения в блоге: bryanshalloway.com/2021/04/21/…

2. Перекрестный вопрос на github в imbs-hl/ranger .