DCGANs (Deep Convolutional Generative Adversarial Networks) | by Connor Shorten | Towards Data Science

One of the most interesting parts of Generative Adversarial Networks is the design of the Generator network. The Generator network is able to take random noise and map it into images such that the discriminator cannot tell which images came from the dataset and which images came from the generator.
This is a very interesting application of neural networks. Typically neural nets map input into a binary output, (1 or 0), maybe a regression output, (some real-valued number), or even multiple categorical outputs, (such as MNIST or CIFAR-10/100).
In this article, we will see how a neural net maps from random noise to an image matrix and how using Convolutional Layers in the generator network produces better results.
We will review the paper presenting DCGANs at ICLR, a generator network architecture that generated bedrooms, and we will review some Python/Keras code from the GANs-in-Action repository.
This is the DCGAN generator presented in the LSUN scene modeling paper. This network takes in a 100x1 noise vector, denoted z, and maps it into the G(Z) output which is 64x64x3.
This architecture is especially interesting the way the first layer expands the random noise. The network goes from 100x1 to 1024x4x4! This layer is denoted ‘project and reshape’.
We see that following this layer, classical convolutional layers are applied which reshape the network with the (N+P — F)/S + 1 equation classically taught with convolutional layers. In the diagram above we can see that the N parameter, (Height/Width), goes from 4 to 8 to 16 to 32, it doesn’t appear that there is any padding, the kernel filter parameter F is 5x5, and the stride is 2. You may find this equation to be useful for designing your own convolutional layers for customized output sizes.
We see the network goes from
100x1 → 1024x4x4 → 512x8x8 → 256x16x16 → 128x32x32 → 64x64x3
Above is the output from the network presented in the paper, citing that this came after 5 epochs of training. Pretty impressive stuff.
Now, let’s look at some python code:
This code is taken from the gans-in-action repository created by Jakub Langr and Vladimir Bok, from what I have found this is the best starter code for implementing GANs in Keras. I don’t think this book has been released yet, but I imagine it will be very good.
github.com
The code below is how I got my first GAN network running, (does not implement DCGANs):
def generator(img_shape, z_dim):  model = Sequential()  # Hidden layer  model.add(Dense(128, input_dim = z_dim))  # Leaky ReLU  model.add(LeakyReLU(alpha=0.01))  # Output layer with tanh activation  model.add(Dense(28*28*1, activation='tanh'))  model.add(Reshape(img_shape)  z = Input(shape=(z_dim,))  img = model(z)  return Model(z, img)
The architecture below isn’t too complicated and actually does produce pretty decent results on the MNIST dataset example. This model takes in the noise vector and maps it to a densely connected layer which maps to an output layer which is a flat 784x1 vector which is reshaped into the 28x28 MNIST digit matrix.
Now let’s contrast this with the DCGAN code provided in the gans-in-action repository:
def generator(img_shape, z_dim):  model = Sequential()   # Reshape input into 7x7x256 tensor via a fully connected layer  model.add(Dense(256*7*7, input_dim = z_dim))  model.add(Reshape((7,7,256))  # Transposed convolution layer, from 7x7x256 into 14x14x128 tensor  model.add(Conv2DTranspose(               128, kernel_size = 3, strides = 2, padding='same'))  #Batch normalization  model.add(BatchNormalization())  #Leaky ReLU  model.add(LeakyReLU(alpha=0.01))  # Transposed convolution layer, from 14x14x128 to 14x14x64 tensor  model.add(Conv2DTranspose(              64, kernel_size=3, strides=1, padding='same'))  # Batch normalization  model.add(BatchNormalization())  # Leaky ReLU  model.add(LeakyReLU(alpha=0.01))  # Transposed convolution layer, from 14x14x64 to 28x28x1 tensor  model.add(Conv2DTranspose(               1, kernel_size = 3, strides = 2, padding='same'))  # Tanh activation  model.add(Activation('tanh'))  z = Input(shape=(z_dim,))  img = model(z)  return Model(z, img)
We see the architecture above is very similar to the DCGAN presented in the ICLR, LSUN scene generator paper. The input is projected from 100x1 noise into a 7x7x256 tensor, which is then convolved over until you reach the 28x28x1 MNIST digit output.
Again, we see this same project and reshape, followed by convolutional layers into the output from the diagram in the starter code.
I hope this article helped you get started building your own DCGANs. I think it at least provides a good explanation of how the high-level architecture should work. The remaining challenge lies in finding the right parameters for the convolutional layers, as well as the project and reshape layer.
I really found the combination of this open source code repository and the ICLR paper to help me understand this concept. I am very excited about building GANs and seeing what they can do, please leave a comment with any additional resources that you think are really helpful. Please follow if you would like to stay notified on further research using these DCGANs for Data Augmentation.
Connor Shorten is a Computer Science student at Florida Atlantic University. Research interests in computer vision, deep learning, and software engineering.