README.md in prophet-rb-0.4.0 vs README.md in prophet-rb-0.4.1

- old
+ new

@@ -86,11 +86,12 @@ - [Trend Changepoints](#trend-changepoints) - [Holidays and Special Events](#holidays-and-special-events) - [Multiplicative Seasonality](#multiplicative-seasonality) - [Uncertainty Intervals](#uncertainty-intervals) - [Non-Daily Data](#non-daily-data) -- [Saving Models](#saving-models) +- [Diagnostics](#diagnostics) +- [Additional Topics](#additional-topics) ## Advanced Quick Start [Explanation](https://facebook.github.io/prophet/docs/quick_start.html) @@ -175,15 +176,28 @@ ```ruby df = Rover.read_csv("example_wp_log_R.csv") df["cap"] = 8.5 m = Prophet.new(growth: "logistic") m.fit(df) -future = m.make_future_dataframe(periods: 365) +future = m.make_future_dataframe(periods: 1826) future["cap"] = 8.5 forecast = m.predict(future) ``` +Saturating minimum + +```ruby +df["y"] = 10 - df["y"] +df["cap"] = 6 +df["floor"] = 1.5 +future["cap"] = 6 +future["floor"] = 1.5 +m = Prophet.new(growth: "logistic") +m.fit(df) +forecast = m.predict(future) +``` + ## Trend Changepoints [Explanation](https://facebook.github.io/prophet/docs/trend_changepoints.html) Plot changepoints @@ -306,14 +320,69 @@ m = Prophet.new(changepoint_prior_scale: 0.01).fit(df) future = m.make_future_dataframe(periods: 300, freq: "H") forecast = m.predict(future) ``` -## Saving Models +## Diagnostics -[Explanation](https://facebook.github.io/prophet/docs/additional_topics.html#saving-models) +[Explanation](http://facebook.github.io/prophet/docs/diagnostics.html) +Cross validation + +```ruby +df_cv = Prophet::Diagnostics.cross_validation(m, initial: "730 days", period: "180 days", horizon: "365 days") +``` + +Custom cutoffs + +```ruby +cutoffs = ["2013-02-15", "2013-08-15", "2014-02-15"].map { |v| Time.parse("#{v} 00:00:00 UTC") } +df_cv2 = Prophet::Diagnostics.cross_validation(m, cutoffs: cutoffs, horizon: "365 days") +``` + +Get performance metrics + +```ruby +df_p = Prophet::Diagnostics.performance_metrics(df_cv) +``` + +Plot cross validation metrics + +```ruby +Prophet::Plot.plot_cross_validation_metric(df_cv, metric: "mape") +``` + +Hyperparameter tuning + +```ruby +param_grid = { + changepoint_prior_scale: [0.001, 0.01, 0.1, 0.5], + seasonality_prior_scale: [0.01, 0.1, 1.0, 10.0] +} + +# Generate all combinations of parameters +all_params = param_grid.values[0].product(*param_grid.values[1..-1]).map { |v| param_grid.keys.zip(v).to_h } +rmses = [] # Store the RMSEs for each params here + +# Use cross validation to evaluate all parameters +all_params.each do |params| + m = Prophet.new(**params).fit(df) # Fit model with given params + df_cv = Prophet::Diagnostics.cross_validation(m, cutoffs: cutoffs, horizon: "30 days") + df_p = Prophet::Diagnostics.performance_metrics(df_cv, rolling_window: 1) + rmses << df_p["rmse"][0] +end + +# Find the best parameters +tuning_results = Rover::DataFrame.new(all_params) +tuning_results["rmse"] = rmses +p tuning_results +``` + +## Additional Topics + +[Explanation](https://facebook.github.io/prophet/docs/additional_topics.html) + Save a model ```ruby File.write("model.json", m.to_json) ``` @@ -323,9 +392,37 @@ ```ruby m = Prophet.from_json(File.read("model.json")) ``` Uses the same format as Python, so models can be saved and loaded in either language + +Flat trend + +```ruby +m = Prophet.new(growth: "flat") +``` + +Updating fitted models + +```ruby +def stan_init(m) + res = {} + ["k", "m", "sigma_obs"].each do |pname| + res[pname] = m.params[pname][0, true][0] + end + ["delta", "beta"].each do |pname| + res[pname] = m.params[pname][0, true] + end + res +end + +df = Rover.read_csv("example_wp_log_peyton_manning.csv") +df1 = df[df["ds"] <= "2016-01-19"] # All data except the last day +m1 = Prophet.new.fit(df1) # A model fit to all data except the last day + +m2 = Prophet.new.fit(df) # Adding the last day, fitting from scratch +m2 = Prophet.new.fit(df, init: stan_init(m1)) # Adding the last day, warm-starting from m1 +``` ## Resources - [Forecasting at Scale](https://peerj.com/preprints/3190.pdf)