对于一个预定义的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_________________________________________________________________