Exponential Smoothing — Simple, Holt-Winters
Statistics
Forecasting With Weighted Averages of Past Observations
Exponential smoothing assigns exponentially decreasing weights to older data, making forecasts responsive to recent changes while remaining stable. From simple single-parameter models to triple Holt-Winters, these methods adapt to level, trend, and seasonality.
-
Retail Forecasting — Predict daily sales that respond to recent promotions
-
Supply Chain — Generate short-term demand forecasts for inventory management
-
Financial Markets — Smooth price series for technical analysis signals
Recent data speaks louder — exponential smoothing listens with mathematical precision.
Exponential smoothing methods assign exponentially decreasing weights to past observations. More recent data gets higher weight, making these methods responsive to level changes.
Simple Exponential Smoothing (SES)
For data with no trend and no seasonality.
Equivalent Formulation
Holt's Linear Trend (Double Smoothing)
Extends SES to capture trend using two equations.
Forecast
Holt-Winters (Triple Smoothing)
Extends Holt's method to capture seasonality. Two variants exist.
Additive Seasonality
Multiplicative Seasonality
Parameter Optimization
The smoothing parameters are typically chosen by minimizing a loss function.
Common loss functions:
-
MSE: (most common)
-
MAE: (more robust to outliers)
-
MAPE: (scale-free)
Python Implementation
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.holtwinters import ExponentialSmoothing
np.random.seed(42)
# Simulate monthly data with trend and seasonality
n = 120
t = np.arange(n)
trend = 200 + 1.5 * t
seasonal = 15 * np.tile(np.sin(2*np.pi*np.arange(12)/12), n//12)
noise = np.random.randn(n) * 3
y = trend + seasonal + noise
dates = pd.date_range('2015', periods=n, freq='M')
ts = pd.Series(y, index=dates)
# Simple Exponential Smoothing
ses = ExponentialSmoothing(ts, trend=None, seasonal=None).fit(smoothing_level=0.3)
print(f"SES alpha: {ses.params['smoothing_level']:.3f}")
# Holt's Linear Trend
holt = ExponentialSmoothing(ts, trend='add', seasonal=None).fit()
print(f"Holt alpha: {holt.params['smoothing_level']:.3f}, beta: {holt.params['smoothing_trend']:.3f}")
# Holt-Winters Multiplicative
hw = ExponentialSmoothing(ts, trend='add', seasonal='mul', seasonal_periods=12).fit()
print(f"HW alpha: {hw.params['smoothing_level']:.3f}, beta: {hw.params['smoothing_trend']:.3f}, gamma: {hw.params['smoothing_seasonal']:.3f}")
# Forecast
forecast = hw.forecast(12)
print(f"\n12-month forecast: {forecast.round(1).values}")
Worked Example
Key Takeaways
Related Topics
-
See ARIMA Models for more flexible time series models
-
See Seasonal Decomposition for understanding components
-
See Stationarity for testing stationarity before modeling