簡體   English   中英

用另一層替換預訓練的 model 中的 Keras 層

[英]Replacing a Keras layer in a pretrained model with another layer

我正在使用 Keras 和 Tensorflow 版本 2.7 作為后端。 我指的是 stackoverflow 上的帖子Removing then Inserting a New Middle Layer in a Keras Model 我的目標是實例化一個 Imag.net 預訓練 VGG16 model 並用 AveragePooling2D 層替換每個 MaxPooling2D 層:

import os
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.layers import *
from tensorflow.keras import applications
from tensorflow.keras.models import Model
model_input = (224,224,3)
model = applications.VGG16(include_top=False,
                           weights='imagenet',
                           input_shape=model_input)
model.summary()

for layer in tuple(model.layers):
    layer_type = type(layer).__name__
    if layer.__name__ == 'MaxPooling2D':
        pool_name = layer.name + "_averagepooling2d"
        pool = AveragePooling2D() if layer_type == "MaxPooling2D" else pool(name=pool_name)
        model.add(pool)        

model.summary()

我收到以下錯誤:

  File "C:\Users\AppData\Local\Temp\2/ipykernel_26864/1200445239.py", line 15, in <module>
    if layer.__name__ == 'MaxPooling2D':

AttributeError: 'InputLayer' object has no attribute '__name__'

此外,我不確定這是否是在所有類型的預訓練模型(包括具有跳過連接和密集塊的模型)中將 MaxPooling 層替換為 AveragePooling 層的正確方法。 請求在這方面進行代碼更正。

這是實現該目標的方法之一:

原始vgg16

import tensorflow as tf
vgg=tf.keras.applications.vgg16.VGG16(
    include_top=True,
    weights='imagenet',
    input_tensor=None,
    input_shape=None,
    pooling=None,
    classes=1000,
    classifier_activation='softmax'
)
vgg.summary()

Output:

在此處輸入圖像描述

修改后的 vgg16

#One of the following two:
#model_input=vgg.input
model_input=tf.keras.Input(shape=(224, 224, 3,))

x=model_input
for layer in vgg.layers[1:]:
    if isinstance(layer, tf.keras.layers.MaxPooling2D):
        kwargs=layer.get_config()
        x=tf.keras.layers.AveragePooling2D(**kwargs)(x)
    else:
        x=layer(x)
model=tf.keras.Model(inputs=model_input, outputs=x, name="vgg_avg")
model.summary()

Output:

在此處輸入圖像描述


筆記

通過將MaxPooling2D層替換為對應的AveragePooling2D層,最初優化的權重可能不再是最優的。 因此,可能需要某種程度的調優(學習率較小)。

Keras 提供定義一個自定義的 model,其中它允許根據他們的要求自定義層Keras Custom Model 雖然 vgg16 model 有定義池化類型的參數,但它只是全局的(即僅適用於模型最后一個卷積塊的 output) Keras Vgg16

可以定義自定義 model,如下所示,

import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import backend as K
from keras.engine import training
from keras import layers
from keras.layers import Dense
from keras.applications import imagenet_utils
from keras.utils import layer_utils

def MyVgg16Model(
                 include_top=True,
                 weights="imagenet",
                 input_tensor=None,
                 input_shape=None,
                 pooling=None,
                 classes=1000,
                 classifier_activation="softmax"):

                
    input_shape = imagenet_utils.obtain_input_shape(
                                            input_shape,
                                            default_size=224,
                                            min_size=32,
                                            data_format=K.image_data_format(),
                                            require_flatten=include_top,
                                            weights=weights,
                                        )
                                        
    if input_tensor is None:
        img_input = layers.Input(shape=input_shape)
    else:
        if not K.is_keras_tensor(input_tensor):
            img_input = layers.Input(tensor=input_tensor, shape=input_shape)
        else:
            img_input = input_tensor

    # Block 1
    x = layers.Conv2D(
        64, (3, 3), activation="relu", padding="same", name="block1_conv1"
    )(img_input)
    x = layers.Conv2D(
        64, (3, 3), activation="relu", padding="same", name="block1_conv2"
    )(x)
    x = layers.AveragePooling2D((2, 2), strides=(2, 2), name="block1_pool")(x)

    # Block 2
    x = layers.Conv2D(
        128, (3, 3), activation="relu", padding="same", name="block2_conv1"
    )(x)
    x = layers.Conv2D(
        128, (3, 3), activation="relu", padding="same", name="block2_conv2"
    )(x)
    x = layers.AveragePooling2D((2, 2), strides=(2, 2), name="block2_pool")(x)

    # Block 3
    x = layers.Conv2D(
        256, (3, 3), activation="relu", padding="same", name="block3_conv1"
    )(x)
    x = layers.Conv2D(
        256, (3, 3), activation="relu", padding="same", name="block3_conv2"
    )(x)
    x = layers.Conv2D(
        256, (3, 3), activation="relu", padding="same", name="block3_conv3"
    )(x)
    x = layers.AveragePooling2D((2, 2), strides=(2, 2), name="block3_pool")(x)

    # Block 4
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block4_conv1"
    )(x)
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block4_conv2"
    )(x)
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block4_conv3"
    )(x)
    x = layers.AveragePooling2D((2, 2), strides=(2, 2), name="block4_pool")(x)

    # Block 5
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block5_conv1"
    )(x)
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block5_conv2"
    )(x)
    x = layers.Conv2D(
        512, (3, 3), activation="relu", padding="same", name="block5_conv3"
    )(x)
    x = layers.AveragePooling2D((2, 2), strides=(2, 2), name="block5_pool")(x)

    if include_top:
        # Classification block
        x = layers.Flatten(name="flatten")(x)
        x = Dense(4096, activation="relu", name="fc1")(x)
        x = Dense(4096, activation="relu", name="fc2")(x)

        imagenet_utils.validate_activation(classifier_activation, weights)
        x = layers.Dense(
            classes, activation=classifier_activation, name="predictions"
        )(x)
    else:
        if pooling == "avg":
            x = layers.GlobalAveragePooling2D()(x)
        elif pooling == "max":
            x = layers.GlobalMaxPooling2D()(x)

    if input_tensor is not None:
        inputs = layer_utils.get_source_inputs(input_tensor)
    else:
        inputs = img_input
    # Create model.
    model = training.Model(inputs, x, name="vgg16")

    return model

model_input = (224,224,3)
model = MyVgg16Model(include_top=False,
                           weights='imagenet',
                           input_shape=model_input)
model.summary()

在model總結中,可以看到如下圖的變化,

Model: "vgg16"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 input_1 (InputLayer)        [(None, 224, 224, 3)]     0

 block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792

 block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928

 block1_pool (AveragePooling  (None, 112, 112, 64)     0
 2D)

 block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856

 block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584

 block2_pool (AveragePooling  (None, 56, 56, 128)      0
 2D)

 block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168

 block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080

 block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080

 block3_pool (AveragePooling  (None, 28, 28, 256)      0
 2D)

 block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160

 block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808

 block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808

 block4_pool (AveragePooling  (None, 14, 14, 512)      0
 2D)

 block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808   

 block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808

 block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808

 block5_pool (AveragePooling  (None, 7, 7, 512)        0
 2D)

=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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