Lecture slide 44 (of 47) -Using Keras to duplicate calculations

Here is the Transpose version:

# Cell to experiment with padding on Conv2DTranspose
print("padding = 'valid' stride = 1")
playmodel = tf.keras.Sequential()
playmodel.add(Conv2DTranspose(filters = 3, kernel_size = 3, strides = 1, padding = 'valid'))
for playimage, _ in processed_image_ds.take(1):
    playimage = tf.expand_dims(playimage, 0)
    print(f"playimage.shape {playimage.shape}")
    playout = playmodel(playimage)
    print(f"playout.shape {playout.shape}")

print("padding = 'valid' stride = 2")
playmodel = tf.keras.Sequential()
playmodel.add(Conv2DTranspose(filters = 3, kernel_size = 3, strides = 2, padding = 'valid'))
for playimage, _ in processed_image_ds.take(1):
    playimage = tf.expand_dims(playimage, 0)
    print(f"playimage.shape {playimage.shape}")
    playout = playmodel(playimage)
    print(f"playout.shape {playout.shape}")
    
print("padding = 'same' stride = 1")
playmodel = tf.keras.Sequential()
playmodel.add(Conv2DTranspose(filters = 3, kernel_size = 3, strides = 1, padding = 'same'))
for playimage, _ in processed_image_ds.take(1):
    playimage = tf.expand_dims(playimage, 0)
    print(f"playimage.shape {playimage.shape}")
    playout = playmodel(playimage)
    print(f"playout.shape {playout.shape}")

print("padding = 'same' stride = 2")
playmodel = tf.keras.Sequential()
playmodel.add(Conv2DTranspose(filters = 3, kernel_size = 3, strides = 2, padding = 'same'))
for playimage, _ in processed_image_ds.take(1):
    playimage = tf.expand_dims(playimage, 0)
    print(f"playimage.shape {playimage.shape}")
    playout = playmodel(playimage)
    print(f"playout.shape {playout.shape}")
    
print("padding = 'same' stride = 3")
playmodel = tf.keras.Sequential()
playmodel.add(Conv2DTranspose(filters = 3, kernel_size = 3, strides = 3, padding = 'same'))
for playimage, _ in processed_image_ds.take(1):
    playimage = tf.expand_dims(playimage, 0)
    print(f"playimage.shape {playimage.shape}")
    playout = playmodel(playimage)
    print(f"playout.shape {playout.shape}")

And here is the output from running the above:

padding = 'valid' stride = 1
playimage.shape (1, 96, 128, 3)
playout.shape (1, 98, 130, 3)

padding = 'valid' stride = 2
playimage.shape (1, 96, 128, 3)
playout.shape (1, 193, 257, 3)

padding = 'same' stride = 1
playimage.shape (1, 96, 128, 3)
playout.shape (1, 96, 128, 3)

padding = 'same' stride = 2
playimage.shape (1, 96, 128, 3)
playout.shape (1, 192, 256, 3)

padding = 'same' stride = 3
playimage.shape (1, 96, 128, 3)
playout.shape (1, 288, 384, 3)

My current understanding is that the size formula is:

n_{out} = (n_{in} - 1) * s + f - 2p

I’m not sure I believe that based on the numbers I’m seeing above. More research required …

But the bottom line here is that it is the same story as with forward convolutions: “same” only means “same” if the stride is 1. Otherwise it is not the same.

Update: We later got an explanation for the ambuigities in the formula for computing the output size of a transpose convolution. Here’s a thread from Raymond which gives the explanation.