{"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":"code","source":"import os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"_kg_hide-input":true,"scrolled":true,"execution":{"iopub.status.busy":"2023-03-09T20:18:28.105867Z","iopub.execute_input":"2023-03-09T20:18:28.107061Z","iopub.status.idle":"2023-03-09T20:18:31.874657Z","shell.execute_reply.started":"2023-03-09T20:18:28.107014Z","shell.execute_reply":"2023-03-09T20:18:31.871586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Setup TPU-ra","metadata":{}},{"cell_type":"code","source":"!pip install tensorflow-addons","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:29.137546Z","iopub.execute_input":"2023-03-09T19:51:29.137852Z","iopub.status.idle":"2023-03-09T19:51:32.757442Z","shell.execute_reply.started":"2023-03-09T19:51:29.137826Z","shell.execute_reply":"2023-03-09T19:51:32.756390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport tensorflow_addons as tfa\nfrom kaggle_datasets import KaggleDatasets\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n\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)\n\nPARALLEL = tf.data.experimental.AUTOTUNE\n    \nprint(tf.__version__)","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:32.759098Z","iopub.execute_input":"2023-03-09T19:51:32.759440Z","iopub.status.idle":"2023-03-09T19:51:32.768282Z","shell.execute_reply.started":"2023-03-09T19:51:32.759409Z","shell.execute_reply":"2023-03-09T19:51:32.767552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Adatok betöltése","metadata":{}},{"cell_type":"code","source":"GCS_PATH = KaggleDatasets().get_gcs_path()\n\nMONET_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":"2023-03-09T19:51:32.770458Z","iopub.execute_input":"2023-03-09T19:51:32.770759Z","iopub.status.idle":"2023-03-09T19:51:33.267890Z","shell.execute_reply.started":"2023-03-09T19:51:32.770732Z","shell.execute_reply":"2023-03-09T19:51:33.267096Z"},"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=PARALLEL)\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:33.268922Z","iopub.execute_input":"2023-03-09T19:51:33.269345Z","iopub.status.idle":"2023-03-09T19:51:33.274025Z","shell.execute_reply.started":"2023-03-09T19:51:33.269317Z","shell.execute_reply":"2023-03-09T19:51:33.273309Z"},"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) # rgb\n    image = (tf.cast(image, tf.float32) / 127.5) -1 # [-1, 1] rangebe teszi\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    return image\n\ndef read_tfrecord(example):\n    #megadja milyen formátumban kérünk be a tfrecord-ból\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":"2023-03-09T19:51:33.275118Z","iopub.execute_input":"2023-03-09T19:51:33.275413Z","iopub.status.idle":"2023-03-09T19:51:33.285959Z","shell.execute_reply.started":"2023-03-09T19:51:33.275387Z","shell.execute_reply":"2023-03-09T19:51:33.285178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_ds = load_dataset(MONET_FILENAMES).batch(1)\nphoto_ds = load_dataset(PHOTO_FILENAMES).batch(1)","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:33.287129Z","iopub.execute_input":"2023-03-09T19:51:33.287416Z","iopub.status.idle":"2023-03-09T19:51:33.548587Z","shell.execute_reply.started":"2023-03-09T19:51:33.287390Z","shell.execute_reply":"2023-03-09T19:51:33.547436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Gyors kirajzolás","metadata":{}},{"cell_type":"code","source":"example_monet = next(iter(monet_ds))\nexample_photo = next(iter(photo_ds))\n\nplt.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":"2023-03-09T19:51:33.550176Z","iopub.execute_input":"2023-03-09T19:51:33.550527Z","iopub.status.idle":"2023-03-09T19:51:35.295710Z","shell.execute_reply.started":"2023-03-09T19:51:33.550497Z","shell.execute_reply":"2023-03-09T19:51:35.294653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Generátor része a dolgoknak\n\nAmit használunk az a UNET architektúra, itt a kép átmegy először egy folyamaton (encoder), ahol a kép információit tömörítjük, majd a kiterjesztő (decoder) részben a tömörített információt visszafejtjük, hogy előállítsuk a bemenetnek megfelelő kimenetet.\n\nIgazából nem törénik sok csak átmegy a képen oda meg vissza egy Conv2D layer plusz még pár secondary dolog.","metadata":{}},{"cell_type":"code","source":"def downsample(filters, size, apply_instancenorm=True):\n    init = 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(\n        filters, \n        size, \n        strides=2, \n        padding='same',\n        kernel_initializer = init,\n        use_bias = False))\n    if apply_instancenorm:\n        result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n    result.add(layers.LeakyReLU())\n    return result","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:35.297050Z","iopub.execute_input":"2023-03-09T19:51:35.297364Z","iopub.status.idle":"2023-03-09T19:51:35.304557Z","shell.execute_reply.started":"2023-03-09T19:51:35.297338Z","shell.execute_reply":"2023-03-09T19:51:35.303551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upsample(filters, size, apply_dropout=False):\n    init = 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(\n        filters,\n        size,\n        strides=2,\n        padding='same',\n        kernel_initializer=init,\n        use_bias=False))\n    result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n    if apply_dropout:\n        result.add(layers.Dropout(0.4))\n    result.add(layers.ReLU())\n    return result","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:35.307587Z","iopub.execute_input":"2023-03-09T19:51:35.307882Z","iopub.status.idle":"2023-03-09T19:51:35.317232Z","shell.execute_reply.started":"2023-03-09T19:51:35.307855Z","shell.execute_reply":"2023-03-09T19:51:35.316211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Generator():\n    \n    inputs = layers.Input(shape=[256, 256, 3])\n    \n    #elvileg ha értékes infot akarunk kinyerni a képből ennyiszer el kell végezzük \n    downsample_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    #és ugyanúgy visszafele is\n    upsample_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    init = tf.random_normal_initializer(0., 0.02)\n    last_layer = layers.Conv2DTranspose(\n        3, # rgb\n        4, # ?\n        strides=2,\n        padding='same',\n        kernel_initializer = init,\n        activation = 'tanh'\n    )\n    \n    x = inputs\n    \n    #kb lementtjük, majd összerakjuk később a dekódolásnál kapott értékkel\n    #és ez elvileg jó\n    skips = []\n    \n    #encode\n    for down in downsample_stack:\n        x = down(x)\n        skips.append(x)\n        \n    skips = reversed(skips[:-1]) #visszafordítjuk, hogy kijöjjenek a shape-ek\n       \n    #decode\n    for up, skip in zip(upsample_stack, skips):\n        x = up(x)\n        x = layers.Concatenate()([x, skip])\n        \n    #utsó layer még\n    x = last_layer(x)\n    \n    return keras.Model(inputs = inputs, outputs = x)\n    ","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:35.318362Z","iopub.execute_input":"2023-03-09T19:51:35.318650Z","iopub.status.idle":"2023-03-09T19:51:35.337480Z","shell.execute_reply.started":"2023-03-09T19:51:35.318623Z","shell.execute_reply":"2023-03-09T19:51:35.336484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# És most a diszkriminátor\n\nEz kap majd képeket bemenetként és meg kell mondania róluk, hogy valódi vagy pedig generált képek.","metadata":{}},{"cell_type":"code","source":"def Discriminator():\n    init = tf.random_normal_initializer(0., 0.02)\n    gamma_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n    \n    inputs = layers.Input(shape=[256, 256, 3], name = 'input_image')\n    \n    x = inputs\n    x = downsample(64, 4)(x)\n    x = downsample(128, 4)(x)\n    x = downsample(256, 4)(x)\n    x = layers.ZeroPadding2D()(x)\n    x = layers.Conv2D(512, 4, strides=1, kernel_initializer=init, use_bias=False)(x)\n    x = tfa.layers.InstanceNormalization(gamma_initializer = gamma_init)(x)\n    x = layers.LeakyReLU()(x)\n    x = layers.ZeroPadding2D()(x)\n    x = layers.Conv2D(1, 4, strides=1, kernel_initializer=init)(x)\n    \n    return tf.keras.Model(inputs = inputs, outputs = x)","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:35.338767Z","iopub.execute_input":"2023-03-09T19:51:35.339104Z","iopub.status.idle":"2023-03-09T19:51:35.357042Z","shell.execute_reply.started":"2023-03-09T19:51:35.339058Z","shell.execute_reply":"2023-03-09T19:51:35.355739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Na most hogy ezek megvannak általános esetekre, most a mi példánk miatt kettébontjuk.","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n    monet_generator = Generator() # photo -> Monet-esque painting\n    photo_generator = Generator() # Monet paintings -> be more like photos\n\n    monet_discriminator = Discriminator() # real Monet paintings <-> generated Monet paintings\n    photo_discriminator = Discriminator() # real photos <-> generated photos","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:35.358413Z","iopub.execute_input":"2023-03-09T19:51:35.358706Z","iopub.status.idle":"2023-03-09T19:51:38.889805Z","shell.execute_reply.started":"2023-03-09T19:51:35.358679Z","shell.execute_reply":"2023-03-09T19:51:38.888575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Összerakjuk az egészet\n\nÖrököljük a keras.Model osztályt, hogy használhassuk a fit() metódusát.\nDefiniáljuk hogy nézzen ki egy train lépés is: \n*      van egy kép (rendes fotó)\n*      a generátor átalakítja egy Monet-type képpé\n*      majd visszaalakítja fotóvá\n*      ha végzett kiszámolja mekkorát tévedett, majd ez alapján optimalizál","metadata":{}},{"cell_type":"code","source":"class CycleGAN(keras.Model):\n    \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    # első értelmes függvény az osztályban\n    # ezt fogja meghívogatni a fit()\n    def train_step(self, batch_data):\n        real_monet, real_photo = batch_data\n        \n        # lehetővé teszi a gradiens számítását a tensorokhoz kapcsolódó műveletekhez. \n        # A \"persistent=True\" azt jelzi, \n        # hogy a GradientTape objektumot újra használhatjuk anélkül, \n        # hogy újra létre kellene hoznunk a számítási gráfot. \n        # Ez hasznos lehet például akkor, amikor több gradienst kell számítani ugyanazon a számítási gráfon. \n        # A \"tape\" objektum rögzíti a gradiens számításához szükséges műveleteket, \n        # majd a \"tape.gradient()\" függvény segítségével kiszámítható a gradiens.\n        \n        with tf.GradientTape(persistent=True) as tape:\n            #photo -> monet -> photo\n            fake_monet = self.m_gen(real_photo, training=True)\n            cycled_photo = self.p_gen(fake_monet, training=True)\n        \n            #monet -> photo -> monet\n            fake_photo = self.p_gen(real_monet, training=True)\n            cycled_monet = self.m_gen(fake_photo, training=True)\n            \n            #önmagát\n            same_monet = self.m_gen(real_monet, training=True)\n            same_photo = self.p_gen(real_photo, training=True)\n        \n            #lossok\n            disc_real_monet = self.m_disc(real_monet, training = True)\n            disc_real_photo = self.p_disc(real_photo, training = True)\n            disc_fake_monet = self.p_disc(fake_monet, training = True)\n            disc_fake_photo = self.p_disc(fake_photo, training = True)\n            \n            monet_gen_loss = self.gen_loss_fn(disc_fake_monet)\n            photo_gen_loss = self.gen_loss_fn(disc_fake_photo)\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            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            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            #gradiensek kiszámolása optimalizáláshoz\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            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            #train\n            self.m_gen_optimizer.apply_gradients(zip(monet_generator_gradients, \n                                                self.m_gen.trainable_variables))\n            self.p_gen_optimizer.apply_gradients(zip(photo_generator_gradients,\n                                                 self.p_gen.trainable_variables))\n            self.m_disc_optimizer.apply_gradients(zip(monet_discriminator_gradients,\n                                                  self.m_disc.trainable_variables))\n            self.p_disc_optimizer.apply_gradients(zip(photo_discriminator_gradients,\n                                                  self.p_disc.trainable_variables))\n                                                 \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            \n            \n            ","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:38.891289Z","iopub.execute_input":"2023-03-09T19:51:38.891619Z","iopub.status.idle":"2023-03-09T19:51:38.914175Z","shell.execute_reply.started":"2023-03-09T19:51:38.891588Z","shell.execute_reply":"2023-03-09T19:51:38.913327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Loss function leírások következnek","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n    def discriminator_loss(real, generated):\n        real_loss = tf.keras.losses.BinaryCrossentropy(\n            from_logits = True, \n            reduction = tf.keras.losses.Reduction.NONE)(tf.ones_like(real), real)\n        generated_loss = tf.keras.losses.BinaryCrossentropy(\n            from_logits = True, \n            reduction = tf.keras.losses.Reduction.NONE)(tf.zeros_like(generated), generated)\n        \n        total_disc_loss = real_loss + generated_loss\n        return total_disc_loss * 0.5","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:38.915351Z","iopub.execute_input":"2023-03-09T19:51:38.915618Z","iopub.status.idle":"2023-03-09T19:51:38.930724Z","shell.execute_reply.started":"2023-03-09T19:51:38.915592Z","shell.execute_reply":"2023-03-09T19:51:38.929890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def generator_loss(generated):\n        loss = tf.keras.losses.BinaryCrossentropy(\n            from_logits = True,\n            reduction = tf.keras.losses.Reduction.NONE\n            )(tf.ones_like(generated), generated)\n        return loss","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:38.931849Z","iopub.execute_input":"2023-03-09T19:51:38.932177Z","iopub.status.idle":"2023-03-09T19:51:38.940514Z","shell.execute_reply.started":"2023-03-09T19:51:38.932148Z","shell.execute_reply":"2023-03-09T19:51:38.939654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def calc_cycle_loss(real, cycled, LAMBDA):\n        loss = tf.reduce_mean(tf.abs(real-cycled))\n        return LAMBDA*loss","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:38.941633Z","iopub.execute_input":"2023-03-09T19:51:38.941923Z","iopub.status.idle":"2023-03-09T19:51:38.950481Z","shell.execute_reply.started":"2023-03-09T19:51:38.941896Z","shell.execute_reply":"2023-03-09T19:51:38.949530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def identity_loss(real, cycled, LAMBDA):\n        loss = tf.reduce_mean(tf.abs(real-cycled))\n        return LAMBDA*0.5*loss","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:45.783679Z","iopub.execute_input":"2023-03-09T19:51:45.784655Z","iopub.status.idle":"2023-03-09T19:51:45.789718Z","shell.execute_reply.started":"2023-03-09T19:51:45.784613Z","shell.execute_reply":"2023-03-09T19:51:45.788801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Edzés","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":"2023-03-09T19:51:48.647594Z","iopub.execute_input":"2023-03-09T19:51:48.648684Z","iopub.status.idle":"2023-03-09T19:51:48.662469Z","shell.execute_reply.started":"2023-03-09T19:51:48.648644Z","shell.execute_reply":"2023-03-09T19:51:48.661390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    cycle_gan_model = CycleGAN(\n        monet_generator,\n        photo_generator,\n        monet_discriminator,\n        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":"2023-03-09T19:51:51.370807Z","iopub.execute_input":"2023-03-09T19:51:51.372130Z","iopub.status.idle":"2023-03-09T19:51:51.396569Z","shell.execute_reply.started":"2023-03-09T19:51:51.372061Z","shell.execute_reply":"2023-03-09T19:51:51.395543Z"},"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=10\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-09T19:51:54.127168Z","iopub.execute_input":"2023-03-09T19:51:54.127996Z","iopub.status.idle":"2023-03-09T19:53:22.815338Z","shell.execute_reply.started":"2023-03-09T19:51:54.127955Z","shell.execute_reply":"2023-03-09T19:53:22.813831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}