簡體   English   中英

如何在 keras 中編輯功能模型?

[英]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。 向前傳球后,

  • 這些將它們接收/生成的 KTensor 存儲在它們的inputoutput屬性中。
  • 模型本身還將存儲您提供給它的 KTensor 以及相應的最終輸出 KTensor 在其inputsoutputs屬性中(注意 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM