对于模型时间中的递归面板数据,提取置信区间和残差失败

Posted

技术标签:

【中文标题】对于模型时间中的递归面板数据,提取置信区间和残差失败【英文标题】:Extracting confidence intervals and residuals is failing for recursive panel data in modeltime 【发布时间】:2022-01-09 17:11:41 【问题描述】:

在我的前一个问题中,我确实在模型时间中提取了递归集成的置信区间。但是,如果我将数据输入更改为时间序列面板,则预测(事前)对象中生成的置信区间列仅显示 NA。

在工作流程过程中肯定有一些错误,我猜到目前为止我没有发现。也许你们中的某个人可以提供帮助。

# Time Series ML
library(tidymodels)
library(modeltime)
library(modeltime.ensemble)

# Core
library(tidyverse)
library(timetk)


FORECAST_HORIZON <- 24

data = m750    # -----------> Single time series input works fine!

# changing the input to panel results in NA for residuals conf_hi and conf_lo...
data <- m4_monthly %>%
  group_by(id) %>%
  future_frame(
    .length_out = FORECAST_HORIZON,
    .bind_data  = TRUE
  ) %>%
  ungroup()

# data def
lag_transformer_grouped <- function(data)
  data %>%
    group_by(id) %>%
    tk_augment_lags(value, .lags = 1:FORECAST_HORIZON) %>%
    ungroup()


data_lags <- data %>%
  lag_transformer_grouped()

test_data <- data_lags %>%
  group_by(id) %>%
  slice_tail(n = 12) %>%
  ungroup()

train_data <- data_lags %>%
  drop_na()

future_data <- data_lags %>%
  filter(is.na(value))

# rec
recipe_spec <- recipe(value ~ date, train_data) %>%
  step_timeseries_signature(date) %>%
  step_rm(matches("(.iso$)|(.xts$)")) %>%
  step_normalize(matches("(index.num$)|(_year$)")) %>%
  step_dummy(all_nominal()) %>%
  step_fourier(date, K = 1, period = 12)

recipe_spec %>% prep() %>% juice()

# elnet 
model_fit_glmnet <- linear_reg(penalty = 1) %>%
  set_engine("glmnet") 

wflw_fit_glmnet <- workflow() %>%
  add_model(model_fit_glmnet) %>%
  add_recipe(recipe_spec %>% step_rm(date)) %>%
  fit(train_data)  %>%
  recursive(
    transform  = lag_transformer_grouped,
    train_tail = panel_tail(train_data, id, FORECAST_HORIZON),
    id         = "id"
  )

# xgboost    
model_fit_xgboost <- boost_tree("regression", learn_rate = 0.35) %>%
  set_engine("xgboost")

wflw_fit_xgboost <- workflow() %>%
  add_model(model_fit_xgboost) %>%
  add_recipe(recipe_spec %>% step_rm(date)) %>%
  fit(train_data) %>%
  recursive(
    transform  = lag_transformer_grouped,
    train_tail = panel_tail(train_data, id, FORECAST_HORIZON),
    id         = "id"
  )

# mtbl
data_models <- modeltime_table(
  wflw_fit_xgboost,
  wflw_fit_glmnet
)

# ensemble
ensemble_fit <- data_models %>% 
  ensemble_weighted(loadings = c(4, 6)) 

# doing calibration for panel with id, as indicated in the documentation 
calibration_tbl <- modeltime_table(
 ensemble_fit) %>%
 modeltime_calibrate(test_data, id = "id", quiet = FALSE) 

# but no residuals for me :(
calib_out <- calibration_tbl$.calibration_data[[1]] %>% 
  left_join(test_data %>% select(id, date, value))

# this function is explicitly for residual extraction. But without panel capability
residuals_method2 <- data_models %>%
  modeltime_calibrate(new_data = test_data) %>%
  modeltime_residuals() 

# Forecast ex ante
data_prepared_tbl <- bind_rows(train_data, test_data)

future_tbl <- data_prepared_tbl %>%
  group_by(id) %>%
  future_frame(.length_out = "2 years") %>%
  ungroup()

# documentation indicates, that calculation of conf_lo and conf_hi should work
ex_ante_obj <- 
  calibration_tbl %>%
  modeltime_forecast(
    new_data    = future_tbl,
    actual_data = data,
    keep_data = TRUE,
    conf_interval = 0.95,
    conf_by_id = TRUE
  )

【问题讨论】:

【参考方案1】:

幸运的是,我通过 github 获得了一些帮助。再次感谢马特丹乔!

我将在下面演示正确的工作流程。这只是我使用的面板数据的错误定义,但你自己看看:

# Time Series ML
library(tidymodels)
library(modeltime)
library(modeltime.ensemble)

# Core
library(tidyverse)
library(timetk)


FORECAST_HORIZON <- 24

# changing the input to panel results in NA for conf_hi and conf_lo...
data <- m4_monthly %>%
  group_by(id) %>%
  ungroup()

# data def
lag_transformer_grouped <- function(data)
  data %>%
    group_by(id) %>%
    tk_augment_lags(value, .lags = 1:FORECAST_HORIZON) %>%
    ungroup()


data_lags <- data %>%
  lag_transformer_grouped()

test_data <- data_lags %>%
  group_by(id) %>%
  slice_tail(n = FORECAST_HORIZON) %>%
  ungroup()

train_data <- data_lags %>%
  drop_na()


# rec
recipe_spec <- recipe(value ~ date, train_data) %>%
  step_timeseries_signature(date) %>%
  step_rm(matches("(.iso$)|(.xts$)")) %>%
  step_normalize(matches("(index.num$)|(_year$)")) %>%
  step_dummy(all_nominal()) %>%
  step_fourier(date, K = 1, period = 12)

recipe_spec %>% prep() %>% juice()

# elnet 
model_fit_glmnet <- linear_reg(penalty = 1) %>%
  set_engine("glmnet") 

wflw_fit_glmnet <- workflow() %>%
  add_model(model_fit_glmnet) %>%
  add_recipe(recipe_spec %>% step_rm(date)) %>%
  fit(train_data)  %>%
  recursive(
    transform  = lag_transformer_grouped,
    train_tail = panel_tail(train_data, id, FORECAST_HORIZON),
    id         = "id"
  )

# xgboost    
model_fit_xgboost <- boost_tree("regression", learn_rate = 0.35) %>%
  set_engine("xgboost")

wflw_fit_xgboost <- workflow() %>%
  add_model(model_fit_xgboost) %>%
  add_recipe(recipe_spec %>% step_rm(date)) %>%
  fit(train_data) %>%
  recursive(
    transform  = lag_transformer_grouped,
    train_tail = panel_tail(train_data, id, FORECAST_HORIZON),
    id         = "id"
  )

# mtbl
data_models <- modeltime_table(
  wflw_fit_xgboost,
  wflw_fit_glmnet
)

# ensemble
ensemble_fit <- data_models %>% 
  ensemble_weighted(loadings = c(4, 6)) 

# doing calibration for panel with id, as indicated in the documentation 
calibration_tbl <- modeltime_table(
  ensemble_fit) %>%
  modeltime_calibrate(test_data, id = "id", quiet = FALSE) 

# but no residuals for me :(
calib_out <- calibration_tbl$.calibration_data[[1]] %>% 
  left_join(test_data %>% select(id, date, value))


# Forecast ex ante
data_prepared_tbl <- bind_rows(train_data, test_data)

future_tbl <- data_prepared_tbl %>%
  group_by(id) %>%
  future_frame(.length_out = "2 years") %>%
  ungroup()

# documentation indicates, that calculation of conf_lo and conf_hi should work
ex_ante_obj <- 
  calibration_tbl %>%
  modeltime_forecast(
    new_data    = future_tbl,
    actual_data = data,
    keep_data = TRUE,
    conf_interval = 0.95,
    conf_by_id = TRUE
  )

【讨论】:

以上是关于对于模型时间中的递归面板数据,提取置信区间和残差失败的主要内容,如果未能解决你的问题,请参考以下文章

用matlab进行曲线拟合时,如何判断拟合的好坏

matlab-线性回归

R - 对每组数据使用不同的模型进行预测和置信区间

Logistic 回归的预测和置信区间

R中线性回归模型后的置信区间[关闭]

置信区间、显著性检验和统计学意义