Keras - 如何使用 2 个独立的全连接层共享 CNN 的卷积部分

Keras - How to share the convolutional part of a CNN with 2 separate FullyConnected layers

我正在研究 CNN,旨在从一组心脏 MRI 图像中预测 2 个不同的体积(收缩压和舒张压)。

我做的第一件事是实施 2 个独立的 "sequential" CNN,每个都预测一个体积。

首先定义模型:

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 个不同的体积:

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)

但是,我因此必须训练两个不同的模型,具有 2 个卷积部分。

===> 我想共享我网络的卷积部分,并向其添加 2 个不同的 FC 层来预测我的体积(1 个独特的卷积部分和两个独立的 FC 层共享卷积部分)

你知道如何用 Keras 做到这一点吗?我必须切换到 Keras Graph 模式吗?

非常感谢您的帮助。

当您调用 get_model() 两次时,它会创建两个不同的实例。这意味着它们将使用两组不同的初始权重进行初始化。此外,它们是不同的模型,因此它们在反向传播过程中没有任何关系。

您将不得不切换到 Model class。我强烈建议您更新 Keras,以便获得 Model class 而不是 Graph.

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'])

基本上,图层现在是可调用的。所以我首先创建了一个卷积层并用两个不同的输入调用它,所以它的权重是共享的。但是,我通过实例化两次(如Dense(512))调用了两个密集层,因此它们不共享。