<jupyter_start><jupyter_text>Forecasting Facebook Prophethttps://facebook.github.io/prophet/https://research.fb.com/blog/2017/02/prophet-forecasting-at-scale/https://peerj.com/preprints/3190.pdf<jupyter_code>import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

mpl.rcParams['figure.figsize']=(16,10)
pd.set_option('display.max_rows',500)

import plotly.graph_objects as go
#attention might have problems with holiday package, 
#downgrate holidays via: pip install 'holidays==0.9.12'
from fbprophet import Prophet 
plt.style.use('fivethirtyeight')<jupyter_output><empty_output><jupyter_text>Trivial Forecast (rolling mean)<jupyter_code>df=pd.DataFrame({'X':np.arange(0,10)})
df['y']=df.rolling(3).mean()
df
df_all=pd.read_csv("../data/processed/COVID_small_flat_table.csv",sep=';')
df=df_all[['date','Germany']]
df=df.rename(columns={'date':'ds','Germany':'y'})
ax = df.set_index('ds').plot(figsize=(12, 8),
                             logy=True)
ax.set_ylabel('Daily Number of confimed cases')
ax.set_xlabel('Date')

plt.show()
my_model=Prophet(growth='logistic')                      #(interval_width=0.95)
df['cap'] = 1000000      #remove this if using intervl/linear fitting
my_model.fit(df)
future_dates=my_model.make_future_dataframe(periods=50,freq='D')
future_dates['cap']=1000000. #needed for logistic model
future_dates.tail()
forecast=my_model.predict(future_dates) # forecast will contain entire data, in this case df and forecasted data
my_model.plot(forecast,uncertainty=True);
import plotly.offline as py
from fbprophet.plot import plot_plotly

fig=plot_plotly(my_model,forecast) # This returns a plotly figure

fig.update_layout(
    width=1024,
    height=900,
    xaxis_title="Time",
    yaxis_title="Confirmed infected people (source johns hopkins csse, log-scale)",
    )
fig.update_yaxes(type="log",range=[1.1,5.5])
py.iplot(fig)

forecast.sort_values(by='ds').head()
my_model.plot_components(forecast);#second graph shows the seasonality (weekly behavior)
forecast[['ds','trend']].set_index('ds').plot(figsize=(12, 8),logy=True) #linear trend model with changepoint detection
#is used in facebook prophet. refer the third link in the start of the paper to read about this. section(3.1.2)<jupyter_output><empty_output><jupyter_text>Cross Validation<jupyter_code>from fbprophet.diagnostics import cross_validation
df_cv=cross_validation(my_model,
                      initial='50 days', # we take the first 30 days for training
                      period='1 days',# every  days a new prediction run
                      horizon='7 days')#we predict 7days into the future

# the 'initial'(1-50) value is taken for training and predicts the 'horizon' number of days. The the window 
# moves my one day (2-51) and use it as training and predicts fr next 7 days.
my_model.plot(df_cv,uncertainty=True);
df_cv.sort_values(by=['cutoff','ds'])[0:14]
from fbprophet.diagnostics import performance_metrics
df_p=performance_metrics(df_cv)  # shows the performance metrics for the horizon number of days
df_p
from fbprophet.plot import plot_cross_validation_metric
fig=plot_cross_validation_metric(df_cv,'mape')<jupyter_output><empty_output><jupyter_text>Diagonal Plot gives a good understanding for the under and over estimation w.r.t. magnitude Every forecast model should be checked by a diagonal plot. A diagonal plot is used to fid out distortionor bias in underestimating or overestimating<jupyter_code>horizon='7 days'
df_cv['horizon']=df_cv.ds-df_cv.cutoff #subtracting the dates
date_vec=df_cv[df_cv['horizon']==horizon]['ds']
y_hat=df_cv[df_cv['horizon']==horizon]['yhat']
y=df_cv[df_cv['horizon']==horizon]['y']
df_cv_7=df_cv[df_cv['horizon']==horizon]
df_cv_7.head()
type(df_cv['horizon'][0])
fig, ax=plt.subplots(1,1)
ax.plot(np.arange(max(y)),np.arange(max(y)),'--',label='diagonal')
ax.plot(y,y_hat,'-',label=horizon)
ax.set_title('Diagonal plot')
ax.set_ylim(10,max(y))
ax.set_xlabel('truth:y')
ax.set_ylabel('prediction: y_hat')
ax.set_yscale('log')
ax.set_xlim(10,max(y))
ax.set_xscale('log')
ax.legend(loc='best');<jupyter_output><empty_output><jupyter_text>Trivial Forecast<jupyter_code>def mean_absolute_percentage_error(y_true,y_pred):
    return np.mean(np.abs((y_true-y_pred)/y_true))*100
parse_dates=['date']
df_all = pd.read_csv('../data/processed/COVID_small_flat_table.csv',sep=';',parse_dates=parse_dates)
df_trivial=df_all[['date','Germany']]
df_trivial=df_trivial.rename(columns={'date': 'ds',
                        'Germany': 'y'})<jupyter_output><empty_output><jupyter_text>One of the standard forecast is a rolling mean An other standard forecast is the exponentially-weighted moving average,check pandas.ewma<jupyter_code>df_trivial['y_mean_3']=df_trivial['y'].rolling(3).mean()
df_trivial['cutoff']=df_trivial['ds'].shift(7)
df_trivial['y_hat']=df_trivial['y_mean_3'].shift(7)
df_trivial['horizon']=df_trivial['ds']-df_trivial['cutoff']
print('MAPE: '+str(mean_absolute_percentage_error(df_trivial['y_hat'].iloc[12:,], df_trivial['y'].iloc[12:,])))
df_trivial<jupyter_output>MAPE: 168.0626838435285
StarcoderdataJupyterStructuredCleanDedup