I'm newbie with Python 3.7.7 and Tensorflow 2.1.0 and I'm trying to understand Conv2DTranspose. I have tried this code:
def vgg16_decoder(input_size = (7, 7, 512)):
inputs = Input(input_size, name = 'input')
conv1 = Conv2DTranspose(512, (2, 2), dilation_rate = 2, name = 'conv1')(inputs)
model = Model(inputs = inputs, outputs = conv1, name = 'vgg-16_decoder')
opt = Adam(lr=0.001)
model.compile(optimizer=opt, loss=keras.losses.categorical_crossentropy, metrics=['accuracy'])
return model
And this is its summary:
Model: "vgg-16_decoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input (InputLayer) (None, 7, 7, 512) 0 _________________________________________________________________ conv1 (Conv2DTranspose) (None, 9, 9, 512) 1049088 ================================================================= Total params: 1,049,088 Trainable params: 1,049,088 Non-trainable params: 0 _________________________________________________________________
But I want an output of (None, 14, 14, 512) from conv1.
I have changed filter size to (3, 3) and I get this summary:
Model: "vgg-16_decoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input (InputLayer) (None, 7, 7, 512) 0 _________________________________________________________________ conv1 (Conv2DTranspose) (None, 11, 11, 512) 2359808 ================================================================= Total params: 2,359,808 Trainable params: 2,359,808 Non-trainable params: 0 _________________________________________________________________
I'm trying to get to this using Conv2DTranspose:
# A piece of code from U-NET implementation
up6 = Conv2D(512, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name = 'up6')(UpSampling2D(size = (2,2), name = 'upsp1')(drop5))
And its summary:
drop5 (Dropout) (None, 16, 16, 1024) 0 conv5_2[0][0] __________________________________________________________________________________________________ upsp1 (UpSampling2D) (None, 32, 32, 1024) 0 drop5[0][0] __________________________________________________________________________________________________ up6 (Conv2D) (None, 32, 32, 512) 2097664 upsp1[0][0] __________________________________________________________________________________________________
It upsamples by 2 its input and it changes its number of filters.
How can I do that with Conv2DTranspose?
UPDATE:
I think, or I suppose, I did it, but I don't understand what I did:
conv1 = Conv2DTranspose(512, (2, 2), strides = 2, name = 'conv1')(inputs)
With the previous statement, I get this summary:
Model: "vgg-16_decoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input (InputLayer) (None, 7, 7, 512) 0 _________________________________________________________________ conv1 (Conv2DTranspose) (None, 14, 14, 512) 1049088 ================================================================= Total params: 1,049,088 Trainable params: 1,049,088 Non-trainable params: 0 _________________________________________________________________
If you want to correct me or explain what I have done here, you are welcome.
UPDATE 2:
By the way, I'm trying to create an VGG-16 decoder. This is the code for my VGG-16 encoder:
def vgg16_encoder(input_size = (224,224,3)):
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)
opt = Adam(lr=0.001)
model = Model(inputs = inputs, outputs = pool5, name = 'vgg-16_encoder')
model.compile(optimizer=opt, loss=keras.losses.categorical_crossentropy, metrics=['accuracy'])
return model