C4_W1: How to calculate output volume for a `Conv2DTranspose` filter?

Does the output volume calculation taught in this course apply equally well if the filter used is Conv2DTranspose? I try to do that but it differs in the calculation result. For example, in https://www.tensorflow.org/tutorials/generative/dcgan the generator output volume of the last 2 Conv2DTranspose layers calculation do not match up:

# Previous layer output is (None, 7, 7, 128)

self.model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same'))
# Input: 7x7x128
# Filter: 64 5x5 s:2 p = (f-1)/2 = 2
# Nh[l] = floor((Nh[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(7 + 4 - 5)/2 + 1 = 4
# Nw[l] = floor((Nw[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(7 + 4 - 5)/2 + 1 = 4
# Output volume = Nh[l] x Nw[l] x Nc[l] = 4 * 4 * 64 = 6272
assert self.model.output_shape == (None, 14, 14, 64) # XXX
self.model.add(layers.BatchNormalization())
self.model.add(layers.LeakyReLU())

self.model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', activation='tanh'))
# Input: 14x14x64
# Filter: 1 5x5 s:2 p = (f-1)/2 = 2
# Nh[l] = floor((Nh[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(14 + 4 - 5)/2 + 1 = 7
# Nw[l] = floor((Nw[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(14 + 4 - 5)/2 + 1 = 7
# Output volume = Nh[l] x Nw[l] x Nc[l] = 7 * 7 * 1 = 6272
assert self.model.output_shape == (None, 28, 28, 1) # XXX

Only the first Conv2DTranspose match with the calculation formula. What do I miss?

It turns out that the output shape of a transpose convolution is ambiguous. There are at least two ways it could work out. Here’s a thread on which mentor Raymond explains how this arises. You need to read most of the thread to get to Raymond’s post.

If I’m missing your point, please let me know. :smiley:

# Previous layer output is (None, 7, 7, 128)

self.model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same'))
# Input: 7x7x128
# Filter: 64 5x5 s:2 p = (f-1)/2 = 2
# Nh[l] = floor((Nh[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(7 + 4 - 5)/2 + 1 = 4
# Nw[l] = floor((Nw[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(7 + 4 - 5)/2 + 1 = 4
# Output volume = Nh[l] x Nw[l] x Nc[l] = 4 * 4 * 64 = 6272
# Nout = (Nin  - 1) * s + f - 2p = (7-1) * 2 + 5 - 2*2 = 6*2 + 5 - 4 = 12 + 5 - 4 = 13 <- XXX
assert self.model.output_shape == (None, 14, 14, 64) # XXX
self.model.add(layers.BatchNormalization())
self.model.add(layers.LeakyReLU())

self.model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', activation='tanh'))
# Input: 14x14x64
# Filter: 1 5x5 s:2 p = (f-1)/2 = 2
# Nh[l] = floor((Nh[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(14 + 4 - 5)/2 + 1 = 7
# Nw[l] = floor((Nw[l-1] + 2p[l] - f[l]) / s[l]) + 1 = floor(14 + 4 - 5)/2 + 1 = 7
# Output volume = Nh[l] x Nw[l] x Nc[l] = 7 * 7 * 1 = 6272
# Nout = (Nin  - 1) * s + f - 2p = (14-1) * 2 + 5 - 2*2 = 13*2 + 5 - 4 = 26 + 5 - 4 = 27 <- XXX
assert self.model.output_shape == (None, 28, 28, 1) # XXX

No, you meant to use this equation Nout = (Nin - 1) * s + f - 2p, it still doesn’t give the correct answers.