[英]How to edit functional model in keras?
我正在使用tf.keras.applications.efficientnet_v2.EfficientNetV2L
模型,我想編輯模型的最后一層以使模型成為回歸和分類層。 但是,我不確定如何編輯此模型,因為它不是線性順序模型,因此我不能這樣做:
for layer in model.layers[:-2]:
model.add(layer)
因為模型的某些層有多個輸入。 除了最后一層之外,有沒有辦法保留模型,這樣模型會在最后一層之前發散?
efficentnet[:-2]
|
|
/ \
/ \
/ \
output1 output2
要使功能模型具有分類層和回歸層,您可以按如下方式更改模型。 請注意,有多種方法可以實現這一點,這是其中之一。
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
得到的類似的輸出。 檢查模型摘要以進行目視檢查。
Keras 的功能 API 通過鏈接 Keras張量(在此稱為 KTensor)而不是您日常的 TF 張量來工作。
因此,您需要做的第一件事是將適當形狀的 KTensor(使用tf.keras.Input
創建)提供給原始模型。 這將觸發前向鏈,促使模型的層產生自己的輸出 KTensor,這些輸出 KTensor 正確鏈接到輸入 KTensor。 向前傳球后,
input
和output
屬性中。inputs
和outputs
屬性中(注意 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')>]
一旦你獲得了這些內部 KTensor,一切都變得微不足道。 要在最后兩層之前提取 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])
請注意,您在第一步中輸入的 KTensor 的形狀必須符合接收它們的層的形狀要求。 在我的示例中,輸入 KTensor 將被饋送到Dense(1)
層。 由於Dense
需要在最后一維中定義輸入形狀,因此輸入 KTensor 可以是形狀,例如(10,)
或(None,10)
但不是(None,)
或(10, None)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.