2016-10-24 3 views
6

この質問はgithub issueとしても存在します。 私は、2次元畳み込みとLSTMレイヤの両方を含むKerasにニューラルネットワークを構築したいと考えています。Keras:lstmとconvを接続するための再構成

ネットワークはMNISTを分類する必要があります。 MNISTのトレーニングデータは、0〜9の手書き数字の60000グレースケール画像です。各画像は28x28ピクセルです。

イメージを4つの部分(左/右、上/下)に分割し、4つの順序で並べ替えてLSTMのシーケンスを取得しました。小サブ画像の

|  |  |1 | 2| 
|image| -> ------- -> 4 sequences: |1|2|3|4|, |4|3|2|1|, |1|3|2|4|, |4|2|3|1| 
|  |  |3 | 4| 

つの寸法を有する14 X 14 4つのシーケンスは、(幅または高さかどうかは問題ではありません)の幅に沿って互いに積層されています。

これは形状のベクトルを作成し、[60000、4、1、56、14]:サンプル

  • 4の数は、配列の要素数である

    • 60000(#時間ステップ)の
    • 1は、色の深さがKerasモデルに与えられるべきである(グレースケール)
    • 56及び14の幅であり、高さは今、この

    あります。 問題は、CNNとLSTMの間の入力ディメンションを変更することです。 私はオンラインで検索して、この質問を見つけました:Python keras how to change the size of input after convolution layer into lstm layer

    ソリューションは、画像を平坦化するが、(BATCH_SIZE以外のすべてを崩壊してしまう平坦化層とは反対に)タイムステップを保持リシェープ層であるように思われます。

    ここに私のコードは、これまでのところです:

    nb_filters=32 
    kernel_size=(3,3) 
    pool_size=(2,2) 
    nb_classes=10 
    batch_size=64 
    
    model=Sequential() 
    
    model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1], 
        border_mode="valid", input_shape=[1,56,14])) 
    model.add(Activation("relu")) 
    model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1])) 
    model.add(Activation("relu")) 
    model.add(MaxPooling2D(pool_size=pool_size)) 
    
    
    model.add(Reshape((56*14,))) 
    model.add(Dropout(0.25)) 
    model.add(LSTM(5)) 
    model.add(Dense(50)) 
    model.add(Dense(nb_classes)) 
    model.add(Activation("softmax")) 
    

    このコードは、エラーメッセージを作成します。

    ValueError: total size of new array must be unchanged

    はどうやらリシェープ層への入力が正しくありません。別の方法として、私はあまりにも、形状変更層にタイムステップを渡そうとしました:

    model.add(Reshape((4,56*14))) 
    

    をこれは右感じていないし、いずれにしても、エラーは同じままです。

    これは正しい方法ですか? ReshapeレイヤはCNNとLSTMを接続する適切なツールですか?

    この問題にはかなり複雑なアプローチがあります。 このように: https://github.com/fchollet/keras/pull/1456 タイムディストリビューションされたレイヤーで、次のレイヤーからタイムステップディメンションを隠しているようです。

    またはhttps://github.com/anayebi/keras-extra CNNとLSTMを組み合わせるための特別なレイヤのセット。

    シンプルな変形(Reshape)がそのトリックを行うなら、なぜ複雑(少なくとも彼らは私にとっては複雑に見えます)のソリューションはありますか?

    UPDATE

    あきれるほど、あまりにも、畳み込みを、私は寸法がプールで変更されることを忘れて(パディングの不足のため)。 kgrmは、model.summary()を使用して寸法を確認するように指示されました。

    リシェイプレイヤーの前のレイヤーの出力が(None, 32, 26, 5), に変更されました。model.add(Reshape((32*26*5,)))に変更されました。

    今とValueErrorが消えて、代わりにLSTMは文句:

    Exception: Input 0 is incompatible with layer lstm_5: expected ndim=3, found ndim=2

    私はネットワーク全体を通じてタイムステップ寸法を渡す必要があるように思え。どうやってやるの ?私はコンボリューションのinput_shapeにそれを追加した場合、それはあまりにも、文句:Convolution2D(nb_filters, kernel_size[0], kernel_size[1], border_mode="valid", input_shape=[4, 1, 56,14])

    Exception: Input 0 is incompatible with layer convolution2d_44: expected ndim=4, found ndim=5

  • 答えて

    5

    Convolution2D定義に従えば、あなたの入力は寸法(samples, channels, rows, cols)で4次元でなければなりません。これがエラーを起こす直接的な理由です。

    解決するには、TimeDistributedラッパーを使用する必要があります。これにより、時間の経過とともに静的(反復的ではない)レイヤーを使用することができます。

    関連する問題