首页 文章

在Keras中预先训练好的VGG16模型中移除中间层

提问于
浏览
0

大家,

我有一个关于如何在Keras中修改预先培训的VGG16网络的问题 . 我尝试在最后三个卷积层的末尾删除最大池化层,并在每个卷积层的末尾添加批量标准化层 . 同时,我想保留参数 . 这意味着整个修改过程不仅包括删除一些中间层,添加一些新图层,还将修改后的图层与其余图层连接起来 .

我在Keras还是很新 . 我能找到的唯一方法如Removing then Inserting a New Middle Layer in a Keras Model所示

所以我编辑的代码如下:

from keras import applications
from keras.models import Model
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers.normalization import BatchNormalization
vgg_model = applications.VGG16(weights='imagenet',
                           include_top=False,
                           input_shape=(160, 80, 3))
# Disassemble layers
layers = [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.
layer_dict = dict([(layer.name, layer) for layer in vgg_model.layers])
x = layer_dict['block3_conv3'].output

for i in range(11, len(layers)-5):
    # layers[i].trainable = False
    x = layers[i](x)

for j in range(15, len(layers)-1):
    # layers[j].trainable = False
    x = layers[j](x)

x = Conv2D(filters=128, kernel_size=(1, 1))(x)
x = BatchNormalization()(x)
x = Conv2D(filters=128, kernel_size=(1, 1))(x)
x = BatchNormalization()(x)
x = Conv2D(filters=128, kernel_size=(1, 1))(x)
x = BatchNormalization()(x)
x = Flatten()(x)
x = Dense(50, activation='softmax')(x)


custom_model = Model(inputs=vgg_model.input, outputs=x)
for layer in custom_model.layers[:16]:
    layer.trainable = False

custom_model.summary()

然而,块4和块5中的卷积层的输出形状是多个 . 我尝试通过添加一层MaxPool2D(batch_size =(1,1),stride = none)来纠正它,但输出形状仍然是多个 . 像这样:

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 160, 80, 3)        0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 160, 80, 64)       1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 160, 80, 64)       36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 80, 40, 64)        0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 80, 40, 128)       73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 80, 40, 128)       147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 40, 20, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 40, 20, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 40, 20, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 40, 20, 256)       590080    
_________________________________________________________________
block4_conv1 (Conv2D)        multiple                  1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        multiple                  2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        multiple                  2359808   
_________________________________________________________________
block5_conv1 (Conv2D)        multiple                  2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        multiple                  2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        multiple                  2359808   
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 40, 20, 128)       65664     
_________________________________________________________________
batch_normalization_1 (Batch (None, 40, 20, 128)       512       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 40, 20, 128)       16512     
_________________________________________________________________
batch_normalization_2 (Batch (None, 40, 20, 128)       512       
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 40, 20, 128)       16512     
_________________________________________________________________
batch_normalization_3 (Batch (None, 40, 20, 128)       512       
_________________________________________________________________
flatten_1 (Flatten)          (None, 102400)            0         
_________________________________________________________________
dense_1 (Dense)              (None, 50)                5120050   
=================================================================
Total params: 19,934,962
Trainable params: 5,219,506
Non-trainable params: 14,715,456
_________________________________________________________________

任何人都可以提供一些有关如何实现目标的建议吗?

非常感谢 .

1 回答

  • 0

    multiple 输出形状存在,因为这些图层被调用了两次,因此它们有两个输出形状 . 您可以看到here,如果调用 layer.output_shape 引发AttributeError,则打印输出形状将为'multiple' .

    如果您调用 custom_model.layers[10].output_shape ,您将收到此错误:
    AttributeError: The layer "block4_conv1 has multiple inbound nodes, with different output shapes. Hence the notion of "output shape" is ill-defined for the layer. Useget_output_shape_at(node_index)instead.

    如果然后调用 custom_model.layers[10].get_output_shape_at(0) ,您将获得与初始网络对应的输出形状,对于 custom_model.layers[10].get_output_shape_at(1) ,您将获得您期望的输出形状 .

    我只想表达一下,我怀疑你对此修改的意图:如果删除MaxPooling图层,并将下一层(编号11)应用于MaxPooling图层之前的输出,则学习的滤镜是"expecting"图像分辨率低两倍,所以它们可能无法工作 .

    让's imagine that one filter is 1292356 for eyes and that usually eyes are 10 pixels wide, you' ll需要一个20像素宽的眼睛来触发图层中的相同激活 .
    我的例子显然过于简单而且不准确,但只是为了表明原始想法是错误的,你应该重新训练模型的顶部/保持MaxPooling层/在顶层的block3_conv3上定义一个全新的模型 .

相关问题