{"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)\nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import save_img\nimport sklearn\nimport os,matplotlib\nimport time\nimport matplotlib.pyplot as plt\nfrom matplotlib.pylab import rc\nimport os\nimport h5py\nimport math\nimport os.path\nimport tensorflow as tf\nimport keras\nimport pickle\nimport pathlib\nimport random\nfrom tensorflow.keras import layers\ntf.enable_eager_execution()\ntf.VERSION\nAUTOTUNE = tf.data.experimental.AUTOTUNE\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# Give credit to the tensorflow website: https://www.tensorflow.org/beta/tutorials/generative/dcgan\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":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"data_root = pathlib.Path(\"../input/all-dogs/\")\nall_image_paths = list(data_root.glob(\"*/*\"))\nprint(\"Input pics number %d\"%len(all_image_paths))\nrandom.shuffle(all_image_paths)\nimage_count = len(all_image_paths)\n# read Annotation (later)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# read dog classes:\n# We don't need the name of the dog for now:\nclass_name_all = [str(i).split(\"_\")[0].split(\"/\")[-1] for i in all_image_paths]\nclass_name_unique = set(class_name_all)\nprint(len(class_name_unique),len(class_name_all))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Define some pre-processing of data\n# I want to use a resnet as an generator\nsize=224\n# The inout shape is 224*224*3\n# I will make a general version for this, for now I will fix that to 224*224 since it's the size of the Resnet in keras :)\n\n# latent dimension, which is the input shape from generator:\nlatent_dim = 100\ndef preprocess_image(image):\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = tf.image.resize_images(image, [size, size])\n    image /= 255.0  # normalize to [0,1] range\n    image = image*2-1  # normalize to [-1,1] range\n    return image\n\n\ndef load_and_preprocess_image(path):\n    image = tf.read_file(path)\n    return preprocess_image(image)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Image pre-processing:\n# We pre-define how to read image and how to pre-process data\nall_image_paths = [str(path) for path in all_image_paths]\npath_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)\n# load data:\nimage_ds = path_ds.map(load_and_preprocess_image)\n# use cache to boost up the speed [This is experimental feature and can use autotune in tf2.0]\n# disable cache if you do not have enough RAM\n#ds = image_ds.cache()\nds = image_ds\n\"\"\"\nds = ds.apply(\n  tf.data.experimental.shuffle_and_repeat(buffer_size=64))\n\n\"\"\"\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define generator: upsamepl until you reach size of the fig: 56-112-224\ndef Generator():\n    model = tf.keras.Sequential()\n    # The input shape should be the latent_dim,\n    \n    # Add 28*28*256 neurons for the first layer\n    model.add(layers.Dense(int(size/4)*int(size/4)*256, use_bias=False, input_shape=(latent_dim,)))\n    # Add batch normalization to avoid over fitting. You can also use dropout here:\n    model.add(layers.BatchNormalization())\n    # By default the leaky relu alpha=0.3, you can adjust it.\n    model.add(layers.LeakyReLU())\n\n    model.add(layers.Reshape((int(size/4),int(size/4), 256)))\n    # assert for debugging :)\n    \n    assert model.output_shape == (None, int(size/4),int(size/4), 256) # Note: None is the batch size\n    \n    # Add Transpose layer since we need to go from output to input\n    # Use (1,1) stride\n    # Here we use (5,5) filter size and 128 filters, use same padding to make sure the output is the same as input\n    model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))\n    assert model.output_shape == (None, int(size/4), int(size/4), 128)\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU())\n    \n    # continue to lower the resolution for the neural net work.This time set stride=2 \n\n    model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))\n    assert model.output_shape == (None, int(size/2), int(size/2), 64)\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU())\n    # same here, but only one filter and the return shape is the same as input\n    model.add(layers.Conv2DTranspose(3, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))\n    assert model.output_shape == (None, size, size, 3)\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# summary of the generator\ngenerator = Generator()\ngenerator.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check our generator:\n\n\n\n\n# batch size=3\nnoise = tf.random.normal([3,latent_dim])\ngenerated_image = generator(noise, training=False)\n\nplt.imshow(generated_image[0,:, :, 0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define discriminator:\n# A simple discriminator \n# Remember the output of the discriminator is a classifier: (True/Fake)\ndef discriminator():\n    model = tf.keras.Sequential()\n    # first layer should be a Dense layer: Shape is the same as the shape from generator\n    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same',\n                                     input_shape=[size, size, 3]))\n    # Use leaky relu as activation function to avoid \"always positive\" from relu \n    # default alpha=0.3\n    model.add(layers.LeakyReLU())\n    # default =0.5, here we use 0.3\n    model.add(layers.Dropout(0.3))\n\n    model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))\n    model.add(layers.LeakyReLU())\n    model.add(layers.Dropout(0.3))\n\n    model.add(layers.Flatten())\n    model.add(layers.Dense(1))\n\n    return model\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check our discriminator from the generated fake image\ndiscriminator = discriminator()\ndecision = discriminator(generated_image)\n# The values are different since it's from different random seed, and it means our model is correct :)\nprint (decision)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"discriminator.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Let's build our GAN !!\n\n# loss for discriminator: it's binary cross-entropy since we only need to tell yes or no:\n# set from_logits=True to avoid probability conversion :)\ncross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n\ndef discriminator_loss(real_output, fake_output):\n    # compare real_image_output \n    # Here 1 is real, so we compare \"real\" for real output\" to evaluate how well the discriminator can tell it's real\n    real_loss = cross_entropy(tf.ones_like(real_output), real_output)\n    # compare fake_image_output: Zero means false and vice versa\n    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)\n    # tot\n    total_loss = real_loss + fake_loss\n    return total_loss\n\n# generator loss:\n# Let's tell how well the generator can \"trick\" the discriminator\ndef generator_loss(fake_output):\n    return cross_entropy(tf.ones_like(fake_output), fake_output)\n\n\n# define optimizer for both the generator and discriminator: use adam\ngenerator_optimizer = tf.keras.optimizers.Adam(1e-4)\ndiscriminator_optimizer = tf.keras.optimizers.Adam(1e-4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check points:\ncheckpoint_dir = 'checkpoints_1.ckpt'\ncheckpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,\n                                 discriminator_optimizer=discriminator_optimizer,\n                                 generator=generator,\n                                 discriminator=discriminator)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# epochs and batch_size\nn_epochs = 25\nbatch_size=32\n\nnoise_dim = latent_dim\nds = ds.batch(batch_size=batch_size).prefetch(buffer_size=64)\nprint(\"Doing image batch\")\n#image_batch = next(iter(ds))\nN_step=int(image_count/batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train(image_batch):\n    # print(\"Doing %d epoch of %d epoch\" % (epoch, n_epochs))\n\n    # GradientTape: automatically calculate the gradient of a computation with respect to its input variables\n    # The generator start with noise\n    noise = tf.random.normal([batch_size, noise_dim])\n    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n        generated_images = generator(noise, training=True)\n\n        real_output = discriminator(image_batch, training=True)\n        fake_output = discriminator(generated_images, training=True)\n\n        gen_loss = generator_loss(fake_output)\n        disc_loss = discriminator_loss(real_output, fake_output)\n\n    # The gradient\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    # optimize the gradient\n    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))\n    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))\n    \n    return gen_loss,disc_loss\n        \n\n\n\n\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Start training\")\n## Let's train it:\n\nfor epoch in range(n_epochs):\n    print(\"Doing %d of %d epoch\"%(epoch,n_epochs))\n    start = time.time()\n    count=0\n    for i in iter(ds):\n        \n        gen_loss,disc_loss=train(i)\n    \n        if count%50==0:\n            print(\"%d of %d step\"%(count,N_step))\n            print(\"Generator loss=%.2f Discriminator loss=%.2f\"%(gen_loss,disc_loss))\n        \n        count+=1\n\n    #save:\n\n\nprint(\"Finish training!\")\n#checkpoint_prefix = \"toy.ckpt\"\n#checkpoint.save(file_prefix = checkpoint_prefix)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Done\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# predict\nn_test=10000\nbatch_test = 100\ncount=0\nos.system(\"mkdir %s\"%(\"images_out\"))\nfor i in range(n_test//batch_test):\n    print(\"Doing %d of %d\"%(batch_test*i,n_test))\n    noise = tf.random.normal([batch_test,latent_dim])\n    generated_images_i = generator(noise, training=False)\n    image_temp = tf.image.resize_images(generated_images_i, [64, 64])\n    # save image:\n    for j in range(batch_test):\n        save_img(\"images_out/\"+'{}.JPEG'.format(count), tf.image.resize_images(generated_images_i[j,:,:,:], [64,64]))\n        count+=1\n        \n    \n    \n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# restore\n\n# restored_model = checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nbatch_test = 100\nos.system(\"mkdir -p %s\"%(\"images\"))\nnoise = tf.random.normal([batch_test,latent_dim])\ngenerated_images_i = generator(noise, training=False)\ngenerated_images_i = tf.image.resize_images(generated_images_i, [64,64])\nsave_img(\"images\"+'t1.JPEG', generated_images_i[0,:,:,:])\n\nimage = tf.read_file('t1.JPEG')\nimage = tf.image.decode_jpeg(image, channels=3)\n\n\"\"\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\nshutil.make_archive('images', 'zip', 'images_out')\n# os.system(\"rm -r images\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.system(\"rm -r images_out\")\nprint(\"All finished\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{"trusted":true},"cell_type":"code","source":"ls","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}