使用寓言包计算 R 中测试集的 1 步预测误差的正确方法是什么?
What is the correct way to calculate 1 step forecast errors over a test set in R using the fable package?
我正在努力理解使用 R 的 {fable}
包计算测试集上的一步预测误差的正确方法。
首先,我对单步预测误差的理解是:
- 在时间t,我们预测下一个时间段,t+1
- 观察t+1,计算残差等
- 根据我们在 t+1 观察到的新数据对 t+2 进行预测(使用我们在时间 t 所做的相同 model/coefs)
- 对测试集重复步骤 1-3。
我看过这个 post: which aligns with the method discussed in FPP3,但我得到的结果与我的直觉不符。当测试集小于拟合模型的季节性 window 时,此方法也会失败。此外,当没有 refit()
方法可用于预测算法时,您会怎么做? (例如提供的 THETA()
技术)。
下面是用 2 种不同方式截取的代码,我认为应该在拟合模型后计算 24m 测试集上的 1 步预测误差。第一个基于上面链接的 post 中的方法,第二个是我想出的循环。
这两种方法都产生了准确性和预测,但它们的差异并不小。他们为什么不同?哪一个是正确的?
一般来说,如果我有一个模型并对 t+1 进行预测,观察 y_{t+1},我并不清楚我将如何使用经过训练的模型和新的观察来进行预测对于 t+2。
# Init
library(tidyverse)
library(fable)
#> Loading required package: fabletools
# Prepare data
us_accidental_deaths <- as_tsibble(USAccDeaths)
deaths_train <- head(us_accidental_deaths, -24)
deaths_test <- tail(us_accidental_deaths, 24)
# Get models on training data
deaths_fits_0 <- deaths_train %>%
model(ets = ETS(value))
##############
# Normal way #
##############
# 'refit' without estimating new params/coefs on the new data
deaths_fits_1 <- deaths_fits_0 %>%
refit(deaths_test, reestimate = FALSE)
# what happens here if the test set is smaller than the seasonality windows?
# 1-step forecast accuracy on the test set?
deaths_fits_1 %>%
accuracy()
#> # A tibble: 1 x 10
#> .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ets Training 30.4 142. 111. 0.334 1.24 0.428 0.416 -0.105
# The 1-step forecasts?
fitted(deaths_fits_1)
#> # A tsibble: 24 x 3 [1M]
#> # Key: .model [1]
#> .model index .fitted
#> <chr> <mth> <dbl>
#> 1 ets 1977 Jan 7770.
#> 2 ets 1977 Feb 6906.
#> 3 ets 1977 Mar 7680.
#> 4 ets 1977 Apr 8135.
#> 5 ets 1977 May 8964.
#> 6 ets 1977 Jun 9264.
#> 7 ets 1977 Jul 10457.
#> 8 ets 1977 Aug 9547.
#> 9 ets 1977 Sep 8520.
#> 10 ets 1977 Oct 8660.
#> # ... with 14 more rows
################
# Using a loop #
################
# Initialise fit
death_fits_2 <- deaths_fits_0
# List to store 1 step forecasts in
test_forecasts_list <- list()
# Begin loop
for (i in 1:length(unique(deaths_test$index))){
# 1 step forecast
one_step_fc <- death_fits_2 %>%
forecast(h = 1)
# store
test_forecasts_list[[i]] <- one_step_fc
# refit using the newly observed datapoint
death_fits_2 <- deaths_fits_0 %>%
refit(
bind_rows(
deaths_train,
deaths_test %>%
arrange(index) %>%
slice_head(n=i)
),
reestimate=FALSE
)
}
test_forecasts_2 <- bind_rows(test_forecasts_list)
# 1-step forecast accuracy over test set
test_forecasts_2 %>%
accuracy(data=us_accidental_deaths)
#> # A tibble: 1 x 10
#> .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ets Test 37.0 255. 194. 0.308 2.19 0.352 0.380 -0.305
# 1-step forecasts
test_forecasts_2
#> # A fable: 24 x 4 [1M]
#> # Key: .model [1]
#> .model index value .mean
#> <chr> <mth> <dist> <dbl>
#> 1 ets 1977 Jan N(7837, 110265) 7837.
#> 2 ets 1977 Feb N(7129, 95555) 7129.
#> 3 ets 1977 Mar N(7783, 93292) 7783.
#> 4 ets 1977 Apr N(7912, 91760) 7912.
#> 5 ets 1977 May N(8894, 89411) 8894.
#> 6 ets 1977 Jun N(9418, 87442) 9418.
#> 7 ets 1977 Jul N(10072, 85241) 10072.
#> 8 ets 1977 Aug N(9891, 89234) 9891.
#> 9 ets 1977 Sep N(8388, 93841) 8388.
#> 10 ets 1977 Oct N(8679, 91768) 8679.
#> # ... with 14 more rows
由 reprex package (v2.0.1)
于 2022-05-31 创建
ETS模型中有两组参数,初始状态和平滑参数。使用原始初始状态并将它们应用于不同的时间段几乎没有任何意义,因此默认情况下 refit()
re-estimates 初始状态但在提供的模型中保留平滑参数。
在您的第一次尝试中,初始状态在测试数据开始时为 re-estimated,而在您的循环中,初始状态在每次迭代中为 re-estimated。
您可能想要的不是 re-estimate 任何东西,而是查看您的模型在测试集上的表现如何。您可以通过将模型重新拟合到训练集和测试集的组合,然后过滤掉测试集上的结果来做到这一点。像这样:
# 'refit' without estimating new params/coefs on all data
deaths_fits_1 <- deaths_fits_0 %>%
refit(us_accidental_deaths, reinitialise=FALSE)
# 1-step forecasts on the test set
deaths_fits_1 %>%
fitted() %>%
tail(24)
这也避免了当测试集小于季节性周期时产生错误的问题。
我正在努力理解使用 R 的 {fable}
包计算测试集上的一步预测误差的正确方法。
首先,我对单步预测误差的理解是:
- 在时间t,我们预测下一个时间段,t+1
- 观察t+1,计算残差等
- 根据我们在 t+1 观察到的新数据对 t+2 进行预测(使用我们在时间 t 所做的相同 model/coefs)
- 对测试集重复步骤 1-3。
我看过这个 post:refit()
方法可用于预测算法时,您会怎么做? (例如提供的 THETA()
技术)。
下面是用 2 种不同方式截取的代码,我认为应该在拟合模型后计算 24m 测试集上的 1 步预测误差。第一个基于上面链接的 post 中的方法,第二个是我想出的循环。
这两种方法都产生了准确性和预测,但它们的差异并不小。他们为什么不同?哪一个是正确的?
一般来说,如果我有一个模型并对 t+1 进行预测,观察 y_{t+1},我并不清楚我将如何使用经过训练的模型和新的观察来进行预测对于 t+2。
# Init
library(tidyverse)
library(fable)
#> Loading required package: fabletools
# Prepare data
us_accidental_deaths <- as_tsibble(USAccDeaths)
deaths_train <- head(us_accidental_deaths, -24)
deaths_test <- tail(us_accidental_deaths, 24)
# Get models on training data
deaths_fits_0 <- deaths_train %>%
model(ets = ETS(value))
##############
# Normal way #
##############
# 'refit' without estimating new params/coefs on the new data
deaths_fits_1 <- deaths_fits_0 %>%
refit(deaths_test, reestimate = FALSE)
# what happens here if the test set is smaller than the seasonality windows?
# 1-step forecast accuracy on the test set?
deaths_fits_1 %>%
accuracy()
#> # A tibble: 1 x 10
#> .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ets Training 30.4 142. 111. 0.334 1.24 0.428 0.416 -0.105
# The 1-step forecasts?
fitted(deaths_fits_1)
#> # A tsibble: 24 x 3 [1M]
#> # Key: .model [1]
#> .model index .fitted
#> <chr> <mth> <dbl>
#> 1 ets 1977 Jan 7770.
#> 2 ets 1977 Feb 6906.
#> 3 ets 1977 Mar 7680.
#> 4 ets 1977 Apr 8135.
#> 5 ets 1977 May 8964.
#> 6 ets 1977 Jun 9264.
#> 7 ets 1977 Jul 10457.
#> 8 ets 1977 Aug 9547.
#> 9 ets 1977 Sep 8520.
#> 10 ets 1977 Oct 8660.
#> # ... with 14 more rows
################
# Using a loop #
################
# Initialise fit
death_fits_2 <- deaths_fits_0
# List to store 1 step forecasts in
test_forecasts_list <- list()
# Begin loop
for (i in 1:length(unique(deaths_test$index))){
# 1 step forecast
one_step_fc <- death_fits_2 %>%
forecast(h = 1)
# store
test_forecasts_list[[i]] <- one_step_fc
# refit using the newly observed datapoint
death_fits_2 <- deaths_fits_0 %>%
refit(
bind_rows(
deaths_train,
deaths_test %>%
arrange(index) %>%
slice_head(n=i)
),
reestimate=FALSE
)
}
test_forecasts_2 <- bind_rows(test_forecasts_list)
# 1-step forecast accuracy over test set
test_forecasts_2 %>%
accuracy(data=us_accidental_deaths)
#> # A tibble: 1 x 10
#> .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ets Test 37.0 255. 194. 0.308 2.19 0.352 0.380 -0.305
# 1-step forecasts
test_forecasts_2
#> # A fable: 24 x 4 [1M]
#> # Key: .model [1]
#> .model index value .mean
#> <chr> <mth> <dist> <dbl>
#> 1 ets 1977 Jan N(7837, 110265) 7837.
#> 2 ets 1977 Feb N(7129, 95555) 7129.
#> 3 ets 1977 Mar N(7783, 93292) 7783.
#> 4 ets 1977 Apr N(7912, 91760) 7912.
#> 5 ets 1977 May N(8894, 89411) 8894.
#> 6 ets 1977 Jun N(9418, 87442) 9418.
#> 7 ets 1977 Jul N(10072, 85241) 10072.
#> 8 ets 1977 Aug N(9891, 89234) 9891.
#> 9 ets 1977 Sep N(8388, 93841) 8388.
#> 10 ets 1977 Oct N(8679, 91768) 8679.
#> # ... with 14 more rows
由 reprex package (v2.0.1)
于 2022-05-31 创建ETS模型中有两组参数,初始状态和平滑参数。使用原始初始状态并将它们应用于不同的时间段几乎没有任何意义,因此默认情况下 refit()
re-estimates 初始状态但在提供的模型中保留平滑参数。
在您的第一次尝试中,初始状态在测试数据开始时为 re-estimated,而在您的循环中,初始状态在每次迭代中为 re-estimated。
您可能想要的不是 re-estimate 任何东西,而是查看您的模型在测试集上的表现如何。您可以通过将模型重新拟合到训练集和测试集的组合,然后过滤掉测试集上的结果来做到这一点。像这样:
# 'refit' without estimating new params/coefs on all data
deaths_fits_1 <- deaths_fits_0 %>%
refit(us_accidental_deaths, reinitialise=FALSE)
# 1-step forecasts on the test set
deaths_fits_1 %>%
fitted() %>%
tail(24)
这也避免了当测试集小于季节性周期时产生错误的问题。