我使用的是tf.keras.applications.efficientnet_v2.EfficientNetV2L模型,我想编辑模型的最后几个层,使模型成为一个回归和分类层。但是,我不知道如何编辑这个模型,因为它不是线性顺序模型,因此我不能:
for layer in model.layers[:-2]:
model.add(layer)因为模型的某些层有多个输入。除了最后一层外,是否有一种保留模型的方法,这样模型就会在最后一层之前发散?
efficentnet[:-2]
|
|
/ \
/ \
/ \
output1 output2发布于 2022-06-17 06:08:50
要使功能模型具有分类层和回归层,可以按以下方式更改模型。注意,有多种方法来实现这一点,这就是其中之一。
import tensorflow as tf
from tensorflow import keras
prev_model = keras.applications.EfficientNetV2B0(
input_tensor=keras.Input(shape=(224, 224, 3)),
include_top=False
)接下来,我们将编写我们预期的头部层,如下所示。
neck_branch = keras.Sequential(
[
# we can add more layers i.e. batch norm, etc.
keras.layers.GlobalAveragePooling2D()
],
name='neck_head'
)
classification_head = keras.Sequential(
[
keras.layers.Dense(10, activation='softmax')
],
name='classification_head'
)
regression_head = keras.Sequential(
[
keras.layers.Dense(1, activation=None)
],
name='regression_head'
)现在,我们可以构建所需的模型。
x = neck_branch(prev_model.output)
output_a = classification_head(x)
output_b = regression_head(x)
final_model = keras.Model(prev_model.inputs, [output_a, output_b])测试
keras.utils.plot_model(final_model, expand_nested=True)
# OK
final_model(tf.ones(shape=(1, 224, 224, 3)))
# OK更新
根据你的评论,
,如果前面的模型是从
h5文件中导入的,您将如何处理这个问题,因为在那里我不能声明顶层不包括在内?
如果我理解您的查询,您将有一个带有顶层的保存模型(以.h5格式)。在这种情况下,您没有include_top参数来排除顶级分支。因此,您可以做的是首先删除保存的模型的顶部分支。以下是如何,
# a saved model with top layers
prev_model = keras.models.load_model('model.h5')
prev_model_with_top_remove = keras.Model(
prev_model.input ,
prev_model.layers[-4].output
)
prev_model_with_top_remove.summary()此prev_model.layers[-4].output将移除顶部分支。最后,您将提供与include_top=True类似的输出。检查模型摘要以进行视觉检查。
发布于 2022-06-17 06:45:05
Keras的functional是通过链接Keras张量(特此称为KTensor)来工作的,而不是您日常使用的TF张量。
因此,您需要做的第一件事是将具有适当形状的KTensors (使用tf.keras.Input创建)添加到原始模型中。这将触发前向链,促使模型层生成自己的输出KTensors,并将其正确地链接到输入KTensors。前传之后,
层将将接收/生成的attributes.
input中,output
inputs和outputs属性中的最终输出KTensors (注s)。就像这样,
>>> from tensorflow.keras import Input
>>> from tensorflow.keras.layers import Dense
>>> from tensorflow.keras.models import Sequential, Model
>>> seq_model = Sequential()
>>> seq_model.add(Dense(1))
>>> seq_model.add(Dense(2))
>>> seq_model.add(Dense(3))
>>> hasattr(seq_model.layers[0], 'output')
False
>>> seq_model.inputs is None
True
>>> _ = seq_model(Input(shape=(10,))) # <--- Feed input KTensor to the model
>>> seq_model.layers[0].output
<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'dense')>
>>> seq_model.inputs
[<KerasTensor: shape=(None, 10) dtype=float32 (created by layer 'dense_input')>]一旦获得了这些内部KTensors,一切就变得琐碎了。若要在最后两层之前提取KTensor并将其转发到两个不同的分支以形成新的功能模型,请执行以下操作
>>> intermediate_ktensor = seq_model.layers[-3].output
>>> branch_1_output = Dense(20)(intermediate_ktensor)
>>> branch_2_output = Dense(30)(intermediate_ktensor)
>>> branched_model = Model(inputs=seq_model.inputs, outputs=[branch_1_output, branch_2_output])请注意,您在第一步输入的KTensors的形状必须符合接收它们的层的形状要求。在我的示例中,输入KTensor将被输入到Dense(1)层。由于Dense需要在最后一个维度中定义输入形状,因此输入KTensor可以是形状,例如(10,)或(None,10),而不是(None,)或(10, None)。
https://stackoverflow.com/questions/72654051
复制相似问题