環境システム株式会社公式HP

〒660-0083 兵庫県尼崎市道意町7-1-3
尼崎リサーチ・インキュベーションセンター512

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

蛇使いな彼女BLOG

【第85回】 Tensorflowの時系列予測に関しての備忘録 #3.

2023.05.19

【予測結果の参照に関する注意点】


学習済みモデルの予測値とラベルの参照に関する注意点ですが、チュートリアルではこのようにtrain_dftest_dfのデータ編集と呼び出しもWindowGeneratorに関数で連結させてしまっています。
これのどこが問題になるのかというと、

サイキット・ラーンでよく目にする予測方法を例に挙げてみましょう。
以下のように学習済みモデルからテストデータの予測値を取得したとします。
answer=Model.predict(wide_window.test)

このときモデルの予測結果は変数代入によってanswerに固定されるが、test_dfの正解ラベルは参照不能となっているはずです。
なぜかと言うとwide_window.testを呼び出すことによって、以下のtestメソッドが動きます。(train/valも同じ)

@property
def test(self):
 return self.make_dataset(self.test_df)


「@property」は値を呼び出す目的で直下の関数が動くようにハンドリングします。
よって、この場合make_dataset関数とWindowGeneratorからtest_dfが<同時に呼び出され、shuffle=Trueの影響からWindowGenerator.testを実行するたびに毎回シャッフルされたデータセットが出力されます(°°;)

買ったばかりのトランプは箱から出して表を見ると、カードの並びが統一されていますよね。
元のtestデータは時系列順なので新品のトランプAに例えると、1回の予測につきAは裏向きで1度シャッフルされた状態からモデルによって予測結果が返されます。
当然デッキは裏向きなので実際の答えはひっくり返さないと見れませんね?
私が言いたいのは、デッキの表面を見るとき(testデータを参照するとき)、WindowGenerator.testからtestデータを呼び出すことによって、予測結果answerの元となった正解のシャッフルデッキとは別物になってしまうという事です。(これはAとは別物の新品のトランプBを1回シャッフルして表向きに開示したものです。)

チュートリアルのメソッドではこのようなルールでコードが組まれています。
この問題をどう処理するかについてですが、shuffle=Falseに設定を変更するか、モデルに入力する前にデータセットの参照値を保存しておくかのどちらかの手段を取る必要があります。
(※ここでself、selfってなんやねん!と思う人も居るかと思いますが、平たく言うとクラスのWindowGeneratorがselfで、self.test_df = test_dfという関係です。
WindowGenerator.testはtest_dfではなく@property直下のdef test(self)を意味しています。
ややこしいですね~。)

以下テンソルで作ったデータセットの参照方法について2通り示します。


【as_numpy_iterator()】


特徴3列目をラベルにした場合のデータセットをas_numpy_iteratorでリスト化して取り出した場合、(バッチ層数n,インプットラベル,バッチ数,Time行,特徴列数)
⇒(12,2,32,24,3)という形式で返ってきます。

↑スクショではインプットに対応するラベルをセットで表示しています。
見て分かるとおりデータセット全体の階層を表す次元の次にインプットデータとラベルデータ2つのデータが格納されています。
データを順番に取り出す場合は繰り返し構文などを使うと良さそうですね。
次にnextとiter関数を使った参照方法ではコレクションの中から1つ参照する事が出来ます。


【next(iter())】


この方法はexampleメソッドで使用されていて、チュートリアルではシェイプの参照や描画用に参照値が利用されています。
exampleメソッドでは内部でWindowGenerator.train=trainメソッドを呼び出し、next(iter())で参照した値をresultに留めておくことでデータセットが自動的にシャッフルされるのを防ぐことを可能にしています。


def example(self):
"""Get and cache an example batch of `inputs, labels` for plotting."""
result = getattr(self, '_example', None)
if result is None:
# No example batch was found, so get one from the `.train` dataset
result = next(iter(self.train))
# And cache it for next time
self._example = result
return result



getattr(オブジェクト,‘名前’,デフォルト値)はオブジェクトの値を取得することができるPython組み込み関数です。
最初の result = getattr(self, '_example', None)ではself._exampleは存在しないので、デフォルトで設定されているNoneを返します。
result=Noneであるとき、trainメソッドが呼び出されシャッフルされたデータセットの最初のバッチがself._exampleに固定されます。

すると二回目以降の呼び出しはresultの値が出力されます。
testデータの参照目的では画期的に思いますが、各バッチごとにモデルに代入しないと正解ラベルとの比較が出来ませんね。
なのでチュートリアルではサンプルデータの描画用にのみexampleメソッドを使用しています。

pagetop