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

今回は、LightGBMを使って予想したいと思います。ハイパーパラメーターチューニングにOptunaというパッケージを使用します。なお、調べた範囲ではRのlightGBMにはoptunaのようにチューニングしてくれるものはないようです。

まずは、feature engineeringを行います。time seriesなので、過去3レコード分のデータを説明変数に追加したいと思います。また、次の観測値(next)を目的変数にします。

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))
)

df3.head()

過去データがないところがNaNになってしまいました。削除します。

df3 = df3 >> tail(-3)
df3.tail()

一番下にも、NaNがあります。このレコードも削除します。

df3 = df3 >> head(-1)

日付を直接変数として取り込むことができないので、日付を整数の連番とします。

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

LightGBM

lightgbmパッケージとoptunaパッケージをインストールします。

!pip -q install lightgbm
import lightgbm as lgb
!pip -q install optuna
import optuna.integration.lightgbm as LGB_optuna

データフレームをlgb用のデータに変換する必要があります。前処理をしてからlgb.Dataset()にデータを渡します。

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

split = int(len(X_train_validation)*0.8)

X_train = X_train_validation.iloc[0:split,:]
X_validation = X_train_validation.iloc[split:,:]

y_train = y_train_validation.iloc[0:split,:]
y_validation = y_train_validation.iloc[split:,:]

lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_validation, y_validation)

paramに設定をして、チューニングします。

param = {
        'objective': 'regression',
        'metric': 'mae',
    }
best = LGB_optuna.train(param, 
                 lgb_train,
                 valid_sets=lgb_eval)

終わったらパラメーターを確認します。

best.params

{‘bagging_fraction’: 0.8788963832078169, ‘bagging_freq’: 1, ‘feature_fraction’: 1.0, ‘feature_pre_filter’: False, ‘lambda_l1’: 0.011069685334331, ‘lambda_l2’: 0.0004885866098954412, ‘metric’: ‘l1’, ‘min_child_samples’: 10, ‘num_leaves’: 31, ‘objective’: ‘regression’}

このパラメータがいいということなので、このパラメータを使ってモデルを訓練し、予想したいと思います。1レコードずつ予想します。time seriesのCVです。

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

split = len(df4) - 13
nrow = len(df4)

for i in range(split,nrow):

  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] # omit target and train period
  y_test = (df4 >> select(X["next"])).iloc[i] # pick up target and forecast period

  lgb_train_data = lgb.Dataset(X_train, y_train)
  
 # best parameter使用
  model = lgb.train(best.params, lgb_train_data) 
  pred = model.predict(X_test)
 
  result_LightGBM.iloc[i-(split),0] = pred
  result_LightGBM.iloc[i-(split),1] = y_test.values

result_LightGBM["mae"] = abs(result_LightGBM["true_value"]-result_LightGBM["pred"])
result_LightGBM["mae"].mean()

38.28

AUTOARIMAでMAE36なので、autoarimaに負けています。。

optunaを使ったhyper parameterのチューニングについては以下の記事で研究しています。

次は、AutoKerasをやってみたいと思います。

Categories:

category