[英]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.