{"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":"# Description\n\nWe recognize the works of artists through their unique style, such as color choices or brush strokes. The “je ne sais quoi” of artists like Claude Monet can now be imitated with algorithms thanks to generative adversarial networks (GANs). In this getting started competition, you will bring that style to your photos or recreate the style from scratch!\n\nComputer vision has advanced tremendously in recent years and GANs are now capable of mimicking objects in a very convincing way. But creating museum-worthy masterpieces is thought of to be, well, more art than science. So can (data) science, in the form of GANs, trick classifiers into believing you’ve created a true Monet? That’s the challenge you’ll take on!","metadata":{}},{"cell_type":"markdown","source":"# The Challenge:\nA GAN consists of at least two neural networks: a generator model and a discriminator model. The generator is a neural network that creates the images. For our competition, you should generate images in the style of Monet. This generator is trained using a discriminator.\n\nThe 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\nYour task is to build a GAN that generates 7,000 to 10,000 Monet-style images.","metadata":{}},{"cell_type":"markdown","source":"## Footnote:\nI am trying to learn data science and improve myself. You can specify the places you see missing. If you have any suggestions, you can comment. If you like my work, I would be very happy if you support me. Thank you.","metadata":{}},{"cell_type":"markdown","source":"<font color=\"blue\">\nContent:\n    \n1. [We should make the 'Accelerator' 'tpu' from the 'Setting' section](#1)\n2. [Let's load our datasets separately](#2)\n3. [These images are RGB images so set the channel to 3. Additionally, we need to scale the images to a [-1, 1] scale. We don't need the labels or the image id so we'll only return the image from the tfrecord](#3)\n4. [Extract the image](#4)\n5. [We have to load our datasets](#5)\n6. [Example](#6)\n7. [Building the generator](#7)\n8. [Building the discriminator](#8)\n9. [Our generators are not trained yet](#9)\n10. [Building the CycleGAN model](#10)\n11. [Define loss functions](#11)\n12. [Train the CycleGAN](#12)\n13. [Visualization](#13)\n14. [Creating](#14)\n ","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport tensorflow_addons as tfa\nfrom kaggle_datasets import KaggleDatasets as KD\nimport matplotlib.pyplot as plt\nimport numpy as np\ntry:\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)\nautoTone = tf.data.experimental.AUTOTUNE   \nprint(tf.__version__)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a> <hr>\n\n***We should make the 'Accelerator' 'tpu' from the 'Setting' section***","metadata":{}},{"cell_type":"code","source":"gcsPath = KD().get_gcs_path()","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:09.799143Z","iopub.execute_input":"2022-11-10T22:41:09.799892Z","iopub.status.idle":"2022-11-10T22:41:10.151795Z","shell.execute_reply.started":"2022-11-10T22:41:09.799847Z","shell.execute_reply":"2022-11-10T22:41:10.150716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"2\"></a> <hr>\n***Let's load our datasets separately***","metadata":{}},{"cell_type":"code","source":"photoFilenames = tf.io.gfile.glob(str(gcsPath + '/photo_tfrec/*.tfrec'))\nprint('Photo tfRecord Files:', len(photoFilenames))","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.154287Z","iopub.execute_input":"2022-11-10T22:41:10.154667Z","iopub.status.idle":"2022-11-10T22:41:10.217321Z","shell.execute_reply.started":"2022-11-10T22:41:10.154624Z","shell.execute_reply":"2022-11-10T22:41:10.216231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monetFilenames = tf.io.gfile.glob(str(gcsPath + '/monet_tfrec/*.tfrec'))\nprint('Monet tfRecord Files:', len(monetFilenames))","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.219222Z","iopub.execute_input":"2022-11-10T22:41:10.219543Z","iopub.status.idle":"2022-11-10T22:41:10.267565Z","shell.execute_reply.started":"2022-11-10T22:41:10.219512Z","shell.execute_reply":"2022-11-10T22:41:10.266693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"3\"></a> <hr>\n***These images are RGB images so set the channel to 3. Additionally, we need to scale the images to a [-1, 1] scale. We don't need the labels or the image id so we'll only return the image from the tfrecord***","metadata":{}},{"cell_type":"code","source":"imgSize = [256, 256]\n\ndef decode_image(img):\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = (tf.cast(img, tf.float32) / 127.5) - 1\n    img = tf.reshape(img, [*imgSize, 3])\n    return img\n\ndef read_tfrecord(exm):\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    exm = tf.io.parse_single_example(exm, tfrecord_format)\n    img = decode_image(exm['image'])\n    return img","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.268646Z","iopub.execute_input":"2022-11-10T22:41:10.269428Z","iopub.status.idle":"2022-11-10T22:41:10.276850Z","shell.execute_reply.started":"2022-11-10T22:41:10.269394Z","shell.execute_reply":"2022-11-10T22:41:10.276034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"4\"></a> <hr>\n***Extract the image***","metadata":{}},{"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=autoTone)\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.277878Z","iopub.execute_input":"2022-11-10T22:41:10.278098Z","iopub.status.idle":"2022-11-10T22:41:10.289754Z","shell.execute_reply.started":"2022-11-10T22:41:10.278074Z","shell.execute_reply":"2022-11-10T22:41:10.288870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"5\"></a> <hr>\n***We have to load our datasets***","metadata":{}},{"cell_type":"code","source":"monetDs = load_dataset(monetFilenames, labeled=True).batch(1)\nphotoDs = load_dataset(photoFilenames, labeled=True).batch(1)","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.291295Z","iopub.execute_input":"2022-11-10T22:41:10.291668Z","iopub.status.idle":"2022-11-10T22:41:10.482106Z","shell.execute_reply.started":"2022-11-10T22:41:10.291627Z","shell.execute_reply":"2022-11-10T22:41:10.481173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"exmMonet = next(iter(monetDs))\nexmPhoto = next(iter(photoDs))","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:10.483308Z","iopub.execute_input":"2022-11-10T22:41:10.483569Z","iopub.status.idle":"2022-11-10T22:41:11.430569Z","shell.execute_reply.started":"2022-11-10T22:41:10.483540Z","shell.execute_reply":"2022-11-10T22:41:11.429607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"6\"></a> <hr>\n***Example***","metadata":{}},{"cell_type":"code","source":"plt.subplot(121)\nplt.title('Photo')\nplt.imshow(exmPhoto[0] * 0.5 + 0.5)\n\nplt.subplot(122)\nplt.title('Monet')\nplt.imshow(exmMonet[0] * 0.5 + 0.5)","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:11.431771Z","iopub.execute_input":"2022-11-10T22:41:11.432015Z","iopub.status.idle":"2022-11-10T22:41:11.858523Z","shell.execute_reply.started":"2022-11-10T22:41:11.431987Z","shell.execute_reply":"2022-11-10T22:41:11.857777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"7\"></a> <hr>\n***Building the generator***","metadata":{}},{"cell_type":"code","source":"outputChannels = 3\n\ndef downsample(filters, size, apply_instancenorm=True):\n    initializer = tf.random_normal_initializer(0., 0.02)\n    gammaInit = 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=gammaInit))\n\n    result.add(layers.LeakyReLU())\n\n    return result","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:11.861174Z","iopub.execute_input":"2022-11-10T22:41:11.861797Z","iopub.status.idle":"2022-11-10T22:41:11.868177Z","shell.execute_reply.started":"2022-11-10T22:41:11.861763Z","shell.execute_reply":"2022-11-10T22:41:11.867187Z"},"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    gammaInit = 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=gammaInit))\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-11-10T22:41:11.869768Z","iopub.execute_input":"2022-11-10T22:41:11.870253Z","iopub.status.idle":"2022-11-10T22:41:11.881956Z","shell.execute_reply.started":"2022-11-10T22:41:11.870211Z","shell.execute_reply":"2022-11-10T22:41:11.880991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Generator():\n    inputs = layers.Input(shape=[256,256,3])\n    downStack = [\n        downsample(64, 4, apply_instancenorm=False),\n        downsample(128, 4), \n        downsample(256, 4), \n        downsample(512, 4), \n        downsample(512, 4), \n        downsample(512, 4), \n        downsample(512, 4), \n        downsample(512, 4), \n    ]\n\n    upStack = [\n        upsample(512, 4, apply_dropout=True), \n        upsample(512, 4, apply_dropout=True), \n        upsample(512, 4, apply_dropout=True), \n        upsample(512, 4), \n        upsample(256, 4),\n        upsample(128, 4), \n        upsample(64, 4), \n    ]\n\n    initializer = tf.random_normal_initializer(0., 0.02)\n    last = layers.Conv2DTranspose(outputChannels, 4,\n                                  strides=2,\n                                  padding='same',\n                                  kernel_initializer=initializer,\n                                  activation='tanh')\n\n    x = inputs\n    \n    skips = []\n    \n    for down in downStack:\n        x = down(x)\n        skips.append(x)\n\n    skips = reversed(skips[:-1])\n    for up, skip in zip(upStack, 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-11-10T22:41:11.883319Z","iopub.execute_input":"2022-11-10T22:41:11.884176Z","iopub.status.idle":"2022-11-10T22:41:11.896460Z","shell.execute_reply.started":"2022-11-10T22:41:11.884131Z","shell.execute_reply":"2022-11-10T22:41:11.895330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"8\"></a> <hr>\n***Building the discriminator***","metadata":{}},{"cell_type":"code","source":"def Discriminator():\n    initializer = tf.random_normal_initializer(0., 0.02)\n    gammaInit = 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) \n    down2 = downsample(128, 4)(down1)\n    down3 = downsample(256, 4)(down2)\n\n    zeroPad1 = layers.ZeroPadding2D()(down3) \n    conv = layers.Conv2D(512, 4, strides=1,\n                         kernel_initializer=initializer,\n                         use_bias=False)(zeroPad1) \n\n    norm1 = tfa.layers.InstanceNormalization(gamma_initializer=gammaInit)(conv)\n\n    leakyRelu = layers.LeakyReLU()(norm1)\n\n    zeroPad2 = layers.ZeroPadding2D()(leakyRelu) \n\n    last = layers.Conv2D(1, 4, strides=1,\n                         kernel_initializer=initializer)(zeroPad2) \n\n    return tf.keras.Model(inputs=inp, outputs=last)","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:11.897723Z","iopub.execute_input":"2022-11-10T22:41:11.898434Z","iopub.status.idle":"2022-11-10T22:41:11.914104Z","shell.execute_reply.started":"2022-11-10T22:41:11.898401Z","shell.execute_reply":"2022-11-10T22:41:11.912979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    monetGenerator = Generator() \n    photoGenerator = Generator() \n\n    monetDiscriminator = Discriminator() \n    photoDiscriminator = Discriminator()","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:11.915393Z","iopub.execute_input":"2022-11-10T22:41:11.915846Z","iopub.status.idle":"2022-11-10T22:41:21.825335Z","shell.execute_reply.started":"2022-11-10T22:41:11.915800Z","shell.execute_reply":"2022-11-10T22:41:21.824574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"9\"></a> <hr>\n***Our generators are not trained yet***","metadata":{}},{"cell_type":"code","source":"toMonet = monetGenerator(exmPhoto)\n\nplt.subplot(1, 2, 1)\nplt.title(\"Original Photo\")\nplt.imshow(exmPhoto[0] * 0.5 + 0.5)\n\nplt.subplot(1, 2, 2)\nplt.title(\"Monet-esque Photo\")\nplt.imshow(toMonet[0] * 0.5 + 0.5)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:21.826809Z","iopub.execute_input":"2022-11-10T22:41:21.827313Z","iopub.status.idle":"2022-11-10T22:41:22.476389Z","shell.execute_reply.started":"2022-11-10T22:41:21.827272Z","shell.execute_reply":"2022-11-10T22:41:22.475384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"10\"></a> <hr>\n***Building the CycleGAN model***","metadata":{}},{"cell_type":"code","source":"class CycleGan(keras.Model):\n    def __init__(\n        self,\n        monetGenerator,\n        photoGenerator,\n        monetDiscriminator,\n        photoDiscriminator,\n        lambda_cycle=10,\n    ):\n        super(CycleGan, self).__init__()\n        self.m_gen = monetGenerator\n        self.p_gen = photoGenerator\n        self.m_disc = monetDiscriminator\n        self.p_disc = photoDiscriminator\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        }\n","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:22.478196Z","iopub.execute_input":"2022-11-10T22:41:22.478516Z","iopub.status.idle":"2022-11-10T22:41:22.498025Z","shell.execute_reply.started":"2022-11-10T22:41:22.478479Z","shell.execute_reply":"2022-11-10T22:41:22.496793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"11\"></a> <hr>\n***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-11-10T22:41:22.499675Z","iopub.execute_input":"2022-11-10T22:41:22.500474Z","iopub.status.idle":"2022-11-10T22:41:22.515057Z","shell.execute_reply.started":"2022-11-10T22:41:22.500418Z","shell.execute_reply":"2022-11-10T22:41:22.513865Z"},"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-11-10T22:41:22.516531Z","iopub.execute_input":"2022-11-10T22:41:22.516874Z","iopub.status.idle":"2022-11-10T22:41:22.530608Z","shell.execute_reply.started":"2022-11-10T22:41:22.516837Z","shell.execute_reply":"2022-11-10T22:41:22.529354Z"},"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-11-10T22:41:22.532292Z","iopub.execute_input":"2022-11-10T22:41:22.532629Z","iopub.status.idle":"2022-11-10T22:41:22.541497Z","shell.execute_reply.started":"2022-11-10T22:41:22.532573Z","shell.execute_reply":"2022-11-10T22:41:22.540711Z"},"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-11-10T22:41:22.542857Z","iopub.execute_input":"2022-11-10T22:41:22.543236Z","iopub.status.idle":"2022-11-10T22:41:22.553141Z","shell.execute_reply.started":"2022-11-10T22:41:22.543198Z","shell.execute_reply":"2022-11-10T22:41:22.552220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"12\"></a> <hr>\n***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-11-10T22:41:22.554756Z","iopub.execute_input":"2022-11-10T22:41:22.555190Z","iopub.status.idle":"2022-11-10T22:41:22.565286Z","shell.execute_reply.started":"2022-11-10T22:41:22.555151Z","shell.execute_reply":"2022-11-10T22:41:22.564352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    cycle_gan_model = CycleGan(\n        monetGenerator, photoGenerator, monetDiscriminator, photoDiscriminator\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-11-10T22:41:22.566705Z","iopub.execute_input":"2022-11-10T22:41:22.567504Z","iopub.status.idle":"2022-11-10T22:41:22.638490Z","shell.execute_reply.started":"2022-11-10T22:41:22.567471Z","shell.execute_reply":"2022-11-10T22:41:22.637490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cycle_gan_model.fit(\n    tf.data.Dataset.zip((monetDs, photoDs)),\n    epochs=30\n)","metadata":{"execution":{"iopub.status.busy":"2022-11-10T22:41:22.640050Z","iopub.execute_input":"2022-11-10T22:41:22.640322Z","iopub.status.idle":"2022-11-10T23:02:22.131341Z","shell.execute_reply.started":"2022-11-10T22:41:22.640293Z","shell.execute_reply":"2022-11-10T23:02:22.130670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"13\"></a> <hr>\n***Visualization***","metadata":{}},{"cell_type":"code","source":"_, ax = plt.subplots(5, 2, figsize=(14, 14))\nfor i, img in enumerate(photoDs.take(5)):\n    prediction = monetGenerator(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-11-10T23:02:22.132752Z","iopub.execute_input":"2022-11-10T23:02:22.133184Z","iopub.status.idle":"2022-11-10T23:02:24.440002Z","shell.execute_reply.started":"2022-11-10T23:02:22.133154Z","shell.execute_reply":"2022-11-10T23:02:24.439033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"14\"></a> <hr>\n***Creating***","metadata":{}},{"cell_type":"code","source":"import PIL\n! mkdir ../images","metadata":{"execution":{"iopub.status.busy":"2022-11-10T23:02:24.441183Z","iopub.execute_input":"2022-11-10T23:02:24.441429Z","iopub.status.idle":"2022-11-10T23:02:25.551984Z","shell.execute_reply.started":"2022-11-10T23:02:24.441400Z","shell.execute_reply":"2022-11-10T23:02:25.550470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i = 1\nfor img in photoDs:\n    prediction = monetGenerator(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    i += 1","metadata":{},"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-11-10T23:33:35.720560Z","iopub.execute_input":"2022-11-10T23:33:35.720884Z","iopub.status.idle":"2022-11-10T23:33:39.366125Z","shell.execute_reply.started":"2022-11-10T23:33:35.720853Z","shell.execute_reply":"2022-11-10T23:33:39.365113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"15\"></a> <hr>\n<h1 style=\"color:green;\">Finish</h1>","metadata":{}}]}