在Keras模型中移除然后插入新的中间层

对于一个预定义的Keras模型,我试图首先加载预训练的权重,然后移除模型内部的一到三个(非最后几个)层,并用另一个层替换它。

我似乎在keras.io上找不到任何关于如何做到这一点或从预定义模型中移除层的文档。

我使用的模型是一个经典的VGG-16网络,它在一个函数中被实例化,如下所示:

def model(self, output_shape):    # Prepare image for input to model    img_input = Input(shape=self._input_shape)    # Block 1    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)    # Block 2    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)    # Block 3    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)    # Block 4    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)    x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)    # Block 5    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)    x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)    # Classification block    x = Flatten(name='flatten')(x)    x = Dense(4096, activation='relu', name='fc1')(x)    x = Dropout(0.5)(x)    x = Dense(4096, activation='relu', name='fc2')(x)    x = Dropout(0.5)(x)    x = Dense(output_shape, activation='softmax', name='predictions')(x)    inputs = img_input    # Create model.    model = Model(inputs, x, name=self._name)    return model

例如,我希望移除Block 1中的两个卷积层,并用一个卷积层替换它们,在将原始权重加载到所有其他层之后。

有什么想法吗?


回答:

假设你有一个模型vgg16_model,它可以通过你上面的函数或keras.applications.VGG16(weights='imagenet')初始化。现在,你需要在中间插入一个新层,同时保存其他层的权重。

思路是将整个网络拆解成独立的层,然后再组装回去。以下是专门针对你的任务的代码:

vgg_model = applications.VGG16(include_top=True, weights='imagenet')# Disassemble layerslayers = [l for l in vgg_model.layers]# Defining new convolutional layer.# Important: the number of filters should be the same!# Note: the receiptive field of two 3x3 convolutions is 5x5.new_conv = Conv2D(filters=64,                   kernel_size=(5, 5),                  name='new_conv',                  padding='same')(layers[0].output)# Now stack everything back# Note: If you are going to fine tune the model, do not forget to#       mark other layers as un-trainablex = new_convfor i in range(3, len(layers)):    layers[i].trainable = False    x = layers[i](x)# Final touchresult_model = Model(inputs=layer[0].input, outputs=x)result_model.summary()

以上代码的输出如下:

_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================input_50 (InputLayer)        (None, 224, 224, 3)       0         _________________________________________________________________new_conv (Conv2D)            (None, 224, 224, 64)      1792      _________________________________________________________________block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         _________________________________________________________________block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     _________________________________________________________________block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    _________________________________________________________________block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         _________________________________________________________________block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    _________________________________________________________________block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    _________________________________________________________________block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    _________________________________________________________________block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         _________________________________________________________________block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   _________________________________________________________________block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   _________________________________________________________________block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   _________________________________________________________________block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         _________________________________________________________________block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   _________________________________________________________________block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   _________________________________________________________________block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   _________________________________________________________________block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         _________________________________________________________________flatten (Flatten)            (None, 25088)             0         _________________________________________________________________fc1 (Dense)                  (None, 4096)              102764544 _________________________________________________________________fc2 (Dense)                  (None, 4096)              16781312  _________________________________________________________________predictions (Dense)          (None, 1000)              4097000   =================================================================Total params: 138,320,616Trainable params: 1,792Non-trainable params: 138,318,824_________________________________________________________________

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注