【问题标题】:Remove middle layers in the pre-trained VGG16 model in Keras删除 Keras 中预训练的 VGG16 模型中的中间层
【发布时间】:2018-12-11 23:25:33
【问题描述】:

大家,

我有一个关于如何在 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
_________________________________________________________________

谁能提供一些关于如何实现我的目标的建议?

非常感谢。

【问题讨论】:

  • 你能发布一些你到目前为止所做的代码吗?
  • 您是否考虑过编写一个全新的模型并导入预训练的权重?
  • @kosnik,我重新编辑了我的问题,希望这对你来说很清楚。
  • @mpariente,我正在考虑...谢谢。

标签: keras


【解决方案1】:

multiple 输出形状在那里,因为这些层被调用了两次,所以它们有两个输出形状。 你可以看到here,如果调用layer.output_shape 引发一个AttributeError,打印的输出形状将是“多个”。

如果你调用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. Use `get_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 层之前的输出,学习过滤器“期望”分辨率低两倍的图像,因此它们可能无法正常工作。

让我们假设一个过滤器正在“寻找”眼睛,并且通常眼睛是 10 像素宽,您需要一个 20 像素宽的眼睛来触发图层中的相同激活。
我的示例显然过于简单且不准确,但这只是为了表明最初的想法是错误的,您应该重新训练模型的顶部/保留 MaxPooling 层/在顶层 block3_conv3 上定义一个全新的模型。

【讨论】:

  • 嗨,@mpariente,感谢您的回答,但我对您对我为何称这些层的解释感到有些困惑。如何从我构建的模型中找到它?我尝试在代码“custom_model = Model(inputs=vgg_model.input, outputs=x)”之后直接添加代码“custom_model.layers[10].get_output_shape_at(1)”(不确定是否正确),然后我得到了这个值错误: ValueError: Asked to get output shape at node 1, but the layer 只有 1 inbound 节点。然后我改成“custom_model.layers[10].get_output_shape_at(1)”,没有报错,但是还是有
  • 那里有相同的“倍数”。你能给我更多的解释吗?至于这个网络的意图,它来自已发表论文中的一个方法。由于没有可用的代码,我尝试对其进行重构以将其性能与其他方法进行比较。作者删除了最大池化层以增加输出的大小,以实现更准确的目标定位,因为他们使用的图像非常小。我不确定这一步是否真的能给最终的结果带来好处,我必须执行它来确认它的性能。再次感谢:)
  • 关于我的第一条评论的一些更正: 1. 我对你为什么我两次调用这些层的解释有点困惑 2.将其更改为“custom_model.layers[10].get_output_shape_at(0) "
猜你喜欢
  • 1970-01-01
  • 2021-08-18
  • 2017-07-07
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 2019-11-28
  • 1970-01-01
  • 2018-12-21
相关资源
最近更新 更多