簡體   English   中英

使用 keras 順序提取嵌套層特征(從預訓練模型) API

[英]Extracting nested layer features (from a pretrained model) with keras sequential API

我有以下簡單的 model 用於遷移學習,預訓練 model (VGG16) 沒有 FC 層,后面是一些新層,定義為keras順序 API。

IMG_SHAPE = (224, 224, 3)

# vgg16
pretrained_model = tf.keras.applications.vgg16.VGG16(
        weights='imagenet', 
        include_top=False, 
        input_shape=IMG_SHAPE,
    )
# freeze pretrained layers
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(3, activation='softmax'),
])

請注意 model 的摘要不顯示VGG16的內部層:

model.summary()

#Model: "sequential"
#_________________________________________________________________
# Layer (type)                Output Shape              Param #   
#=================================================================
# vgg16 (Functional)          (None, 4, 4, 512)         14714688  
#                                                                 
# batch_normalization (BatchN  (None, 4, 4, 512)        2048      
# ormalization)                                                   
#                                                                 
# flatten (Flatten)           (None, 8192)              0         
                                                                 
# dense (Dense)               (None, 2)                 16386     
                                                                 
#=================================================================
#Total params: 14,733,122
#Trainable params: 17,410
#Non-trainable params: 14,715,712

我已經在我的自定義數據集上訓練了上面的 model,並通過遷移學習在我的測試數據集上獲得了所需的准確性。

現在,假設我想創建一個新的 model(例如,計算激活圖),它接受輸入作為前一個 model 的輸入,作為輸出,我想要一個中間值 output(通過在卷積層提取特征,例如block5_conv3訓練模型的 block5_conv3 )以及之前的 model 中的 output。這就是我卡住的地方,我遇到了錯誤。 例如,我定義了新的 model,如下所示:

grad_model = tf.keras.models.Model(
        [pretrained_model.inputs], 
        [pretrained_model.get_layer('block5_conv3').output, model.output]
    )

我收到以下錯誤的地方:

ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 150, 150, 3), dtype=tf.float32, name='vgg16_input'), name='vgg16_input', description="created by layer 'vgg16_input'") at layer "vgg16". The following previous layers were accessed without issue: ['block1_conv1', 'block1_conv2', 'block1_pool', 'block2_conv1', 'block2_conv2', 'block2_pool', 'block3_conv1', 'block3_conv2', 'block3_conv3', 'block3_pool', 'block4_conv1', 'block4_conv2', 'block4_conv3']

或喜歡以下內容:

grad_model = tf.keras.models.Model(
        [model.inputs], 
        [pretrained_model.get_layer('block5_conv3').output, model.output]
    )

我收到以下錯誤的地方:

ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 150, 150, 3), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'vgg16'") at layer "block1_conv1". The following previous layers were accessed without issue: []

我還嘗試設置 model 的輸入層名稱和嵌套在其中的預訓練 model ,以便輸入層名稱相同:

pretrained_model.layers[0]._name = model.layers[0]._name

但得到同樣的錯誤。

我認為可以更改 model 結構(例如,使用keras函數式 API 等)來定義grad_model ,但不確定如何更改。 此外,我更想知道是否有一種方法可以在不更改 model 結構/不需要我重新培訓的情況下解決問題。

到目前為止,按照@M.Innat 的評論,我可以使用keras功能 API 解決問題(注意參數數量保持不變)並重新訓練:

inputs = tf.keras.Input(shape=IMG_SHAPE)

x = keras.applications.xception.Xception(
    input_tensor=inputs, 
    include_top=False,
    weights='imagenet'
)

x.trainable = False

x = tf.keras.layers.BatchNormalization()(x.output) 
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(2, activation='softmax')(x)

model = tf.keras.Model(inputs, x)

model.summary()

# Model: "model_1262"
#_________________________________________________________________
# Layer (type)                Output Shape              Param #   
#=================================================================
# input_3 (InputLayer)        [(None, 150, 150, 3)]     0        
#                                                                 
# block1_conv1 (Conv2D)       (None, 150, 150, 64)      1792      
#                                                                 
# block1_conv2 (Conv2D)       (None, 150, 150, 64)      36928     
#                                                                 
# block1_pool (MaxPooling2D)  (None, 75, 75, 64)        0         
#                                                                 
# block2_conv1 (Conv2D)       (None, 75, 75, 128)       73856     
#                                                                 
# block2_conv2 (Conv2D)       (None, 75, 75, 128)       147584    
#                                                                 
# block2_pool (MaxPooling2D)  (None, 37, 37, 128)       0         
#                                                                 
# block3_conv1 (Conv2D)       (None, 37, 37, 256)       295168    
#                                                                 
# block3_conv2 (Conv2D)       (None, 37, 37, 256)       590080    
#                                                                 
# block3_conv3 (Conv2D)       (None, 37, 37, 256)       590080    
#                                                                 
# block3_pool (MaxPooling2D)  (None, 18, 18, 256)       0         
#                                                                 
# block4_conv1 (Conv2D)       (None, 18, 18, 512)       1180160   
#                                                                 
# block4_conv2 (Conv2D)       (None, 18, 18, 512)       2359808   
#                                                                 
# block4_conv3 (Conv2D)       (None, 18, 18, 512)       2359808   
#                                                                 
# block4_pool (MaxPooling2D)  (None, 9, 9, 512)         0         
#                                                                 
# block5_conv1 (Conv2D)       (None, 9, 9, 512)         2359808   
#                                                                 
# block5_conv2 (Conv2D)       (None, 9, 9, 512)         2359808   
#                                                                 
# block5_conv3 (Conv2D)       (None, 9, 9, 512)         2359808   
#                                                                 
# block5_pool (MaxPooling2D)  (None, 4, 4, 512)         0         
#                                                                 
# batch_normalization_9 (Batc  (None, 4, 4, 512)        2048      
# hNormalization)                                                 
#                                                                 
# flatten_1 (Flatten)         (None, 8192)              0         
#                                                                 
# dense_1 (Dense)             (None, 2)                 16386     
#                                                                 
#=================================================================
#Total params: 14,733,122
#Trainable params: 17,410
#Non-trainable params: 14,715,712
#_________________________________________________________________

以及以下用於提取 class 激活 map 的中間特征的代碼有效:

grad_model = tf.keras.models.Model(
        [model.inputs], [model.get_layer('block5_conv3').output, model.output] 
    )

暫無
暫無

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

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