【问题标题】:Keras - How to share the convolutional part of a CNN with 2 separate FullyConnected layersKeras - 如何与 2 个独立的完全连接层共享 CNN 的卷积部分
【发布时间】:2017-05-08 21:06:57
【问题描述】:

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

我做的第一件事是实现 2 个独立的“顺序”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 模式吗?

非常感谢您的帮助。

【问题讨论】:

    标签: python tensorflow keras theano conv-neural-network


    【解决方案1】:

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

    您将不得不切换到Model 课程。我强烈建议您更新 Keras,以便获得 Model 类而不是 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))调用了两个密集层,因此它们不共享。

    【讨论】:

    • 太好了,非常感谢,我今晚试试。
    • 好的。您将不得不花一些时间学习新的Model 课程,但这是值得的。如果这能解决您的问题,请将答案标记为已接受。
    • 为什么我们需要展平模型?
    • @aditya 因为conv1 的输出需要使用Dense 层。现在,Dense 层只执行f(w^T * x),其中f 是激活,w 是权重矩阵,xconv1 的输出。但是,如果没有展平,conv1 的输出是批次中每个样本的 3D 张量,所以我们展平它,否则矩阵尺寸将不匹配w^T * x 的乘法。由于这个原因,密集层不考虑空间关系。此外,包含密集层将不允许您更改输入的大小。
    猜你喜欢
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 2018-06-21
    • 2018-07-13
    相关资源
    最近更新 更多