{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":21755,"databundleVersionId":1475600},{"sourceType":"datasetVersion","sourceId":15222399,"datasetId":9739090,"databundleVersionId":16118046},{"sourceType":"datasetVersion","sourceId":15219882,"datasetId":9737267,"databundleVersionId":16115306},{"sourceType":"datasetVersion","sourceId":15220051,"datasetId":9737388,"databundleVersionId":16115485},{"sourceType":"datasetVersion","sourceId":1461759,"datasetId":857144,"databundleVersionId":1495448}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# InstanceNormalization implemented manually (replaces tensorflow_addons)\nclass InstanceNormalization(layers.Layer):\n    def __init__(self, **kwargs):\n        super(InstanceNormalization, self).__init__(**kwargs)\n\n    def build(self, input_shape):\n        self.gamma = self.add_weight(\n            name='gamma',\n            shape=(input_shape[-1],),\n            initializer=keras.initializers.RandomNormal(mean=0.0, stddev=0.02),\n            trainable=True)\n        self.beta = self.add_weight(\n            name='beta',\n            shape=(input_shape[-1],),\n            initializer='zeros',\n            trainable=True)\n\n    def call(self, x):\n        mean, variance = tf.nn.moments(x, axes=[1, 2], keepdims=True)\n        epsilon = 1e-5\n        x_norm = (x - mean) / tf.sqrt(variance + epsilon)\n        return self.gamma * x_norm + self.beta\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\nAUTOTUNE = tf.data.experimental.AUTOTUNE\nprint(tf.__version__)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:03.063296Z","iopub.execute_input":"2026-03-17T16:43:03.063617Z","iopub.status.idle":"2026-03-17T16:43:28.495331Z","shell.execute_reply.started":"2026-03-17T16:43:03.063590Z","shell.execute_reply":"2026-03-17T16:43:28.494562Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Photos from the competition dataset\nPHOTO_FILENAMES = tf.io.gfile.glob('/kaggle/input/competitions/gan-getting-started/photo_tfrec/*.tfrec')\nprint('Photo TFRecord Files:', len(PHOTO_FILENAMES))\n\n# Van Gogh paintings - replaces Monet entirely\nVANGOGH_FILENAMES = tf.io.gfile.glob('/kaggle/input/datasets/jackbyte/van-gogh-tfrecord/*.tfrecord')\nprint('Van Gogh TFRecord Files:', len(VANGOGH_FILENAMES))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:33.466395Z","iopub.execute_input":"2026-03-17T16:43:33.467403Z","iopub.status.idle":"2026-03-17T16:43:33.505137Z","shell.execute_reply.started":"2026-03-17T16:43:33.467357Z","shell.execute_reply":"2026-03-17T16:43:33.504576Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:39.961833Z","iopub.execute_input":"2026-03-17T16:43:39.962135Z","iopub.status.idle":"2026-03-17T16:43:39.967713Z","shell.execute_reply.started":"2026-03-17T16:43:39.962110Z","shell.execute_reply":"2026-03-17T16:43:39.966811Z"}},"outputs":[],"execution_count":null},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:43.533227Z","iopub.execute_input":"2026-03-17T16:43:43.533998Z","iopub.status.idle":"2026-03-17T16:43:43.539400Z","shell.execute_reply.started":"2026-03-17T16:43:43.533958Z","shell.execute_reply":"2026-03-17T16:43:43.538636Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"photo_ds = load_dataset(PHOTO_FILENAMES, labeled=True).batch(1)\nvangogh_ds = load_dataset(VANGOGH_FILENAMES, labeled=True).batch(1)\n\nexample_vangogh = next(iter(vangogh_ds))\nexample_photo = next(iter(photo_ds))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:47.271509Z","iopub.execute_input":"2026-03-17T16:43:47.272069Z","iopub.status.idle":"2026-03-17T16:43:48.673872Z","shell.execute_reply.started":"2026-03-17T16:43:47.272034Z","shell.execute_reply":"2026-03-17T16:43:48.673261Z"}},"outputs":[],"execution_count":null},{"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('Van Gogh')\nplt.imshow(example_vangogh[0] * 0.5 + 0.5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:53.316743Z","iopub.execute_input":"2026-03-17T16:43:53.317076Z","iopub.status.idle":"2026-03-17T16:43:53.678329Z","shell.execute_reply.started":"2026-03-17T16:43:53.317050Z","shell.execute_reply":"2026-03-17T16:43:53.677522Z"}},"outputs":[],"execution_count":null},{"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\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(InstanceNormalization())\n\n    result.add(layers.LeakyReLU())\n    return result","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:43:59.569835Z","iopub.execute_input":"2026-03-17T16:43:59.570173Z","iopub.status.idle":"2026-03-17T16:43:59.575556Z","shell.execute_reply.started":"2026-03-17T16:43:59.570145Z","shell.execute_reply":"2026-03-17T16:43:59.574805Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def upsample(filters, size, apply_dropout=False):\n    initializer = tf.random_normal_initializer(0., 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(InstanceNormalization())\n\n    if apply_dropout:\n        result.add(layers.Dropout(0.5))\n\n    result.add(layers.ReLU())\n    return result","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:03.803446Z","iopub.execute_input":"2026-03-17T16:44:03.803746Z","iopub.status.idle":"2026-03-17T16:44:03.808876Z","shell.execute_reply.started":"2026-03-17T16:44:03.803722Z","shell.execute_reply":"2026-03-17T16:44:03.808052Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def Generator():\n    inputs = layers.Input(shape=[256,256,3])\n\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    skips = []\n    for down in down_stack:\n        x = down(x)\n        skips.append(x)\n\n    skips = reversed(skips[:-1])\n\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    return keras.Model(inputs=inputs, outputs=x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:07.218537Z","iopub.execute_input":"2026-03-17T16:44:07.219130Z","iopub.status.idle":"2026-03-17T16:44:07.226362Z","shell.execute_reply.started":"2026-03-17T16:44:07.219105Z","shell.execute_reply":"2026-03-17T16:44:07.225526Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def Discriminator():\n    initializer = tf.random_normal_initializer(0., 0.02)\n\n    inp = layers.Input(shape=[256, 256, 3], name='input_image')\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)\n    conv = layers.Conv2D(512, 4, strides=1,\n                         kernel_initializer=initializer,\n                         use_bias=False)(zero_pad1)\n\n    norm1 = InstanceNormalization()(conv)\n    leaky_relu = layers.LeakyReLU()(norm1)\n    zero_pad2 = layers.ZeroPadding2D()(leaky_relu)\n    last = layers.Conv2D(1, 4, strides=1,\n                         kernel_initializer=initializer)(zero_pad2)\n\n    return tf.keras.Model(inputs=inp, outputs=last)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:14.791871Z","iopub.execute_input":"2026-03-17T16:44:14.792525Z","iopub.status.idle":"2026-03-17T16:44:14.798273Z","shell.execute_reply.started":"2026-03-17T16:44:14.792494Z","shell.execute_reply":"2026-03-17T16:44:14.797410Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_strategy().scope():\n    vangogh_generator = Generator()      # transforms photos → Van Gogh style\n    photo_generator = Generator()        # transforms Van Gogh paintings → photos\n\n    vangogh_discriminator = Discriminator()  # real vs fake Van Gogh\n    photo_discriminator = Discriminator()    # real vs fake photos","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:18.750866Z","iopub.execute_input":"2026-03-17T16:44:18.751693Z","iopub.status.idle":"2026-03-17T16:44:20.652075Z","shell.execute_reply.started":"2026-03-17T16:44:18.751660Z","shell.execute_reply":"2026-03-17T16:44:20.651443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"to_vangogh = vangogh_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(\"Van Gogh-esque Photo (untrained)\")\nplt.imshow(to_vangogh[0] * 0.5 + 0.5)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:23.017450Z","iopub.execute_input":"2026-03-17T16:44:23.017784Z","iopub.status.idle":"2026-03-17T16:44:25.706801Z","shell.execute_reply.started":"2026-03-17T16:44:23.017758Z","shell.execute_reply":"2026-03-17T16:44:25.706009Z"}},"outputs":[],"execution_count":null},{"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(self, m_gen_optimizer, p_gen_optimizer, m_disc_optimizer,\n                p_disc_optimizer, gen_loss_fn, disc_loss_fn, cycle_loss_fn, identity_loss_fn):\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_vangogh, real_photo = batch_data\n\n        with tf.GradientTape(persistent=True) as tape:\n            # Forward cycle: photo → Van Gogh → photo\n            fake_vangogh = self.m_gen(real_photo, training=True)\n            cycled_photo = self.p_gen(fake_vangogh, training=True)\n\n            # Backward cycle: Van Gogh → photo → Van Gogh\n            fake_photo = self.p_gen(real_vangogh, training=True)\n            cycled_vangogh = self.m_gen(fake_photo, training=True)\n\n            # Identity\n            same_vangogh = self.m_gen(real_vangogh, training=True)\n            same_photo = self.p_gen(real_photo, training=True)\n\n            # Discriminator on real images\n            disc_real_vangogh = self.m_disc(real_vangogh, training=True)\n            disc_real_photo = self.p_disc(real_photo, training=True)\n\n            # Discriminator on fake images\n            disc_fake_vangogh = self.m_disc(fake_vangogh, training=True)\n            disc_fake_photo = self.p_disc(fake_photo, training=True)\n\n            # Generator losses\n            vangogh_gen_loss = self.gen_loss_fn(disc_fake_vangogh)\n            photo_gen_loss = self.gen_loss_fn(disc_fake_photo)\n\n            # Cycle consistency loss\n            total_cycle_loss = self.cycle_loss_fn(real_vangogh, cycled_vangogh, self.lambda_cycle) + \\\n                               self.cycle_loss_fn(real_photo, cycled_photo, self.lambda_cycle)\n\n            # Total generator losses\n            total_vangogh_gen_loss = vangogh_gen_loss + total_cycle_loss + \\\n                                     self.identity_loss_fn(real_vangogh, same_vangogh, self.lambda_cycle)\n            total_photo_gen_loss = photo_gen_loss + total_cycle_loss + \\\n                                   self.identity_loss_fn(real_photo, same_photo, self.lambda_cycle)\n\n            # Discriminator losses\n            vangogh_disc_loss = self.disc_loss_fn(disc_real_vangogh, disc_fake_vangogh)\n            photo_disc_loss = self.disc_loss_fn(disc_real_photo, disc_fake_photo)\n\n        # Gradients\n        vangogh_generator_gradients = tape.gradient(total_vangogh_gen_loss, self.m_gen.trainable_variables)\n        photo_generator_gradients = tape.gradient(total_photo_gen_loss, self.p_gen.trainable_variables)\n        vangogh_discriminator_gradients = tape.gradient(vangogh_disc_loss, self.m_disc.trainable_variables)\n        photo_discriminator_gradients = tape.gradient(photo_disc_loss, self.p_disc.trainable_variables)\n\n        # Apply gradients\n        self.m_gen_optimizer.apply_gradients(zip(vangogh_generator_gradients, self.m_gen.trainable_variables))\n        self.p_gen_optimizer.apply_gradients(zip(photo_generator_gradients, self.p_gen.trainable_variables))\n        self.m_disc_optimizer.apply_gradients(zip(vangogh_discriminator_gradients, self.m_disc.trainable_variables))\n        self.p_disc_optimizer.apply_gradients(zip(photo_discriminator_gradients, self.p_disc.trainable_variables))\n\n        return {\n            \"vangogh_gen_loss\": total_vangogh_gen_loss,\n            \"photo_gen_loss\": total_photo_gen_loss,\n            \"vangogh_disc_loss\": vangogh_disc_loss,\n            \"photo_disc_loss\": photo_disc_loss\n        }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:32.558217Z","iopub.execute_input":"2026-03-17T16:44:32.558840Z","iopub.status.idle":"2026-03-17T16:44:32.570092Z","shell.execute_reply.started":"2026-03-17T16:44:32.558813Z","shell.execute_reply":"2026-03-17T16:44:32.569290Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_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\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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:38.485759Z","iopub.execute_input":"2026-03-17T16:44:38.486292Z","iopub.status.idle":"2026-03-17T16:44:38.491059Z","shell.execute_reply.started":"2026-03-17T16:44:38.486262Z","shell.execute_reply":"2026-03-17T16:44:38.490450Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_strategy().scope():\n    def generator_loss(generated):\n        return tf.keras.losses.BinaryCrossentropy(\n            from_logits=True,\n            reduction=tf.keras.losses.Reduction.NONE)(tf.ones_like(generated), generated)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:41.350003Z","iopub.execute_input":"2026-03-17T16:44:41.350336Z","iopub.status.idle":"2026-03-17T16:44:41.354951Z","shell.execute_reply.started":"2026-03-17T16:44:41.350307Z","shell.execute_reply":"2026-03-17T16:44:41.354185Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_strategy().scope():\n    def calc_cycle_loss(real_image, cycled_image, LAMBDA):\n        loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))\n        return LAMBDA * loss1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:44.281603Z","iopub.execute_input":"2026-03-17T16:44:44.281905Z","iopub.status.idle":"2026-03-17T16:44:44.286827Z","shell.execute_reply.started":"2026-03-17T16:44:44.281879Z","shell.execute_reply":"2026-03-17T16:44:44.286031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:51.666873Z","iopub.execute_input":"2026-03-17T16:44:51.667654Z","iopub.status.idle":"2026-03-17T16:44:51.671873Z","shell.execute_reply.started":"2026-03-17T16:44:51.667624Z","shell.execute_reply":"2026-03-17T16:44:51.670948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_strategy().scope():\n    vangogh_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    vangogh_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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:54.039697Z","iopub.execute_input":"2026-03-17T16:44:54.039981Z","iopub.status.idle":"2026-03-17T16:44:54.055970Z","shell.execute_reply.started":"2026-03-17T16:44:54.039957Z","shell.execute_reply":"2026-03-17T16:44:54.055164Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.distribute.get_strategy().scope():\n    cycle_gan_model = CycleGan(\n        vangogh_generator, photo_generator,\n        vangogh_discriminator, photo_discriminator\n    )\n\n    cycle_gan_model.compile(\n        m_gen_optimizer = vangogh_generator_optimizer,\n        p_gen_optimizer = photo_generator_optimizer,\n        m_disc_optimizer = vangogh_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":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:44:59.007178Z","iopub.execute_input":"2026-03-17T16:44:59.007511Z","iopub.status.idle":"2026-03-17T16:44:59.021208Z","shell.execute_reply.started":"2026-03-17T16:44:59.007486Z","shell.execute_reply":"2026-03-17T16:44:59.020567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cycle_gan_model.fit(\n    tf.data.Dataset.zip((vangogh_ds, photo_ds)),\n    epochs=50\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T16:46:08.146064Z","iopub.execute_input":"2026-03-17T16:46:08.146420Z","iopub.status.idle":"2026-03-17T17:46:05.484905Z","shell.execute_reply.started":"2026-03-17T16:46:08.146394Z","shell.execute_reply":"2026-03-17T17:46:05.484073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"_, ax = plt.subplots(5, 2, figsize=(12, 12))\nfor i, img in enumerate(photo_ds.take(5)):\n    prediction = vangogh_generator(img, training=False)[0].numpy()\n    prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n    img_show = (img[0] * 127.5 + 127.5).numpy().astype(np.uint8)\n\n    ax[i, 0].imshow(img_show)\n    ax[i, 1].imshow(prediction)\n    ax[i, 0].set_title(\"Input Photo\")\n    ax[i, 1].set_title(\"Van Gogh-esque\")\n    ax[i, 0].axis(\"off\")\n    ax[i, 1].axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T17:46:31.390625Z","iopub.execute_input":"2026-03-17T17:46:31.391287Z","iopub.status.idle":"2026-03-17T17:46:32.226747Z","shell.execute_reply.started":"2026-03-17T17:46:31.391253Z","shell.execute_reply":"2026-03-17T17:46:32.225945Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import PIL\n! mkdir -p ../images\ni = 1\nfor img in photo_ds:\n    prediction = vangogh_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    i += 1\n\nimport shutil\nshutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")\nprint(\"Done! Images saved.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T17:47:14.097719Z","iopub.execute_input":"2026-03-17T17:47:14.098383Z","iopub.status.idle":"2026-03-17T17:53:43.085254Z","shell.execute_reply.started":"2026-03-17T17:47:14.098354Z","shell.execute_reply":"2026-03-17T17:53:43.084107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import PIL\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Correct path\nimg_path = '/kaggle/input/datasets/rahulhiremath1208/main-building/kletechbvb_cover.jpg'\n\n# Preprocess\nimg = tf.io.read_file(img_path)\nimg = tf.image.decode_jpeg(img, channels=3)\nimg = tf.image.resize(img, [256, 256])\nimg = (tf.cast(img, tf.float32) / 127.5) - 1\nimg = tf.expand_dims(img, axis=0)\n\n# Generate Van Gogh version\nprediction = vangogh_generator(img, training=False)[0].numpy()\nprediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n\n# Display\noriginal = (img[0].numpy() * 127.5 + 127.5).astype(np.uint8)\n\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.title(\"Input: Main Building\")\nplt.imshow(original)\nplt.axis(\"off\")\n\nplt.subplot(1, 2, 2)\nplt.title(\"Van Gogh-esque\")\nplt.imshow(prediction)\nplt.axis(\"off\")\nplt.show()\n\n# Save\nim = PIL.Image.fromarray(prediction)\nim.save(\"/kaggle/working/Main Building.jpg\")\nprint(\"Saved!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T18:42:12.841824Z","iopub.execute_input":"2026-03-17T18:42:12.842463Z","iopub.status.idle":"2026-03-17T18:42:13.275785Z","shell.execute_reply.started":"2026-03-17T18:42:12.842431Z","shell.execute_reply":"2026-03-17T18:42:13.274984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Create a directory to save weights\nos.makedirs(\"/kaggle/working/cyclegan_weights\", exist_ok=True)\n\n# Save all 4 model weights\nvangogh_generator.save_weights(\"/kaggle/working/cyclegan_weights/vangogh_generator.weights.h5\")\nphoto_generator.save_weights(\"/kaggle/working/cyclegan_weights/photo_generator.weights.h5\")\nvangogh_discriminator.save_weights(\"/kaggle/working/cyclegan_weights/vangogh_discriminator.weights.h5\")\nphoto_discriminator.save_weights(\"/kaggle/working/cyclegan_weights/photo_discriminator.weights.h5\")\n\nprint(\"All weights saved successfully!\")\n\n# Zip them so you can download as one file\nimport shutil\nshutil.make_archive(\"/kaggle/working/cyclegan_weights_backup\", 'zip', \"/kaggle/working/cyclegan_weights\")\nprint(\"Zipped! Download 'cyclegan_weights_backup.zip' from the output panel.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-17T18:07:47.472048Z","iopub.execute_input":"2026-03-17T18:07:47.472443Z","iopub.status.idle":"2026-03-17T18:08:12.560325Z","shell.execute_reply.started":"2026-03-17T18:07:47.472407Z","shell.execute_reply":"2026-03-17T18:08:12.559520Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}