時系列データ分析SARIMAモデル 「学習データのinputについて」【statsmodels】
stasmodelsのSARIMAX
statsmodelsのSARIMAXに学習データを読み込む際の注意点についてのメモです。
学習データ
statsmodelsではSARIMAモデルを扱うのに下記のクラスを使用します。 学習データは、endogに入力します。(arrayやDataframeに対応)←今回の問題箇所
class statsmodels.tsa.statespace.sarimax.SARIMAX(endog, exog=None, order=(1, 0, 0), seasonal_order=(0, 0, 0, 0), trend=None, measurement_error=False, time_varying_regression=False, mle_regression=True, simple_differencing=False, enforce_stationarity=True, enforce_invertibility=True, hamilton_representation=False, **kwargs)
私の場合は下記のようにpandasのDataframeでフォルダ内のcsvを全部読み込んで結合してendogに入力していました。 もっとスマートに作りたかったのは内緒です。
import pandas as pd import glob,os def CombineFiletoDF(folderpath): csvs = glob.glob(folderpath + '\*.csv') for csv in csvs: if csv == csvs[0]: df = pd.read_csv(csvs[0],dtype=np.float64,encoding='SHIFT-JIS',index_col=[0],parse_dates=[0]) else: df = df.append(pd.read_csv(csv,encoding='SHIFT-JIS',index_col=[0],parse_dates=[0],skiprows=0)) df = df.resample('H').asfreq() return df
で、下記のようにtrainDFつくって入力してフィッティングして、実データと比較してました。 ソフトウェアエンジニアではないので、私の場合はプロトタイプ作成を行った形です。 出力結果としては、タイムスタンプ付きのDataframe(Series?)として出力されます。
mod = sm.tsa.statespace.SARIMAX(endog = trainDF,#Dataframeで入力 enforce_stationarity=False, enforce_invertibility=False, order=SARIMAorder, seasonal_order=SARIMAORDER, freq='H' ) prediction_result = mod.fit(disp=False) prediction_result.predict(start=49,end=72) # Output 2017-01-24 01:00:00 3.074818 2017-01-24 02:00:00 3.000000 2017-01-24 03:00:00 3.925182 2017-01-24 04:00:00 3.074818 2017-01-24 05:00:00 3.925182 2017-01-24 06:00:00 3.074818 2017-01-24 07:00:00 3.925182 2017-01-24 08:00:00 3.074818 2017-01-24 09:00:00 1426.854329 2017-01-24 10:00:00 1479.087658 2017-01-24 11:00:00 1384.257394 2017-01-24 12:00:00 1287.257394 2017-01-24 13:00:00 1279.074818 2017-01-24 14:00:00 1165.202675 2017-01-24 15:00:00 1131.945281 2017-01-24 16:00:00 1111.496370 2017-01-24 17:00:00 1027.658846 2017-01-24 18:00:00 802.657166 2017-01-24 19:00:00 312.232253 2017-01-24 20:00:00 313.782805 2017-01-24 21:00:00 300.346733 2017-01-24 22:00:00 26.996639 2017-01-24 23:00:00 2.224455 2017-01-25 00:00:00 2.925182 Freq: H, dtype: float64
他方、ソフトウェア開発を行っている協力会社の方は、numpyのarrayでendogに入力していました。numpyのarrayにはindexがついていません。要するにどのデータを実際に使ったのかをindexで確認できない状況でした。結果としては、同じ値が出力されています。
mod = sm.tsa.statespace.SARIMAX(endog = np.array(trainDF),#numpyのarrayで入力 enforce_stationarity=False, enforce_invertibility=False, order=SARIMAorder, seasonal_order=SARIMAORDER, freq='H' ) prediction_result = mod.fit(disp=False) prediction_result.predict(start=49,end=72) # Output array([ 3.0748185 , 3. , 3.9251815 , 3.0748185 , 3.9251815 , 3.0748185 , 3.9251815 , 3.0748185 , 1426.85432885, 1479.08765798, 1384.25739448, 1287.25739448, 1279.0748185 , 1165.20267547, 1131.94528099, 1111.49637 , 1027.65884648, 802.65716595, 312.23225339, 313.78280451, 300.346733 , 26.99663893, 2.2244555 , 2.9251815 ])
start,endの固定値は、協力会社さんの作ったプログラムから出力した結果を決め打ちで入れています。
何が問題って、本来予測したかったのは、2017/1/25であったこと。
Dataframe入力しておけば、すぐ気づけた間違いも、np.arrayにしたことで見えなくなってしまってました。 データの操作が色々あったので、配列のほうが都合がよかったのかと思いますが、僕はDataframeで入力することをお勧めします。
だって、時系列データ分析してるのに、タイムスタンプとったらわけわからんと思うんだ。