Python Code on Holt-Winters Forecasting

Etqad Khan
Analytics Vidhya
Published in
5 min readJan 5, 2021

Patience is the only prerequisite here.

I'm glad if you are here, and if you're clueless about what Holt-Winters Exponential Smoothing is, check out this article here,

This would act as a good starting point and will help you through the basic idea of it. Go ahead, read it, I shall wait. And if in case you want me to cut the chase and start coding, your prayers have just been answered.

We have taken a Time Series data of the number of International Airline Passengers (in thousands) between January 1949 to December 1960. One can find the dataset here,

Let's start by importing the libraries

# dataframe opertations - pandas
import pandas as pd
# plotting data - matplotlib
from matplotlib import pyplot as plt
# time series - statsmodels
# Seasonality decomposition
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.seasonal import seasonal_decompose # holt winters
# single exponential smoothing
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
# double and triple exponential smoothing
from statsmodels.tsa.holtwinters import ExponentialSmoothing

Let’s just quickly import the data and see how it looks. We will also check the shape of the dataframe and a few data points.

airline = pd.read_csv('airline_passengers.csv',index_col='Month', parse_dates=True)airline = pd.read_csv('airline_passengers.csv',index_col='Month', parse_dates=True)# finding shape of the dataframe
print(airline.shape)
# having a look at the data
print(airline.head())
# plotting the original data
airline[['Thousands of Passengers']].plot(title='Passengers Data')

Decomposing the Time Series

Now we will be decomposing the Time Series and will look for Levels, Trends and Seasonality in the data,

decompose_result = seasonal_decompose(airline[‘Thousands of Passengers’],model=’multiplicative’)
decompose_result.plot();

We can quite clearly see that the data has all 3, Levels, Trends, Seasonality.

Fitting the Data with Holt-Winters Exponential Smoothing

Now we shall fit this data on Single, Double, and Triple Exponential Smoothing respectively, and will see how it performs.

Before starting with the models, we shall first define the weight coefficient Alpha and the Time Period. We also set the DateTime frequency to a monthly level.

# Set the frequency of the date time index as Monthly start as indicated by the data
airline.index.freq = ‘MS’
# Set the value of Alpha and define m (Time Period)
m = 12
alpha = 1/(2*m)

Now, we will fit the data on the Single Exponential Smoothing,

Single HWES

airline[‘HWES1’] = SimpleExpSmoothing(airline[‘Thousands of Passengers’]).fit(smoothing_level=alpha,optimized=False,use_brute=True).fittedvaluesairline[[‘Thousands of Passengers’,’HWES1']].plot(title=’Holt Winters Single Exponential Smoothing’);

As expected, it didn’t fit quite well, and rightfully so, because if we remember, Single ES doesn’t work for data with Trends and Seasonality.

Double HWES

So, we’d fit the data on Double ES, on both Additive and Multiplicative Trend,

airline[‘HWES2_ADD’] = ExponentialSmoothing(airline[‘Thousands of Passengers’],trend=’add’).fit().fittedvaluesairline[‘HWES2_MUL’] = ExponentialSmoothing(airline[‘Thousands of Passengers’],trend=’mul’).fit().fittedvaluesairline[[‘Thousands of Passengers’,’HWES2_ADD’,’HWES2_MUL’]].plot(title=’Holt Winters Double Exponential Smoothing: Additive and Multiplicative Trend’);

Well, this looks a little better, but since we know there is Seasonality, we shall move into Triple ES and look at how it fits.

Triple HWES

airline[‘HWES3_ADD’] = ExponentialSmoothing(airline[‘Thousands of Passengers’],trend=’add’,seasonal=’add’,seasonal_periods=12).fit().
fittedvalues
airline[‘HWES3_MUL’] = ExponentialSmoothing(airline[‘Thousands of Passengers’],trend=’mul’,seasonal=’mul’,seasonal_periods=12).fit().
fittedvalues
airline[[‘Thousands of Passengers’,’HWES3_ADD’,’HWES3_MUL’]].plot(title=’Holt Winters Triple Exponential Smoothing: Additive and Multiplicative Seasonality’);

This looks promising! Here we have plotted for both Additive and Multiplicative Seasonality.

Forecasting with Holt-Winters Exponential Smoothing (Triple ES)

Let’s try and forecast sequences, let us start by dividing the dataset into Train and Test Set. We have taken 120 data points as Train set and the last 24 data points as Test Set.

forecast_data = pd.read_csv(‘airline_passengers.csv’,index_col=’Month’,
parse_dates=True)

forecast_data.index.freq = ‘MS’

# Split into train and test set
train_airline = forecast_data[:120]
test_airline = forecast_data[120:]

What are we even waiting for, Let’s fit and forecast,

fitted_model = ExponentialSmoothing(train_airline[‘Thousands of Passengers’],trend=’mul’,seasonal=’mul’,seasonal_periods=12).fit()
test_predictions = fitted_model.forecast(24)
train_airline[‘Thousands of Passengers’].plot(legend=True,label=’TRAIN’)
test_airline[‘Thousands of Passengers’].plot(legend=True,label=’TEST’,figsize=(6,4))
test_predictions.plot(legend=True,label=’PREDICTION’)
plt.title(‘Train, Test and Predicted Test using Holt Winters’)

As we close in on the forecasted segment, it seems that the model has done a decent job overall.

test_airline[‘Thousands of Passengers’].plot(legend=True,label=’TEST’,figsize=(9,6))test_predictions.plot(legend=True,label=’PREDICTION’,xlim=[‘1959–01–01’,’1961–01–01']);

Evaluation Metrics

Let’s see how the model has fared in terms of error term calculations. We would be using MAE(Mean Absolute Error) and MSE(Mean Squared Error) as metrics.

from sklearn.metrics import mean_absolute_error,mean_squared_errorprint(f’Mean Absolute Error = {mean_absolute_error(test_airline,test_predictions)}’)print(f’Mean Squared Error = {mean_squared_error(test_airline,test_predictions)}’)

Well, this is all I have. I think this will help you with Univariate Forecasting. Basics of Holt-Winters Exponential Smoothing is done here. See you all again (hopefully soon). Stay Hydrated!

--

--