business-science / modeltime

Modeltime unlocks time series forecast models and machine learning in one framework
https://business-science.github.io/modeltime/
Other
532 stars 82 forks source link

Prophet Regressors #36

Closed wprucknic closed 4 years ago

wprucknic commented 4 years ago
    # Add regressors
    xreg_nms <- names(xreg_tbl)
    if (length(xreg_nms) > 0) {
        for (nm in xreg_nms) {
            m <- prophet::add_regressor(m, name = nm, prior.scale = 10000)
        }
    }

The add_regressor function also allows one to specify if the regressor will be standardized TRUE/FALSE. Is it possible to include this option in the modeltime framework?

mdancho84 commented 4 years ago

This is a good call. I've changed the internals of the prophet_fit_impl() to allow you to pass arguments to prophet::add_regressors() via set_engine(). Here's an example:

library(modeltime)
library(tidymodels)
library(tidyverse)
library(timetk)
library(lubridate)

m750 <- m4_monthly %>%
    filter(id == "M750")

splits <- initial_time_split(m750, prop = 0.9)

model_fit_prophet <- prophet_reg() %>%
    set_engine("prophet", 
               regressors.prior.scale = 0.1, 
               regressors.standardize = FALSE, 
               regressors.mode = "multiplicative") %>%
    fit(value ~ date + month(date, label = TRUE), training(splits))

When the new arguments are added, the model will update for any regressors that are being added.

image

wprucknic commented 4 years ago

Thank you!

Are these "tune()-able"?

mdancho84 commented 4 years ago

Yes - via set_engine().

library(modeltime)
library(tidymodels)
library(tidyverse)
library(timetk)
library(lubridate)

m750 <- m4_monthly %>%
    filter(id == "M750")

splits <- initial_time_split(m750, prop = 0.9)

model_spec <- prophet_reg() %>%
    set_engine("prophet", 
               regressors.prior.scale = tune("regressors.prior.scale"))

recipe_spec <- recipe(value ~ date, training(splits)) %>% 
    step_timeseries_signature(date)

grid <- tibble(regressors.prior.scale = c(1, 10, 1000, 10000))

resamp <- vfold_cv(training(splits), v = 5)

tune_results <- tune_grid(
    model_spec,
    preprocessor = recipe_spec,
    grid         = grid,
    resamples    = resamp
)

tune_results %>% tune::show_best()
#> Warning: No value of `metric` was given; metric 'rmse' will be used.
#> # A tibble: 4 x 7
#>   regressors.prior.scale .metric .estimator  mean     n std_err .config
#>                    <dbl> <chr>   <chr>      <dbl> <int>   <dbl> <chr>  
#> 1                      1 rmse    standard    244.     5    10.5 Model1 
#> 2                     10 rmse    standard    244.     5    10.8 Model2 
#> 3                   1000 rmse    standard    244.     5    10.5 Model3 
#> 4                  10000 rmse    standard    244.     5    11.3 Model4

Created on 2020-09-03 by the reprex package (v0.3.0)