前回の続きです。ハンガリーにおけるchikenpox(水疱瘡)のデータを使って、BUTAPESTにおける患者数の3か月分の予想を行っています。前前回は、AUTOARIMAでMAE36を叩き出しました。前回は、LightGBMでMAE38でした。今度は、AutoKerasを使って予想したいと思います。

Feature engineering

前回と同じですが、次の観測数値を、現在の観測数値と過去3レコード分の数値を使って予想します。

next = now + past1 + past2 + past3

そして日付列を整数順列にします。

df = pd.read_csv("/content/drive/MyDrive/hungary_chickenpox.csv")

df3 = df >> select(X["Date"],X["BUDAPEST"])

df3 = (df3 >>  
  mutate(next = lead(X["BUDAPEST"],1)) >>
  mutate(past1 = lag(X["BUDAPEST"],1)) >>
  mutate(past2 = lag(X["BUDAPEST"],2)) >> 
  mutate(past3 = lag(X["BUDAPEST"],3)) >>
  tail(-3) >> 
  head(-1)
)

df4 = df3 >> select(~X["Date"])
df4 = df4.reset_index(drop=True)
df4 = df4.reset_index()
df4

AutoKeras

Autokerasは、neural network(NN)のAutoMLです。NNの構造は、自由すぎて逆にどうすればいいのかわからないですが、AutoKerasでいい感じのを選んでくれます。GPUを使えますので計算早くできます。

必要パッケージをインストールします。

!pip -q install autokeras
!pip -q install tensorflow
import autokeras as ak

データをtrain+validation とtestセットに分割します。直近3か月分(13レコード分)を予想したいので、train+validationは最後の13レコードを除いたものにします。また、target variable と explanation variable のデータフレームに分ける必要があります。

X_train_validation = (df4 >> select(~X["next"]))[:-13] # omit target and forecast period
y_train_validation = (df4 >> select(X["next"]))[:-13] # pick up target and omit forecast period

AutoKerasに学習してもらいます。

ak_model = ak.StructuredDataRegressor(max_trials=100,
                                      overwrite=True,
                                      metrics=['mae'])

ak_model.fit(X_train_validation, y_train_validation, epochs=200,validation_split=0.2)

""" モデルを保存・保存したものを読込む場合
# Evaluate the best model with testing data.
model_autokeras = reg.export_model()
model_autokeras.save("/content/drive/MyDrive/autokeras_model.h5")

from tensorflow.keras.models import load_model
ak_model = load_model("/content/drive/MyDrive/autokeras_model.h5",custom_objects=ak.CUSTOM_OBJECTS)
"""

30分くらいで最適なNeural Networkの構成を見つけてくれます。

最適な構成で予測を行います。時系列データなので、1未来づつ予測します。autokerasのモデルは再学習可能なので、現在までのデータで逐次学習させます。

from tensorflow.keras.callbacks import ModelCheckpoint

result_AK = pd.DataFrame(0,
                  index=np.arange(13),
                  columns=["pred", "true_diff"])

last30 = len(df4)-13
last = len(df4)

for i in range(last30,last):
  X_train = (df4 >> select(~X["next"])).iloc[0:i]
  y_train = (df4 >> select(X["next"])).iloc[0:i]

  X_test = (df4 >> select(~X["next"])).iloc[i:i+1] 
  y_test = (df4 >> select(X["next"])).iloc[i:i+1] 

  checkpointer = ModelCheckpoint(filepath='logs',
                               verbose=1,
                               save_best_only=True)
  
  ak_model.fit(x = X_train, y= y_train,
          epochs = 50,
          validation_split=0.1,
          callbacks = [checkpointer])
  
  pred = ak_model.predict(X_test)
  result_AK.iloc[i-(last30),0] = float(pred)
  result_AK.iloc[i-(last30),1] = y_test.values[0,0]

result_AK["mae"] = abs(result_AK["true_diff"]-result_AK["pred"])
result_AK["mae"].mean()

31.8

MAE 31は今までで一番いいスコアがでました。今のところ、autoarima、lightGBM with optuna tuning よりもいいスコアです。

ちなみにNNの構造を見てみます。

from tensorflow.keras.utils import plot_model
plot_model(ak_model.export_model(), show_shapes=True, show_layer_names=True)

プロットしてみます。

import seaborn as sns
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
sns.lineplot(x=df2["Date"] >> tail(-3) >> head(-1) >> tail(50) >> head(-13),y=df2["BUDAPEST"]>> tail(-3) >> head(-1) >>  tail(50) >> head(-13),color="blue",legend='auto')
sns.lineplot(x=df2["Date"]>>tail(-3) >> head(-1) >> tail(13),y=df2["BUDAPEST"]>>tail(-3) >> head(-1) >>tail(13),color="skyblue",legend='auto')
sns.lineplot(x =(df2["Date"]>>tail(-3) >> head(-1) >> tail(13)).reset_index(drop=True),y=result_AK["pred"], color="red",legend='auto')
ax.legend(["True value", "True value", "Predicted value"])
sns.set_theme(style="darkgrid")
plt.show()

次は、tpotでAutoMLを実施します。

Categories:

category