{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"},{"sourceId":9550777,"sourceType":"datasetVersion","datasetId":5819135}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"'''monet_generator.save('monet_generator.h5')\nphoto_generator.save('photo_generator.h5')\nmonet_discriminator.save('monet_discriminator.h5')\nphoto_discriminator.save('photo_discriminator.h5')'''","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T19:46:22.218472Z","iopub.execute_input":"2024-12-03T19:46:22.218785Z","iopub.status.idle":"2024-12-03T19:46:22.224448Z","shell.execute_reply.started":"2024-12-03T19:46:22.21876Z","shell.execute_reply":"2024-12-03T19:46:22.223614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!pip install --upgrade tensorflow\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T19:46:22.225715Z","iopub.execute_input":"2024-12-03T19:46:22.225962Z","iopub.status.idle":"2024-12-03T19:46:22.235935Z","shell.execute_reply.started":"2024-12-03T19:46:22.225937Z","shell.execute_reply":"2024-12-03T19:46:22.235181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, random, json, PIL, shutil, re, imageio, glob\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom PIL import Image, ImageDraw\nimport matplotlib.pyplot as plt\nfrom kaggle_datasets import KaggleDatasets\nimport tensorflow as tf\nimport tensorflow.keras.layers as L\nimport tensorflow.keras.backend as K\nfrom tensorflow.keras import Model, losses, optimizers\nfrom tensorflow.keras.callbacks import Callback\n#from tensorflow.distribute import MirroredStrategy\n\n\n\n# Instead of using MirroredStrategy directly from tensorflow.distribute, try:\nstrategy = tf.distribute.MirroredStrategy()\n\n# Set up parallel calls for dataset loading\nAUTO = tf.data.AUTOTUNE\n\ndef seed_everything(seed=0):\n    random.seed(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\n\nSEED = 0\nseed_everything(SEED)\n\nHEIGHT = 256\nWIDTH = 256\nHEIGHT_RESIZE = 128\nWIDTH_RESIZE = 128\nCHANNELS = 3\nBATCH_SIZE = 16\nEPOCHS = 100\nTRANSFORMER_BLOCKS = 6\nGENERATOR_LR = 2e-4\nDISCRIMINATOR_LR = 2e-4\n\nGCS_PATH = KaggleDatasets().get_gcs_path('gan-getting-started')\n\nMONET_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/monet_tfrec/monet*.tfrec'))\nPHOTO_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/photo_tfrec/photo*.tfrec'))\n\ndef count_data_items(filenames):\n    n = [int(re.compile(r\"-([0-9]*)\\.tfrec\").search(filename).group(1)) for filename in filenames]\n    return np.sum(n)\n\nn_monet_samples = count_data_items(MONET_FILENAMES)\nn_photo_samples = count_data_items(PHOTO_FILENAMES)\n\nprint(f'Monet TFRecord files: {len(MONET_FILENAMES)}')\nprint(f'Monet image files: {n_monet_samples}')\nprint(f'Photo TFRecord files: {len(PHOTO_FILENAMES)}')\nprint(f'Photo image files: {n_photo_samples}')\n\ndef data_augment(image):\n    p_spatial = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n    p_rotate = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n    \n    # 90º rotations\n    if p_rotate > .8:\n        image = tf.image.rot90(image, k=3) # rotate 270º\n    elif p_rotate > .6:\n        image = tf.image.rot90(image, k=2) # rotate 180º\n    elif p_rotate > .4:\n        image = tf.image.rot90(image, k=1) # rotate 90º\n        \n    # Flips\n    image = tf.image.random_flip_left_right(image)\n    image = tf.image.random_flip_up_down(image)\n    if p_spatial > .75:\n        image = tf.image.transpose(image)\n        \n    # Train on crops\n    image = tf.image.random_crop(image, size=[HEIGHT_RESIZE, WIDTH_RESIZE, CHANNELS])\n    \n    return image\n\ndef normalize_img(img):\n    img = tf.cast(img, dtype=tf.float32)\n    # Map values in the range [-1, 1]\n    return (img / 127.5) - 1.0\n\ndef decode_image(image):\n    image = tf.image.decode_jpeg(image, channels=CHANNELS)\n    image = tf.reshape(image, [HEIGHT, WIDTH, CHANNELS])\n    return image\n\ndef read_tfrecord(example):\n    tfrecord_format = {\n        'image': 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\n\ndef load_dataset(filenames):\n    dataset = tf.data.TFRecordDataset(filenames)\n    dataset = dataset.map(read_tfrecord, num_parallel_calls=AUTO)\n    return dataset\n    \ndef get_dataset(filenames, augment=None, repeat=True, shuffle=True, batch_size=1):\n    dataset = load_dataset(filenames)\n\n    if augment:\n        dataset = dataset.map(augment, num_parallel_calls=AUTO)\n    dataset = dataset.map(normalize_img, num_parallel_calls=AUTO)\n    if repeat:\n        dataset = dataset.repeat()\n    if shuffle:\n        dataset = dataset.shuffle(512)\n        \n    dataset = dataset.batch(batch_size)\n    dataset = dataset.cache()\n    dataset = dataset.prefetch(AUTO)\n    \n    return dataset\n\n\ndef create_gif(images_path, gif_path):\n    images = []\n    filenames = glob.glob(images_path)\n    filenames.sort(key=lambda x: int(''.join(filter(str.isdigit, x))))\n    for epoch, filename in enumerate(filenames):\n        img = Image.open(filename)\n        draw = ImageDraw.Draw(img)\n        draw.text((0, 0), f'Epoch {epoch+1}')\n        images.append(img)\n    imageio.mimsave(gif_path, images, fps=2) # Save gif\n\n@tf.function\ndef linear_schedule_with_warmup(step):\n    \"\"\" Create a schedule with a learning rate that decreases linearly after\n    linearly increasing during a warmup period.\n    \"\"\"\n    lr_start = 2e-4\n    lr_max = 2e-4\n    lr_min = 0.0\n    \n    steps_per_epoch = int(max(n_monet_samples, n_photo_samples) // BATCH_SIZE)\n    total_steps = EPOCHS * steps_per_epoch\n    warmup_steps = 1\n    hold_max_steps = total_steps * 0.8\n    \n    if step < warmup_steps:\n        lr = (lr_max - lr_start) / warmup_steps * step + lr_start\n    elif step < warmup_steps + hold_max_steps:\n        lr = lr_max\n    else:\n        lr = lr_max * ((total_steps - step) / (total_steps - warmup_steps - hold_max_steps))\n        if lr_min is not None:\n            lr = tf.math.maximum(lr_min, lr)\n\n    return lr\n\nsteps_per_epoch = int(max(n_monet_samples, n_photo_samples) // BATCH_SIZE)\ntotal_steps = EPOCHS * steps_per_epoch\nrng = [i for i in range(0, total_steps, 50)]\ny = [linear_schedule_with_warmup(x) for x in rng]\n\nsns.set(style=\"whitegrid\")\nfig, ax = plt.subplots(figsize=(20, 6))\nplt.plot(rng, y)\nprint(f'{EPOCHS} total epochs and {steps_per_epoch} steps per epoch')\nprint(f'Learning rate schedule: {y[0]:.3g} to {max(y):.3g} to {y[-1]:.3g}')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T19:46:22.237634Z","iopub.execute_input":"2024-12-03T19:46:22.237889Z","iopub.status.idle":"2024-12-03T19:46:26.504206Z","shell.execute_reply.started":"2024-12-03T19:46:22.237865Z","shell.execute_reply":"2024-12-03T19:46:26.503335Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\n\n\n# Generator model\n\nclass InstanceNormalization(L.Layer):\n    def __init__(self, epsilon=1e-5, **kwargs):\n        super(InstanceNormalization, self).__init__(**kwargs)\n        self.epsilon = epsilon\n\n    def call(self, inputs):\n        mean, variance = tf.nn.moments(inputs, axes=[1, 2], keepdims=True)\n        return (inputs - mean) / tf.sqrt(variance + self.epsilon)\n\ndef generator_fn(height=128, width=128, channels=CHANNELS, transformer_blocks=TRANSFORMER_BLOCKS):\n    OUTPUT_CHANNELS = 3\n    inputs = L.Input(shape=[height, width, channels], name='input_image')\n\n    # Encoder\n    enc_1 = L.Conv2D(64, 7, strides=1, padding='same', use_bias=False, name='encoder_block_1')(inputs)\n    enc_1 = InstanceNormalization()(enc_1)\n    enc_1 = L.ReLU()(enc_1)\n    \n    enc_2 = L.Conv2D(128, 3, strides=2, padding='same', use_bias=False, name='encoder_block_2')(enc_1)\n    enc_2 = InstanceNormalization()(enc_2)\n    enc_2 = L.ReLU()(enc_2)\n    \n    enc_3 = L.Conv2D(256, 3, strides=2, padding='same', use_bias=False, name='encoder_block_3')(enc_2)\n    enc_3 = InstanceNormalization()(enc_3)\n    enc_3 = L.ReLU()(enc_3)\n\n    # Transformer\n    x = enc_3\n    for i in range(transformer_blocks):\n        x_skip = x\n        x = L.Conv2D(256, 3, strides=1, padding='same', use_bias=False, name=f'transformer_block_1_{i}')(x)\n        x = InstanceNormalization()(x)\n        x = L.ReLU()(x)\n        x = L.Conv2D(256, 3, strides=1, padding='same', use_bias=False, name=f'transformer_block_2_{i}')(x)\n        x = InstanceNormalization()(x)\n        x = L.Add()([x, x_skip])\n    \n    # Decoder\n    dec_1 = L.Conv2DTranspose(128, 3, strides=2, padding='same', use_bias=False, name='decoder_block_1')(x)\n    dec_1 = InstanceNormalization()(dec_1)\n    dec_1 = L.ReLU()(dec_1)\n    \n    dec_2 = L.Conv2DTranspose(64, 3, strides=2, padding='same', use_bias=False, name='decoder_block_2')(dec_1)\n    dec_2 = InstanceNormalization()(dec_2)\n    dec_2 = L.ReLU()(dec_2)\n    \n    outputs = L.Conv2D(OUTPUT_CHANNELS, 7, strides=1, padding='same', activation='tanh', name='output_block')(dec_2)\n    \n    return Model(inputs=inputs, outputs=outputs, name='generator')\n\n\n# Discriminator model\ndef discriminator_fn(height=128, width=128, channels=CHANNELS):\n    inputs = L.Input(shape=[height, width, channels], name='input_image')\n\n    x = L.Conv2D(64, 4, strides=2, padding='same', use_bias=False, name='disc_block_1')(inputs)\n    x = L.LeakyReLU(0.2)(x)\n    \n    x = L.Conv2D(128, 4, strides=2, padding='same', use_bias=False, name='disc_block_2')(x)\n    x = InstanceNormalization()(x)\n    x = L.LeakyReLU(0.2)(x)\n    \n    x = L.Conv2D(256, 4, strides=2, padding='same', use_bias=False, name='disc_block_3')(x)\n    x = InstanceNormalization()(x)\n    x = L.LeakyReLU(0.2)(x)\n    \n    x = L.Conv2D(512, 4, strides=1, padding='same', use_bias=False, name='disc_block_4')(x)\n    x = InstanceNormalization()(x)\n    x = L.LeakyReLU(0.2)(x)\n    \n    outputs = L.Conv2D(1, 4, strides=1, padding='same', name='output_block')(x)\n    \n    return Model(inputs=inputs, outputs=outputs, name='discriminator')\n\n\n# CycleGAN model class\nclass CycleGAN(Model):\n    def __init__(\n        self,\n        monet_generator,\n        photo_generator,\n        monet_discriminator,\n        photo_discriminator,\n        lambda_cycle=10.0,\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            # 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, inputting 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, inputting 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, self.m_gen.trainable_variables)\n        photo_generator_gradients = tape.gradient(total_photo_gen_loss, self.p_gen.trainable_variables)\n        monet_discriminator_gradients = tape.gradient(monet_disc_loss, self.m_disc.trainable_variables)\n        photo_discriminator_gradients = tape.gradient(photo_disc_loss, self.p_disc.trainable_variables)\n\n        # Apply the gradients to the optimizers\n        self.m_gen_optimizer.apply_gradients(zip(monet_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(monet_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            '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\ndef discriminator_loss(real, generated):\n    real_loss = losses.BinaryCrossentropy(from_logits=True)(tf.ones_like(real), real)\n    generated_loss = losses.BinaryCrossentropy(from_logits=True)(tf.zeros_like(generated), generated)\n    return (real_loss + generated_loss) * 0.5\n\n\ndef generator_loss(generated):\n    return losses.BinaryCrossentropy(from_logits=True)(tf.ones_like(generated), generated)\n\n\n'''def cycle_loss(real_image, cycled_image, lambda_cycle):\n    loss = tf.reduce_mean(tf.abs(real_image - cycled_image))\n    return lambda_cycle * loss\n\n\ndef identity_loss(real_image, same_image, lambda_cycle):\n    loss = tf.reduce_mean(tf.abs(real_image - same_image))\n    return lambda_cycle * 0.5 * loss'''\ndef cycle_loss(real_image, cycled_image, lambda_cycle):\n    real_image = tf.cast(real_image, tf.float32)\n    cycled_image = tf.cast(cycled_image, tf.float32)\n    loss = tf.reduce_mean(tf.abs(real_image - cycled_image))\n    return lambda_cycle * loss\n\n\ndef identity_loss(real_image, same_image, lambda_cycle):\n    real_image = tf.cast(real_image, tf.float32)\n    same_image = tf.cast(same_image, tf.float32)\n    loss = tf.reduce_mean(tf.abs(real_image - same_image))\n    return lambda_cycle * 0.5 * loss\n\n####################################################################################Callbacks\nimport zipfile\nimport os\n\nclass SaveGeneratedImagesToZip(Callback):\n    def __init__(self, generator, dataset, output_zip_path, num_images=7000, batch_size=16):\n        self.generator = generator\n        self.dataset = dataset\n        self.output_zip_path = output_zip_path\n        self.num_images = num_images\n        self.batch_size = batch_size\n\n    def on_epoch_end(self, epoch, logs=None):\n        generated_count = 0  # Reset count at the start of each epoch\n        ds_iter = iter(self.dataset)\n\n        # Open the zip file in write mode to overwrite the existing file\n        with zipfile.ZipFile(self.output_zip_path, 'w') as zipf:\n            while generated_count < self.num_images:\n                input_images = next(ds_iter)\n                generated_images = self.generator(input_images, training=False).numpy()\n                generated_images = (generated_images * 0.5) + 0.5  # Rescale to [0, 1]\n                \n                for i in range(min(self.batch_size, self.num_images - generated_count)):\n                    img = Image.fromarray((generated_images[i] * 255).astype(np.uint8))\n                    img = img.resize((256, 256))  # Resize to 256x256\n                    img_filename = f\"generated_img_{generated_count + 1}.jpg\"\n\n                    # Save the image directly to the zip file\n                    with zipf.open(img_filename, 'w') as img_file:\n                        img.save(img_file, format='JPEG')\n                    \n                    generated_count += 1\n                    if generated_count >= self.num_images:\n                        break\n\n\nclass SaveCheckpointCallback(tf.keras.callbacks.Callback):\n    def on_epoch_end(self, epoch, logs=None):\n        # Save the checkpoint\n        checkpoint_manager.save(checkpoint_number=epoch)\n        print(f\"Checkpoint saved at epoch {epoch + 1}\")\n\n###################################################Save weights and models\n\n\n\n\nimport os\nimport tensorflow as tf\n\n##########################################################################\nwith strategy.scope():\n    # Create the generators and discriminators\n    monet_generator = generator_fn()\n    photo_generator = generator_fn()\n    monet_discriminator = discriminator_fn()\n    photo_discriminator = discriminator_fn()\n\n\n    # Create and compile the CycleGAN model with the optimizers and loss functions\n    cyclegan = CycleGAN(\n        monet_generator,\n        photo_generator,\n        monet_discriminator,\n        photo_discriminator\n    )\n\n    # Compile the model\n    cyclegan.compile(\n        m_gen_optimizer=optimizers.Adam(GENERATOR_LR, beta_1=0.5),\n        p_gen_optimizer=optimizers.Adam(GENERATOR_LR, beta_1=0.5),\n        m_disc_optimizer=optimizers.Adam(DISCRIMINATOR_LR, beta_1=0.5),\n        p_disc_optimizer=optimizers.Adam(DISCRIMINATOR_LR, beta_1=0.5),\n        gen_loss_fn=generator_loss,\n        disc_loss_fn=discriminator_loss,\n        cycle_loss_fn=cycle_loss,\n        identity_loss_fn=identity_loss,\n    )\n\n\n    monet_ds = get_dataset(MONET_FILENAMES, augment=data_augment, batch_size=BATCH_SIZE)\n    photo_ds = get_dataset(PHOTO_FILENAMES, augment=data_augment, batch_size=BATCH_SIZE)\n    train_ds = tf.data.Dataset.zip((monet_ds, photo_ds))\n\n    output_zip_path = '/kaggle/working/images.zip'\n    save_images_to_zip_callback = SaveGeneratedImagesToZip(\n        generator=monet_generator,\n        dataset=photo_ds,\n        output_zip_path=output_zip_path,\n        num_images=7000,  # Set to the desired number of images (e.g., 7000-10000)\n        batch_size=BATCH_SIZE\n    )\n\n    # Define the checkpoint directory and prefix\n    checkpoint_dir = './checkpoints'\n    checkpoint_prefix = os.path.join(checkpoint_dir, \"ckpt\")\n\n    # Create a checkpoint object\n    checkpoint = tf.train.Checkpoint(\n        monet_generator=monet_generator,\n        photo_generator=photo_generator,\n        monet_discriminator=monet_discriminator,\n        photo_discriminator=photo_discriminator,\n        m_gen_optimizer=cyclegan.m_gen_optimizer,\n        p_gen_optimizer=cyclegan.p_gen_optimizer,\n        m_disc_optimizer=cyclegan.m_disc_optimizer,\n        p_disc_optimizer=cyclegan.m_disc_optimizer\n    )\n\n    # Create a checkpoint manager\n    checkpoint_manager = tf.train.CheckpointManager(\n        checkpoint, directory=checkpoint_dir, max_to_keep=5)\n    # Restore the latest checkpoint if it exists\n    if checkpoint_manager.latest_checkpoint:\n        checkpoint.restore(checkpoint_manager.latest_checkpoint)\n        print('Latest checkpoint restored from {}'.format(checkpoint_manager.latest_checkpoint))\n        # Extract the epoch number from the checkpoint filename\n        initial_epoch = int(checkpoint_manager.latest_checkpoint.split('-')[-1])\n    else:\n        print('Starting training from scratch.')\n        initial_epoch = 0\n\n    # Instantiate the checkpoint callback\n    save_checkpoint_callback = SaveCheckpointCallback()\n\n    # Train the model\n    try:\n        cyclegan.fit(\n            train_ds,\n            epochs=EPOCHS,\n            initial_epoch=initial_epoch,\n            steps_per_epoch=(max(n_monet_samples, n_photo_samples) // BATCH_SIZE),\n            callbacks=[save_images_to_zip_callback, save_checkpoint_callback]\n        )\n    except KeyboardInterrupt:\n        checkpoint_manager.save()\n        print('Training interrupted. Checkpoint saved.')\n\n#cyclegan.fit(train_ds, epochs=EPOCHS, steps_per_epoch=(max(n_monet_samples, n_photo_samples) // BATCH_SIZE))\n\n#create_gif('/kaggle/working/monet/*.png', 'monet.gif')\n\n#display_generated_samples = lambda ds, model, n: [plt.imshow(model(next(iter(ds)), training=False)[0] * 0.5 + 0.5) for _ in range(n)]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T19:46:26.506495Z","iopub.execute_input":"2024-12-03T19:46:26.506988Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''import matplotlib.pyplot as plt\n\ndef display_generated_samples(ds, model, n):\n    ds_iter = iter(ds)\n    for i in range(n):\n        input_image = next(ds_iter)\n        generated_image = model(input_image, training=False)[0].numpy()  # Take the first image from the batch\n        generated_image = (generated_image * 0.5) + 0.5  # Rescale from [-1, 1] to [0, 1]\n        \n        plt.figure()  # Create a new figure for each image\n        plt.imshow(generated_image)\n        plt.axis('off')\n        plt.title(f'Generated Sample {i + 1}')\n        plt.show()\n\n# Usage\ndisplay_generated_samples(photo_ds, monet_generator, 5)'''\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!rm -rf /kaggle/working/*\n\n#!kaggle competitions submit -c gan-getting-started -f images.zip -m \"Generated Images Submission\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T19:52:42.073878Z","iopub.execute_input":"2024-12-03T19:52:42.074388Z","iopub.status.idle":"2024-12-03T19:52:43.484941Z","shell.execute_reply.started":"2024-12-03T19:52:42.074338Z","shell.execute_reply":"2024-12-03T19:52:43.483379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''import os\nimport zipfile\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3, preprocess_input\nfrom tensorflow.keras.preprocessing import image\nfrom scipy.linalg import sqrtm\n\n# Extract images.zip\nwith zipfile.ZipFile('/kaggle/working/images.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/generated_images')\n\ndef load_images(image_dir, image_size=(299, 299), batch_size=16):\n    # Load and preprocess images from the given directory\n    images = []\n    for img_name in os.listdir(image_dir):\n        img_path = os.path.join(image_dir, img_name)\n        img = image.load_img(img_path, target_size=image_size)\n        img = image.img_to_array(img)\n        images.append(img)\n        if len(images) == batch_size:\n            yield np.array(images)\n            images = []\n    if images:\n        yield np.array(images)\n\ndef calculate_activations(model, image_dir, batch_size=16):\n    activations = []\n    for batch in load_images(image_dir, batch_size=batch_size):\n        batch = preprocess_input(batch)\n        batch_activations = model.predict(batch)\n        activations.append(batch_activations)\n    return np.concatenate(activations, axis=0)\n\ndef calculate_statistics(activations):\n    # Calculate mean and covariance of the activations\n    mu = np.mean(activations, axis=0)\n    sigma = np.cov(activations, rowvar=False)\n    return mu, sigma\n\ndef calculate_fid(mu1, sigma1, mu2, sigma2):\n    # Calculate the Fréchet Inception Distance between two sets of statistics\n    diff = mu1 - mu2\n    covmean, _ = sqrtm(sigma1.dot(sigma2), disp=False)\n    if np.iscomplexobj(covmean):\n        covmean = covmean.real\n    fid = diff.dot(diff) + np.trace(sigma1 + sigma2 - 2.0 * covmean)\n    return fid\n\ndef calculate_mifid(real_image_dir, generated_image_dir, batch_size=16):\n    # Load InceptionV3 model for feature extraction\n    inception_model = InceptionV3(include_top=False, pooling='avg', input_shape=(299, 299, 3))\n\n    # Calculate activations for real and generated images\n    real_activations = calculate_activations(inception_model, real_image_dir, batch_size=batch_size)\n    generated_activations = calculate_activations(inception_model, generated_image_dir, batch_size=batch_size)\n\n    # Calculate statistics (mean and covariance) for real and generated images\n    mu_real, sigma_real = calculate_statistics(real_activations)\n    mu_generated, sigma_generated = calculate_statistics(generated_activations)\n\n    # Calculate MiFID\n    mifid = calculate_fid(mu_real, sigma_real, mu_generated, sigma_generated)\n    return mifid\n\n# Example usage\nreal_image_dir = '/kaggle/input/gan-getting-started/photo_jpg'\ngenerated_image_dir = '/kaggle/working/generated_images'\nmifid_value = calculate_mifid(real_image_dir, generated_image_dir, batch_size=16)\nprint(f'MiFID: {mifid_value}')\n'''","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}