SARIMAXのexog(外生変数)の入力方法


概要

  • SARIMAXで電力量を予測する。
  • SARIMAXに外生変数を入力する。
  • エネルギーデータと外気温度でどの程度変化するか確認する。

注意
exogのデータ数は、fit時はendogと同じ数だけ入力、forecast時は、steps数と同じ数だけ入力する。

実装

import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib as plt
plt.rcParams['font.family'] = 'IPAexGothic'

df = pd.read_csv(r'C:\Users\***\OneDrive\ドキュメント\Study\Qiita\SampleData.csv',
                 engine='python',
                 index_col=[0],
                 parse_dates=[0],
                )
df.index.freq = 'H'

# 予測日を2017年8月3日として、過去3日間のデータをSARIMAXのendogとしました。
# endog,exogは共に3日分のデータです。(exogが外生変数(外気温))
# order,seasonal_orderはコレログラムとか使って推定するのですが、面倒だったのでaicが一番低いものを入れました。

forecastdate = pd.datetime(2017,8,3,0,0)
train_df = df.loc[forecastdate -pd.offsets.Day(3) :forecastdate - pd.offsets.Hour(1),:]
temp_df = pd.DataFrame(df.loc[forecastdate:forecastdate + pd.offsets.Hour(23),'外気温度'])
ele_df = df.loc[forecastdate:forecastdate + pd.offsets.Hour(23),'高圧受電']

fit_with_temp = sm.tsa.statespace.SARIMAX(  endog=train_df.loc[:,'高圧受電'],
                                            exog=train_df.loc[:,'外気温度'],
                                            enforce_invertibility=False,
                                            enforce_stationarity=False,
                                            order=(1,0,1),
                                            seasonal_order=(1,0,0,24)).fit()

fit = sm.tsa.statespace.SARIMAX(endog=train_df.loc[:,'高圧受電'],
                                enforce_invertibility=False,
                                enforce_stationarity=False,
                                order=(1,0,1),
                                seasonal_order=(1,0,0,24)).fit()

result_df = pd.DataFrame({'実績値':ele_df,
                          '予測値_外生変数有':fit_with_temp.forecast(steps=24,exog=temp_df),
                          '予測値_外生変数無':fit.forecast(steps=24)
                         }
                        )

result_df.plot(figsize=(15,5))

結果

  • 外生変数入力の有無で、結果に差が出たか比較する。

項目 予測精度(RMSE)
外生変数有 3.817
外生変数無 5.457

逐次的に処理ができる環境であれば、より精度よく予想できそうであるが、1日1回ではなかなか難しいようである。

fit_with_temp.params

外気温度         1.398241
ar.L1        0.851124
ma.L1        0.108688
ar.S.L24     0.608674
sigma2      22.464773
dtype: float64

係数を確認すると、外気温度が上昇すれば、電力量が高くなるようである。
問題は、冬季ではこれが逆転してしまうこと・・・

まとめ

  • 電力量に対して、外生変数(外気温度)を入力することで一定の効果がみられる。
  • 予測するデータ分の外気温度の予報値が必要。
  • 逐次的に処理すれば、予測精度の改善ができそう