mxnetでの最初のLSTM

FXのデータで研究を始めてみたものの、全く収束する気配がありません。

もしかしたらLSTMの使い方を間違っているのかも?

確認のため簡単なシミュレーションデータで実装してみました。
データはよく使われるsin波(に少し手を加えたもの)です。

簡単なLSTMモデルの定義

loss = gloss.L2Loss() # 損失関数

### sequentilalモデルを作ってもよいけれど、これでいく!
class RNNModel(nn.Block):
    def __init__(self, rnn_layer, **kwargs):
        super(RNNModel, self).__init__(**kwargs)
        self.rnn = rnn_layer
        self.dense = nn.Dense(1)

    def forward(self, inputs, state):
        X=inputs
        Y, state = self.rnn(X, state)
        output = self.dense(Y)       
        return output, state

    def begin_state(self, *args, **kwargs):
        return self.rnn.begin_state(*args, **kwargs)

100エポックでの結果

200エポックでの結果

結果を見ると、エポックを進めるたびに

  1. 損失関数の結果が、いい感じに収束している(#1の図)
  2. 予測結果が実測値に近づいている(#2の図)
  3. 予測値と実測値の差の分布が小さくなっている(#3の図)

ので、大きく間違ってはいないのではないか?と考えています。

実装時に特に悩んだのは次の2点

  1. LSTMの入力データってどんな形状とすべきなのか?

特徴量、タイムステップ、バッチサイズの3次元データになるのですが、以前cntkを使っているときには軸をどうすればよいのかわからず、サンプル、英語ブログを調べまくって「多分こうだろう・・・」でやっていました。
ところがmxnetではドキュメントにしっかりと明記してありました!

data: input tensor with shape (sequence_length, batch_size, input_size) when layout is “TNC”. For other layouts, dimensions are permuted accordingly using transpose() operator which adds performance overhead. Consider creating batches in TNC layout during data batching step.

http://mxnet.incubator.apache.org/api/python/gluon/rnn.html#mxnet.gluon.rnn.RNN

以前は普通にNTCで考えていたので、「どうやって時系列で処理しているのか?」理解できなかったのですが、正しくはTNCということでスッキリしました。

2. 隠れ層の初期化タイミングはいつか?

dive into deeplearningのサンプルを見ていてわからなくなっていたのですが、よくよく読み込むことで

・繰り返し毎に初期化(全く引き継がない)

でよいとわかりました。

色々と試行錯誤しているうちに

ラーニングレートとバッチサイズはハイパーパラメータ(人が決める)である

を痛感しました。
バッチサイズなんて処理速度に影響するだけだろう?と考えていたのが間違いでしたw

ディープラーニングはあまりに深すぎて、理解できないこと、もっと知りたいことがたくさんあります。
FXに応用できるまではまだまだ時間がかかりそうです・・・(´;ω;`)ウゥゥ

コメントを残す

メールアドレスが公開されることはありません。