{"cells":[{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"from __future__ import absolute_import, division, print_function, unicode_literals\nimport tensorflow.compat.v1 as tf\ntf.disable_v2_behavior() # ml framework\ntf.enable_eager_execution() # operations are executed immediately as they are called from Python\nimport numpy as np # linear algebra\nimport warnings\nfrom PIL import Image # image processing library\nimport IPython.display as display # for inspecting the images by displaying them in the kernel\nimport random # for the random seed used as input for the generator\nfrom numpy.random import choice\nimport matplotlib.pyplot as plt, zipfile # plotting library\nimport xml.etree.ElementTree as ET # xml parser used during pre-processing stage\nimport time # time the execution of codeblocks\nimport xml.dom.minidom # for printing the annotation xml nicely\nimport pydot\nimport graphviz\nfrom IPython.display import FileLink, FileLinks\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os, glob # for managing files/directories\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!unzip '../input/generative-dog-images/Annotation.zip'\n!unzip '../input/generative-dog-images/all-dogs.zip'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGES = os.listdir('./all-dogs')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGES","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"breeds=os.listdir('./Annotation')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"breeds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BUFFER_SIZE = 20000\nBATCH_SIZE = 32\nWEIGHT_INIT = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.2)\ndim = 64\nEPOCHS = 166\nnoise_dim = 100\nnum_examples_to_generate = 16\nseed = tf.random.normal([num_examples_to_generate, noise_dim])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"idxIn = 0; namesIn = []\nimagesIn = np.zeros((25000,64,64,3))\n\n# CROP WITH BOUNDING BOXES TO GET DOGS ONLY\n# iterate through each directory in annotation\nfor breed in breeds:\n    #print(breed)\n    # iterate through each file in the directory\n    for dog in os.listdir('./Annotation/'+breed):\n        try: img = Image.open('./all-dogs/'+dog+'.jpg') \n        except: continue           \n        # Element Tree library allows for parsing xml and getting specific tag values    \n        tree = ET.parse('./Annotation/'+breed+'/'+dog)\n        # take a look at the print out of an xml previously to get what is going on\n        root = tree.getroot() # <annotation>\n        objects = root.findall('object') # <object>\n        for o in objects:\n            bndbox = o.find('bndbox') # <bndbox>\n            xmin = int(bndbox.find('xmin').text) # <xmin>\n            ymin = int(bndbox.find('ymin').text) # <ymin>\n            xmax = int(bndbox.find('xmax').text) # <xmax>\n            ymax = int(bndbox.find('ymax').text) # <ymax>\n            w = np.min((xmax - xmin, ymax - ymin))\n            img2 = img.crop((xmin, ymin, xmin+w, ymin+w))\n            img2 = img2.resize((64,64), Image.ANTIALIAS)\n            imagesIn[idxIn,:,:,:] = np.asarray(img2)\n            #print(\"hello\")\n            namesIn.append(breed)\n            idxIn += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"idxIn","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"imagesIn is a {} with {} {} by {} rgb({}) images. Shape: {}\".format(type(imagesIn), \n                                                                           imagesIn.shape[0], \n                                                                           imagesIn.shape[1], imagesIn.shape[2],\n                                                                           imagesIn.shape[3], imagesIn.shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x = np.random.randint(0,idxIn,25)\n\nfor k in range(5):\n    plt.figure(figsize=(15,3))\n    for j in range(5):\n        plt.subplot(1,5,j+1)\n        img = Image.fromarray( imagesIn[x[k*5+j],:,:,:].astype('uint8') )\n        plt.axis('off')\n        plt.title(namesIn[x[k*5+j]].split('-')[1],fontsize=11)\n        plt.imshow(img)\n    plt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imagesIn = (imagesIn[:idxIn,:,:,:]-127.5)/127.5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(8,8))\nfor image in range(4):\n    plt.subplot(2,2, image+1)\n    plt.imshow((imagesIn[image]))\n    plt.xlabel('shape: {}'.format(imagesIn[image].shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imagesIn = tf.cast(imagesIn, 'float32')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds = tf.data.Dataset.from_tensor_slices(imagesIn).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)\nprint(ds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_generator():\n    model = tf.keras.Sequential(\n        [\n            # first layer with 32,768 nodes expecting an input of vector size 100 (random noise)\n            tf.keras.layers.Dense(8*8*512, use_bias=False, input_shape=(100,)),\n            # Normalize the activations of the previous layer at each batch\n            tf.keras.layers.BatchNormalization(),\n            # apply leaky relu activation: f(x) = {x if x > 0 : 0.01*x}\n            tf.keras.layers.LeakyReLU(),\n            # reshape input to (8,8,512)\n            tf.keras.layers.Reshape((8, 8, 512)),\n            \n            # second layer Conv2DTranspose so it is doing the opposite of a convolutional layer\n            tf.keras.layers.Conv2DTranspose(256, (5,5), strides=(2,2), padding='same', use_bias=False,\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n            tf.keras.layers.Dropout(0.3),\n            \n            tf.keras.layers.Conv2DTranspose(128, (5,5), strides=(2,2), padding='same', use_bias=False,\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n            tf.keras.layers.Dropout(0.3),\n            \n            tf.keras.layers.Conv2DTranspose(64, (5,5), strides=(2,2), padding='same', use_bias=False,\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n            \n            tf.keras.layers.Dense(3,activation='tanh', use_bias=False,\\\n                kernel_initializer=WEIGHT_INIT)\n        ]\n    )\n    return model\n# create an instance of the generator model defined\ngenerator = make_generator()\nprint(generator.summary())\ntf.keras.utils.plot_model(\n    generator,\n    to_file='/tmp/gen_mdl.png',\n    show_shapes=True,\n    show_layer_names=True,\n    rankdir='TB',\n)\n# random noise vector\nnoise = tf.random.normal([1,100])\n# run the generator model with the noise vector as input\ngenerated_image = generator(noise, training=False)\n# display output\nplt.imshow(generated_image[0, :, :, :])\nprint(generated_image.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_discriminator():\n    model = tf.keras.Sequential(\n        [\n            tf.keras.layers.Conv2D(64, (4,4), strides=(2,2), padding='same', input_shape=[dim,dim,3],\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n#             tf.keras.layers.Dropout(0.25),\n            \n            tf.keras.layers.Conv2D(128, (4,4), strides=(2,2), padding='same',\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n#             tf.keras.layers.Dropout(0.25),\n            \n            tf.keras.layers.Conv2D(256, (4,4), strides=(2,2), padding='same',\\\n                kernel_initializer=WEIGHT_INIT),\n            tf.keras.layers.BatchNormalization(),\n            tf.keras.layers.LeakyReLU(),\n#             tf.keras.layers.Dropout(0.25),\n            \n            # flatten input into 1-D and output a single a number from the last layer using sigmoid activation\n            tf.keras.layers.Flatten(),\n            tf.keras.layers.Dense(1, activation='sigmoid')\n        ]\n    )\n    return model\n\ndiscriminator = make_discriminator()\ntf.keras.utils.plot_model(\n    generator,\n    to_file='/tmp/dis_mdl.png',\n    show_shapes=True,\n    show_layer_names=True,\n    rankdir='TB',\n)\nprint(discriminator.summary())\ndecision = discriminator(generated_image)\nprint (decision)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def smooth_positive_labels(y):\n    return y - 0.3 + (np.random.random(y.shape) * 0.3)\n\ndef smooth_negative_labels(y):\n    return y + np.random.random(y.shape) * 0.5\n\n# Recomended to introduce some noise to the labels, so out of 1000 real labels, approximately 50 should be flipped to 0 (5%)\n# randomly flip some labels\ndef noisy_labels(y, p_flip):\n    # determine the number of labels to flip\n    n_select = int(p_flip * y.shape[0].value)\n    # choose labels to flip\n    flip_ix = choice([i for i in range(y.shape[0].value)], size=n_select)\n    # invert the labels in place\n    y[flip_ix] = 1 - y[flip_ix]\n    return y\n# This method returns a helper function to compute cross entropy loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def discriminator_loss(real_output, fake_output):\n    # tf.ones_like changes all values in the tensor to 1s\n    # similarly tf.zeros_like changes all values in the tensor to 0\n    # then apply label smoothing\n    real_output_smooth = smooth_positive_labels(tf.ones_like(real_output))\n#     real_output_noisy = noisy_labels(real_output_smooth, 0.05)\n    fake_output_smooth = smooth_negative_labels(tf.zeros_like(fake_output))\n#     fake_output_noisy = noisy_labels(fake_output_smooth, 0.05)\n    real_loss = cross_entropy(real_output_smooth, real_output)\n    fake_loss = cross_entropy(fake_output_smooth, fake_output)\n    total_loss = real_loss + fake_loss\n    return total_loss\n\n# The Generator loss function\n\ndef generator_loss(fake_output):\n    fake_output_smooth = smooth_negative_labels(tf.ones_like(fake_output))\n#     fake_output_noisy = noisy_labels(fake_output_smooth, 0.05)\n    return cross_entropy(fake_output_smooth, fake_output)\n\n# optimizers -- Adam\ngenerator_optimizer = tf.train.AdamOptimizer(learning_rate=0.0002, beta1=0.5)\ndiscriminator_optimizer = tf.train.AdamOptimizer(learning_rate=0.0002, beta1=0.5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_step(images, G_loss_list, D_loss_list):\n    noise = tf.random.normal([BATCH_SIZE, noise_dim])\n    \n    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n        # the following are the operations recorded onto the \"tape\"\n        generated_images = generator(noise, training=True)\n        \n        real_output = discriminator(images, training=True)\n        fake_output = discriminator(generated_images, training=True)\n        gen_loss = generator_loss(fake_output)\n        disc_loss = discriminator_loss(real_output, fake_output)\n        \n    G_loss_list.append(gen_loss.numpy())\n    D_loss_list.append(disc_loss.numpy())\n    # the following lines are taking the derivatives and applying gradients using Adam optimizer\n    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)\n    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)\n    \n    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))\n    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train(dataset, epochs):\n    G_loss = []\n    D_loss = []\n    for epoch in range(epochs):\n        start = time.time()\n        for image_batch in dataset:\n            train_step(image_batch, G_loss, D_loss)\n            \n        plot_loss(G_loss, D_loss, epoch)\n        G_loss = []\n        D_loss = []\n        if (epoch % 10 == 0):\n            display.clear_output(wait=True)\n            generate_and_save_images(generator,\n                                 epoch + 1,\n                                 seed)\n        print ('Time for epoch {} is {} sec'.format(epoch + 1, time.time()-start))\n        \n            \n    # Generate after the final epoch\n    print(\"Final Epoch\")\n    generate_and_save_images(generator,\n                           epochs,\n                           seed)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import time\ndef generate_and_save_images(model, epoch, test_input):\n    # Notice `training` is set to False.\n    # This is so all layers run in inference mode (batchnorm).\n    predictions = model(test_input, training=False)    \n    fig = plt.figure(figsize=(8,8))\n    for i in range(predictions.shape[0]):\n        plt.subplot(4, 4, i+1)\n        plt.imshow((predictions[i, :, :, :]+1.)/2.)\n        plt.axis('off')\n#     plt.savefig('image_at_epoch_{}.png'.format(epoch+1))\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_loss (G_losses, D_losses, epoch):\n    plt.figure(figsize=(10,5))\n    plt.title(\"Generator and Discriminator Loss - EPOCH {}\".format(epoch+1))\n    plt.plot(G_losses,label=\"G\")\n    plt.plot(D_losses,label=\"D\")\n    plt.xlabel(\"iterations\")\n    plt.ylabel(\"Loss\")\n    plt.legend()\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\nprint('Starting training')\ntrain(ds, EPOCHS)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n# SAVE TO ZIP FILE NAMED IMAGES.ZIP\nz = zipfile.PyZipFile('images.zip', mode='w')\n\nfilename = 'model.h5'\ntf.keras.models.save_model(\n    generator,\n    filename,\n    overwrite=True,\n    include_optimizer=True,\n    save_format=None\n)\n\nfor k in range(10000):\n    generated_image = generator(tf.random.normal([1, noise_dim]), training=False)\n    f = str(k)+'.png'\n    img = ((generated_image[0,:,:,:]+1.)/2.).numpy()\n    tf.keras.preprocessing.image.save_img(\n        f,\n        img,\n        scale=True\n    )\n    z.write(f); os.remove(f)\nz.close()\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir('./')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}