为每个目标时间序列提供不同的变换参数

问题描述 投票:0回答:1

问:在 tidyverts/fable 预测框架中,有很多目标时间序列需要预测,如何为每个序列提供不同的目标变换参数?

特别是,我想对每个时间序列进行 Box-Cox 变换,但对每个序列使用“不同”的 lambda,例如,根据每个序列的 Guerrero 方法估计的 lambda。我如何在框架内做到这一点? 以下是我的几次尝试。我收到错误。

如果在框架内没有办法做到这一点,我可以使用一个好的技巧吗?理想情况下,它仍然可以处理分层时间序列。

下面,我提出了一个 hack。我不确定它是否仍然适用于分层时间序列。我应该检查一下。无论如何,我认为大多数人都有更好的方法来处理事情。

library(fpp3) # construct data in transformed space directly z1 <- arima.sim(n=104,list(ar=0.9)) z2 <- arima.sim(n=104,list(ma=0.5)) # inverse to get data in the untransformed space y1 <- fabletools::inv_box_cox(z1, lambda=0.25) y2 <- fabletools::inv_box_cox(z2, lambda=0.75) # create tsibble for time series modeling tibble(idx=1:104, y1=y1, y2=y2) %>% pivot_longer(cols=c(y1,y2), names_to='series', values_to='value') %>% tsibble(index=idx, key=series) -> dat # estimate optimal box-cox transform lambda for each series using guerrero # method dat %>% fabletools::features(value, features='guerrero') -> lambdas # # A tibble: 2 × 2 # series lambda_guerrero # <chr> <dbl> # 1 y1 0.0991 # 2 y2 0.751 # set up the optimal lambdas as exogenous regressors? dat %>% inner_join(lambdas, by=join_by(series)) -> dat.xrg dat.xrg %>% model(arima=ARIMA(box_cox(value,lambda=lambda))) -> fit # Error in `.g()`: # ! Response variable transformation has incompatible lengths, all arguments must be the length of the data 104 or 1. # Run `rlang::last_trace()` to see where the error occurred. # Try defining lambda outside, and of the length desired? lambdas %>% pull(lambda_guerrero) %>% rep(each=104) -> lambda length(lambda) # [1] 208 dat %>% model(arima=ARIMA(box_cox(value, lambda=lambda))) -> fit # Error in `.g()`: # ! Response variable transformation has incompatible lengths, all arguments must be the length of the data 208 or 1. # Run `rlang::last_trace()` to see where the error occurred. # just going with a tidy-hack # is this the best one can do? dat %>% nest(.by=series) %>% inner_join(lambdas, by = "series") %>% mutate( fit=map2( data, lambda_guerrero, \(.dat,.lambda) model( .dat, arima=ARIMA(box_cox(value, lambda=.lambda)) ) ) ) %>% unnest(cols=fit) %>% select(series, arima) %>% as_mable(key='series', model='arima') -> fit # looks right fit # # A mable: 2 x 2 # # Key: series [2] # series arima # <chr> <model> # 1 y1 <ARIMA(1,0,2)> # 2 y2 <ARIMA(0,0,1)> # still get access to all the nice fable tools fit %>% accuracy() # # A tibble: 2 × 11 # series .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1 # <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> # 1 y1 arima Training 0.311 3.97 1.91 -450. 512. 0.956 0.961 -0.123 # 2 y2 arima Training 0.269 1.16 0.918 -884. 1003. 0.879 0.840 0.00342 # can make a nice plot fit %>% augment() %>% ggplot(aes(x=idx, y=value)) + geom_point() + geom_line(aes(y=.fitted),color='blue') + facet_grid(rows=vars(series))

my nice plot

r purrr forecasting fable-r
1个回答
0
投票

# The column name for the lambda parameter in dat.xrg is lambda_guerrero, not lambda dat.xrg %>% model(arima=ARIMA(box_cox(value,lambda=lambda_guerrero)))

但请注意,检测到的响应变量现在是 
box_cox(value,lambda=lambda_guerrero)

而不是

value
,因此输出不会自动反向转换。这是因为
value
lambda_guerrero
具有相同的长度,因此响应变量检测算法不会将
value
识别为预期响应。
您可以使用 

resp()

:

 明确说明什么变量是响应变量
dat.xrg %>% model(arima=ARIMA(box_cox(resp(value), lambda=lambda_guerrero))) -> fit

这种在数据集中提供与响应长度相同的 
lambda_guerrero

的方法允许转换参数随时间变化。因此,这还要求您在预测时指定

lambda_guerrero
的未来值。
如果您希望它不随时间变化,您可能想使用单个值 

lambda

。如果在转换响应时使用长度为 1 的输入/变量,它将被缓存并重新用于预测。要在转换中使用 length-1 变量,您可以使用

first(lambda_guerrero)
:
dat.xrg %>%
  model(arima=ARIMA(box_cox(value, lambda=first(lambda_guerrero)))) ->
  fit

或者也许是最简单和最简洁的,您可以直接在转换中计算 
guerrero()

library(fpp3)

# construct data in transformed space directly
z1 <- arima.sim(n=104,list(ar=0.9))
z2 <- arima.sim(n=104,list(ma=0.5))

# inverse to get data in the untransformed space
y1 <- fabletools::inv_box_cox(z1, lambda=0.25)
y2 <- fabletools::inv_box_cox(z2, lambda=0.75)

# create tsibble for time series modeling
tibble(idx=1:104, y1=y1, y2=y2) %>% 
  pivot_longer(cols=c(y1,y2), names_to='series', values_to='value') %>%
  tsibble(index=idx, key=series) ->
  dat

dat |> 
  model(arima=ARIMA(box_cox(value, lambda=guerrero(value))))
#> # A mable: 2 x 2
#> # Key:     series [2]
#>   series          arima
#>   <chr>         <model>
#> 1 y1     <ARIMA(1,0,0)>
#> 2 y2     <ARIMA(0,0,1)>

创建于 2024-05-14,使用 

reprex v2.0.2

© www.soinside.com 2019 - 2024. All rights reserved.