{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Introduction\n\n## 1. Problem Statement\n\nTo build a GAN that generates 7,000 to 10,000 Monet-style images.\n\n## 2. Architectures\n\n### 2.1 GAN\n\n<img src=\"https://developers.google.com/machine-learning/gan/images/gan_diagram.svg\" alt=\"drawing\" width=\"800\"/>\n\nA **GAN** consists of at least two neural networks: a **generator model** and a **discriminator model**. \n\n\"**Generative**\" describes a class of statistical models that contrasts with **discriminative models**.\n\nInformally:\n\n* Generative models can generate new data instances.\n* Discriminative models discriminate between different kinds of data instances.\n\n\n### 2.2 Solving Photo-Monet problem with GANs\n\nWhat if generator learned to produce output that is independent of input? Only one output is being produced no matter what input you give?\n\nThis problem is known as **Mode Collapse**\n\n\n### 2.3 CycleGAN\n\n<img src=\"https://hardikbansal.github.io/CycleGANBlog/images/model.jpg\" alt=\"drawing\" width=\"800\"/>\n<img src=\"https://hardikbansal.github.io/CycleGANBlog/images/model1.jpg\" alt=\"drawing\" width=\"800\"/>\n\n<div align=\"center\">CycleGAN Architecture</div>\n\nSome features of CycleGAN:\n* CycleGAN have two Generators and two discriminators\n* GeneratorA2B and GeneratorB2A are in some sense inverse of each other\n* **Identity mapping** - If GeneratorA2B gets a zebra as input, than it should not do anything (same goes for GeneratorB2A)\n* There will be many more loss functions - 4\n    * **Cycle-consistency loss** is defined by summation of loss between Input_A<->Cyclic_A and between Input_B<->Cyclic_B\n\n### 1.2 The Project\n\nIn this project, the generator is a neural network that creates the images. We should generate images in the style of Monet. This generator is trained using a discriminator. The two models will work against each other, with the generator trying to trick the discriminator, and the discriminator trying to accurately classify the real vs. generated images.\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"## 2 Submission File\n\n* We are going to generate 7,000-10,000 Monet-style images that are in jpg format. Their sizes should be 256x256x3 (RGB). Then we need to zip those images and our output from our Kernel should only have ONE output file named images.zip.\n\n* The submission file must be named images.zip, containing a zip file of 7,000-10,000 images sized 256x256.\n\n# Data\n\nThe dataset contains four directories: \n    <code>monet_tfrec<\\code>\n    <code>photo_tfrec<\\code>\n    <code>monet_jpg<\\code>\n    <code>photo_jpg<\\code>\n        \nThe monet_tfrec and monet_jpg directories contain the same painting images, and the photo_tfrec and photo_jpg irectories contain the same photos.\n\nThe **monet** directories contain Monet paintings. Use these images to train your model.\n\nThe **photo** directories contain photos. Add Monet-style to these images and submit your generated jpeg images as a zip file. Other photos outside of this dataset can be transformed but keep your submission file limited to 10,000 images.\n\nNote: *Monet-style art can be created from scratch using other GAN architectures like DCGAN. The submitted image files do not necessarily have to be transformed photos.*\n        \n\n","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport tensorflow_addons as tfa\n\nfrom kaggle_datasets import KaggleDatasets\nimport matplotlib.pyplot as plt\nimport numpy as np","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Device:', tpu.master())\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nexcept:\n    strategy = tf.distribute.get_strategy()\nprint('Number of replicas:', strategy.num_replicas_in_sync)\n\nAUTOTUNE = tf.data.experimental.AUTOTUNE\n    \nprint(tf.__version__)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:44.195284Z","iopub.execute_input":"2022-04-13T05:12:44.195843Z","iopub.status.idle":"2022-04-13T05:12:50.128349Z","shell.execute_reply.started":"2022-04-13T05:12:44.195808Z","shell.execute_reply":"2022-04-13T05:12:50.127859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load in the data","metadata":{}},{"cell_type":"code","source":"GCS_PATH = KaggleDatasets().get_gcs_path()","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:50.129157Z","iopub.execute_input":"2022-04-13T05:12:50.129361Z","iopub.status.idle":"2022-04-13T05:12:50.722654Z","shell.execute_reply.started":"2022-04-13T05:12:50.129336Z","shell.execute_reply":"2022-04-13T05:12:50.721919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MONET_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/monet_tfrec/*.tfrec'))\nprint('Monet TFRecord Files:', len(MONET_FILENAMES))\n\nPHOTO_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/photo_tfrec/*.tfrec'))\nprint('Photo TFRecord Files:', len(PHOTO_FILENAMES))","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:50.725372Z","iopub.execute_input":"2022-04-13T05:12:50.725811Z","iopub.status.idle":"2022-04-13T05:12:50.891793Z","shell.execute_reply.started":"2022-04-13T05:12:50.725767Z","shell.execute_reply":"2022-04-13T05:12:50.890945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMAGE_SIZE = [256, 256]\n\ndef decode_image(image):\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = (tf.cast(image, tf.float32) / 127.5) - 1\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    return image\n\ndef read_tfrecord(example):\n    tfrecord_format = {\n        \"image_name\": tf.io.FixedLenFeature([], tf.string),\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"target\": tf.io.FixedLenFeature([], tf.string)\n    }\n    example = tf.io.parse_single_example(example, tfrecord_format)\n    image = decode_image(example['image'])\n    return image","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:50.893237Z","iopub.execute_input":"2022-04-13T05:12:50.893542Z","iopub.status.idle":"2022-04-13T05:12:50.902044Z","shell.execute_reply.started":"2022-04-13T05:12:50.893504Z","shell.execute_reply":"2022-04-13T05:12:50.901396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dataset(filenames, labeled=True, ordered=False):\n    dataset = tf.data.TFRecordDataset(filenames)\n    dataset = dataset.map(read_tfrecord, num_parallel_calls=AUTOTUNE)\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:50.903483Z","iopub.execute_input":"2022-04-13T05:12:50.903788Z","iopub.status.idle":"2022-04-13T05:12:50.911624Z","shell.execute_reply.started":"2022-04-13T05:12:50.903761Z","shell.execute_reply":"2022-04-13T05:12:50.911002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_ds = load_dataset(MONET_FILENAMES, labeled=True).batch(1)\nphoto_ds = load_dataset(PHOTO_FILENAMES, labeled=True).batch(1)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:50.913108Z","iopub.execute_input":"2022-04-13T05:12:50.913378Z","iopub.status.idle":"2022-04-13T05:12:51.096958Z","shell.execute_reply.started":"2022-04-13T05:12:50.91334Z","shell.execute_reply":"2022-04-13T05:12:51.096062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_monet = next(iter(monet_ds))\nexample_photo = next(iter(photo_ds))","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:51.098322Z","iopub.execute_input":"2022-04-13T05:12:51.098632Z","iopub.status.idle":"2022-04-13T05:12:52.307433Z","shell.execute_reply.started":"2022-04-13T05:12:51.098591Z","shell.execute_reply":"2022-04-13T05:12:52.306745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.subplot(121)\nplt.title('Photo')\nplt.imshow(example_photo[0] * 0.5 + 0.5)\n\nplt.subplot(122)\nplt.title('Monet')\nplt.imshow(example_monet[0] * 0.5 + 0.5)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.308477Z","iopub.execute_input":"2022-04-13T05:12:52.308799Z","iopub.status.idle":"2022-04-13T05:12:52.718486Z","shell.execute_reply.started":"2022-04-13T05:12:52.308774Z","shell.execute_reply":"2022-04-13T05:12:52.717808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build the generator","metadata":{}},{"cell_type":"code","source":"OUTPUT_CHANNELS = 3\n\ndef downsample(filters, size, apply_instancenorm=True):\n    initializer = tf.random_normal_initializer(0., 0.02)\n    gamma_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n\n    result = keras.Sequential()\n    result.add(layers.Conv2D(filters, size, strides=2, padding='same',\n                             kernel_initializer=initializer, use_bias=False))\n\n    if apply_instancenorm:\n        result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n\n    result.add(layers.LeakyReLU())\n\n    return result","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.72084Z","iopub.execute_input":"2022-04-13T05:12:52.721202Z","iopub.status.idle":"2022-04-13T05:12:52.727955Z","shell.execute_reply.started":"2022-04-13T05:12:52.721173Z","shell.execute_reply":"2022-04-13T05:12:52.72705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upsample(filters, size, apply_dropout=False):\n    initializer = tf.random_normal_initializer(0., 0.02)\n    gamma_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n\n    result = keras.Sequential()\n    result.add(layers.Conv2DTranspose(filters, size, strides=2,\n                                      padding='same',\n                                      kernel_initializer=initializer,\n                                      use_bias=False))\n\n    result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n\n    if apply_dropout:\n        result.add(layers.Dropout(0.5))\n\n    result.add(layers.ReLU())\n\n    return result","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.729308Z","iopub.execute_input":"2022-04-13T05:12:52.729521Z","iopub.status.idle":"2022-04-13T05:12:52.741046Z","shell.execute_reply.started":"2022-04-13T05:12:52.729498Z","shell.execute_reply":"2022-04-13T05:12:52.740235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Generator():\n    inputs = layers.Input(shape=[256,256,3])\n\n    # bs = batch size\n    down_stack = [\n        downsample(64, 4, apply_instancenorm=False), # (bs, 128, 128, 64)\n        downsample(128, 4), # (bs, 64, 64, 128)\n        downsample(256, 4), # (bs, 32, 32, 256)\n        downsample(512, 4), # (bs, 16, 16, 512)\n        downsample(512, 4), # (bs, 8, 8, 512)\n        downsample(512, 4), # (bs, 4, 4, 512)\n        downsample(512, 4), # (bs, 2, 2, 512)\n        downsample(512, 4), # (bs, 1, 1, 512)\n    ]\n\n    up_stack = [\n        upsample(512, 4, apply_dropout=True), # (bs, 2, 2, 1024)\n        upsample(512, 4, apply_dropout=True), # (bs, 4, 4, 1024)\n        upsample(512, 4, apply_dropout=True), # (bs, 8, 8, 1024)\n        upsample(512, 4), # (bs, 16, 16, 1024)\n        upsample(256, 4), # (bs, 32, 32, 512)\n        upsample(128, 4), # (bs, 64, 64, 256)\n        upsample(64, 4), # (bs, 128, 128, 128)\n    ]\n\n    initializer = tf.random_normal_initializer(0., 0.02)\n    last = layers.Conv2DTranspose(OUTPUT_CHANNELS, 4,\n                                  strides=2,\n                                  padding='same',\n                                  kernel_initializer=initializer,\n                                  activation='tanh') # (bs, 256, 256, 3)\n\n    x = inputs\n\n    # Downsampling through the model\n    skips = []\n    for down in down_stack:\n        x = down(x)\n        skips.append(x)\n\n    skips = reversed(skips[:-1])\n\n    # Upsampling and establishing the skip connections\n    for up, skip in zip(up_stack, skips):\n        x = up(x)\n        x = layers.Concatenate()([x, skip])\n\n    x = last(x)\n\n    return keras.Model(inputs=inputs, outputs=x)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.742323Z","iopub.execute_input":"2022-04-13T05:12:52.742931Z","iopub.status.idle":"2022-04-13T05:12:52.755157Z","shell.execute_reply.started":"2022-04-13T05:12:52.742887Z","shell.execute_reply":"2022-04-13T05:12:52.754246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build the discriminator","metadata":{}},{"cell_type":"code","source":"def Discriminator():\n    initializer = tf.random_normal_initializer(0., 0.02)\n    gamma_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n\n    inp = layers.Input(shape=[256, 256, 3], name='input_image')\n\n    x = inp\n\n    down1 = downsample(64, 4, False)(x) # (bs, 128, 128, 64)\n    down2 = downsample(128, 4)(down1) # (bs, 64, 64, 128)\n    down3 = downsample(256, 4)(down2) # (bs, 32, 32, 256)\n\n    zero_pad1 = layers.ZeroPadding2D()(down3) # (bs, 34, 34, 256)\n    conv = layers.Conv2D(512, 4, strides=1,\n                         kernel_initializer=initializer,\n                         use_bias=False)(zero_pad1) # (bs, 31, 31, 512)\n\n    norm1 = tfa.layers.InstanceNormalization(gamma_initializer=gamma_init)(conv)\n\n    leaky_relu = layers.LeakyReLU()(norm1)\n\n    zero_pad2 = layers.ZeroPadding2D()(leaky_relu) # (bs, 33, 33, 512)\n\n    last = layers.Conv2D(1, 4, strides=1,\n                         kernel_initializer=initializer)(zero_pad2) # (bs, 30, 30, 1)\n\n    return tf.keras.Model(inputs=inp, outputs=last)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.756541Z","iopub.execute_input":"2022-04-13T05:12:52.757327Z","iopub.status.idle":"2022-04-13T05:12:52.772617Z","shell.execute_reply.started":"2022-04-13T05:12:52.75728Z","shell.execute_reply":"2022-04-13T05:12:52.77196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    monet_generator = Generator() # transforms photos to Monet-esque paintings\n    photo_generator = Generator() # transforms Monet paintings to be more like photos\n\n    monet_discriminator = Discriminator() # differentiates real Monet paintings and generated Monet paintings\n    photo_discriminator = Discriminator() # differentiates real photos and generated photos","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:12:52.773778Z","iopub.execute_input":"2022-04-13T05:12:52.774509Z","iopub.status.idle":"2022-04-13T05:13:02.426672Z","shell.execute_reply.started":"2022-04-13T05:12:52.774477Z","shell.execute_reply":"2022-04-13T05:13:02.425938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"to_monet = monet_generator(example_photo)\n\nplt.subplot(1, 2, 1)\nplt.title(\"Original Photo\")\nplt.imshow(example_photo[0] * 0.5 + 0.5)\n\nplt.subplot(1, 2, 2)\nplt.title(\"Monet-esque Photo\")\nplt.imshow(to_monet[0] * 0.5 + 0.5)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:02.427783Z","iopub.execute_input":"2022-04-13T05:13:02.428016Z","iopub.status.idle":"2022-04-13T05:13:03.082395Z","shell.execute_reply.started":"2022-04-13T05:13:02.427991Z","shell.execute_reply":"2022-04-13T05:13:03.081568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build the cycleGAN model","metadata":{}},{"cell_type":"code","source":"class CycleGan(keras.Model):\n    def __init__(\n        self,\n        monet_generator,\n        photo_generator,\n        monet_discriminator,\n        photo_discriminator,\n        lambda_cycle=10,\n    ):\n        super(CycleGan, self).__init__()\n        self.m_gen = monet_generator\n        self.p_gen = photo_generator\n        self.m_disc = monet_discriminator\n        self.p_disc = photo_discriminator\n        self.lambda_cycle = lambda_cycle\n        \n    def compile(\n        self,\n        m_gen_optimizer,\n        p_gen_optimizer,\n        m_disc_optimizer,\n        p_disc_optimizer,\n        gen_loss_fn,\n        disc_loss_fn,\n        cycle_loss_fn,\n        identity_loss_fn\n    ):\n        super(CycleGan, self).compile()\n        self.m_gen_optimizer = m_gen_optimizer\n        self.p_gen_optimizer = p_gen_optimizer\n        self.m_disc_optimizer = m_disc_optimizer\n        self.p_disc_optimizer = p_disc_optimizer\n        self.gen_loss_fn = gen_loss_fn\n        self.disc_loss_fn = disc_loss_fn\n        self.cycle_loss_fn = cycle_loss_fn\n        self.identity_loss_fn = identity_loss_fn\n        \n    def train_step(self, batch_data):\n        real_monet, real_photo = batch_data\n        \n        with tf.GradientTape(persistent=True) as tape:\n            # photo to monet back to photo\n            fake_monet = self.m_gen(real_photo, training=True)\n            cycled_photo = self.p_gen(fake_monet, training=True)\n\n            # monet to photo back to monet\n            fake_photo = self.p_gen(real_monet, training=True)\n            cycled_monet = self.m_gen(fake_photo, training=True)\n\n            # generating itself\n            same_monet = self.m_gen(real_monet, training=True)\n            same_photo = self.p_gen(real_photo, training=True)\n\n            # discriminator used to check, inputing real images\n            disc_real_monet = self.m_disc(real_monet, training=True)\n            disc_real_photo = self.p_disc(real_photo, training=True)\n\n            # discriminator used to check, inputing fake images\n            disc_fake_monet = self.m_disc(fake_monet, training=True)\n            disc_fake_photo = self.p_disc(fake_photo, training=True)\n\n            # evaluates generator loss\n            monet_gen_loss = self.gen_loss_fn(disc_fake_monet)\n            photo_gen_loss = self.gen_loss_fn(disc_fake_photo)\n\n            # evaluates total cycle consistency loss\n            total_cycle_loss = self.cycle_loss_fn(real_monet, cycled_monet, self.lambda_cycle) + self.cycle_loss_fn(real_photo, cycled_photo, self.lambda_cycle)\n\n            # evaluates total generator loss\n            total_monet_gen_loss = monet_gen_loss + total_cycle_loss + self.identity_loss_fn(real_monet, same_monet, self.lambda_cycle)\n            total_photo_gen_loss = photo_gen_loss + total_cycle_loss + self.identity_loss_fn(real_photo, same_photo, self.lambda_cycle)\n\n            # evaluates discriminator loss\n            monet_disc_loss = self.disc_loss_fn(disc_real_monet, disc_fake_monet)\n            photo_disc_loss = self.disc_loss_fn(disc_real_photo, disc_fake_photo)\n\n        # Calculate the gradients for generator and discriminator\n        monet_generator_gradients = tape.gradient(total_monet_gen_loss,\n                                                  self.m_gen.trainable_variables)\n        photo_generator_gradients = tape.gradient(total_photo_gen_loss,\n                                                  self.p_gen.trainable_variables)\n\n        monet_discriminator_gradients = tape.gradient(monet_disc_loss,\n                                                      self.m_disc.trainable_variables)\n        photo_discriminator_gradients = tape.gradient(photo_disc_loss,\n                                                      self.p_disc.trainable_variables)\n\n        # Apply the gradients to the optimizer\n        self.m_gen_optimizer.apply_gradients(zip(monet_generator_gradients,\n                                                 self.m_gen.trainable_variables))\n\n        self.p_gen_optimizer.apply_gradients(zip(photo_generator_gradients,\n                                                 self.p_gen.trainable_variables))\n\n        self.m_disc_optimizer.apply_gradients(zip(monet_discriminator_gradients,\n                                                  self.m_disc.trainable_variables))\n\n        self.p_disc_optimizer.apply_gradients(zip(photo_discriminator_gradients,\n                                                  self.p_disc.trainable_variables))\n        \n        return {\n            \"monet_gen_loss\": total_monet_gen_loss,\n            \"photo_gen_loss\": total_photo_gen_loss,\n            \"monet_disc_loss\": monet_disc_loss,\n            \"photo_disc_loss\": photo_disc_loss\n        }","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.083757Z","iopub.execute_input":"2022-04-13T05:13:03.083996Z","iopub.status.idle":"2022-04-13T05:13:03.104185Z","shell.execute_reply.started":"2022-04-13T05:13:03.083969Z","shell.execute_reply":"2022-04-13T05:13:03.103249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Define loss functions","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n    def discriminator_loss(real, generated):\n        real_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.ones_like(real), real)\n\n        generated_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.zeros_like(generated), generated)\n\n        total_disc_loss = real_loss + generated_loss\n\n        return total_disc_loss * 0.5","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.105325Z","iopub.execute_input":"2022-04-13T05:13:03.105988Z","iopub.status.idle":"2022-04-13T05:13:03.121561Z","shell.execute_reply.started":"2022-04-13T05:13:03.105951Z","shell.execute_reply":"2022-04-13T05:13:03.120474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def generator_loss(generated):\n        return tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.ones_like(generated), generated)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.123023Z","iopub.execute_input":"2022-04-13T05:13:03.123264Z","iopub.status.idle":"2022-04-13T05:13:03.133963Z","shell.execute_reply.started":"2022-04-13T05:13:03.123235Z","shell.execute_reply":"2022-04-13T05:13:03.132946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def calc_cycle_loss(real_image, cycled_image, LAMBDA):\n        loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))\n\n        return LAMBDA * loss1","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.135416Z","iopub.execute_input":"2022-04-13T05:13:03.135634Z","iopub.status.idle":"2022-04-13T05:13:03.146522Z","shell.execute_reply.started":"2022-04-13T05:13:03.135609Z","shell.execute_reply":"2022-04-13T05:13:03.145551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def identity_loss(real_image, same_image, LAMBDA):\n        loss = tf.reduce_mean(tf.abs(real_image - same_image))\n        return LAMBDA * 0.5 * loss","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.148141Z","iopub.execute_input":"2022-04-13T05:13:03.148442Z","iopub.status.idle":"2022-04-13T05:13:03.159241Z","shell.execute_reply.started":"2022-04-13T05:13:03.148402Z","shell.execute_reply":"2022-04-13T05:13:03.158354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train the cycleGAN","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n    monet_generator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n    photo_generator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n\n    monet_discriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n    photo_discriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.160509Z","iopub.execute_input":"2022-04-13T05:13:03.160764Z","iopub.status.idle":"2022-04-13T05:13:03.173971Z","shell.execute_reply.started":"2022-04-13T05:13:03.160736Z","shell.execute_reply":"2022-04-13T05:13:03.172785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    cycle_gan_model = CycleGan(\n        monet_generator, photo_generator, monet_discriminator, photo_discriminator\n    )\n\n    cycle_gan_model.compile(\n        m_gen_optimizer = monet_generator_optimizer,\n        p_gen_optimizer = photo_generator_optimizer,\n        m_disc_optimizer = monet_discriminator_optimizer,\n        p_disc_optimizer = photo_discriminator_optimizer,\n        gen_loss_fn = generator_loss,\n        disc_loss_fn = discriminator_loss,\n        cycle_loss_fn = calc_cycle_loss,\n        identity_loss_fn = identity_loss\n    )","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.1754Z","iopub.execute_input":"2022-04-13T05:13:03.175658Z","iopub.status.idle":"2022-04-13T05:13:03.238366Z","shell.execute_reply.started":"2022-04-13T05:13:03.175629Z","shell.execute_reply":"2022-04-13T05:13:03.23757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cycle_gan_model.fit(\n    tf.data.Dataset.zip((monet_ds, photo_ds)),\n    epochs=50\n)","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:13:03.23962Z","iopub.execute_input":"2022-04-13T05:13:03.239971Z","iopub.status.idle":"2022-04-13T05:46:20.3804Z","shell.execute_reply.started":"2022-04-13T05:13:03.239939Z","shell.execute_reply":"2022-04-13T05:46:20.379332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize our Monet-esque photos","metadata":{}},{"cell_type":"code","source":"_, ax = plt.subplots(5, 2, figsize=(12, 12))\nfor i, img in enumerate(photo_ds.take(5)):\n    prediction = monet_generator(img, training=False)[0].numpy()\n    prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n    img = (img[0] * 127.5 + 127.5).numpy().astype(np.uint8)\n\n    ax[i, 0].imshow(img)\n    ax[i, 1].imshow(prediction)\n    ax[i, 0].set_title(\"Input Photo\")\n    ax[i, 1].set_title(\"Monet-esque\")\n    ax[i, 0].axis(\"off\")\n    ax[i, 1].axis(\"off\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:46:20.381892Z","iopub.execute_input":"2022-04-13T05:46:20.382227Z","iopub.status.idle":"2022-04-13T05:46:22.592676Z","shell.execute_reply.started":"2022-04-13T05:46:20.382186Z","shell.execute_reply":"2022-04-13T05:46:22.592018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create submission file","metadata":{}},{"cell_type":"code","source":"import PIL\n! mkdir ../images","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:46:22.593639Z","iopub.execute_input":"2022-04-13T05:46:22.594124Z","iopub.status.idle":"2022-04-13T05:46:23.399729Z","shell.execute_reply.started":"2022-04-13T05:46:22.594083Z","shell.execute_reply":"2022-04-13T05:46:23.398529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i = 1\nfor img in photo_ds:\n    prediction = monet_generator(img, training=False)[0].numpy()\n    prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n    im = PIL.Image.fromarray(prediction)\n    im.save(\"../images/\" + str(i) + \".jpg\")\n    print(i)\n    i += 1","metadata":{"execution":{"iopub.status.busy":"2022-04-13T05:46:23.401566Z","iopub.execute_input":"2022-04-13T05:46:23.401957Z","iopub.status.idle":"2022-04-13T06:20:49.575134Z","shell.execute_reply.started":"2022-04-13T05:46:23.401909Z","shell.execute_reply":"2022-04-13T06:20:49.573936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")","metadata":{"execution":{"iopub.status.busy":"2022-04-13T06:20:49.57645Z","iopub.execute_input":"2022-04-13T06:20:49.576664Z","iopub.status.idle":"2022-04-13T06:20:53.350485Z","shell.execute_reply.started":"2022-04-13T06:20:49.576639Z","shell.execute_reply":"2022-04-13T06:20:53.349669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i","metadata":{"execution":{"iopub.status.busy":"2022-04-13T06:20:53.354344Z","iopub.execute_input":"2022-04-13T06:20:53.354608Z","iopub.status.idle":"2022-04-13T06:20:53.362852Z","shell.execute_reply.started":"2022-04-13T06:20:53.354579Z","shell.execute_reply":"2022-04-13T06:20:53.361988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}