周期的な変動に予測モデルを追従させるときに起きる問題
本連載の、値の変動に周期性がある場合は予測がその周期性に追従できているか、という点も予測モデルを評価する際に気になるポイントになります。
第3回で扱った「都道府県ごとの月次転入数を予測するモデル」にて、時間ラグを追加して作成したモデルが出力する予測値と実績値について、鹿児島県の例を振り返ってみましょう。
時間ラグ期を追加した鹿児島県の月次転入数を予測するモデル
第3回では、毎年4月にピークを迎える季節変動性のある実績値に対して予測値のピークが発生する時期は追従できている、と紹介しました。しかし、より詳細に見ると実績値ではピークとなる4月の手前の3月にも準ピークと言える転入者数の増加があるにもかかわらず、準ピークには予測値は追従できていないように見えます。
この問題の要因について、次のことが考えられます。
- 説明変数を第2回のモデルと同じくラグ1期のみとした場合、ピークである4月の予測において準ピークである3月の入力が有効であったが、平年並みである5月の予測において4月の入力が効きすぎてしまい、過剰に大きい予測値となり、位相ずれのように見えた。
- 説明変数を第3回のモデルと同じくラグ1期と2期とした場合、ラグ1期から2期への増加分もモデルは理解することができるようになった。4月の予測において平年並みである2月から3月への増加分の入力が有効であったが、3月の予測においては1月から2月への増加分はあまりないため準ピーク的な予測値となっていない。
2点目における「ラグ1期から2期への増加分もモデルは理解した」という仮説については、他の根拠として、6月の予測値が実績値に対して過少となっている部分は4月から5月への減少分の影響を受けている、と考えることができます。
これらの問題に対する代表的な対応方法として、以下2つを紹介します。
- 周期性を表現するデータを入力(説明変数)に追加する。例えば、前年同月の実績値を説明変数に追加することで、年間における月ごとの周期的な変動成分も予測モデルが表現できるようにする。
- 時間を表現する成分を入力に追加する。例えば、「月」という説明変数を追加する。
このような情報を予測モデルに追加することで、転入者数について3月は準ピーク、4月はピークという、月ごとの周期的な特徴を予測モデルが学習できるでしょう。
ディープラーニングにおける、設計・チューニングの重要性
本記事ではディープラーニングそのものには焦点を当てていないため、そのネットワーク設計やチューニングについては一切触れておりません。ここでは、その一部分ですが紹介します。
記事中で紹介した予測モデルの結果について、実際にマシン環境を構築してソースコードを実行された際に、記事の内容と多少異なっていることに気づいたかもしれません。実は、何回か再実行していただくと分かりますが、実行ごとに異なる予測モデルが作成されます。これは、以下のコードにてネットワーク内の各ノードにおけるパラメータの初期値(kernel_initializer)を乱数で設定しているためです。
### DL学習設定
…
def weight_variable(shape, name=None):
return np.sqrt(2000.0 / shape[0]) * np.random.normal(size=shape)
…
for i, input_dim in enumerate(([n_in] + n_hiddens)[:-1]):
model.add(Dense(n_hiddens[i], input_dim=input_dim,
kernel_initializer=weight_variable))
…
…
model.add(Dense(n_out, kernel_initializer=weight_variable))
各ノードにおけるパラメータの初期値はとても重要であり、ディープラーニング中のさまざまな外部パラメータをよほどチューニングしていない限りは初期値次第でさまざまな予測モデルができてしまい、その学習結果の予測モデルは数多くあるどこかの局所最適解に収束してしまいます。
社会から求められる予測モデルの内部構造の説明が難しい
最後に、本記事で用いたディープラーニングの技術実装について、TensorFlowに付属されている学習過程やネットワーク構造を可視化するツール「TensorBoard」を紹介します。
下はTensorBoardを使用するためにコードを追加、変更した部分です。
### tensorboardのための事前設定
import shutil
import os
from tensorflow.keras.callbacks import Callback, TensorBoard
logdir = 'log'
shutil.rmtree(logdir, ignore_errors=True)
os.mkdir(logdir)
list_cb = []
list_cb.append(early_stopping)
list_cb.append(TensorBoard(log_dir=logdir))
### DL学習
hist = model.fit(train_x, train_y, epochs=epochs,
…
callbacks=list_cb)
TensorBoard用の記録ファイルを残すためのディレクトリ(log)を作成し、学習(model.fit())の際にコールバック関数として呼び出すリスト(list_cb)にTensorBoard関数を追加することで、学習の実行時に記録ファイルが作成されるようにします。
このコードを用いたディープラーニングの実行後、コマンドライン環境から以下のコマンドでTensorBoardを起動します。
$ tensorboard –logdir=log TensorBoard 1.14.0 at http://localhost:6006/ (Press CTRL+C to quit)
tensorboardというコマンドは、TensorFlowがインストールできていれば合わせて使えるようになっています。コマンドが無事に実行されると、マシン内でWEBサーバプロセスが起動されます。WEBブラウザからURL「http://localhost:6006」にてWEBサーバにアクセスします。下はTensorBoardのWEB画面にて「GRAPHS」タブを選び、「dense_1」をダブルクリックして拡大したグラフです。
「dense_1」を拡大したグラフ
「kernel」から「MatMul」に向かう矢印には「19×200」と書かれています。これは入力層(説明変数の数19)から第1隠れ層(ノード数200)への重み変数の個数を示しています。同様に「bias」から「BiasAdd」に向かう矢印に書かれた「200」は、第1隠れ層にある定数項の数を示しています。
紹介したのは一部分だけですが、このようにソースコードとして記述したネットワークの設計が、実際に設計通りに実装されているか確認することができます。
PoCプロジェクトなどでディープラーニングを用いるときに起こりやすい問題として、作成した予測モデルの内部構造を説明することが難しい、ということがあります。少し前までは、「ディープラーニングの中身はブラックボックスで、説明が難しい」という説明が通用していました。しかし最近では社会的に問題となるような予測結果を出してしまった、というようなニュースが多く出てくるようになり、ディープラーニングにも「説明可能性」が求められるようになってきました。このような課題へのアプローチにもTensorBoardによるネットワーク設計の可視化は一助になる可能性があります。
おわりに
本記事では時系列データを用いた予測モデルの作り方、また、実際に現場で働いているAIエンジニアの目線から、どのようなことを期待されているか、どのようなことを考えながらその仕事をしているか、を紹介しました。
AIの技術や製品・サービスに関心はあるけれど、その裏側で動作するシステムやプログラムなどには実際に自分で触ったことはない、という方もいらっしゃると思います。動作するソースコードも紹介させていただきましたので、実際にご自身の手で、ディープラーニングを動かしてみるのはいかがでしょうか。
