Simple Exponential Smoothing was used to analyze the Victoria pigs series. The smoothing parameter was calculated to be \(\alpha = 0.3239\) with an initial level of 94,200.
All the forecasts for the four-step-ahead values are equal to 95,183.97. This is because the Simple Exponential Smoothing model has no trend or seasonality component and therefore reverts to the last calculated level of the series.
Hence, the next four period forecasts remain the same at around 95,184.
Using the fitted simple exponential smoothing model, the initial forecast is 95,183.97, with a residual standard deviation of 9,351.81.
With such a level of uncertainty involved in the forecast, the 95% prediction interval for the next value is approximately between 76,854.42 and 113,513.52. This means that there is a 95% chance that the next value will fall within that range.
The width of the interval reflects the variability present in the data and indicates a level of uncertainty with the forecast.
Exercise 8.5
Part A
import pandas as pdimport matplotlib.pyplot as pltglobal_economy = pd.read_csv("global_economy.csv")global_economy["ds"] = pd.to_datetime(global_economy["ds"], format="%Y")country ="United States"exports = global_economy.loc[ global_economy["unique_id"] == country, ["unique_id", "ds", "Exports"]].dropna().sort_values("ds")plt.figure(figsize=(10, 5))plt.plot(exports["ds"], exports["Exports"], linewidth=2)plt.title(f"Exports: {country}")plt.xlabel("Year")plt.ylabel("Exports (% of GDP)")plt.tight_layout()plt.show()
The export data from the US tells a clear story. If we look at the data on an annual basis, there is no real seasonal variability to speak of. Looking at the data over time, we can see that the overall growth in exports continues to increase over the years, suggesting a long-run increase in exports as a percentage of GDP. Of course, there are some ups and downs along the way, including in the early 1980s and again in the early 2000s, likely reflecting an overall economic slowdown.
Part B
from statsforecast import StatsForecastfrom statsforecast.models import AutoETSimport matplotlib.pyplot as pltexports_df = exports.rename(columns={"Exports": "y"}).copy()exports_df["unique_id"] ="US_exports"sf = StatsForecast( models=[AutoETS(model="ANN", alias="ETS_ANN")], freq="YE")fc_ann = sf.forecast(df=exports_df, h=10, fitted=True)plt.figure(figsize=(10, 5))plt.plot(exports_df["ds"], exports_df["y"], linewidth=2, label="Observed")plt.plot(fc_ann["ds"], fc_ann["ETS_ANN"], linewidth=2, label="Forecast")plt.title("ETS(A,N,N) Forecast for US Exports")plt.xlabel("Year")plt.ylabel("Exports (% of GDP)")plt.legend()plt.tight_layout()plt.show()
The ETS(A,N,N) model is essentially a simple exponential smoothing model. It assumes a series has a level component but no trend or seasonal component. As a consequence, the forecast is constant and equal to the level component. In this case, the forecast is close to the last export value because it simply updates its level component using recent values.
The value of RMSE for the ETS(A,N,N) model is 0.6265, indicating the magnitude of the errors in the data set. As it is in the same units as the response variable, it indicates that the average difference between observed values and the model’s fitted values is around 0.63 percent GDP.
The addition of the additive trend component to the level component of the ETS(A,N,N) model allows the ETS(A,A,N) model to account for any increases or decreases in the time series over time.
From the values of the RMSE, the ETS(A,N,N) model has an RMSE of 0.6265, whereas the ETS(A,A,N) model has an RMSE of 0.6144. This implies that the ETS(A,A,N) model provides a slightly better fit to the historical data on exports because of the inclusion of the trend component.
Part E
import matplotlib.pyplot as pltplt.figure(figsize=(10,5))plt.plot(exports_df["ds"], exports_df["y"], label="Observed", linewidth=2)plt.plot(fc_ann["ds"], fc_ann["ETS_ANN"], label="ETS(A,N,N)", linewidth=2)plt.plot(fc_aan["ds"], fc_aan["ETS_AAN"], label="ETS(A,A,N)", linewidth=2)plt.title("Forecast Comparison for US Exports")plt.xlabel("Year")plt.ylabel("Exports (% of GDP)")plt.legend()plt.tight_layout()plt.show()
However, the models differ with respect to how they account for the underlying series’ structure. In the case of ETS(A,N,N), the model only accounts for the level present in the series, meaning that the forecasted values will remain constant at the last estimated level. In the case of ETS(A,A,N), an additive trend is incorporated into the model, meaning that the forecasted values will continue with the trend that has been present in the series over time.
A 95% prediction interval for the first forecast may be approximated by
\[
\hat{y} \pm 1.96s
\]
where \(s\) represents the standard deviation of residuals in the model.
Using this formula to compute a prediction interval for the first forecast using the ETS(A,N,N) model, we obtain
\[
(10.68,\; 13.11)
\]
This interval represents where the next observed export value is likely to fall with a 95% probability, assuming normal distribution of forecast errors.
From the Chinese GDP figures, it is clear there is a constant and strong growth in GDP over the years, reflecting the high growth rate of China’s economy in recent decades. There is a pick-up in the rate of growth after 2000, indicating a high growth rate in China’s economy. As the figures are annual, there is no seasonal effect in this data series. Overall, it indicates a growth in GDP over the years, with the rate of increase in GDP increasing in recent years.
ETS Forecast
from statsforecast import StatsForecastfrom statsforecast.models import AutoETSimport matplotlib.pyplot as pltsf = StatsForecast( models=[AutoETS(model="ZZZ", alias="ETS")], freq="YE")fc_china = sf.forecast(df=china, h=15)plt.figure(figsize=(10,5))plt.plot(china["ds"], china["y"], label="Observed", linewidth=2)plt.plot(fc_china["ds"], fc_china["ETS"], label="Forecast", linewidth=2)plt.title("Chinese GDP Forecast (ETS)")plt.xlabel("Year")plt.ylabel("GDP")plt.legend()plt.tight_layout()plt.show()
As can be seen from the graph produced by the ETS model, the forecasts continue to move along the same high trend that we have been seeing with the Chinese GDP data. As we can see, the data has been steadily increasing over time, which is why the model has factored that in with a trend that allows the forecasts to increase over time as well.
However, as can be seen from the graph produced by the model, the forecasts increase very sharply, which is a problem with trend-based models when we see a high trend over time with our data. This can make the forecasts unrealistically high if we assume that the trend will continue indefinitely.
The standard ETS model and the damped trend model may appear similar for the immediate future, but as we extend the forecast, the two begin to diverge. In the ETS model, the residual momentum caused by the long-term GDP boom continues to drive the forecast up, indicating extremely high growth rates in the future.
In the damped trend model, the trend is damped as we extend the forecast. This means that the forecast still increases, but at a slower rate. This is more realistic, as it takes into account the fact that the extremely high growth rate will not continue indefinitely.
A Box-Cox transformation was used for the Chinese economic series based on GDP before the application of the ETS model. The value of the transformed series’ \(\lambda\) was -0.1366. Essentially, this is a log transformation. This type of transformation is often used for economic series with high rates of growth. It helps to normalize the variance while also limiting the effects of extreme values.
Finally, the ETS model was applied to the transformed series. Then the forecasts were reversed to the original series. With this method, the forecasts increase very quickly as the forecast horizon increases. This is due to the fact that the series for the Chinese economic series based on GDP increases exponentially. Then the inverse mapping is applied to the forecasts.
Comparing the three methods, we see that the standard ETS model maintains the high growth pattern of the series. With the damped trend model, the long-run forecasts increase moderately. With the Box-Cox method, the forecasts increase very steeply if the series increases exponentially.
Exercise 8.7
import pandas as pdimport matplotlib.pyplot as pltgas = pd.read_csv("aus_production.csv")gas["ds"] = pd.to_datetime(gas["ds"])gas = gas.sort_values("ds")gas_df = gas[["ds","Gas"]].dropna().copy()gas_df["unique_id"] ="Gas"gas_df = gas_df.rename(columns={"Gas":"y"})gas_df = gas_df[["unique_id","ds","y"]]plt.figure(figsize=(10,5))plt.plot(gas_df["ds"], gas_df["y"], linewidth=2)plt.title("Australian Gas Production")plt.xlabel("Quarter")plt.ylabel("Gas Production")plt.tight_layout()plt.show()
The data on gas production in Australia follows a simple pattern. Production increases over time, and every year the pattern of seasonality repeats itself.
An important point to note about this data is that the seasonality increases as the level of the data increases. Initially, the peaks and troughs of seasonality are small, while later on, the seasonality becomes larger. In other words, the seasonality increases as the level of the data increases.
Since the seasonality increases as the level of the data increases, a multiplicative model of seasonality would be more appropriate. This is because the seasonality can increase as the level of the data increases.
from statsforecast import StatsForecastfrom statsforecast.models import AutoETSsf_gas = StatsForecast( models=[AutoETS(model="ZZZ", alias="AutoETS")], freq="Q")fc_gas = sf_gas.forecast(df=gas_df, h=8)plt.figure(figsize=(10,5))plt.plot(gas_df["ds"], gas_df["y"], label="Observed", linewidth=2)plt.plot(fc_gas["ds"], fc_gas["AutoETS"], label="Forecast", linewidth=2)plt.title("Australian Gas Production Forecast")plt.xlabel("Quarter")plt.ylabel("Gas Production")plt.legend()plt.tight_layout()plt.show()
As the ETS model predicts the gas output to rise further, it follows the same pattern of rise as the historical data series showed. It also maintains the same pattern of rise and fall as the original series showed.
As the rise and fall are proportional to the level of the series, the model must have multiplicative seasonality. This implies that the rise and fall are expected to increase slightly as the overall output increases.
Overall, the ETS model provides a sensible forecast, reflecting the trend and the seasonality already present in the data series.
Exercise 8.8
Part A
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltaus_retail = pd.read_csv("aus_retail.csv")print(aus_retail.head())print(aus_retail.columns)
State Industry \
0 Australian Capital Territory Cafes, restaurants and catering services
1 Australian Capital Territory Cafes, restaurants and catering services
2 Australian Capital Territory Cafes, restaurants and catering services
3 Australian Capital Territory Cafes, restaurants and catering services
4 Australian Capital Territory Cafes, restaurants and catering services
Series ID Month Turnover
0 A3349849A 1982-04-01 4.4
1 A3349849A 1982-05-01 3.4
2 A3349849A 1982-06-01 3.6
3 A3349849A 1982-07-01 4.0
4 A3349849A 1982-08-01 3.6
Index(['State', 'Industry', 'Series ID', 'Month', 'Turnover'], dtype='object')
As the seasonal variations in this series of retail sales increase in proportion with the size of the overall data, the series is said to have multiplicative seasonality. Though in the initial years the seasonal highs and lows are minimal, they increase significantly as the series progresses. Thus, the size of the seasonal variations changes in proportion with the overall level of the series. Accordingly, the multiplicative model is more appropriate for this retail time series than the additive model.
The Holt-Winters multiplicative models were used for the retail data with a 12-month seasonal cycle. This approach allows the models to detect the rising trend and the seasonal fluctuations present in the series.
The two models were the standard multiplicative Holt-Winters and the damped trend version of the Holt-Winters model. Both models were able to detect the seasonality and the overall rising trend in the series. However, the damped trend version of the model adjusts the long-term growth downwards, resulting in a more conservative growth path than the standard multiplicative version.
We used a comparison of one-step ahead forecast RMSEs for the following models: the standard multiplicative form of the Holt-Winters method and its damped counterpart. The standard multiplicative form of the Holt-Winters method yielded an RMSE of 31.71, while its damped counterpart yielded an RMSE of 35.66. Therefore, the undamped form of the Holt-Winters method is preferable.
Part D
from statsmodels.graphics.tsaplots import plot_acfimport matplotlib.pyplot as pltfitted_hw = sf_hw.forecast_fitted_values()fitted_best = fitted_hw[["unique_id", "ds", "HW_Mult"]].copy()residuals = retail.merge(fitted_best, on=["unique_id", "ds"], how="left")residuals["resid"] = residuals["y"] - residuals["HW_Mult"]residuals = residuals.dropna(subset=["resid"]).copy()print(residuals.head())print(residuals["resid"].describe())print("Number of residuals:", residuals["resid"].notna().sum())
unique_id ds y HW_Mult resid
0 A3349721R 1982-04-01 161.8 156.683101 5.116899
1 A3349721R 1982-05-01 158.7 160.099418 -1.399418
2 A3349721R 1982-06-01 166.6 157.259629 9.340371
3 A3349721R 1982-07-01 172.9 167.871052 5.028948
4 A3349721R 1982-08-01 165.9 170.076865 -4.176865
count 441.000000
mean 3.225776
std 31.584479
min -89.416941
25% -12.019447
50% 2.529823
75% 16.019481
max 117.041271
Name: resid, dtype: float64
Number of residuals: 441
plt.figure(figsize=(10,4))plt.plot(residuals["ds"], residuals["resid"], linewidth=1.2)plt.axhline(0, linestyle="--")plt.title("Residuals from Holt-Winters Multiplicative Model")plt.xlabel("Date")plt.ylabel("Residual")plt.tight_layout()plt.show()
Residual diagnostics for the Holt-Winters multiplicative model were performed. The plot of the residuals over time shows the values moving in and out of zero, with the impression that the values are increasing a little towards the end of the time series. The distribution of the residuals in the histogram is fairly symmetric and centered at zero, which indicates that the errors are normally distributed.
However, the results from the ACF plot are quite different. Several significant values are observed at the early lags, beyond the confidence interval. This indicates that the residuals are not pure white noise; they have patterns in them.
The retail series was split into a training set up to 2010 and a test set from 2011. The forecasts were generated using two methods: the Holt-Winters multiplicative method and the seasonal naive method. The accuracy of the models was determined based on the RMSE of the test set.
For the test set, the Holt-Winters method gave an RMSE of 334.29, while the seasonal naive method gave an RMSE of 361.60. Therefore, the Holt-Winters method has a lower RMSE and hence a better forecasting accuracy for the retail series.
This implies that the Holt-Winters multiplicative method has a better fit for the trend and seasonal components of the series than the seasonal naive method.
For this same retail series, we have performed the STL decomposition on the training data after applying the Box-Cox transformation, using a lambda of 0.1359. We have removed the seasonality component from the data and then performed the ETS model on the seasonally adjusted data. After that, we have proceeded to forecast the data for the test period. We have readded the seasonality component and performed the inverse transformation back to the original scale.
The STL + Box-Cox + ETS strategy has produced a test RMSE of 195.45, which is significantly lower than the best model so far—the Holt-Winters multiplicative method—which produced a test RMSE of 334.29.
This proves that the STL strategy provides much better forecast results for this retail series. This is because the seasonality component has been separated first and then the trend and the residuals have been handled by the ETS model.