摘要:如何强制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内的每一层(如图所示)。conv_base.summary()
model.summary()
- 相关问题
尽管可以通过model.get_layer('vgg16').layers
访问vgg层,但这仍然偶尔会导致其他问题,包括:
(1) 加载权重:有时会搞乱权重加载过程。
model.load_weights('~path/weights.hdf5')
(2) 构建新模型:在调用model
层来构建新模型时也会导致错误。
model2 = Model(inputs=model.inputs, outputs=model.get_layer('vgg16').layers[1].output, name='Vis_Model')
思考:我可以想象通过将keras.application.VGG
的层逐一复制到新模型中来部分解决这个问题。但如何使用预训练的权重可能会是个问题。欢迎任何其他建议。
回答:
编辑:根据您的评论,这里是更新后的解决方案。
您可以通过迭代层并将它们附加到顺序模型来展平嵌套模型。以下代码中我使用了一个很棒的解决方案。
import numpy as np
import tensorflow as tf
from tensorflow.keras.applications import VGG16
from tensorflow.keras import layers, Model, utils
# 实例化VGG模型
conv_base = VGG16(weights='imagenet', # 使用ImageNet预训练
include_top=False, # 排除顶部的三层
input_shape=(64, 64, 3),
pooling = 'max')
# 定义次级嵌套模型
inp = layers.Input((64,64,3))
cnn = conv_base(inp)
x = layers.BatchNormalization()(cnn)
x = layers.Dropout(0.2)(x)
x = layers.Dense(256, activation='linear')(x)
x = layers.BatchNormalization()(x)
x = layers.Dropout(0.2)(x)
out = layers.Dense(1, activation='linear')(x)
model = Model(inp, out)
# 展平嵌套模型
def flatten_model(model_nested):
layers_flat = []
for layer in model_nested.layers:
try:
layers_flat.extend(layer.layers)
except AttributeError:
layers_flat.append(layer)
model_flat = tf.keras.models.Sequential(layers_flat)
return model_flat
model_flat = flatten_model(model)
model_flat.summary()