Skip to content

Commit 972c95c

Browse files
DCGAN_tensorflow (pclubiitk#16)
* Create DCGAN_tensorflow * Add files via upload * Delete DCGAN_tensorflow * Update README.md * Delete image_at_epoch_0001 - Copy.png * Delete image_at_epoch_0002.png * Delete image_at_epoch_0003.png * Feat:Reqd Changes * changes accompalished * Update main.py * Update README.md Co-authored-by: Nirmal Suthar <[email protected]>
1 parent ad39276 commit 972c95c

File tree

8 files changed

+306
-0
lines changed

8 files changed

+306
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# TensorFlow Implementation of DCGAN
2+
## Usage
3+
```bash
4+
$ python3 main.py --EPOCHS 50 --noise_dim 100
5+
```
6+
> **_NOTE:_** on Colab Notebook use following command:
7+
```python
8+
!git clone link-to-repo
9+
%run main.py --EPOCHS 50 --noise_dim 100
10+
```
11+
12+
## Help log
13+
```
14+
usage: main.py [-h] [--EPOCHS EPOCHS]
15+
[--noise_dim NOISE_DIM]
16+
[--BATCH_SIZE BATCH_SIZE] [--num_examples_to_generate num_examples_to_generate]
17+
[--lr_gen lr_gen][--lr_disc lr_disc]
18+
[--outdir OUTDIR]
19+
20+
optional arguments:
21+
-h, --help show this help message and exit
22+
--EPOCHS EPOCHS No of epochs: default 50
23+
--noise_dim NOISE_DIM Dimension of noise vector
24+
--batch_size BATCH_SIZE Batch size, default 256
25+
--num_examples_to_generate no of images shown after each epoch in output, default 16
26+
--lr_gen learning rate of generator's optimizer,default 0.0002
27+
--lr_disc learning rate of discriminator's optimizer,default 0.0002
28+
--outdir OUTDIR Directory in which to store data
29+
30+
```
31+
32+
## Contributed by:
33+
* [Shivamshree Gupta](https://github.com/shvmshri)
34+
35+
## References
36+
37+
* **Title**: Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks
38+
* **Authors**: Alec Radford, Luke Metz, Soumith Chintala
39+
* **Link**: [https://arxiv.org/pdf/1511.06434.pdf](https://arxiv.org/pdf/1511.06434.pdf)
40+
* **Tags**: Neural Network, Generative Networks, GANs
41+
* **Year**: 2015
42+
43+
## SUMMARY
44+
### *Deep Convolutional Generative Adversarial Networks*
45+
#### Introduction
46+
One way to build good natural images is by training Generative Adversarial Networks (GANS). ,and we can later even reuse parts of the generator and discriminator networks as feature extractors for supervised tasks .DCGANs is actually one of the class of GANs using CNNs architecture for both of its components i.e. a generator and a discriminator.
47+
#### Model Architecture
48+
In general, GANs consist of a generator and a discriminator. These two are separately a CNN architecture and are trained together.
49+
50+
![alt text](https://github.com/shvmshri/DCGAN_Tensorflow/blob/master/images/DG.png)
51+
##### GENERATOR :
52+
A ANN model which is aimed for the generation of new images. They took in input a random noise z and various convolution transpose layers are applied and it generates a image i.e. a matrices of pixel values (G(z)) .Generator never get to see the real world actual images or the training dataset of images.
53+
##### DISCRIMINATOR:
54+
A CNN classification model used to classify whether an image passed to it is real or fake (generated by the generator).It take image from training examples x and from those generated by generator (G (z)) and predicts the probability of the image to be real (D(x)) or fake (D (G (z))).
55+
56+
Now, while training the model, generator tries to increase the discriminator error as it tries to fool discriminator by improving its generated image so that they resemble real images while discriminator tries to decrease it’s error by trying to judge correctly the real and the fake images. For weights of the model normally initiated ,we first train generator say for y no. of images keeping the discriminator’s weights constant .Then, as generator’s weight are updated ,we train discriminator keeping generator’s weights to be constant for y fake and y real images and this process is then repeated for several epochs using cross entropy loss function.
57+
58+
![alt text](https://github.com/shvmshri/DCGAN_Tensorflow/blob/master/images/loss%20eq.jpg)
59+
60+
This becomes a __minimax__ type loss function as above illustrated.
61+
62+
#### Architecture guidelines for stable Deep Convolutional GANs
63+
• Replace any pooling layers with strided convolutions (discriminator) and fractional-strided convolutions (generator).
64+
• Use batchnorm in both the generator and the discriminator except at the generator’s output layer and discriminator’s input layer.
65+
• Remove fully connected hidden layers for deeper architectures.
66+
• Use ReLU activation in generator for all layers except for the output, which uses Tanh.
67+
• Use LeakyReLU activation in the discriminator for all layers.
68+
69+
#### Implementation and Training details
70+
1. Pre-processing -: scaling images to [-1 1]. No data augmentation.
71+
2. Batch size -: 128.
72+
3. Weights initialization -: using normal distribution.
73+
4. LeakyReLU -: slope of leak=0.2.
74+
5. Adam optimizer-: learning rate=0.0002, momentum=0.5.
75+
6. Epochs -: 50.
76+
7. Noise dimension -: 100
77+
78+
#### Images generated of MNIST dataset after 50 epochs:
79+
80+
![alt text](https://github.com/shvmshri/DCGAN_Tensorflow/blob/master/images/image_at_epoch_0050.png)
81+
82+
#### Plot of generator loss vs. discriminator loss
83+
84+
![alt text](https://github.com/shvmshri/DCGAN_Tensorflow/blob/master/images/loss_plot.png)
85+
86+
## Sources
87+
1. [Deep Learning Part -II(CS7015),Lec-1](https://www.youtube.com/watch?v=1ju4qmdtRdY&t=142s)
88+
2. [Deep Learning Part -II(CS7015),Lec-2](https://www.youtube.com/watch?v=uyuYfTMHZM0)
6.57 KB
Loading
Loading
Loading
Loading
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import tensorflow as tf
2+
import numpy as np
3+
import os
4+
import PIL
5+
from tensorflow.keras.models import Sequential, Model, load_model
6+
from tensorflow.keras.optimizers import Adam
7+
from tensorflow.keras.losses import BinaryCrossentropy
8+
9+
from MNIST_model import make_generator,make_discriminator
10+
from utils.py import plot_loss,generate_and_save_images
11+
import argparse
12+
13+
parser = argparse.ArgumentParser()
14+
15+
parser.add_argument('--EPOCHS', type = int, default = 50, help = "No of EPOCHS: default 50 ")
16+
parser.add_argument('--noise_dim', type = int, default = 100, help = "Noise dimension, default 100 ")
17+
parser.add_argument('--BATCH_SIZE', type = int, default = 128, help = "Batch size, default 128")
18+
parser.add_argument('--num_examples_to_generate', type = int, default = 16, help = "no of images shown after each epoch in output, default 16")
19+
parser.add_argument('--lr_gen', type = int, default = 0.0002, help = "Learning rate for generator optimizer,default 0.0002 ")
20+
parser.add_argument('--lr_disc', type = int, default = 0.0002, help = "Learning rate for discriminator optimizer,default 0.0002 ")
21+
parser.add_argument('--outdir', type = str, default = '.', help = "Directory in which to store data")
22+
23+
args = parser.parse_args()
24+
25+
# Loading MNIST_Dataset
26+
(train_images, train_labels),(_,_) = tf.keras.datasets.mnist.load_data()
27+
28+
BUFFER_SIZE=60000
29+
BATCH_SIZE = args.BATCH_SIZE
30+
EPOCHS = args.EPOCHS
31+
noise_dim = args.noise_dim
32+
num_examples_to_generate = args.num_examples_to_generate
33+
lr_gen = args.lr_gen
34+
lr_disc = args.lr_disc
35+
36+
37+
seed = tf.random.normal([num_examples_to_generate, noise_dim])
38+
39+
# Preparing and Normalising Dataset
40+
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
41+
train_images = (train_images - 127.5) / 127.5
42+
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
43+
44+
# Making generator and Discriminator
45+
generator=make_generator(noise_dim)
46+
discriminator=make_discriminator()
47+
48+
# Defining generator and discriminator losses
49+
cross_entropy = BinaryCrossentropy(from_logits=True)
50+
51+
def discriminator_loss(real_output, fake_output):
52+
real_loss = cross_entropy(tf.ones_like(real_output), real_output)
53+
fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
54+
total_loss = real_loss + fake_loss
55+
return total_loss
56+
57+
def generator_loss(fake_output):
58+
return cross_entropy(tf.ones_like(fake_output), fake_output)
59+
60+
# Defining optimizers
61+
generator_optimizer = Adam(learning_rate=lr_gen)
62+
discriminator_optimizer = Adam(learning_rate=lr_disc)
63+
64+
# Saving Checkpoints
65+
checkpoint_dir = os.path.join(args.outdir, "training_checkpoints")
66+
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
67+
checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,
68+
discriminator_optimizer=discriminator_optimizer,
69+
generator=generator,
70+
discriminator=discriminator)
71+
72+
# Defining Training Loop
73+
@tf.function
74+
def train_step(images):
75+
noise = tf.random.normal([BATCH_SIZE, noise_dim])
76+
77+
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
78+
generated_images = generator(noise, training=True)
79+
80+
real_output = discriminator(images, training=True)
81+
fake_output = discriminator(generated_images, training=True)
82+
83+
gen_loss = generator_loss(fake_output)
84+
disc_loss = discriminator_loss(real_output, fake_output)
85+
86+
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
87+
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
88+
89+
generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
90+
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))
91+
return gen_loss,disc_loss
92+
93+
def train(dataset, epochs):
94+
for epoch in range(epochs):
95+
gen_loss_list = []
96+
disc_loss_list = []
97+
98+
for image_batch in dataset:
99+
t=train_step(image_batch)
100+
gen_loss_list.append(t[0])
101+
disc_loss_list.append(t[1])
102+
103+
gen_loss = sum(gen_loss_list) / len(gen_loss_list)
104+
disc_loss = sum(disc_loss_list) / len(disc_loss_list)
105+
106+
107+
print (f'Epoch {epoch+1}, gen loss={gen_loss},disc loss={disc_loss}')
108+
109+
generate_and_save_images(generator,
110+
epoch + 1,
111+
seed)
112+
113+
# Save the model every 15 epochs
114+
if (epoch + 1) % 15 == 0:
115+
checkpoint.save(file_prefix = checkpoint_prefix)
116+
117+
return gen_loss_list,disc_loss_list
118+
119+
# Training our model
120+
plo=train(train_dataset, EPOCHS)
121+
122+
#Ploting generator and discriminator losses
123+
plot_loss(plo[0],plo[1])
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Importing Libraries
2+
3+
import tensorflow as tf
4+
from tensorflow.keras.layers import Input, Reshape, Dropout, Dense ,Flatten
5+
from tensorflow.keras.layers import BatchNormalization
6+
from tensorflow.keras.layers import LeakyReLU,ReLU
7+
from tensorflow.keras.layers import Conv2DTranspose,Conv2D
8+
from tensorflow.keras.models import Sequential, Model, load_model
9+
import numpy as np
10+
11+
# Model of Generator
12+
13+
def make_generator(noise_dim):
14+
model=Sequential()
15+
16+
model.add(Dense(7*7*256,input_shape=(noise_dim)))
17+
model.add(BatchNormalization(momentum=0.5))
18+
model.add(ReLU())
19+
20+
model.add(Reshape((7,7,256)))
21+
22+
model.add(Conv2DTranspose(128,(3,3),strides=(1,1),padding='same',use_bias='False'))
23+
model.add(BatchNormalization(momentum=0.5))
24+
model.add(ReLU())
25+
26+
model.add(Conv2DTranspose(64,(3,3),strides=(2,2),padding='same',use_bias='False'))
27+
model.add(BatchNormalization(momentum=0.5))
28+
model.add(ReLU())
29+
30+
model.add(Conv2DTranspose(1,(3,3),strides=(2,2),padding='same',use_bias='False',activation='tanh'))
31+
return model
32+
33+
# Model of discriminator
34+
35+
def make_discriminator():
36+
model=Sequential()
37+
38+
model.add(Conv2D(64,(3,3),strides=(2,2),padding='same',input_shape=[28,28,1]))
39+
model.add(LeakyReLU(alpha= 0.2))
40+
model.add(Dropout(0.3))
41+
42+
model.add(Conv2D(128,(3,3),strides=(2,2),padding='same'))
43+
model.add(BatchNormalization(momentum=0.5))
44+
model.add(LeakyReLU(alpha= 0.2))
45+
model.add(Dropout(0.3))
46+
47+
model.add(Conv2D(256,(3,3),strides=(2,2),padding='same'))
48+
model.add(BatchNormalization(momentum=0.5))
49+
model.add(LeakyReLU(alpha= 0.2))
50+
model.add(Dropout(0.3))
51+
52+
model.add(Conv2D(512,(3,3),strides=(2,2),padding='same'))
53+
model.add(BatchNormalization(momentum=0.5))
54+
model.add(LeakyReLU(alpha= 0.2))
55+
model.add(Dropout(0.3))
56+
57+
model.add(Flatten())
58+
model.add(Dense(1))
59+
60+
return model
61+
62+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import PIL
2+
import matplotlib.pyplot as plt
3+
from IPython import display
4+
from tensorflow.keras.models import Sequential, Model, load_model
5+
6+
# Generate and save images
7+
def generate_and_save_images(model, epoch, test_input):
8+
# Notice `training` is set to False.
9+
# This is so all layers run in inference mode (batchnorm).
10+
predictions = model(test_input, training=False)
11+
12+
fig = plt.figure(figsize=(4,4))
13+
14+
for i in range(predictions.shape[0]):
15+
plt.subplot(4, 4, i+1)
16+
plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')
17+
plt.axis('off')
18+
19+
plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))
20+
plt.show()
21+
22+
# Plotting generator losses and discriminator losses
23+
def plot_loss(gen,disc):
24+
plt.figure(figsize=(10,5))
25+
plt.title("Generator and Discriminator Loss During Training")
26+
plt.plot(gen,label="G")
27+
plt.plot(disc,label="D")
28+
plt.xlabel("iterations")
29+
plt.ylabel("Loss")
30+
plt.legend()
31+
plt.savefig('loss_plot.png')
32+
plt.show()
33+

0 commit comments

Comments
 (0)