prophet-rb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +23 -0
- data/README.md +202 -0
- data/data-raw/generated_holidays.csv +96474 -0
- data/ext/prophet/Makefile +5 -0
- data/ext/prophet/extconf.rb +18 -0
- data/lib/prophet-rb.rb +1 -0
- data/lib/prophet.rb +23 -0
- data/lib/prophet/forecaster.rb +986 -0
- data/lib/prophet/holidays.rb +27 -0
- data/lib/prophet/plot.rb +269 -0
- data/lib/prophet/stan_backend.rb +136 -0
- data/lib/prophet/version.rb +3 -0
- data/stan/unix/prophet.stan +131 -0
- data/stan/win/prophet.stan +162 -0
- metadata +170 -0
@@ -0,0 +1,162 @@
|
|
1
|
+
// Copyright (c) Facebook, Inc. and its affiliates.
|
2
|
+
|
3
|
+
// This source code is licensed under the MIT license found in the
|
4
|
+
// LICENSE file in the root directory of this source tree.
|
5
|
+
|
6
|
+
functions {
|
7
|
+
real[ , ] get_changepoint_matrix(real[] t, real[] t_change, int T, int S) {
|
8
|
+
// Assumes t and t_change are sorted.
|
9
|
+
real A[T, S];
|
10
|
+
real a_row[S];
|
11
|
+
int cp_idx;
|
12
|
+
|
13
|
+
// Start with an empty matrix.
|
14
|
+
A = rep_array(0, T, S);
|
15
|
+
a_row = rep_array(0, S);
|
16
|
+
cp_idx = 1;
|
17
|
+
|
18
|
+
// Fill in each row of A.
|
19
|
+
for (i in 1:T) {
|
20
|
+
while ((cp_idx <= S) && (t[i] >= t_change[cp_idx])) {
|
21
|
+
a_row[cp_idx] = 1;
|
22
|
+
cp_idx = cp_idx + 1;
|
23
|
+
}
|
24
|
+
A[i] = a_row;
|
25
|
+
}
|
26
|
+
return A;
|
27
|
+
}
|
28
|
+
|
29
|
+
// Logistic trend functions
|
30
|
+
|
31
|
+
real[] logistic_gamma(real k, real m, real[] delta, real[] t_change, int S) {
|
32
|
+
real gamma[S]; // adjusted offsets, for piecewise continuity
|
33
|
+
real k_s[S + 1]; // actual rate in each segment
|
34
|
+
real m_pr;
|
35
|
+
|
36
|
+
// Compute the rate in each segment
|
37
|
+
k_s[1] = k;
|
38
|
+
for (i in 1:S) {
|
39
|
+
k_s[i + 1] = k_s[i] + delta[i];
|
40
|
+
}
|
41
|
+
|
42
|
+
// Piecewise offsets
|
43
|
+
m_pr = m; // The offset in the previous segment
|
44
|
+
for (i in 1:S) {
|
45
|
+
gamma[i] = (t_change[i] - m_pr) * (1 - k_s[i] / k_s[i + 1]);
|
46
|
+
m_pr = m_pr + gamma[i]; // update for the next segment
|
47
|
+
}
|
48
|
+
return gamma;
|
49
|
+
}
|
50
|
+
|
51
|
+
real[] logistic_trend(
|
52
|
+
real k,
|
53
|
+
real m,
|
54
|
+
real[] delta,
|
55
|
+
real[] t,
|
56
|
+
real[] cap,
|
57
|
+
real[ , ] A,
|
58
|
+
real[] t_change,
|
59
|
+
int S,
|
60
|
+
int T
|
61
|
+
) {
|
62
|
+
real gamma[S];
|
63
|
+
real Y[T];
|
64
|
+
|
65
|
+
gamma = logistic_gamma(k, m, delta, t_change, S);
|
66
|
+
for (i in 1:T) {
|
67
|
+
Y[i] = cap[i] / (1 + exp(-(k + dot_product(A[i], delta))
|
68
|
+
* (t[i] - (m + dot_product(A[i], gamma)))));
|
69
|
+
}
|
70
|
+
return Y;
|
71
|
+
}
|
72
|
+
|
73
|
+
// Linear trend function
|
74
|
+
|
75
|
+
real[] linear_trend(
|
76
|
+
real k,
|
77
|
+
real m,
|
78
|
+
real[] delta,
|
79
|
+
real[] t,
|
80
|
+
real[ , ] A,
|
81
|
+
real[] t_change,
|
82
|
+
int S,
|
83
|
+
int T
|
84
|
+
) {
|
85
|
+
real gamma[S];
|
86
|
+
real Y[T];
|
87
|
+
|
88
|
+
for (i in 1:S) {
|
89
|
+
gamma[i] = -t_change[i] * delta[i];
|
90
|
+
}
|
91
|
+
for (i in 1:T) {
|
92
|
+
Y[i] = (k + dot_product(A[i], delta)) * t[i] + (
|
93
|
+
m + dot_product(A[i], gamma));
|
94
|
+
}
|
95
|
+
return Y;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
data {
|
100
|
+
int T; // Number of time periods
|
101
|
+
int<lower=1> K; // Number of regressors
|
102
|
+
real t[T]; // Time
|
103
|
+
real cap[T]; // Capacities for logistic trend
|
104
|
+
real y[T]; // Time series
|
105
|
+
int S; // Number of changepoints
|
106
|
+
real t_change[S]; // Times of trend changepoints
|
107
|
+
real X[T,K]; // Regressors
|
108
|
+
vector[K] sigmas; // Scale on seasonality prior
|
109
|
+
real<lower=0> tau; // Scale on changepoints prior
|
110
|
+
int trend_indicator; // 0 for linear, 1 for logistic
|
111
|
+
real s_a[K]; // Indicator of additive features
|
112
|
+
real s_m[K]; // Indicator of multiplicative features
|
113
|
+
}
|
114
|
+
|
115
|
+
transformed data {
|
116
|
+
real A[T, S];
|
117
|
+
A = get_changepoint_matrix(t, t_change, T, S);
|
118
|
+
}
|
119
|
+
|
120
|
+
parameters {
|
121
|
+
real k; // Base trend growth rate
|
122
|
+
real m; // Trend offset
|
123
|
+
real delta[S]; // Trend rate adjustments
|
124
|
+
real<lower=0> sigma_obs; // Observation noise
|
125
|
+
real beta[K]; // Regressor coefficients
|
126
|
+
}
|
127
|
+
|
128
|
+
transformed parameters {
|
129
|
+
real trend[T];
|
130
|
+
real Y[T];
|
131
|
+
real beta_m[K];
|
132
|
+
real beta_a[K];
|
133
|
+
|
134
|
+
if (trend_indicator == 0) {
|
135
|
+
trend = linear_trend(k, m, delta, t, A, t_change, S, T);
|
136
|
+
} else if (trend_indicator == 1) {
|
137
|
+
trend = logistic_trend(k, m, delta, t, cap, A, t_change, S, T);
|
138
|
+
}
|
139
|
+
|
140
|
+
for (i in 1:K) {
|
141
|
+
beta_m[i] = beta[i] * s_m[i];
|
142
|
+
beta_a[i] = beta[i] * s_a[i];
|
143
|
+
}
|
144
|
+
|
145
|
+
for (i in 1:T) {
|
146
|
+
Y[i] = (
|
147
|
+
trend[i] * (1 + dot_product(X[i], beta_m)) + dot_product(X[i], beta_a)
|
148
|
+
);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
model {
|
153
|
+
//priors
|
154
|
+
k ~ normal(0, 5);
|
155
|
+
m ~ normal(0, 5);
|
156
|
+
delta ~ double_exponential(0, tau);
|
157
|
+
sigma_obs ~ normal(0, 0.5);
|
158
|
+
beta ~ normal(0, sigmas);
|
159
|
+
|
160
|
+
// Likelihood
|
161
|
+
y ~ normal(Y, sigma_obs);
|
162
|
+
}
|
metadata
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prophet-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Kane
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-04-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cmdstan
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: daru
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: numo-narray
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '5'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: matplotlib
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: ruby-prof
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email: andrew@chartkick.com
|
127
|
+
executables: []
|
128
|
+
extensions:
|
129
|
+
- ext/prophet/extconf.rb
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- CHANGELOG.md
|
133
|
+
- LICENSE.txt
|
134
|
+
- README.md
|
135
|
+
- data-raw/generated_holidays.csv
|
136
|
+
- ext/prophet/Makefile
|
137
|
+
- ext/prophet/extconf.rb
|
138
|
+
- lib/prophet-rb.rb
|
139
|
+
- lib/prophet.rb
|
140
|
+
- lib/prophet/forecaster.rb
|
141
|
+
- lib/prophet/holidays.rb
|
142
|
+
- lib/prophet/plot.rb
|
143
|
+
- lib/prophet/stan_backend.rb
|
144
|
+
- lib/prophet/version.rb
|
145
|
+
- stan/unix/prophet.stan
|
146
|
+
- stan/win/prophet.stan
|
147
|
+
homepage: https://github.com/ankane/prophet
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
metadata: {}
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '2.4'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubygems_version: 3.1.2
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Time series forecasting for Ruby
|
170
|
+
test_files: []
|