Feng Li
School of Statistics and Mathematics
Central University of Finance and Economics
In general it is easier to forecast a variable when:
import pandas as pd
elec = pd.read_csv('data/electricity.csv', header=0, index_col=False, parse_dates=False)
elec['SETTLEMENTDATE'] = pd.to_datetime(elec['SETTLEMENTDATE'])
elec = elec[['SETTLEMENTDATE','TOTALDEMAND']]
elec.head()
SETTLEMENTDATE | TOTALDEMAND | |
---|---|---|
0 | 2021-04-01 00:30:00 | 7012.00 |
1 | 2021-04-01 01:00:00 | 6815.37 |
2 | 2021-04-01 01:30:00 | 6495.25 |
3 | 2021-04-01 02:00:00 | 6308.43 |
4 | 2021-04-01 02:30:00 | 6179.93 |
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(25, 6))
ax.plot(elec.SETTLEMENTDATE, elec.TOTALDEMAND, color='black')
[<matplotlib.lines.Line2D at 0x7f2a7100cee0>]
elec_ow = elec.head(n=2*24)
fig, ax = plt.subplots(figsize=(25, 6))
ax.plot(elec_ow.SETTLEMENTDATE, elec_ow.TOTALDEMAND, color='black')
[<matplotlib.lines.Line2D at 0x7f2a70f2c640>]
import numpy as np
from statsmodels.tsa.holtwinters import SimpleExpSmoothing, Holt, ExponentialSmoothing
elec_clean = elec.set_index('SETTLEMENTDATE')
train = elec_clean.iloc[0:-48, :]
test = elec_clean.iloc[-48:, :]
The following code fits the model
model = SimpleExpSmoothing(np.asarray(train['TOTALDEMAND']))
fit = model.fit()
fit.summary()
/usr/lib/python3/dist-packages/statsmodels/tsa/holtwinters/model.py:915: ConvergenceWarning: Optimization failed to converge. Check mle_retvals. warnings.warn(
Dep. Variable: | endog | No. Observations: | 1392 |
---|---|---|---|
Model: | SimpleExpSmoothing | SSE | 57739558.709 |
Optimized: | True | AIC | 14805.075 |
Trend: | None | BIC | 14815.552 |
Seasonal: | None | AICC | 14805.104 |
Seasonal Periods: | None | Date: | Fri, 17 Jun 2022 |
Box-Cox: | False | Time: | 23:09:38 |
Box-Cox Coeff.: | None |
coeff | code | optimized | |
---|---|---|---|
smoothing_level | 0.9950000 | alpha | True |
initial_level | 7012.0000 | l.0 | True |
pred = test.copy()
pred = fit.forecast(48)
fitted = fit.fittedvalues
fig, ax = plt.subplots(figsize=(25, 6))
ax.plot(train.index[-96:], train.values[-96:],color='black')
ax.plot(train.index[-96:], fitted[-96:], color='orange')
ax.plot(test.index, pred,color='orangered')
ax.plot(test.index, test.values, color='grey')
plt.title("Simple Exponential Smoothing (Black/grey = Actual, Orange = Fitted/Forecast)")
Text(0.5, 1.0, 'Simple Exponential Smoothing (Black/grey = Actual, Orange = Fitted/Forecast)')
The following code fits the model
model = Holt(np.asarray(train['TOTALDEMAND']))
fit = model.fit()
fit.summary()
Dep. Variable: | endog | No. Observations: | 1392 |
---|---|---|---|
Model: | Holt | SSE | 17201041.078 |
Optimized: | True | AIC | 13123.401 |
Trend: | Additive | BIC | 13144.355 |
Seasonal: | None | AICC | 13123.462 |
Seasonal Periods: | None | Date: | Fri, 17 Jun 2022 |
Box-Cox: | False | Time: | 23:09:38 |
Box-Cox Coeff.: | None |
coeff | code | optimized | |
---|---|---|---|
smoothing_level | 0.9950000 | alpha | True |
smoothing_trend | 0.9950000 | beta | True |
initial_level | 7012.0000 | l.0 | True |
initial_trend | -196.63000 | b.0 | True |
pred = fit.forecast(48)
fig, ax = plt.subplots(figsize=(25, 6))
ax.plot(train.index[-96:], train.values[-96:],color='black')
ax.plot(train.index[-96:], fitted[-96:], color='orange')
ax.plot(test.index, pred,color='orangered')
ax.plot(test.index, test.values, color='grey')
plt.title("Simple Exponential Smoothing (Black/grey = Actual, Orange = Fitted/Forecast)");
The following code fits the model
model = ExponentialSmoothing(np.asarray(train['TOTALDEMAND']),trend='add',seasonal='add',seasonal_periods=48)
fit = model.fit()
fit.summary()
Dep. Variable: | endog | No. Observations: | 1392 |
---|---|---|---|
Model: | ExponentialSmoothing | SSE | 7666658.978 |
Optimized: | True | AIC | 12094.541 |
Trend: | Additive | BIC | 12366.943 |
Seasonal: | Additive | AICC | 12098.984 |
Seasonal Periods: | 48 | Date: | Fri, 17 Jun 2022 |
Box-Cox: | False | Time: | 23:09:39 |
Box-Cox Coeff.: | None |
coeff | code | optimized | |
---|---|---|---|
smoothing_level | 0.9381307 | alpha | True |
smoothing_trend | 0.9112998 | beta | True |
smoothing_seasonal | 0.0247337 | gamma | True |
initial_level | 7214.7871 | l.0 | True |
initial_trend | -29.817169 | b.0 | True |
initial_seasons.0 | 93.239648 | s.0 | True |
initial_seasons.1 | -45.832722 | s.1 | True |
initial_seasons.2 | -242.02690 | s.2 | True |
initial_seasons.3 | -407.34103 | s.3 | True |
initial_seasons.4 | -599.31886 | s.4 | True |
initial_seasons.5 | -724.76436 | s.5 | True |
initial_seasons.6 | -769.41277 | s.6 | True |
initial_seasons.7 | -792.96722 | s.7 | True |
initial_seasons.8 | -781.48527 | s.8 | True |
initial_seasons.9 | -771.21668 | s.9 | True |
initial_seasons.10 | -676.51721 | s.10 | True |
initial_seasons.11 | -553.77344 | s.11 | True |
initial_seasons.12 | -276.17953 | s.12 | True |
initial_seasons.13 | -100.69164 | s.13 | True |
initial_seasons.14 | -75.433699 | s.14 | True |
initial_seasons.15 | -119.39831 | s.15 | True |
initial_seasons.16 | -219.45105 | s.16 | True |
initial_seasons.17 | -356.78664 | s.17 | True |
initial_seasons.18 | -444.39352 | s.18 | True |
initial_seasons.19 | -562.57459 | s.19 | True |
initial_seasons.20 | -612.12994 | s.20 | True |
initial_seasons.21 | -668.48214 | s.21 | True |
initial_seasons.22 | -720.11188 | s.22 | True |
initial_seasons.23 | -732.48385 | s.23 | True |
initial_seasons.24 | -716.98479 | s.24 | True |
initial_seasons.25 | -682.49037 | s.25 | True |
initial_seasons.26 | -619.63748 | s.26 | True |
initial_seasons.27 | -522.08684 | s.27 | True |
initial_seasons.28 | -358.79810 | s.28 | True |
initial_seasons.29 | -164.10064 | s.29 | True |
initial_seasons.30 | 80.519978 | s.30 | True |
initial_seasons.31 | 374.56130 | s.31 | True |
initial_seasons.32 | 642.67196 | s.32 | True |
initial_seasons.33 | 958.01110 | s.33 | True |
initial_seasons.34 | 1225.5055 | s.34 | True |
initial_seasons.35 | 1465.0462 | s.35 | True |
initial_seasons.36 | 1531.8976 | s.36 | True |
initial_seasons.37 | 1404.5379 | s.37 | True |
initial_seasons.38 | 1165.0485 | s.38 | True |
initial_seasons.39 | 979.30432 | s.39 | True |
initial_seasons.40 | 850.12616 | s.40 | True |
initial_seasons.41 | 737.25041 | s.41 | True |
initial_seasons.42 | 650.60912 | s.42 | True |
initial_seasons.43 | 540.71120 | s.43 | True |
initial_seasons.44 | 549.93113 | s.44 | True |
initial_seasons.45 | 434.20512 | s.45 | True |
initial_seasons.46 | 340.90809 | s.46 | True |
initial_seasons.47 | 245.39567 | s.47 | True |
pred = fit.forecast(48)
fig, ax = plt.subplots(figsize=(25, 6))
ax.plot(train.index[-96:], train.values[-96:],color='black')
ax.plot(train.index[-96:], fitted[-96:], color='orange')
ax.plot(test.index, pred,color='orangered')
ax.plot(test.index, test.values, color='grey')
plt.title("Simple Exponential Smoothing (Black/grey = Actual, Orange = Fitted/Forecast)");