1

我需要使用 Keras 中的预训练模型(keras.applications.VGG16)作为从它的第一层创建另一个模型(用于进行迁移学习)的基线。最终目标是冻结和导出模型,以便在带有 AIY 视觉套件的树莓派上部署。

我尝试了以下常用方法:

model_base = keras.applications.VGG16(input_tensor=inputs)
x = model_base.get_layer(backbone_layer).output
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(1)(x)
model = keras.models.Model(inputs=inputs, outputs=x)

我也在尝试使用:

model_base._layers.pop() 

我调用 pop() n 次,其中“n”是我想要摆脱的最终层数。

它似乎在这两种情况下都有效,当我使用 new_model.summary() 它只显示所需的 VGG16 模型的第一层以及为自定义添加的新层,但是当导出模型并为 tf-lite 编译它时,编译器返回:

没有足够的设备内存来运行模型

这很奇怪,因为生成的模型(.pb 文件和层数)比手动定义的可以正确导入的其他模型更小,在分析 tensorboard 并将 .pb 文件导出为文本后,我发现原始模型正在也导出(所有层,即使是未使用的层,也被 pop() 删除)而不仅仅是新层

(如在 tensorboard 中看到的,有 2 个并行模型,右侧是所需的模型,但原始模型的原始层仍显示在左侧,并且原始模型的一部分存在于导出的 .pb 文件中)

在此处输入图像描述

我的问题是我怎样才能明确地从 keras.applications.VGG16 模型中删除未使用的层,只保留第一层 + 新的自定义层?使用 pop() 没有奏效,也尝试了 del 层(在 for 循环中)不成功。

或者我还有什么其他选择可以使用预训练模型作为基线,只保留它的第一层,然后将它连接到其他一些自定义层。

4

3 回答 3

2

最简单的方法是在 VGG16 中设置 include_top=False,pooling=max。然后看下面的代码:

x=backbone.layers[-1].output
predictions=Dense (len(classes), activation='softmax')(x)
model = Model(inputs=backbone.input, outputs=predictions)    
model.compile(Adamax(lr=lr_rate), loss='categorical_crossentropy', metrics=['accuracy'])
于 2020-08-01T14:58:05.183 回答
0

使用 model.save() 保存所需的内容,清除 tf 会话,然后再次加载它解决了问题(如建议的@NatthaphonHongcharoen(在评论中):

model.save(model_file)
del model
keras.backend.clear_session()
model = keras.models.load_model(model_file)

现在 tensorflow 中的导出图仅显示所需的层,并且冻结的图会生成一个较小的 .pb 文件。

然而,另一个问题仍然存在,即使使用单层基础模型并添加一个 Dense 层,编译器仍然会说

没有足够的设备内存来运行模型。

但这是一个不同的问题,在这个问题中没有直接提出。

于 2020-08-08T05:54:58.933 回答
0

它实际上并没有删除层,而是在没有它的情况下创建一个新模型。

我真的不明白你想要做什么,但物体检测器通常会这样做。

inputs = keras.layers.Input((None, None, 3), include_top=False)
backbone = keras.applications.VGG16(input_tensor=inputs)
x = backbone.get_layer('block1_conv2').output
x = keras.layers.Dense(50)(x)
model = keras.models.Model(inputs=inputs, outputs=x, name=backbone.name)

这将产生一个只有前两层的模型,并添加一个新Dense的作为输出。

于 2020-08-01T08:03:24.023 回答