2017-05-08 13 views
2

心臓MRI画像から2つの異なるボリューム(収縮期および拡張期)を予測することを目指しています。Keras - CNNの畳み込み部分を2つの別々の完全接続レイヤーと共有する方法

私がやった最初のことは、2つの別々の「順次」CNNを実装して、それぞれが1つのボリュームを予測することです。

まずモデルの定義:しかし、私はこのように2で、2つの異なるモデルを訓練する必要が

model_systole= get_model() 
model_diastole= get_model() 
print('Fitting systole model...') 
hist_systole = model_systole.fit_generator(generator_train_sys, nb_epoch = 1,samples_per_epoch=N_train,validation_data=generator_validate_sys,nb_val_samples=N_validate) 

print('Fitting Diastole model...') 
hist_diastole = model_diastole.fit_generator(generator_train_dia,nb_epoch = 1,samples_per_epoch=N_train,validation_data=generator_validate_dia, nb_val_samples=N_validate) 

def get_model(): 
    dim_img = 64 
    model = Sequential() 
    model.add(Activation(activation=center_normalize, input_shape=(30, dim_img, dim_img))) 

    # CONVOLUTIONAL LAYERS 
    model.add(Convolution2D(32, 3, 3, border_mode='same')) 
    model.add(Activation('relu')) 
    model.add(Convolution2D(32, 3, 3,border_mode='same')) 
    model.add(Activation('relu')) 
    model.add(Dropout(0.25)) 

    model.add(Convolution2D(64, 3, 3, border_mode='same')) 
    model.add(Activation('relu')) 
    model.add(Convolution2D(64, 3, 3, border_mode='same')) 
    model.add(Activation('relu')) 
    model.add(ZeroPadding2D(padding=(1, 1))) 
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) 
    model.add(Dropout(0.25)) 

    # FULLY CONNECTED LAYERS 
    model.add(Flatten()) 
    model.add(Dense(512, W_regularizer=l2(1e-3))) 
    model.add(Activation('relu')) 
    model.add(Dropout(0.5)) 
    model.add(Dense(1)) 

    adam = Adam(lr=0.0001) 
    model.compile(optimizer=adam, loss=root_mean_squared_error) 
    return model 

をそして、私は2つの異なるボリュームを予測するために、2つの異なるモデルを呼び出します畳み込み部分。

===>私は(1つのユニークな畳み込み部分2つの別々のFC層は畳み込み一部を共有する)私のネットワークの畳み込み一部を共有したい、と私のボリュームの両方を予測することに2つの異なるFCレイヤを追加します

あなたはKerasでこれを行う方法を知っていますか? Kerasグラフモードに切り替える必要がありますか?

ありがとうございました。

答えて

4

get_model()を2回呼び出すと、2つの異なるインスタンスが作成されます。つまり、2つの異なる初期セットの重みで初期化されます。また、それらは異なるモデルであるため、バックプロパゲーションの間は決して関連しません。

Modelクラスに切り替える必要があります。 Graphの代わりにModelクラスを取得するようKerasを更新することを強くお勧めします。

input1 = Input(30 ,64, 64) 
input2 = Input(30 ,64, 64) 
conv1 = Conv2D(32, (3,3), padding='same', activation='relu') # shared 

model1 = conv1(input1) 
model2 = conv1(input2) 
model1 = Flatten()(model1) 
model2 = Flatten()(model2) 

# following dense layers do not share the weight 
model1 = Dense(512, activation='relu', kernel_regularizer=l2(1e-3))(model1) 
model2 = Dense(512, activation='relu', kernel_regularizer=l2(1e-3))(model2) 
model1 = Dense(1)(model1) 
model2 = Dense(1)(model2) 

model = Model(inputs=[input1, input2], outputs=[model1, model2]) 
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) 

基本的に、レイヤーは現在呼び出し可能です。だから私は最初に1つの畳み込みレイヤーを作成し、2つの異なる入力でそれを呼び出すので、そのウェイトは共有されます。しかし、私は2つの密なレイヤーを(Dense(512)のように)2回インスタンス化して呼び出すため、共有されません。

+0

大変ありがとうございました。今晩はこれを試してみます。 – JeromeK

+0

あなたは新しい 'Model'クラスを学ぶのに少し時間を費やす必要がありますが、それはそれだけの価値があります。あなたの問題を解決するには、回答を受け入れたものとしてマークしてください。 –

+0

なぜモデルを平坦化する必要がありますか? – anon

関連する問題