{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# example of a dcgan on dogs\nfrom numpy import expand_dims\nfrom numpy import zeros\nfrom numpy import ones\nfrom numpy import vstack\nfrom numpy.random import randn\nfrom numpy.random import randint\nfrom keras.datasets.cifar10 import load_data\nfrom keras.optimizers import Adam\nfrom keras.models import Sequential\nfrom keras.layers import Dense\nfrom keras.layers import Reshape\nfrom keras.layers import Flatten\nfrom keras.layers import Conv2D\nfrom keras.layers import Conv2DTranspose\nfrom keras.layers import LeakyReLU\nfrom keras.layers import Dropout\nfrom keras.layers import BatchNormalization\nfrom matplotlib import pyplot\n\nimport os\nimport numpy as np\nfrom PIL import Image\nfrom tensorflow.keras.preprocessing.image import img_to_array, array_to_img\nimport xml.etree.ElementTree as et\nimport tensorflow as tf\nprint(tf.__version__)\nimport shutil\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"\n# Batch norm layers are recommended in both the discriminator and generator models, except the output of the generator\n# and input to the discriminator (from DCGAN paper). I found they don't work when momentum at default of 0.99, hence I\n# set to 0.8.\n\n# In GANs, the recommendation is to not use pooling layers, and instead use the stride. Already in brownlee implementation\n\n# define the standalone discriminator model\ndef define_discriminator(in_shape=(64,64,3)):\n    model = Sequential()\n    # normal\n    model.add(Conv2D(64, (3,3), padding='same', input_shape=in_shape))\n    model.add(LeakyReLU(alpha=0.2))\n    # downsample\n    model.add(Conv2D(128, (3,3), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # downsample\n    model.add(Conv2D(128, (3,3), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # downsample\n    model.add(Conv2D(256, (3,3), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # classifier\n    model.add(Flatten())\n    model.add(Dropout(0.4))\n    model.add(Dense(1, activation='sigmoid'))\n    # compile model\n    opt = Adam(lr=0.0002, beta_1=0.5)\n    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])\n    model.summary()\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# define the standalone generator model\ndef define_generator(latent_dim):\n    model = Sequential()\n    # foundation for 8x8 image\n    n_nodes = 256 * 8 * 8\n    model.add(Dense(n_nodes, input_dim=latent_dim))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    model.add(Reshape((8, 8, 256)))\n    # upsample to 16x16\n    model.add(Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # upsample to 32x32\n    model.add(Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # upsample to 64x64\n    model.add(Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))\n    # model.add(BatchNormalization(momentum=0.8))\n    model.add(LeakyReLU(alpha=0.2))\n    # output layer\n    model.add(Conv2D(3, (3,3), activation='tanh', padding='same'))\n    model.summary()\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# define the combined generator and discriminator model, for updating the generator\ndef define_gan(g_model, d_model):\n    # make weights in the discriminator not trainable\n    d_model.trainable = False\n    # connect them\n    model = Sequential()\n    # add generator\n    model.add(g_model)\n    # add the discriminator\n    model.add(d_model)\n    # compile model\n    opt = Adam(lr=0.0002, beta_1=0.5)\n    model.compile(loss='binary_crossentropy', optimizer=opt)\n    model.summary()\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_image(file, bounds):\n    image = open_image(file, bounds)\n    image = normalize_image(image)\n    return image\n\n\ndef open_image(file, bounds):\n    image = Image.open(file)\n    image = image.crop(bounds)\n    image = image.resize((64, 64))\n    return np.array(image)\n\n\n# Normalization, [-1,1] Range\ndef normalize_image(image):\n    image = np.asarray(image, np.float32)\n    image = image / 127.5 - 1\n    return img_to_array(image)\n\n# Restore, [0,255] Range\ndef denormalize_image(image):\n    return ((image+1)*127.5).astype(np.uint8)\n\n\ndef load_images():\n    images = []\n\n    for breed in os.listdir('../input/annotation/Annotation/'):\n        for dog in os.listdir('../input/annotation/Annotation/' + breed):\n            tree = et.parse('../input/annotation/Annotation/' + breed + '/' + dog)\n            root = tree.getroot()\n            objects = root.findall('object')\n            for o in objects:\n                box = o.find('bndbox')\n                xmin = int(box.find('xmin').text)\n                ymin = int(box.find('ymin').text)\n                xmax = int(box.find('xmax').text)\n                ymax = int(box.find('ymax').text)\n\n            bounds = (xmin, ymin, xmax, ymax)\n            try:\n                image = read_image('../input/all-dogs/all-dogs/' + dog + '.jpg', bounds)\n                images.append(image)\n            except:\n                print('No image', dog)\n\n    return np.array(images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# select real samples\ndef generate_real_samples(dataset, n_samples):\n    # choose random instances\n    ix = randint(0, dataset.shape[0], n_samples)\n    # retrieve selected images\n    X = dataset[ix]\n    # generate 'real' class labels (1)\n    y = ones((n_samples, 1))\n    return X, y\n\n# generate points in latent space as input for the generator\ndef generate_latent_points(latent_dim, n_samples):\n    # generate points in the latent space\n    x_input = randn(latent_dim * n_samples)\n    # reshape into a batch of inputs for the network\n    x_input = x_input.reshape(n_samples, latent_dim)\n    return x_input\n\n# use the generator to generate n fake examples, with class labels\ndef generate_fake_samples(g_model, latent_dim, n_samples):\n    # generate points in latent space\n    x_input = generate_latent_points(latent_dim, n_samples)\n    # predict outputs\n    X = g_model.predict(x_input)\n    # create 'fake' class labels (0)\n    y = zeros((n_samples, 1))\n    return X, y\n\n# create and save a plot of generated images\ndef save_plot(examples, epoch, n=7):\n    # scale from [-1,1] to [0,1]\n    examples = (examples + 1) / 2.0\n    # plot images\n    for i in range(n * n):\n        # define subplot\n        pyplot.subplot(n, n, 1 + i)\n        # turn off axis\n        pyplot.axis('off')\n        # plot raw pixel data\n        pyplot.imshow(examples[i])\n    # save plot to file\n    # filename = 'generated_plot_e%03d.png' % (epoch+1)\n    # pyplot.savefig(filename)\n    # pyplot.close()\n    pyplot.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# evaluate the discriminator, plot generated images, save generator model\ndef summarize_performance(epoch, g_model, d_model, dataset, latent_dim, n_samples=150):\n    # prepare real samples\n    X_real, y_real = generate_real_samples(dataset, n_samples)\n    # evaluate discriminator on real examples\n    _, acc_real = d_model.evaluate(X_real, y_real, verbose=0)\n    # prepare fake examples\n    x_fake, y_fake = generate_fake_samples(g_model, latent_dim, n_samples)\n    # evaluate discriminator on fake examples\n    _, acc_fake = d_model.evaluate(x_fake, y_fake, verbose=0)\n    # summarize discriminator performance\n    print('>Accuracy real: %.0f%%, fake: %.0f%%' % (acc_real*100, acc_fake*100))\n    # save plot\n    save_plot(x_fake, epoch)\n    # save the generator model tile file\n    # filename = 'generator_model_%03d.h5' % (epoch+1)\n    # g_model.save(filename)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train the generator and discriminator\ndef train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=500, n_batch=128):\n    bat_per_epo = int(dataset.shape[0] / n_batch)\n    half_batch = int(n_batch / 2)\n    # manually enumerate epochs\n    for i in range(n_epochs):\n        # enumerate batches over the training set\n        for j in range(bat_per_epo):\n            # get randomly selected 'real' samples\n            X_real, y_real = generate_real_samples(dataset, half_batch)\n            # update discriminator model weights\n            d_loss1, _ = d_model.train_on_batch(X_real, y_real)\n            # generate 'fake' examples\n            X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)\n            # update discriminator model weights\n            d_loss2, _ = d_model.train_on_batch(X_fake, y_fake)\n            # prepare points in latent space as input for the generator\n            X_gan = generate_latent_points(latent_dim, n_batch)\n            # create inverted labels for the fake samples\n            y_gan = ones((n_batch, 1))\n            # update the generator via the discriminator's error\n            g_loss = gan_model.train_on_batch(X_gan, y_gan)\n            # summarize loss on this batch\n            print('>%d, %d/%d, d1=%.3f, d2=%.3f g=%.3f' %\n                (i+1, j+1, bat_per_epo, d_loss1, d_loss2, g_loss))\n        # evaluate the model performance, sometimes\n        if (i+1) % 1 == 0:\n            summarize_performance(i, g_model, d_model, dataset, latent_dim)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# size of the latent space\nlatent_dim = 100\n# create the discriminator\nd_model = define_discriminator()\n# create the generator\ng_model = define_generator(latent_dim)\n# create the gan\ngan_model = define_gan(g_model, d_model)\n# load image data\n# dataset = load_real_samples()\ndataset = load_images()\n# train model\ntrain(g_model, d_model, gan_model, dataset, latent_dim)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Submission\ndef save_images(generator):\n    if not os.path.exists('../output'):\n        os.mkdir('../output')\n\n    latent_points = generate_latent_points(100, 10000)\n    generated_images = generator.predict(latent_points)\n\n    for i in range(generated_images.shape[0]):\n        image = denormalize_image(generated_images[i])\n        image = array_to_img(image)\n        image.save('../output/' + str(i) + '.png')\n\n    shutil.make_archive('images', 'zip', '../output')\n\n\nsave_images(g_model)","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":1}