I am trying to implement a convolutional autoencoder with a dense layer at the bottleneck do to some dimensional reduction. I have seen two approaches for this which arent particularly scalable. The first was to introduce 2 dense layers (one at the bottle neck and one before & after that has the same number of nodes as the conv2d layer that precedes the dense layer in the encoder section:

encoding_dims = 20

encoder = Sequential()
encoder.add(Conv2D(32, (3,3), activation="relu, padding="same"))
encoder.add(MaxPooling2D((2), padding="same"))
encoder.add(Dense(32*100*100, activation="relu"))
encoder.add(Dense(encoding_dims, activation="relu"))

#The decoder
decoder = Sequential()
decoder.add(Dense(32*100*100, activation="relu"))
decoder.add(Reshape((100, 100, 32)))
decoder.add(Conv2D(3, (3,3), activation="sigmoid", padding="same"))

Its easy to see why this approach blows up as there are two densely connected layers with (32*100*100) nodes each or more or in that ballpark which is nuts.

Another approach I have found which makes sense for b/w images such as the mnist stuff is to introduce an arbitrary number of encoding dimensions and reshape it (https://medium.com/analytics-vidhya/building-a-convolutional-autoencoder-using-keras-using-conv2dtranspose-ca403c8d144e). The following chunk of code is copied from the link, I claim no credit for it:

inp = Input((28, 28,1))
e = Conv2D(32, (3, 3), activation='relu')(inp)
e = MaxPooling2D((2, 2))(e)
e = Conv2D(64, (3, 3), activation='relu')(e)
e = MaxPooling2D((2, 2))(e)
e = Conv2D(64, (3, 3), activation='relu')(e)
l = Flatten()(e)
l = Dense(49, activation='softmax')(l)
d = Reshape((7,7,1))(l)
d = Conv2DTranspose(64,(3, 3), strides=2, activation='relu', padding='same')(d)
d = BatchNormalization()(d)
d = Conv2DTranspose(64,(3, 3), strides=2, activation='relu', padding='same')(d)
d = BatchNormalization()(d)
d = Conv2DTranspose(32,(3, 3), activation='relu', padding='same')(d)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(d)

The question is then is there a more rigorous way/ accepted of adding a conv2d layer after a 2d layer?


Hi for me this worked perfectly. I encoded with conv2d and dense and then I flatten I and reshape in the decoder after the dense layer so the encoder and decoder are symmetrical. The only difference is that in my case I use images (224,224,1)

        # create encoder
        # 28,28 -> 1st conv2d (filter 3x3,relu activation, padding, strides == 'jumps')
        self.encoder = tf.keras.Sequential([layers.Input(shape=(224,224,1)),
                                            layers.Dense(units=3136,activation='sigmoid')]) # (28,28,4)
        # deconvolution -> decoding 
        self.decoder = tf.keras.Sequential([layers.Input(shape=(3136)),

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.