<p>根据你对我的第一篇文章的第一次评论,我正在添加一篇新的文章,而不是编辑我现有的答案,因为它已经有一篇太长的文章了。无论如何,你的担心是合理的。甚至我也在为子类API <a href="https://stackoverflow.com/q/66513819/9215780">here</a>的某些问题而挣扎。但我似乎在我的问题中写得不太好,因为人们并不觉得这是一个值得关注的问题</p>
<p>无论如何,这里有另一个更简洁和精确的答案,因为我们构建了一个带有<strong>期望输出的单一模型。一个单独的提取器,而不是以前的两个单独的提取器,这会带来额外的计算开销。比如说,我们的顺序模型</p>
<pre><code>import tensorflow as tf
seq_model = tf.keras.Sequential(
[
tf.keras.Input(shape=(32, 32, 3)),
tf.keras.layers.Conv2D(16, 3, activation="relu", name='conv1'),
tf.keras.layers.Conv2D(32, 3, activation="relu", name='conv2'),
tf.keras.layers.Conv2D(64, 3, activation="relu", name='conv3'),
tf.keras.layers.Conv2D(128, 3, activation="relu", name='conv4'),
tf.keras.layers.Conv2D(256, 3, activation="relu", name='conv5'),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(10, activation='softmax')
]
)
for l in seq_model.layers:
print(l.name, l.output_shape)
conv1 (None, 30, 30, 16)
conv2 (None, 28, 28, 32)
conv3 (None, 26, 26, 64)
conv4 (None, 24, 24, 128)
conv5 (None, 22, 22, 256)
global_average_pooling2d_3 (None, 256)
dense_3 (None, 10)
</code></pre>
<p>我们需要一个模型中的<code>conv3</code>和<code>conv5</code>。我们可以很容易地做到这一点,如下所示</p>
<pre><code>model = tf.keras.models.Model(
inputs=[seq_model.input],
outputs=[seq_model.get_layer('conv3').output,
seq_model.get_layer('conv5').output]
)
# check
for i in check_model(tf.keras.Input((32, 32, 3))):
print(i.name, i.shape)
model_13/conv3/Relu:0 (None, 26, 26, 64)
model_13/conv5/Relu:0 (None, 22, 22, 256)
</code></pre>
<p>很好,预期层的两个特征输出。现在,让我们使用这两个层(就像我的第一篇文章)来构建一个功能API模型</p>
<pre><code>encoder_input = tf.keras.Input(shape=(32, 32, 3), name="img")
x = tf.keras.layers.Conv2D(16, 3, activation="relu")(encoder_input)
last_x = check_model(encoder_input)[0]
print(last_x.shape) # (None, 26, 26, 64) - model_13/conv3/Relu:0 (None, 26, 26, 64)
mid_x = check_model(encoder_input)[1] # model_13/conv5/Relu:0 (None, 22, 22, 256)
mid_x = tf.keras.layers.Conv2D(32, kernel_size=3, strides=1)(mid_x)
print(mid_x.shape) # (None, 20, 20, 32)
last_x = tf.keras.layers.GlobalMaxPooling2D()(last_x)
mid_x = tf.keras.layers.GlobalMaxPooling2D()(mid_x)
print(last_x.shape, mid_x.shape) # (None, 64) (None, 32)
encoder_output = tf.keras.layers.Concatenate()([last_x, mid_x])
print(encoder_output.shape) # (None, 96)
encoder_output = tf.keras.layers.Dense(100, activation='softmax')(encoder_output)
print(encoder_output.shape) # (None, 100)
encoder = tf.keras.Model(encoder_input, encoder_output, name="encoder")
tf.keras.utils.plot_model(
encoder,
show_shapes=True,
show_layer_names=True
)
</code></pre>
<pre><code>(None, 26, 26, 64)
(None, 20, 20, 32)
(None, 64) (None, 32)
(None, 96)
(None, 100)
</code></pre>
<p><a href="https://i.stack.imgur.com/hzuWo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hzuWo.png" alt="enter image description here"/></a></p>