2016-11-02 14 views
1

この質問が存在する画像を受け入れ再発レイヤを書く:私は畳込みを実装しようとしているhttps://github.com/fchollet/keras/issues/4266Kerasも、問題として

- LSTMを。 これは、画像を入力として受け取り、畳み込みを使用してLSTMのさまざまなゲートを計算する反復レイヤです。 Recurrentをサブクラス化し、入力ディメンションを変更しようとしています。

私はwriting a custom layerのドキュメントを読んで、ソースコードを読んで、何が起こっているのかを理解するための提案に従っています。

私はrecurrent.pyのコードを読んで、構造が明確であることを考える:あなたはRecurrentから継承していますが呼び出して上書きしない、代わりにカスタムstep機能を提供し、Recurrentは各ステップを適用するの世話をしますシーケンス内のエントリ。

出発点として、私はGRUのコードをとり、それを自分のニーズに合わせようとしました。 2D畳み込みとGRUを結合したい(通常はLSTMだが、それは問題ではない - 私はC-GRUを実装することに決めた)

モデルに通常の2D畳み込み3つの特徴を出力する。これらの3つの機能はGRUのr、z、hアクティベーションとして使用されます。カスタムレイヤーでは、状態を追跡するだけです。私の層は訓練可能な体重を持っていません、彼らは畳み込みに含まれています。元GRUコードへ

注目すべき変更点は次のとおりです。

def step(self, x, states): 
    # the previous state is a 2D vector 
    h_tm1 = states[0] # previous memory 

    z=self.inner_activation(x[:,0,:,:]) 
    r=self.inner_activation(x[:,1,:,:]) 
    hh=self.activation(x[:,2,:,:]) 

    h = z * h_tm1 + (1 - z) * hh 
    return h, [h] 

あなたが見ることができるように、私は単に畳み込みから機能を再利用しています。乗算は要素ごとに実行する必要があります。これをデバッグして、それが意図した動作をしていることを確認します。

状態は2Dとなりますので、私はあまりにも、initial_stateを変更しています:

def get_initial_states(self, x): 
    initial_state=K.zeros_like(x) # (samples, timesteps, input_dim) 
            # input_dim = (3, x_dim, y_dim) 
    initial_state=K.sum(initial_state, axis=(1,2)) # (samples, x_dim, y_dim) 
    return initial_state 

output_shape再発ネットワーク用にハードコードされているようです。私はそれをオーバーライドしています:ハードコードされたのです

def get_output_shape_for(self, input_shape): 
    #TODO: this is hardcoding for th layout 
    return (input_shape[0],1,input_shape[2],input_shape[3]) 

もう一つは、input_specです。コンストラクタで は、スーパーへの呼び出しの後、私は私の入力次元でそれを上書きしています:

class CGRU(Recurrent): 
    def __init__(self, 
       init='glorot_uniform', inner_init='orthogonal', 
       activation='tanh', inner_activation='hard_sigmoid', **kwargs): 

     self.init = initializations.get(init) 
     self.inner_init = initializations.get(inner_init) 
     self.activation = activations.get(activation) 
     self.inner_activation = activations.get(inner_activation) 

     #removing the regularizers and the dropout 

     super(CGRU, self).__init__(**kwargs) 

     # this seems necessary in order to accept 5 input dimensions 
     # (samples, timesteps, features, x, y) 
     self.input_spec=[InputSpec(ndim=5)] 

他の小さな変化があります。 あなたはここに全体のコードを見つけることができます:私はデバッグしようとしているhttp://pastebin.com/Cdmr20Yn

を:ペーストビン上

theano.tensor.var.AsTensorError: ('Cannot convert [None] to TensorType',)

全体のエラーメッセージ:走っhttp://pastebin.com/60ztPis3

が、これは次のエラーメッセージを生成しますコード。しかしそれはむしろ難しく、Kerasのソースコードには深く関わっています。 1つのこと:実行は私のカスタムstepの機能には決して達しません。だから明らかに設定の何かが間違っています。の関数Recurrentでは、input_shapeはエントリを持つタプルです(None, 40,1,40,40)

これは正しいです。私のシーケンスは40の要素を持っています。それぞれ1つの機能と40×40解像度の画像です。私は "th"レイアウトを使用しています。

Recurrentcall関数です。 私のコードがK.rnnへの呼び出しに達すると、セットアップがうまくいくように見えます。 Input_specが正しいようです。 しかし、K.rnnの間にクラッシュします。私のステップ機能に達することなく。

def call(self, x, mask=None): 
    # input shape: (nb_samples, time (padded with zeros), input_dim) 
    # note that the .build() method of subclasses MUST define 
    # self.input_spec with a complete input shape. 
    input_shape = self.input_spec[0].shape 
    if self.stateful: 
     initial_states = self.states 
    else: 
     initial_states = self.get_initial_states(x) 
    constants = self.get_constants(x) 
    preprocessed_input = self.preprocess_input(x) 

    last_output, outputs, states = K.rnn(self.step, preprocessed_input, 
             initial_states, 
             go_backwards=self.go_backwards, 
             mask=mask, 
             constants=constants, 
             unroll=self.unroll, 
             input_length=input_shape[1]) 

この時点で私は失われています。 設定の一部が欠落しているようです。

UPDATE:

フム、今私は奇妙な問題を抱えている: 私のコードは以下のようになります。バックエンドとしてTheanoが可能なコンピュータで

# this is the actual input, fed to the network 
inputs = Input((1, 40, 40, 40)) 

# now reshape to a sequence 
reshaped = Reshape((40, 1, 40, 40))(inputs) 

conv_inputs = Input((1, 40, 40)) 
conv1 = Convolution2D(3, 3, 3, activation='relu', border_mode='same')(conv_inputs) 
convmodel = Model(input=conv_inputs, output=conv1) 
convmodel.summary() 

#apply the segmentation to each layer 
time_dist=TimeDistributed(convmodel)(reshaped) 

from cgru import CGRU 

up=CGRU(go_backwards=False, return_sequences=True, name="up") 

up=up(time_dist) 

output=Reshape([1,40,40,40])(up) 

model=Model(input=inputs, output=output) 
print(model.summary()) 

、これは動作します。 モデルの概要は次のとおりです。

________________________________________________________________________________ 
Layer (type)      Output Shape   Param #  Connected to      
==================================================================================================== 
input_1 (InputLayer)    (None, 1, 40, 40, 40) 0            
____________________________________________________________________________________________________ 
reshape_1 (Reshape)    (None, 40, 1, 40, 40) 0   input_1[0][0]      
____________________________________________________________________________________________________ 
timedistributed_1 (TimeDistribute(None, 40, 3, 40, 40) 30   reshape_1[0][0]     
____________________________________________________________________________________________________ 
up (CGRU)      (None, 40, 1, 40, 40) 0   timedistributed_1[0][0]   
____________________________________________________________________________________________________ 
reshape_2 (Reshape)    (None, 1, 40, 40, 40) 0   up[0][0]       
==================================================================================================== 
Total params: 30 
____________________________________________________________________________________________________ 

しかし、バックエンドとしてtensorflowを持つコンピュータ上で、コードが失敗しました。 convmodelmodel.summary()を追加しました。それまではそれが動作します:

Layer (type)      Output Shape   Param #  Connected to      
==================================================================================================== 
input_4 (InputLayer)    (None, 1, 40, 40)  0            
____________________________________________________________________________________________________ 
convolution2d_2 (Convolution2D) (None, 3, 40, 40)  30   input_4[0][0]      
==================================================================================================== 
Total params: 30 

しかし、その後、プログラムがクラッシュを:

ValueError: Shapes (?, ?, 40, 40) and (40, ?, 40) are not compatible

TheanoとTensorflowがBATCH_SIZEごとに異なる(と互換性のない)プレースホルダを持っているように思え? どちらの場合でも「th」イメージレイアウトを使用するようにKerasを設定しました。

答えて

0

私は問題が解決したと思います。 initial_statesにはリストがあり、output_dimensionを修正する必要がありました。 これはうまくいくようです。 根本的なバックエンド(例えばTheano vs Tensorflow)には他にもいくつかの問題がありますが、それはこの質問のためにはあからさまなようです。

問題が本当に修正され、レイヤーが学習できると確信できたら、この回答を必要なすべての手順で更新します。

関連する問題