0% found this document useful (0 votes)
96 views

A Stochastic Model For Demand Forecating in Python

This document discusses using a stochastic model called SARIMAX (Seasonal Autoregressive Integrated Moving Average with eXogenous regressors) for demand forecasting in Python. It loads airline passenger data, divides it into training, validation and test sets, checks for stationarity and decomposes the time series. Various SARIMAX models are fit to the data and the best model SARIMAX(1,1,1)x(1,1,1,12) is used to generate 50 step ahead forecasts which are plotted along with the actual data for comparison.

Uploaded by

Teto Schedule
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
96 views

A Stochastic Model For Demand Forecating in Python

This document discusses using a stochastic model called SARIMAX (Seasonal Autoregressive Integrated Moving Average with eXogenous regressors) for demand forecasting in Python. It loads airline passenger data, divides it into training, validation and test sets, checks for stationarity and decomposes the time series. Various SARIMAX models are fit to the data and the best model SARIMAX(1,1,1)x(1,1,1,12) is used to generate 50 step ahead forecasts which are plotted along with the actual data for comparison.

Uploaded by

Teto Schedule
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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