You are on page 1of 32

A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

1 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

2 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mlp

#Loading data
data = pd.read_csv('Datasets/AirPassengers.csv',
index_col='Month', parse_dates=['Month'])
data = data.rename(columns
={'#Passengers':'no_passengers'})
data

read_csv().

parse_dates

to_datetime().

index_col='Month'

3 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

plt.plot(data)
plt.show()

4 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

data_for_dist_fitting = data[-70:]

5 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

data_train =
data[~data.isin(data_for_dist_fitting).all(1)]

test_data = data_for_dist_fitting[-20:]

data_for_dist_fitting=data_for_dist_fitting[~data_for_dist
_fitting.isin(test_data).all(1)]

train = plt.plot(data_train,color='blue', label = 'Train


data')

data_f_mc = plt.plot(data_for_dist_fitting, color ='red',


label ='Data for distribution fitting')

test = plt.plot(test_data, color ='black', label = 'Test


data')

plt.legend(loc='best')
plt.title('Data division')
plt.show(block=False)

6 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

7 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

from statsmodels.tsa.stattools import adfuller


def test_stationarity(timeseries):
#Determining rolling statistics
rolmean = timeseries.rolling(window=12).mean()
rolstd = timeseries.rolling(window=12).std()

#plot rolling statistics:


orig = plt.plot(timeseries,color='blue', label =
'Original')
mean = plt.plot(rolmean, color ='red', label ='Rolling
Mean')
std = plt.plot(rolstd, color ='black', label =
'Rolling Std')
plt.legend(loc='best')
plt.title('Rolling Mean and Standard Deviation')
plt.show(block=False)

8 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

#Perform Dickey Fuller test:


print('Results of Dickey Fuller Test:')
dftest = adfuller(timeseries, autolag= 'AIC')
dfoutput = pd.Series(dftest[0:4], index=['Test
Statistic','p-value','#Lags Used','Number of Observations
Used'])

for key,value in dftest[4].items():


dfoutput['Critical Value (%s)'%key] = value
print (dfoutput)

test_stationarity(data_train)

9 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

statsmodels seasonal_decompose

from statsmodels.tsa.seasonal import seasonal_decompose


decomposition = seasonal_decompose(data_train)

trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

plt.subplot(411)
plt.plot(ts_log, label='Original')
plt.legend(loc='best')
plt.subplot(412)
plt.plot(trend, label='Trend')
plt.legend(loc='best')
plt.subplot(413)
plt.plot(seasonal,label='Seasonality')
plt.legend(loc='best')
plt.subplot(414)
plt.plot(residual, label='Residuals')
plt.legend(loc='best')
plt.tight_layout()

10 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

SARIMA(p,d,q).

(P,D,Q).m

11 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

import itertools
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in
list(itertools.product(p, d, q))]
print('Examples of parameter for SARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))

12 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

import warnings
warnings.filterwarnings('ignore')
import statsmodels.api as sm
for param in pdq:
for param_seasonal in seasonal_pdq:
try:
mod =
sm.tsa.statespace.SARIMAX(data_train,order=param,seasonal_
order=param_seasonal,enforce_stationarity=False,enforce_in
vertibility=False)
results = mod.fit()
print('SARIMA{}x{}12 -
AIC:{}'.format(param,param_seasonal,results.aic))
except Exception as E:
print(E)
continue

13 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

14 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

SARIMAX(1, 1, 1)x(1, 1, 1, 12).

from statsmodels.tsa.statespace.sarimax import SARIMAX

mod= SARIMAX(data_train,order=(1,1,1),seasonal_order=(1,
1, 1, 12),enforce_invertibility=False,
enforce_stationarity=False)
results = mod.fit(disp=0)
print(results.summary())

15 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

pred_sarima = results.forecast(50)
predicted =plt.plot(pred_sarima,label='Prediction by
SARIMA', color='red')
Actual = plt.plot(data_for_dist_fitting,label='Actual
data')
plt.legend(loc='best')
plt.title('SARIMA MODEL')
plt.show(block=False)

16 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# plot residual errors of the training data


residual_error = pd.DataFrame(results.resid)
residual_error.plot()
plt.show()

residual_error.plot(kind='kde')
plt.show()
print(residual_error.describe())

17 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

#to suppress warnings


warnings.filterwarnings('ignore')

from sklearn.metrics import mean_squared_error

#creating new dataframe for rolling forescast

18 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

history = np.log(data_train.astype(float))
predictions = list()

for i in range(len(data_for_dist_fitting)):
model = SARIMAX(history,order=
(1,1,1),seasonal_order=(1, 1, 1,
12),enforce_invertibility=False,
enforce_stationarity=False)
model_fit = model.fit(disp = 0)
# generate forcecast for next period
output = model_fit.forecast()
#Save the prediction value in yhat
yhat = np.e ** output[0]
#Append yhat to the list of prediction
predictions.append(yhat)
# grabs the observation at the ith index
obs = data_for_dist_fitting[i : i + 1]
# appends the observation to the estimation data set
history = history.append(np.log(obs.astype(float)))

# prints the MSE of the model for the rolling forecast


period
error = mean_squared_error(data_for_dist_fitting,
predictions)
print('Test MSE: %.3f' % error)

# converts the predictions list to a pandas dataframe with


the same index as the actual values
# for plotting purposes
predictions = pd.DataFrame(predictions)
predictions.index = data_for_dist_fitting.index

# sets the plot size to 12x8


mlp.rcParams['figure.figsize'] = (12,8)

# plots the predicted and actual stock prices


plt.plot(data_for_dist_fitting,label='Actual values')
plt.plot(predictions, color = 'red', label='predicted
rolling forecast')
plt.legend(loc='best')
plt.xlabel('week')
plt.ylabel('#passengers')
plt.title('Predicted vs. Actual #of passengers')
plt.show()

19 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# to suppress warnings
warnings.filterwarnings('ignore')

# sets the plot size to 12x8


mlp.rcParams['figure.figsize'] = (12,8)

# plots the rolling forecast error


rf_errors = data_for_dist_fitting.no_passengers -
predictions[0]
rf_errors.plot(kind = 'kde')

# produces a summary of rolling forecast error


rf_errors.astype(float).describe()

20 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# to suppress warnings

21 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

import warnings
warnings.filterwarnings('ignore')

# imports the fitter function and produces estimated fits


for our rsarima_errors
from fitter import
Fitter,get_common_distributions,get_distributions

f = Fitter(rf_errors, distributions=
['binomial','norm','laplace','uniform'])
f.fit()
f.summary()

22 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

data_for_dist_fitting

np.random.laplace(loc,scale,size)

def lapace_mc_randv_distribution(mean, rf_errors, n_sim):

#gets the estimated beta or mean absolute distance from


the mean
var = (sum(abs(rf_errors - np.mean(rf_errors)))
/ len(rf_errors))

# uses the numpy function to generate an array of


simulated values
est_range = np.random.laplace(mean,var,n_sim)
# converts the array to a list
est_range = list(est_range)
# returns the simulated values
return(est_range)

23 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

def rolling_forecast_MC(train, test, std_dev, n_sims):

# create a new dataframe that will be added to as the


forecast rolls
history = np.log(data_train.astype(float))

# create an empty list that will hold predictions


predictions = list()

# loops through the indexes of the set being forecasted


for i in range(len(test_data)):
model = SARIMAX(history,order=
(1,1,1),seasonal_order=(1, 1, 1,
12),enforce_invertibility=False,
enforce_stationarity=False)
model_fit = model.fit(disp = 0)

# generate forcecast for next period


output = model_fit.forecast().values

#Save the prediction value in yhat


yhat = np.e ** output[0]

# performs monte carlo simulation using the


predicted price as the mean, user-specified
# standard deviation, and number of simulations
randv_range =
lapace_mc_randv_distribution(yhat,std_dev,n_sims)

#Append yhat to the list of prediction


predictions.append([float(i) for i in
randv_range])

# grabs the observation at the ith index


obs = test_data[i : i + 1]

# appends the observation to the estimation data


set
history =
history.append(np.log(obs.astype(float)))

24 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# converts the predictions list to a pandas


dataframe with the same index as the actual
# values for plotting purposes
predictions = pd.DataFrame(predictions)
predictions.index = test_data.index

# returns predictions
return(predictions)

data_train = data_train.append(data_for_dist_fitting)

test_preds = rolling_forecast_MC(data_train,
test_data,
rf_errors,
1000)

MC = plt.plot(test_preds)
Actual=plt.plot(test_data,color='black',label='Actual
Demand')
plt.legend(loc='best')
plt.show()

25 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

print('Expected demand:',np.mean(test_preds.values))
print('Quantile(5%):',np.percentile(test_preds,5))
print('Quantile(95%):',np.percentile(test_preds,95))

26 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

predictions.values.tolist().

def rolling_forecast_MC_for_minmax_range(train, test,


std_dev, n_sims):
# create a new dataframe that will be added to as the
forecast rolls
history = np.log(data_train.astype(float))
# create an empty list that will hold predictions
predictions = list()

# loops through the indexes of the set being forecasted


for i in range(len(test_data)):
model = SARIMAX(history,order=
(1,1,1),seasonal_order=(1, 1, 1,
12),enforce_invertibility=False,
enforce_stationarity=False)
model_fit = model.fit(disp = 0)

# generate forcecast for next period


output = model_fit.forecast().values

#Save the prediction value in yhat


yhat = np.e ** output[0]

# performs monte carlo simulation using the


predicted price as the mean, user-specified
# standard deviation, and number of simulations
randv_range =
lapace_mc_randv_distribution(yhat,std_dev,n_sims)

#Append yhat to the list of prediction


predictions.append([float(i) for i in
randv_range])

# grabs the observation at the ith index


obs = test_data[i : i + 1]

# appends the observation to the estimation data set


history =
history.append(np.log(obs.astype(float)))

# converts the predictions list to a pandas dataframe

27 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

with the same index as the actual


# values for plotting purposes

predictions = pd.DataFrame(predictions)
# converts all the estimated yhats in each column to
one list per row
predictions['predicted_range'] =
predictions.values.tolist()

# grabs only the column with all values in a list


predictions =
pd.DataFrame(predictions['predicted_range'])
predictions.index = test_data.index

# returns predictions
return(predictions)

# produces a rolling forecast with prediction intervals


using 1000 MC sims
test_preds_minmax =
rolling_forecast_MC_for_minmax_range(data_train,
test_data,
rf_errors,
1000)

test_preds_minmax.head()

28 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# creates an empty list


prediction_interval = []
# loops through the rows in the testing data set
for i in range(len(test_data)):
# appends true if the actual price is in the interval
of predicted prices and false
# otherwise

prediction_interval.append(np.where(min(test_preds_minmax.
predicted_range[i]) <=

test_data.no_passengers[i]
<=
max(test_preds_minmax.predicted_range[i]),
True, False))
# prints the percentage of actual prices in the prediction
intervals
print('Percentage of Demand in Predicted Demand Range: %f'
%
(100 * sum(prediction_interval) /
len(prediction_interval)))

29 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

# creates empty lists to append to with minimum and maximum


values for each weeks prediction
min_range = []
max_range = []

# loops through the rows in test_preds


for i in range(len(test_preds_minmax)):
# appends to the list the min or max value as appropriate
min_range.append(min(test_preds_minmax.predicted_range[i]))
max_range.append(max(test_preds_minmax.predicted_range[i]))

# converts the lists to data frames and makes their indexes


match up with the dates they're
# predicting
min_range = pd.DataFrame(min_range)
min_range.index = test_data.index
max_range = pd.DataFrame(max_range)
max_range.index = test_data.index

# plots the actual stock price with prediction intervals


plt.plot(test_data, color ='red',label='Actual Data')
plt.plot(min_range, color = 'm', label='Min range')
plt.plot(max_range, color = 'b', label ='Max range')
plt.legend(loc='best')
plt.xlabel('Month')
plt.ylabel('No of Passengers')
plt.title('Actual Demand with Prediction Intervals')
plt.show()

30 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

31 of 32 3/15/2022, 9:49 AM
A Stochastic Model For Demand Forecating In Python | by Ju... https://medium.com/mlearning-ai/a-stochastic-model-for-de...

32 of 32 3/15/2022, 9:49 AM

You might also like