简体   繁体   中英

How to get the encoder from a trained VGG16 network

I'm using Python 3.7.7. and Tensorflow 2.1.0.

I have a pre-trained VGG16 network, and I want to get the first layers, ie from conv1 layer to conv5 layer.

In the following picture:

在此处输入图像描述

You can see a convolutional encoder-decoder architecture. I want to get the encoder part, that is, the layers that appears on the left of the image:

在此处输入图像描述

This is only an example but If I get the VGG16 from this function:

def vgg16_encoder_decoder(input_size = (200,200,1)):
    #################################
    # Encoder
    #################################
    inputs = Input(input_size, name = 'input')

    conv1 = Conv2D(64, (3, 3), activation = 'relu', padding = 'same', name ='conv1_1')(inputs)
    conv1 = Conv2D(64, (3, 3), activation = 'relu', padding = 'same', name ='conv1_2')(conv1)
    pool1 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_1')(conv1)

    conv2 = Conv2D(128, (3, 3), activation = 'relu', padding = 'same', name ='conv2_1')(pool1)
    conv2 = Conv2D(128, (3, 3), activation = 'relu', padding = 'same', name ='conv2_2')(conv2)
    pool2 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_2')(conv2)
    
    conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_1')(pool2)
    conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_2')(conv3)
    conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_3')(conv3)
    pool3 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_3')(conv3)
    
    conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_1')(pool3)
    conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_2')(conv4)
    conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_3')(conv4)
    pool4 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_4')(conv4)

    conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_1')(pool4)
    conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_2')(conv5)
    conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_3')(conv5)
    pool5 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_5')(conv5)

    #################################
    # Decoder
    #################################
    #conv1 = Conv2DTranspose(512, (2, 2), strides = 2, name = 'conv1')(pool5)

    upsp1 = UpSampling2D(size = (2,2), name = 'upsp1')(pool5)
    conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_1')(upsp1)
    conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_2')(conv6)
    conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_3')(conv6)

    upsp2 = UpSampling2D(size = (2,2), name = 'upsp2')(conv6)
    conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_1')(upsp2)
    conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_2')(conv7)
    conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_3')(conv7)
    zero1 = ZeroPadding2D(padding =  ((1, 0), (1, 0)), data_format = 'channels_last', name='zero1')(conv7)

    upsp3 = UpSampling2D(size = (2,2), name = 'upsp3')(zero1)
    conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_1')(upsp3)
    conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_2')(conv8)
    conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_3')(conv8)

    upsp4 = UpSampling2D(size = (2,2), name = 'upsp4')(conv8)
    conv9 = Conv2D(128, 3, activation = 'relu', padding = 'same', name = 'conv9_1')(upsp4)
    conv9 = Conv2D(128, 3, activation = 'relu', padding = 'same', name = 'conv9_2')(conv9)

    upsp5 = UpSampling2D(size = (2,2), name = 'upsp5')(conv9)
    conv10 = Conv2D(64, 3, activation = 'relu', padding = 'same', name = 'conv10_1')(upsp5)
    conv10 = Conv2D(64, 3, activation = 'relu', padding = 'same', name = 'conv10_2')(conv10)

    conv11 = Conv2D(1, 3, activation = 'relu', padding = 'same', name = 'conv11')(conv10)

    model = Model(inputs = inputs, outputs = conv11, name = 'vgg-16_encoder_decoder')

    return model

I train the network, and after train it. How can I get the encoder part? In other words, get the a model with only the original layers from conv1 to pool5 .

I think it could be something like this:

model_new = Model(input=model_old.layers[0].input, 
                  output=model_old.layers[12].output)
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import Input, Flatten
from tensorflow.keras import Model

input_shape = (W,H,C)
def encoder(input_shape):
     model = VGG16(include_top=False, input_shape=input_shape)
     F1 = Flatten()(model.get_layer(index=1).output)
     F2 = Flatten()(model.get_layer(index=2).output)
     F3 = Flatten()(model.get_layer(index=3).output)
     F4 = Flatten()(model.get_layer(index=4).output)
     F5 = Flatten()(model.get_layer(index=5).output)   
     M = Model(model.inputs,[F1,F2,F3,F4,F5])  
     return M 

Where W,H the image size and C the numbre of chnnel should equal to 3.

To get the enconder from I pre-trained network I have created this function:

def get_encoder(old_model: Model) -> Model:
  # Get encoder
  encoder_input: Model = Model(inputs=old_model.layers[0].input,
                              outputs=old_model.layers[14].output)

  # Create Global Average Pooling.
  encoder_output = GlobalAveragePooling2D()(encoder_input.layers[-1].output)

  # Create the encoder adding the GAP layer as output.
  encoder: Model = Model(encoder_input.input, encoder_output, name='encoder')

  return encoder

The important thing is the number 14 . This is the layer where the enconder ends in the original network. By the way, I have finally used U-Net instead of VGG-16 , so this number only works for U-NET .

I'd suggest the following code, by omitting the last 20 layers from your code.

model_new = Model(model_old.input, model_old.layers[-20].output) model_new.summary()

You may need to slightly adjust it to -19 or -21 to find the last pool5 if I missed the counting of last 20 layers for the decoder.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM