【发布时间】:2019-06-27 18:14:48
【问题描述】:
我正在尝试使用 Keras API 将预训练网络中的最大池化层替换为平均池化层。不知何故,它对我不起作用。如果您能帮助我弄清楚如何实现它,我将不胜感激。
以下是我目前的解决方案:
def replace_max_by_average_pooling(model):
input_layer, *other_layers = model.layers
assert isinstance(input_layer, keras.layers.InputLayer)
x = input_layer.output
for layer in other_layers:
if isinstance(layer, keras.layers.MaxPooling2D):
layer = keras.layers.AveragePooling2D(
pool_size=layer.pool_size,
strides=layer.strides,
padding=layer.padding,
data_format=layer.data_format,
name=f"{layer.name}_av",
)
x = layer(x)
return keras.models.Model(inputs=input_layer.input, outputs=x)
当我尝试在 VGG 网络上使用此功能时:
vgg = keras.applications.vgg19.VGG19(include_top=False, weights="imagenet")
vgg_av = replace_max_by_average_pooling(vgg)
如果我打印摘要,它看起来不错:
_________________________________________________________________ 图层(类型)输出形状参数 #
==================================================== =============== input_1(InputLayer)(无,无,无,3)0
_________________________________________________________________ block1_conv1 (Conv2D)(无,无,无,64)1792
_________________________________________________________________ block1_conv2 (Conv2D)(无,无,无,64)36928
_________________________________________________________________ block1_pool_av(AveragePool(无,无,无,64)0
_________________________________________________________________ block2_conv1 (Conv2D)(无,无,无,128)73856
_________________________________________________________________ block2_conv2 (Conv2D)(无,无,无,128)147584
_________________________________________________________________ block2_pool_av (AveragePool (无,无,无,128) 0
_________________________________________________________________ block3_conv1 (Conv2D)(无,无,无,256)295168
...
但是,如果我尝试基于vgg_av 的几层构建一个新模型:
layer = vgg_av.get_layer("block3_conv1")
keras.models.Model(inputs=vgg_av.layers[0].input, outputs=layer.output).summary()
不知何故,平均池层再次被最大池层取代:
_________________________________________________________________ 图层(类型)输出形状参数 #
==================================================== =============== input_1(InputLayer)(无,无,无,3)0
_________________________________________________________________ block1_conv1 (Conv2D)(无,无,无,64)1792
_________________________________________________________________ block1_conv2 (Conv2D)(无,无,无,64)36928
_________________________________________________________________ block1_pool (MaxPooling2D)(无,无,无,64)0
_________________________________________________________________ block2_conv1 (Conv2D)(无,无,无,128)73856
_________________________________________________________________ block2_conv2 (Conv2D)(无,无,无,128)147584
_________________________________________________________________ block2_pool (MaxPooling2D)(无,无,无,128)0
_________________________________________________________________ block3_conv1 (Conv2D)(无,无,无,256)295168
==================================================== =============== 总参数:555,328 可训练参数:555,328 不可训练参数: 0
我做错了吗?为什么和在哪里?
我的猜测是,在这条线上x = layer(x) 新操作被添加到计算图中,使得新操作的名称为*name of an old operation*_1,当我调用vgg_av.get_layer("block3_conv1") 时,它仍然从vgg 获取子图。但是如果我在vgg_av 中打印图层名称,则名称与vgg 中的名称相同。为什么只有在我尝试获取图层子集时它才会失败?我想完全重建计算图,但也许我缺少一些 Keras API,或者我在概念上缺少一些东西。
【问题讨论】:
-
知道“什么失败了”会很有趣...
-
@DanielMöller 好的,我更新了问题以使其更清楚。基本上,如果我基于来自
vgg_av的层子集构建一个新模型,我会再次获得最大池化层数
标签: python tensorflow keras