{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport xml.etree.ElementTree as ET # for parsing XML\nimport matplotlib\nimport matplotlib.pyplot as plt # to show images\nfrom PIL import Image # to read images\nimport glob\nfrom tqdm import tqdm\nimport random\nimport imageio\nfrom scipy import stats\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 keras\nimport keras.backend as K\nfrom keras import Sequential, Model, regularizers\nfrom keras.layers import Conv2D, Conv2DTranspose, Dense, UpSampling2D, Input, Lambda, Concatenate\nfrom keras.initializers import RandomNormal\nfrom keras.optimizers import Adam\nfrom keras.activations import relu, tanh\nfrom keras.layers import PReLU, LeakyReLU, BatchNormalization, Reshape, Flatten, Dropout, Activation\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.losses import binary_crossentropy\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#defining file paths\nimage_path = '../input/all-dogs/all-dogs'\nannot_path = '../input/annotation/Annotation/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#getting all files\nannot = glob.glob(f'{annot_path}/*/*')\nimages = glob.glob(f'{image_path}/*.jpg')\nprint(len(images),len(annot))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#loades bounding box data from XML files \ndef get_bounding_box(annot):\n    tree = ET.parse(annot)\n    root = tree.getroot()\n    objects = root.findall('object')\n    for o in objects:\n        bndbox = o.find('bndbox') # reading bound box\n        xmin = int(bndbox.find('xmin').text)\n        ymin = int(bndbox.find('ymin').text)\n        xmax = int(bndbox.find('xmax').text)\n        ymax = int(bndbox.find('ymax').text)\n        \n    return (xmin,ymin,xmax,ymax)\n\nbounding_box = {}\nfor i in tqdm(annot):\n    img = i.split('/')[-1]\n    bounding_box[img] = get_bounding_box(i)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#crops images using bounding box\ndef crop_image(img, box):\n    im=Image.open(img)\n    im=im.crop(box)\n    return im","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#looking at random cropped image\nimg_path = random.choice(images)\nimg = img_path.split('/')[-1].split('.')[0]\nimg = crop_image(img_path, bounding_box[img])\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#process images\ndef process_image(img, box):\n    im = crop_image(img, box)\n    im = im.resize((64,64))\n    im = np.array(im)\n    im = (im.astype('float')-127.5)/127.5\n    return im","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#loading and processing all images\nall_images = []\nfor img_path in images:\n    img = img_path.split('/')[-1].split('.')[0]\n    img = process_image(img_path, bounding_box[img])\n    all_images.append(img)\nall_images = np.array(all_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def generator_model():\n    init = RandomNormal(mean=0.0, stddev=0.02)\n    z = Input(shape=(4*4*64,))\n    h = Reshape((4, 4, 64))(z)\n    #out: (4,4,1024)\n    h = Conv2DTranspose(1024, kernel_size=(4,4), strides=(1,1), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    h = PReLU()(h)\n    h = Dropout(0.3)(h)\n    #out: (8,8,512)\n    h = Conv2DTranspose(512, kernel_size=(4,4), strides=(2,2), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    h = PReLU()(h)\n    h = Dropout(0.3)(h)\n    #out: (16,16,256)\n    h = Conv2DTranspose(256, kernel_size=(4,4), strides=(2,2), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    h = PReLU()(h)\n    h = Dropout(0.3)(h)\n    #out: (32,32,128)\n    h = Conv2DTranspose(128, kernel_size=(4,4), strides=(2,2), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    h = PReLU()(h)\n    h = Dropout(0.3)(h)\n    #out: (64,64,64)\n    h = Conv2DTranspose(64, kernel_size=(4,4), strides=(2,2), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    h = PReLU()(h)\n    h = Dropout(0.3)(h)\n    #out: (64,64,3)\n    h = Conv2DTranspose(3, kernel_size=(4,4), strides=(1,1), padding='same', kernel_initializer=init, use_bias=False)(h)\n    h = BatchNormalization(momentum=0.1)(h)\n    x = Activation('tanh')(h)\n    model = Model(z,x, name='Generator')\n    return model\n\ndef discriminator_model():\n    init = RandomNormal(mean=0.0, stddev=0.02)\n    x = Input(shape=(64,64,3))\n    #out: (32,32,64)\n    h = Conv2D(64, (4, 4), strides=(2, 2), padding='same', kernel_initializer=init)(x)\n    h = BatchNormalization()(h)\n    h = LeakyReLU(0.2)(h)\n    h = Dropout(0.4)(h)\n    #out: (16,16,32)\n    h = Conv2D(32, (4, 4), strides=(2, 2), padding='same', kernel_initializer=init)(h)\n    h = BatchNormalization()(h)\n    h = LeakyReLU(0.2)(h)\n    h = Dropout(0.4)(h)\n    #out: (16,16,8)\n    h = Conv2D(8, (4, 4), strides=(2, 2), padding='same', kernel_initializer=init)(h)\n    h = BatchNormalization()(h)\n    h = LeakyReLU(0.2)(h)\n    h = Dropout(0.4)(h)\n    \n    h = Flatten()(h)\n    y = Dense(1, activation='sigmoid')(h)\n    model = Model(x,y,name='Discriminator')\n    return model\n\ndef build_gan(generator, discriminator):\n    model = Sequential()\n    # Combined Generator -> Discriminator model\n    model.add(generator)\n    model.add(discriminator)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"disc_opt = Adam()\ndiscriminator = discriminator_model()\ndiscriminator.compile(loss='binary_crossentropy',\n                      optimizer=disc_opt,\n                      metrics=['accuracy'])\n\n# Build the Generator\ngenerator = generator_model()\ndiscriminator.trainable = False\n\n# Build and compile GAN model with fixed Discriminator to train the Generator\ngan = build_gan(generator, discriminator)\ngan.compile(loss='binary_crossentropy', optimizer=Adam())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"gan.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# generate noisy labels\ndef noisy_labels(y):\n    flip_idx = np.random.choice([i for i in range(y.shape[0])], size=int(y.shape[0]*0.05))\n    y[flip_idx] = 1-y[flip_idx]\n    return y\n\n#prints a sample generated image\ndef sample_image(generator):\n    z = np.random.normal(0, 1, (9, 1024))\n    gen_imgs = generator.predict(z)\n    gen_imgs = (gen_imgs + 1)/2\n    return gen_imgs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 16\ny_real = np.zeros((batch_size, 1))\ny_fake = np.ones((batch_size, 1))\naug = ImageDataGenerator()\naug = ImageDataGenerator(\n    rotation_range=30,\n    horizontal_flip=True,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    fill_mode=\"nearest\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#model training\nlosses = []\naccuracies = []\niteration_checkpoints = []\niterations = 100000\nsample_interval = 5000\n\nfor iteration in range(iterations):\n        \n        # random batch of real images\n        idx = np.random.randint(0, all_images.shape[0], batch_size)\n        imgs = all_images[idx]\n        \n        # data augmentation\n        aug_images = []\n        for X_batch, y_batch in aug.flow(imgs, y_real, batch_size=batch_size, shuffle=True):\n            aug_images.append(X_batch)\n            break\n        aug_images = np.array(aug_images)\n        aug_images = aug_images.reshape([batch_size,64,64,3])\n\n        # label smoothing\n        y_real_smooth = (y_real+0.2)-(np.random.random(y_real.shape)*0.2)\n        y_fake_smooth = (y_fake-0.2)+(np.random.random(y_fake.shape)*0.3)\n        \n        # noisy labels\n        y_real_noisy = noisy_labels(y_real_smooth)\n        y_fake_noisy = noisy_labels(y_fake_smooth)\n        \n        # generate batch of fake images\n        z = np.random.normal(0, 1, (batch_size, 1024))\n        gen_imgs = generator.predict(z)\n\n        # train Discriminator\n        discriminator.trainable=True\n        d_loss_real = discriminator.train_on_batch(aug_images, y_real_noisy)\n        d_loss_fake = discriminator.train_on_batch(gen_imgs, y_fake_noisy)\n        d_loss, accuracy = 0.5 * np.add(d_loss_real, d_loss_fake)\n\n        z = np.random.normal(0, 1, (batch_size, 1024))\n        \n        # train Generator\n        discriminator.trainable=False\n        g_loss = gan.train_on_batch(z, y_real)\n        \n        if (iteration + 1) % sample_interval == 0:\n\n            # Save losses and accuracies so they can be plotted after training\n            losses.append((d_loss, g_loss))\n            accuracies.append(100.0 * accuracy)\n            iteration_checkpoints.append(iteration + 1)\n\n            # Output training progress\n            print(\"%d [D loss: %f, acc.: %.2f%%] [G loss: %f]\" %\n                  (iteration + 1, d_loss, 100.0 * accuracy, g_loss))\n\n            # Output a sample of generated image\n            imgs = sample_image(generator)\n            fig = plt.figure(figsize=(4,4))\n            for i in range(1,10):\n                fig.add_subplot(3,3,i)\n                plt.imshow(imgs[i-1])\n            plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not os.path.exists('../output_images'):\n    os.mkdir('../output_images')\nim_batch_size = 1\nn_images=10000\nfor i_batch in range(0, n_images, im_batch_size):\n    z = stats.truncnorm.rvs(-1,1,size=(im_batch_size, 1024))\n    gen_imgs = generator.predict(z)\n    gen_imgs = 0.5 * gen_imgs + 0.5\n    for i_image in range(gen_imgs.shape[0]):\n        imageio.imwrite(os.path.join('../output_images', f'image_{i_batch+i_image:05d}.png'), gen_imgs[i_image])\n    idx = np.random.randint(0, all_images.shape[0], 4)\n    imgs = all_images[idx]\n    y_real = np.zeros((4,1))\n    y_fake = np.ones((4,1))\n    discriminator.trainable = True\n    discriminator.train_on_batch(imgs, y_real)\n    z = np.random.normal(0, 1, (4, 1024))\n    gen_imgs = generator.predict(z)\n    discriminator.train_on_batch(gen_imgs, y_fake)\n    discriminator.trainable = False\n    z = np.random.normal(0, 1, (4, 1024))\n    gan.train_on_batch(z, y_real)\n\nimport shutil\nshutil.make_archive('images', 'zip', '../output_images')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}