-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
86,822 additions
and
0 deletions.
There are no files selected for viewing
330 changes: 330 additions & 0 deletions
330
.ipynb_checkpoints/.ipynb_checkpoints/DCGAN-checkpoint.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,330 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Generating Faces With A Deep Convolutional Generative Adversarial Network\n", | ||
"\n", | ||
"Recently I found a great repo posted by Erik Lindernoren [https://github.com/eriklindernoren/Keras-GAN/blob/master/dcgan/dcgan.py] providing wire frame code for a whole bunch of different GANs. I've wanted to give GANs a try for a while so, I grabbed the DCGAN code from this repo, a celebrity faces data set posted by Mirantha Jayathilaka at [https://www.floydhub.com/mirantha/datasets/celeba]. Following methods and using code from the DCGAN and gan_rgb folders in Erik Lindernoren's repo, I set up the the DCGAN code to train on RGB images from the Celeba data set. \n", | ||
"\n", | ||
"On a hunch, I wanted to modify the generator network to accept random noise in the same size and shape as the image it is generating, rather than a random vector of lenght 100. My thought was, why 100? I couldn't not think of any theoretical reason to keep the length of the random vector to 100, or any guidence on the size. Without reseraching, I decided to make the random input the same size and dimentions as the output that is to be produced. Following Erik's code, I used his crop and resize pre-processing to generate and discriminate with 28x28 pixel images cropped close to the faces. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stderr", | ||
"output_type": "stream", | ||
"text": [ | ||
"Using TensorFlow backend.\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# Imports \n", | ||
"# code from https://github.com/eriklindernoren/Keras-GAN/blob/master/dcgan/dcgan.py\n", | ||
"from __future__ import print_function, division\n", | ||
"\n", | ||
"from keras.datasets import mnist\n", | ||
"from keras.layers import Input, Dense, Reshape, Flatten, Dropout\n", | ||
"from keras.layers import BatchNormalization, Activation, ZeroPadding2D\n", | ||
"from keras.layers.advanced_activations import LeakyReLU\n", | ||
"from keras.layers.convolutional import UpSampling2D, Conv2D\n", | ||
"from keras.models import Sequential, Model\n", | ||
"from keras.optimizers import Adam\n", | ||
"\n", | ||
"import matplotlib.pyplot as plt\n", | ||
"\n", | ||
"import sys\n", | ||
"\n", | ||
"import numpy as np\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Code from https://github.com/eriklindernoren/Keras-GAN/blob/master/dcgan/dcgan.py\n", | ||
"# with edits to generate from different noise input\n", | ||
"# DC GAN covoutional \n", | ||
"\n", | ||
"# DCGAN class \n", | ||
"class DCGAN():\n", | ||
" def __init__(self):\n", | ||
" self.img_rows = 28 \n", | ||
" self.img_cols = 28\n", | ||
" self.channels = 3\n", | ||
" self.img_shape = (self.img_rows, self.img_cols, self.channels)\n", | ||
"\n", | ||
" optimizer = Adam(0.0002, 0.5)\n", | ||
"\n", | ||
" # Build and compile the discriminator\n", | ||
" self.discriminator = self.build_discriminator()\n", | ||
" self.discriminator.compile(loss='binary_crossentropy',\n", | ||
" optimizer=optimizer,\n", | ||
" metrics=['accuracy'])\n", | ||
"\n", | ||
" # Build and compile the generator\n", | ||
" self.generator = self.build_generator()\n", | ||
" self.generator.compile(loss='binary_crossentropy', optimizer=optimizer)\n", | ||
"\n", | ||
" # The generator takes noise as input and generated imgs\n", | ||
" z = Input(shape=(100,))\n", | ||
" img = self.generator(z)\n", | ||
"\n", | ||
" # For the combined model we will only train the generator\n", | ||
" self.discriminator.trainable = False\n", | ||
"\n", | ||
" # The valid takes generated images as input and determines validity\n", | ||
" valid = self.discriminator(img)\n", | ||
"\n", | ||
" # The combined model (stacked generator and discriminator) takes\n", | ||
" # noise as input => generates images => determines validity\n", | ||
" self.combined = Model(z, valid)\n", | ||
" self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)\n", | ||
"\n", | ||
" def build_generator(self):\n", | ||
"\n", | ||
" noise_shape = (100,)\n", | ||
"\n", | ||
" model = Sequential()\n", | ||
"\n", | ||
" model.add(Dense(128 * 7 * 7, activation=\"relu\", input_shape=noise_shape))\n", | ||
" model.add(Reshape((7, 7, 128)))\n", | ||
" model.add(BatchNormalization(momentum=0.8))\n", | ||
" model.add(UpSampling2D())\n", | ||
" model.add(Conv2D(128, kernel_size=3, padding=\"same\"))\n", | ||
" model.add(Activation(\"relu\"))\n", | ||
" model.add(BatchNormalization(momentum=0.8))\n", | ||
" model.add(UpSampling2D())\n", | ||
" model.add(Conv2D(64, kernel_size=3, padding=\"same\"))\n", | ||
" model.add(Activation(\"relu\"))\n", | ||
" model.add(BatchNormalization(momentum=0.8))\n", | ||
" model.add(Flatten())\n", | ||
" model.add(Dense(np.prod(self.img_shape), activation='tanh'))\n", | ||
" model.add(Reshape(self.img_shape))\n", | ||
"\n", | ||
" model.summary()\n", | ||
"\n", | ||
" noise = Input(shape=noise_shape)\n", | ||
" img = model(noise)\n", | ||
"\n", | ||
" return Model(noise, img)\n", | ||
"\n", | ||
" def build_discriminator(self):\n", | ||
"\n", | ||
" img_shape = (self.img_rows, self.img_cols, self.channels)\n", | ||
"\n", | ||
" model = Sequential()\n", | ||
"\n", | ||
" model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding=\"same\"))\n", | ||
" model.add(LeakyReLU(alpha=0.2))\n", | ||
" model.add(Dropout(0.25))\n", | ||
" model.add(Conv2D(64, kernel_size=3, strides=2, padding=\"same\"))\n", | ||
" model.add(ZeroPadding2D(padding=((0, 1), (0, 1))))\n", | ||
" model.add(LeakyReLU(alpha=0.2))\n", | ||
" model.add(Dropout(0.25))\n", | ||
" model.add(BatchNormalization(momentum=0.8))\n", | ||
" model.add(Conv2D(128, kernel_size=3, strides=2, padding=\"same\"))\n", | ||
" model.add(LeakyReLU(alpha=0.2))\n", | ||
" model.add(Dropout(0.25))\n", | ||
" model.add(BatchNormalization(momentum=0.8))\n", | ||
" model.add(Conv2D(256, kernel_size=3, strides=1, padding=\"same\"))\n", | ||
" model.add(LeakyReLU(alpha=0.2))\n", | ||
" model.add(Dropout(0.25))\n", | ||
"\n", | ||
" model.add(Flatten())\n", | ||
" model.add(Dense(1, activation='sigmoid'))\n", | ||
"\n", | ||
" model.summary()\n", | ||
"\n", | ||
" img = Input(shape=img_shape)\n", | ||
" validity = model(img)\n", | ||
"\n", | ||
" return Model(img, validity)\n", | ||
"\n", | ||
" def train(self, epochs, batch_size=128, save_interval=50):\n", | ||
"\n", | ||
" # Load the dataset\n", | ||
" #(X_train, _), (_, _) = mnist.load_data()\n", | ||
"\n", | ||
" # Rescale -1 to 1\n", | ||
" X_train = (X_train.astype(np.float32) - 127.5) / 127.5\n", | ||
" X_train = np.expand_dims(X_train, axis=3)\n", | ||
"\n", | ||
" half_batch = int(batch_size / 2)\n", | ||
"\n", | ||
" for epoch in range(epochs):\n", | ||
"\n", | ||
" # ---------------------\n", | ||
" # Train Discriminator\n", | ||
" # ---------------------\n", | ||
"\n", | ||
" # Select a random half batch of images\n", | ||
" idx = np.random.randint(0, X_train.shape[0], half_batch)\n", | ||
" imgs = X_train[idx]\n", | ||
"\n", | ||
" # Sample noise and generate a half batch of new images\n", | ||
" noise = np.random.normal(0, 1, (half_batch, 100))\n", | ||
" gen_imgs = self.generator.predict(noise)\n", | ||
"\n", | ||
" # Train the discriminator (real classified as ones and generated as zeros)\n", | ||
" d_loss_real = self.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))\n", | ||
" d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))\n", | ||
" d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)\n", | ||
"\n", | ||
" # ---------------------\n", | ||
" # Train Generator\n", | ||
" # ---------------------\n", | ||
"\n", | ||
" noise = np.random.normal(0, 1, (batch_size, 100))\n", | ||
"\n", | ||
" # Train the generator (wants discriminator to mistake images as real)\n", | ||
" g_loss = self.combined.train_on_batch(noise, np.ones((batch_size, 1)))\n", | ||
"\n", | ||
" # Plot the progress\n", | ||
" print(\"%d [D loss: %f, acc.: %.2f%%] [G loss: %f]\" % (epoch, d_loss[0], 100 * d_loss[1], g_loss))\n", | ||
"\n", | ||
" # If at save interval => save generated image samples\n", | ||
" if epoch % save_interval == 0:\n", | ||
" self.save_imgs(epoch)\n", | ||
"\n", | ||
" def save_imgs(self, epoch):\n", | ||
" r, c = 5, 5\n", | ||
" noise = np.random.normal(0, 1, (r * c, 100))\n", | ||
" gen_imgs = self.generator.predict(noise)\n", | ||
"\n", | ||
" # Rescale images 0 - 1\n", | ||
" gen_imgs = 0.5 * gen_imgs + 0.5\n", | ||
"\n", | ||
" fig, axs = plt.subplots(r, c)\n", | ||
" # fig.suptitle(\"DCGAN: Generated digits\", fontsize=12)\n", | ||
" cnt = 0\n", | ||
" for i in range(r):\n", | ||
" for j in range(c):\n", | ||
" axs[i,j].imshow(gen_imgs[cnt, :,:,:])\n", | ||
" axs[i, j].axis('off')\n", | ||
" cnt += 1\n", | ||
" fig.savefig(\"output/mnist_%d.png\" % epoch)\n", | ||
" plt.close()\n", | ||
" \n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"_________________________________________________________________\n", | ||
"Layer (type) Output Shape Param # \n", | ||
"=================================================================\n", | ||
"conv2d_1 (Conv2D) (None, 14, 14, 32) 896 \n", | ||
"_________________________________________________________________\n", | ||
"leaky_re_lu_1 (LeakyReLU) (None, 14, 14, 32) 0 \n", | ||
"_________________________________________________________________\n", | ||
"dropout_1 (Dropout) (None, 14, 14, 32) 0 \n", | ||
"_________________________________________________________________\n", | ||
"conv2d_2 (Conv2D) (None, 7, 7, 64) 18496 \n", | ||
"_________________________________________________________________\n", | ||
"zero_padding2d_1 (ZeroPaddin (None, 8, 8, 64) 0 \n", | ||
"_________________________________________________________________\n", | ||
"leaky_re_lu_2 (LeakyReLU) (None, 8, 8, 64) 0 \n", | ||
"_________________________________________________________________\n", | ||
"dropout_2 (Dropout) (None, 8, 8, 64) 0 \n", | ||
"_________________________________________________________________\n", | ||
"batch_normalization_1 (Batch (None, 8, 8, 64) 256 \n", | ||
"_________________________________________________________________\n", | ||
"conv2d_3 (Conv2D) (None, 4, 4, 128) 73856 \n", | ||
"_________________________________________________________________\n", | ||
"leaky_re_lu_3 (LeakyReLU) (None, 4, 4, 128) 0 \n", | ||
"_________________________________________________________________\n", | ||
"dropout_3 (Dropout) (None, 4, 4, 128) 0 \n", | ||
"_________________________________________________________________\n", | ||
"batch_normalization_2 (Batch (None, 4, 4, 128) 512 \n", | ||
"_________________________________________________________________\n", | ||
"conv2d_4 (Conv2D) (None, 4, 4, 256) 295168 \n", | ||
"_________________________________________________________________\n", | ||
"leaky_re_lu_4 (LeakyReLU) (None, 4, 4, 256) 0 \n", | ||
"_________________________________________________________________\n", | ||
"dropout_4 (Dropout) (None, 4, 4, 256) 0 \n", | ||
"_________________________________________________________________\n", | ||
"flatten_1 (Flatten) (None, 4096) 0 \n", | ||
"_________________________________________________________________\n", | ||
"dense_1 (Dense) (None, 1) 4097 \n", | ||
"=================================================================\n", | ||
"Total params: 393,281\n", | ||
"Trainable params: 392,897\n", | ||
"Non-trainable params: 384\n", | ||
"_________________________________________________________________\n", | ||
"_________________________________________________________________\n", | ||
"Layer (type) Output Shape Param # \n", | ||
"=================================================================\n", | ||
"dense_2 (Dense) (None, 6272) 633472 \n", | ||
"_________________________________________________________________\n", | ||
"reshape_1 (Reshape) (None, 7, 7, 128) 0 \n", | ||
"_________________________________________________________________\n", | ||
"batch_normalization_3 (Batch (None, 7, 7, 128) 512 \n", | ||
"_________________________________________________________________\n", | ||
"up_sampling2d_1 (UpSampling2 (None, 14, 14, 128) 0 \n", | ||
"_________________________________________________________________\n", | ||
"conv2d_5 (Conv2D) (None, 14, 14, 128) 147584 \n", | ||
"_________________________________________________________________\n", | ||
"activation_1 (Activation) (None, 14, 14, 128) 0 \n", | ||
"_________________________________________________________________\n", | ||
"batch_normalization_4 (Batch (None, 14, 14, 128) 512 \n", | ||
"_________________________________________________________________\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# Code from https://github.com/eriklindernoren/Keras-GAN/blob/master/dcgan/dcgan.py\n", | ||
"# pulled out of the file context to run here in the notebook\n", | ||
"dcgan = DCGAN()\n", | ||
"dcgan.train(epochs=2, batch_size=32, save_interval=1)\n", | ||
"\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.5.2" | ||
}, | ||
"widgets": { | ||
"state": {}, | ||
"version": "1.1.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.