From e33e7c4b37054ae512c384fc08e12051c238b91a Mon Sep 17 00:00:00 2001 From: "Rolando (Max) Espinoza" Date: Thu, 9 Mar 2017 13:47:59 -0300 Subject: [PATCH] Make stan code windows-compatible. (#96) The vector/matrix operations fail to compile in windows due to eigen incompatibility with windows compiler. Here we opt to use a non- vectorized model for windows platform. --- python/MANIFEST.in | 3 +- python/setup.py | 8 ++- .../{ => unix}/prophet_linear_growth.stan | 0 .../{ => unix}/prophet_logistic_growth.stan | 0 python/stan/win/prophet_linear_growth.stan | 45 +++++++++++++++ python/stan/win/prophet_logistic_growth.stan | 57 +++++++++++++++++++ 6 files changed, 111 insertions(+), 2 deletions(-) rename python/stan/{ => unix}/prophet_linear_growth.stan (100%) rename python/stan/{ => unix}/prophet_logistic_growth.stan (100%) create mode 100644 python/stan/win/prophet_linear_growth.stan create mode 100644 python/stan/win/prophet_logistic_growth.stan diff --git a/python/MANIFEST.in b/python/MANIFEST.in index 58bdb6e..9e73428 100644 --- a/python/MANIFEST.in +++ b/python/MANIFEST.in @@ -1,2 +1,3 @@ -include stan/*.stan +include stan/unix/*.stan +include stan/win/*.stan include LICENSE diff --git a/python/setup.py b/python/setup.py index d6d4fc4..06c41bd 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,5 +1,6 @@ import os.path import pickle +import platform import sys from pkg_resources import ( @@ -26,8 +27,13 @@ class BuildPyCommand(build_py): target_dir = os.path.join(self.build_lib, 'fbprophet/stan_models') self.mkpath(target_dir) + if platform.platform().startswith('Win'): + plat = 'win' + else: + plat = 'unix' + for model_type in ['linear', 'logistic']: - with open('stan/prophet_{}_growth.stan'.format(model_type)) as f: + with open('stan/{}/prophet_{}_growth.stan'.format(plat, model_type)) as f: model_code = f.read() sm = StanModel(model_code=model_code) with open(os.path.join(target_dir, '{}_growth.pkl'.format(model_type)), 'wb') as f: diff --git a/python/stan/prophet_linear_growth.stan b/python/stan/unix/prophet_linear_growth.stan similarity index 100% rename from python/stan/prophet_linear_growth.stan rename to python/stan/unix/prophet_linear_growth.stan diff --git a/python/stan/prophet_logistic_growth.stan b/python/stan/unix/prophet_logistic_growth.stan similarity index 100% rename from python/stan/prophet_logistic_growth.stan rename to python/stan/unix/prophet_logistic_growth.stan diff --git a/python/stan/win/prophet_linear_growth.stan b/python/stan/win/prophet_linear_growth.stan new file mode 100644 index 0000000..f7757a4 --- /dev/null +++ b/python/stan/win/prophet_linear_growth.stan @@ -0,0 +1,45 @@ +data { + int T; // Sample size + int K; // Number of seasonal vectors + real t[T]; // Day + real y[T]; // Time-series + int S; // Number of changepoints + real A[T, S]; // Split indicators + real t_change[S]; // Index of changepoints + real X[T,K]; // season vectors + real sigma; // scale on seasonality prior + real tau; // scale on changepoints prior +} + +parameters { + real k; // Base growth rate + real m; // offset + real delta[S]; // Rate adjustments + real sigma_obs; // Observation noise (incl. seasonal variation) + real beta[K]; // seasonal vector +} + +transformed parameters { + real gamma[S]; // adjusted offsets, for piecewise continuity + + for (i in 1:S) { + gamma[i] = -t_change[i] * delta[i]; + } +} + +model { + real Y[T]; + + //priors + k ~ normal(0, 5); + m ~ normal(0, 5); + delta ~ double_exponential(0, tau); + sigma_obs ~ normal(0, 0.5); + beta ~ normal(0, sigma); + + // Likelihood + for (i in 1:T) { + Y[i] = (dot_product(A[i], delta) + k) * t[i] + (dot_product(A[i], gamma) + m) + dot_product(X[i], beta); + } + y ~ normal(Y, sigma_obs); +} diff --git a/python/stan/win/prophet_logistic_growth.stan b/python/stan/win/prophet_logistic_growth.stan new file mode 100644 index 0000000..b51dd38 --- /dev/null +++ b/python/stan/win/prophet_logistic_growth.stan @@ -0,0 +1,57 @@ +data { + int T; // Sample size + int K; // Number of seasonal vectors + real t[T]; // Day + real cap[T]; // Capacities + real y[T]; // Time-series + int S; // Number of changepoints + real A[T, S]; // Split indicators + real t_change[S]; // Index of changepoints + real X[T,K]; // season vectors + real sigma; // scale on seasonality prior + real tau; // scale on changepoints prior +} + +parameters { + real k; // Base growth rate + real m; // offset + real delta[S]; // Rate adjustments + real sigma_obs; // Observation noise (incl. seasonal variation) + real beta[K]; // seasonal vector +} + +transformed parameters { + real gamma[S]; // adjusted offsets, for piecewise continuity + real k_s[S + 1]; // actual rate in each segment + real m_pr; + + // Compute the rate in each segment + k_s[1] = k; + for (i in 1:S) { + k_s[i + 1] = k_s[i] + delta[i]; + } + + // Piecewise offsets + m_pr = m; // The offset in the previous segment + for (i in 1:S) { + gamma[i] = (t_change[i] - m_pr) * (1 - k_s[i] / k_s[i + 1]); + m_pr = m_pr + gamma[i]; // update for the next segment + } +} + +model { + real Y[T]; + + //priors + k ~ normal(0, 5); + m ~ normal(0, 5); + delta ~ double_exponential(0, tau); + sigma_obs ~ normal(0, 0.1); + beta ~ normal(0, sigma); + + // Likelihood + for (i in 1:T) { + Y[i] = cap[i] / (1 + exp(-(k + dot_product(A[i], delta)) * (t[i] - (m + dot_product(A[i], gamma))))) + dot_product(X[i], beta); + } + y ~ normal(Y, sigma_obs); +}