前回、elman_netでやってみた「予測みたいなこと」をLSTMでやってみたら、どうなるのかをやってみます。
2017/12/02追記
>以降の説明の画像は、Version1.00のものです。
>Version1.10でアイコン等のデザインが一部変更になっています。
>しかし、見ればわかる程度と判断して特に貼り替えてません。
なんでやろうと思ったか?
ニューラルネットワークコンソールのGoogleグループで「long_short_term_memory(LSTM).sdcprojに定義されたネットワークをそのままUNITSにした高次のレイヤーを要望したら、既に「あるよ!」とのご返事をいただきました。
それで、そのLSTM(Long Short-Term Memory)ユニットを使ってみたくなったというだけです。
予測みたいなこと?
前にも書きましたが、今回やるのも、「予測」ではなく、「予測みたいなこと」です。
予測をするには、入力(x)に対して、結果(y)を推論します。
ですが、今回は入力(x)に対して、途中経過の出力(x')で評価してます。
なので「予測みたいなこと」です。
実際のところ、Auto_Encoderみたいに学習結果を元に生成している感じに近いです。
そんなことをしている理由は「手軽に予測している雰囲気を味わう」ためです。
厳密に見たら、ツッコミところ満載と思いますが、そこはご容赦を。
ちなみに、過去の数値のトレンドから未来の数値を推測してみる・・みたいな・・もう少し「予測っぽい」アプローチは以下の記事で試みてます。
ちょっと複雑なSINカーブデータを準備する
データは前回、シンプルRNNのケースで使ったものを使いまわします。
ただ、ちょっと数字を適当に加工して、こんな感じの複雑なカーブにしてみました。
あと、グラフだとわかりにくいですけど、なだらかに見えるところも、細かいノイズを入れました。
データセット作成
データの作り方自体は前回のシンプルRNNのケースと同じで、もとになるEXCELの数字をいじくっただけなので、作り方自体は、前回の記事およびCSVテキストベースのデータの作り方をテーマにした記事を参照してもらえればと思います。
ニューラルネットワークコンソールで新規プロジェクト
ニューラルネットワークコンソールを起動し、New Project を開き、適当な名前をつけて保存します。
そこに、以下の順番でレイヤーをドロップします。
- Input
- LSTM
- Affine
- Tanh
- SquaredError
こんな感じです。
ただ、デフォルトのままでは、だめなので、設定を変えていきます。
今回は、LSTMユニットを使ってます。
SONYの小林さんは以下のGoogleグループで「現状LSTMユニットは実験的に用意されているもので、実用的にはLSTMの中身を書き下した状態での利用をおすすめしています。」とコメントされていますが・・まあ、実用性のカケラもないお遊びなので(笑)いいとしましょう。
DATASETタブ
Open Datasetボタンで一覧を開き、データの準備のところで保存したCSVファイルをTrainingとValidationの両方に選択します。
TrainingとValidationの両方に同じデータを設定する理由
TrainingとValidationの両方に同じデータを設定するのが、ちょっと違和感があるかもしれないので、補足します。
分類問題なら「未知のデータを推論する」のが基本なので、こんなことはしません。
でも、今回は学習済のパラメータを使って同じInputデータから推論した結果が、オリジナルとどの程度異なるのか?をためそうとしているわけです。
なので、学習と評価で全く同じデータである必要があるわけです。
ここで、論理的・数学的に「なぜなら・・」と証明できたらカッコいいのですけどね。
自分の場合は、基本、いろいろ試行錯誤してたら、このやり方が一番うまくいったのでそうしている・・という以上のことを言えません(笑)
そのへんはご容赦くださいね。
DATASETタブにおける注意点
さて、話を戻します。
今回、データ・セット用CSVはsin_test.csvという前のままで、データの実態である、0.csv~7.csvの方だけを入れ替えるやり方をとりました。
入れ替え後の状態です。
ここで注意が必要なのが、上記図の赤枠のところです。
今回のように並び順に意味があり、かつ、テキストデータの場合に、Image Normalizationや Shuffle(特に Validationの方)にチェックがついていると、よろしくない結果がおきますので、ちゃんとはずれているかを確認してください。
inputレイヤー設定
25行1列のテキストデータを使うので、sizeを「25,1」に変更します。
LSTMレイヤー設定
LSTMレイヤーで主として変更する必要があるのは、sizeとaxisの2つみたいです。
axisは、時系列の方向が、0=行方向 か 1=列方向かを指定するみたいです。
今回は行数で時系列をあらわしているので、0ですね。
sizeは、LSTM内のニューロンの要素数・・という事なのですが、いくつが適切かの基準がよくわからなかったので、色々と数字を変えて試してみた結果、もっとも成績のよかった「25」でやってます。
その結果は以下の通りです。
AffineレイヤーとTanhレイヤー設定
Affineは、OutShapeだけを変更しました。
Inputと同じ「25,1」を指定しています。
ここを変えると、Tanhの設定も自動的に調整されるので、そっちはさわりません。
SquaredError設定
こちらは例によって、T.Datasetの変数名をInputと同じ「x」にします。
AutoEncoderっぽくやるためです。
CONFIGタブ設定
BatchSizeを小さくするのを忘れないようにしてください。
デフォルトで64ですが、そんなにデータ数がないので、いきなりエラーになって動きません。
とりあえず、「1」にしとけば動くので、そうしておきます。
これで上書き保存します。
これで準備はできました。
学習の実行
学習を実行します。
学習にはそれなりに時間がかかります。
結果のグラフはこんな感じです。
LSTMは収束に時間がかかると聞いていたのですが、意外にすんなり収束しているように見えます。
評価の実行
続けて評価を実行します。
結果で、x'が表示されていれば、0_0000フォルダにファイルはできてます。
トレースの結果を検証
名前をつけて保存したプロジェクトを例えば、my_lstm.sdcprjという名前にしていたら、同じフォルダに「my_lstm.files」というフォルダができているはずです。
そこでTRAININGまたはEVALUATIONの実行時の番号と同じフォルダの下にある、「0_0000」フォルダを開きます。
そこに、0.csvから7.csvというファイルができて、1行25列でデータができているので、それを比較用に、行列を入れ替えて貼り付けます。
そうすると、オリジナルと出力の比較ができます。
今回の最終結果のグラフはこんな感じです。
ほとんど、重なりあっててわかりにくいですが、微妙に点線がずれているところがあるので、オリジナルと予測の2つの線があることがわかります。
ちなみに、別途数字の比較で平均誤差率も計算したのですが、0.56%でした。
まあ、こんなもんですかね。
おまけ・・Sizeパラメータ決定までの試行錯誤
前の方で、LSTMのパラメータの「size」を試行錯誤の結果、25に設定したと書いたのですけれど、 じゃあ・・sizeの数値が適切でないと、どんな結果になるのか?も、ついでに書いておきます。
size=1の時
極端な例の方が面白いので、size=1でやった時の例です。
エラーにはなりません。
でも、学習の結果はこんな感じで、収束が遅くなります。
この状態で評価した結果はこうです。
学習がちゃんとできてないですよね。
ということで、パラメータの指定でエラーになってくれるとわかりやすいですが、こんな風に、エラーにはならないけど、結果が悪い・・こともあります・・という、おまけでした。