<jupyter_start><jupyter_text>Holt-Winters MethodsIn this section we'll look at Double and Triple Exponential Smoothing with the Holt-Winters Methods.  In Double Exponential Smoothing (aka Holt's Method) we introduce a new smoothing factor $\beta$ (beta) that addresses trendWith Triple Exponential Smoothing (aka the Holt-Winters Method) we introduce a smoothing factor 𝛾 (gamma) that addresses seasonalityIn general, higher values for 𝛼, 𝛽 and 𝛾 (values closer to 1), place more emphasis on recent data. Related Functions:statsmodels.tsa.holtwinters.SimpleExpSmoothing(endog)&nbsp;&nbsp;&nbsp;&nbsp;Simple Exponential Smoothingstatsmodels.tsa.holtwinters.ExponentialSmoothing(endog)&nbsp;&nbsp;    Holt-Winters Exponential Smoothing<jupyter_code>import pandas as pd
import numpy as np
%matplotlib inline
df = pd.read_csv('../Data/airline_passengers.csv',index_col='Month',parse_dates=True)<jupyter_output><empty_output><jupyter_text>Setting a DatetimeIndex FrequencyNote that our DatetimeIndex does not have a frequency. In order to build a Holt-Winters smoothing model, statsmodels needs to know the frequency of the data (whether it's daily, monthly etc.). Since observations occur at the start of each month, we'll use MS.A full list of time series offset aliases can be found here.<jupyter_code>df.index.freq = 'MS'
df.index<jupyter_output><empty_output><jupyter_text>___ Simple Exponential SmoothingA variation of the statmodels Holt-Winters function provides Simple Exponential Smoothing. We'll show that it performs the same calculation of the weighted moving average as the pandas .ewm() method:$\begin{split}y_0 &= x_0 \\y_t &= (1 - \alpha) y_{t-1} + \alpha x_t,\end{split}$<jupyter_code>from statsmodels.tsa.holtwinters import SimpleExpSmoothing
span = 12; alpha = 2/(span+1)

# Calculating using pandas
df['EWMA12'] = df['Thousands of Passengers'].ewm(alpha=alpha,adjust=False).mean()

# Calculating using statsmodel
df['SES12']=SimpleExpSmoothing(df['Thousands of Passengers']).fit(smoothing_level=alpha,optimized=False).fittedvalues.shift(-1)
df.head()<jupyter_output><empty_output><jupyter_text>___ Double Exponential SmoothingWhere Simple Exponential Smoothing employs just one smoothing factor $\alpha$ (alpha), Double Exponential Smoothing adds a second smoothing factor $\beta$ (beta) that addresses trends in the data. Like the alpha factor, values for the beta factor fall between zero and one ($0<\beta≤1$). The benefit here is that the model can anticipate future increases or decreases where the level model would only work from recent calculations.We can also address different types of change (growth/decay) in the trend. If a time series displays a straight-line sloped trend, you would use an additive adjustment. If the time series displays an exponential (curved) trend, you would use a multiplicative adjustment.As we move toward forecasting, it's worth noting that both additive and multiplicative adjustments may become exaggerated over time, and require damping that reduces the size of the trend over future periods until it reaches a flat line.  Which method on what situation?Additive Method: When the seasonal variations are roughly constant throughout the series, i.e. strainght line slopeMultiplicative Method:When the seasonal variations are proportion to the level of the series, i.e. exponential or curved<jupyter_code>from statsmodels.tsa.holtwinters import ExponentialSmoothing

df['DESadd12'] = ExponentialSmoothing(df['Thousands of Passengers'], trend='add').fit().fittedvalues.shift(-1)
df.head()
df[['Thousands of Passengers','EWMA12','DESadd12']].iloc[:24].plot(figsize=(12,6)).autoscale(axis='x',tight=True);<jupyter_output><empty_output><jupyter_text>Here we can see that Double Exponential Smoothing is a much better representation of the time series data.Let's see if using a multiplicative seasonal adjustment helps.<jupyter_code>df['DESmul12'] = ExponentialSmoothing(df['Thousands of Passengers'], trend='mul').fit().fittedvalues.shift(-1)
df.head()
df[['Thousands of Passengers','DESadd12','DESmul12']].iloc[:24].plot(figsize=(12,6)).autoscale(axis='x',tight=True);<jupyter_output><empty_output><jupyter_text>___ Triple Exponential SmoothingTriple Exponential Smoothing, the method most closely associated with Holt-Winters, adds support for both trends and seasonality in the data.<jupyter_code>df['TESadd12'] = ExponentialSmoothing(df['Thousands of Passengers'],trend='add',seasonal='add',seasonal_periods=12).fit().fittedvalues
df.head() 
df['TESmul12'] = ExponentialSmoothing(df['Thousands of Passengers'],trend='mul',seasonal='mul',seasonal_periods=12).fit().fittedvalues
df.head()
df[['Thousands of Passengers','TESadd12','TESmul12']].plot(figsize=(12,6)).autoscale(axis='x',tight=True);
df[['Thousands of Passengers','TESadd12','TESmul12']].iloc[:24].plot(figsize=(12,6)).autoscale(axis='x',tight=True);<jupyter_output><empty_output><jupyter_text>Based on the plot above, we might think that Triple Exponential Smoothing does a poorer job of fitting than Double Exponential Smoothing. The key here is to consider what comes next - forecasting. We'll see that having the ability to predict fluctuating seasonal patterns greatly improves our forecast.<jupyter_code>df[['Thousands of Passengers','DESadd12','DESmul12']].iloc[:24].plot(figsize=(12,6)).autoscale(axis='x',tight=True);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1027359017308766, 'fraction_numerical': 0.01358645077238042, 'mean_word_length': 7.3317829457364345, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '585895', 'license': 'MIT', 'n_tokens_mistral': 1671, 'n_tokens_neox': 1544, 'n_words': 515, 'path': 'tsa/jose/07_TSA with StatsModels/44_HW Seasonal Method.ipynb', 'repo_name': 'juspreet51/ml_templates', 'size': '5373'}