2
$\begingroup$

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:

input_image_shape=(200,200,3)
encoding_dims = 20

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

#The decoder
decoder = Sequential()
decoder.add(InputLayer((encoding_dims,)))
decoder.add(Dense(32*100*100, activation="relu"))
decoder.add(Reshape((100, 100, 32)))
decoder.add(UpSampling2D(2))
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:

#ENCODER
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)
#DECODER
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?

$\endgroup$

Your Answer

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

Browse other questions tagged or ask your own question.