如何让Keras自定义模型显示并包含VGG16的全部详细层
如何让keras.applications.VGG16的各层作为独立层显示在自定义模型中
摘要
如何强制让keras.applications.VGG16的各层而非整个vgg模型,作为独立层显示并包含在新建的自定义模型中。
详情
- 我基于
keras.applications.VGG16(记为conv_base)搭建自定义模型(记为model),替换了原模型的最后全连接层为自定义层,代码如下:
conv_base = VGG16(weights='imagenet', # 基于ImageNet预训练 include_top=False, # 排除顶部三层全连接层 input_shape=(64, 64, 3), pooling = 'max') model = models.Sequential() model.add(conv_base) model.add(layers.BatchNormalization()) model.add(layers.Dropout(0.2)) model.add(layers.Dense(256, activation='linear')) model.add(layers.BatchNormalization()) model.add(layers.Dropout(0.2)) model.add(layers.Dense(1, activation='linear'))
- 调用
conv_base.summary()时可以看到conv_base内部的所有层,但调用model.summary()时,自定义模型仅显示vgg16层(类型为Model),无法展示vgg16内部的每一层。 - 关联问题
虽然可以通过model.get_layer('vgg16').layers访问vgg的层,但仍偶尔出现其他问题:
- 加载权重:有时会打乱权重加载流程
model.load_weights('~path/weights.hdf5')
- 构建新模型:调用model的层构建新模型时也会报错
model2 = Model(inputs=model.inputs, outputs=model.get_layer('vgg16').layers[1].output, name='Vis_Model')
个人思路
我考虑过将keras.application.VGG的层逐一复制到新模型中来部分解决该问题,但预训练权重的使用方式存在问题,希望获得其他可行方案。
方案1:逐层添加VGG16层(兼容性最高)
直接遍历VGG16实例的所有层逐个加入自定义模型,预训练权重会自动保留,不需要额外处理,修改后的代码如下:
from tensorflow.keras.applications import VGG16 from tensorflow.keras import models, layers conv_base = VGG16(weights='imagenet', include_top=False, input_shape=(64, 64, 3), pooling='max') model = models.Sequential() # 逐个添加VGG16的所有层,而非将整个conv_base作为单个层加入 for layer in conv_base.layers: model.add(layer) # 后续自定义层保持不变 model.add(layers.BatchNormalization()) model.add(layers.Dropout(0.2)) model.add(layers.Dense(256, activation='linear')) model.add(layers.BatchNormalization()) model.add(layers.Dropout(0.2)) model.add(layers.Dense(1, activation='linear'))
修改后调用model.summary()即可看到VGG16的全部层,权重加载、提取中间层构建新模型的问题都会同步解决。如果需要冻结VGG16的预训练参数不参与训练,添加如下代码:
# 冻结VGG16对应的所有层 for layer in model.layers[:len(conv_base.layers)]: layer.trainable = False
方案2:不修改嵌套结构的兼容方案
如果不想调整原有模型的嵌套写法,可针对遇到的两个问题单独修复:
- 权重加载报错:调用
load_weights时添加by_name=True参数,适配嵌套模型的权重匹配逻辑:
model.load_weights('~path/weights.hdf5', by_name=True)
- 提取嵌套层中间输出构建新模型:先基于VGG子模型构建中间层输出的子模型,再关联到主模型输入即可:
vgg_submodel = model.get_layer('vgg16') # 构建VGG子模型的中间层输出模型 intermediate_model = Model(inputs=vgg_submodel.input, outputs=vgg_submodel.layers[1].output) # 关联主模型输入,得到最终可视化模型 model2 = Model(inputs=model.input, outputs=intermediate_model(model.input), name='Vis_Model')
内容的提问来源于stack exchange,提问作者Joey Fueng
相关产品推荐
相关产品推荐

