{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30558,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Importing Necessary frameworks and Laoding the Data:","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport os\nfrom tensorflow.keras.preprocessing import image\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,"execution":{"iopub.status.busy":"2023-11-30T12:56:37.887450Z","iopub.execute_input":"2023-11-30T12:56:37.887742Z","iopub.status.idle":"2023-11-30T12:56:54.530884Z","shell.execute_reply.started":"2023-11-30T12:56:37.887716Z","shell.execute_reply":"2023-11-30T12:56:54.529921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preporocessing The Images:","metadata":{}},{"cell_type":"code","source":"gan_monet_contents = os.listdir(\"/kaggle/input/gan-getting-started\")","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:56:54.532493Z","iopub.execute_input":"2023-11-30T12:56:54.533065Z","iopub.status.idle":"2023-11-30T12:56:54.541471Z","shell.execute_reply.started":"2023-11-30T12:56:54.533033Z","shell.execute_reply":"2023-11-30T12:56:54.540554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Using the tfrec files, because it's tensorflow friendly:\nmonet_tfrec_path = os.path.join('/kaggle/input/gan-getting-started/', 'monet_tfrec')\nphoto_tfrec_path = os.path.join('/kaggle/input/gan-getting-started/', 'photo_tfrec')","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:03.434366Z","iopub.execute_input":"2023-11-30T12:57:03.435094Z","iopub.status.idle":"2023-11-30T12:57:03.439490Z","shell.execute_reply.started":"2023-11-30T12:57:03.435059Z","shell.execute_reply":"2023-11-30T12:57:03.438574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_description = {\n    'image': tf.io.FixedLenFeature([], tf.string),\n}","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:03.769488Z","iopub.execute_input":"2023-11-30T12:57:03.769845Z","iopub.status.idle":"2023-11-30T12:57:03.774413Z","shell.execute_reply.started":"2023-11-30T12:57:03.769816Z","shell.execute_reply":"2023-11-30T12:57:03.773500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def _parse_function(example_proto):\n    # Parse the input `tf.train.Example` proto using the feature description:\n    parsed_example = tf.io.parse_single_example(example_proto, feature_description)\n    \n    # Decode the image and reshape it:\n    image = tf.io.decode_jpeg(parsed_example['image'])\n    image = tf.image.resize(image, [256, 256])  # Resize to desired size\n    image = (image / 127.5) - 1  # Normalize to [-1, 1]\n    \n    return image","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:04.226557Z","iopub.execute_input":"2023-11-30T12:57:04.227260Z","iopub.status.idle":"2023-11-30T12:57:04.232600Z","shell.execute_reply.started":"2023-11-30T12:57:04.227226Z","shell.execute_reply":"2023-11-30T12:57:04.231579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Gathering the tfrec Monet data:\nmonet_dataset = tf.data.Dataset.list_files(monet_tfrec_path + '/*.tfrec')\nmonet_dataset = monet_dataset.interleave(tf.data.TFRecordDataset, cycle_length=4)\nmonet_dataset = monet_dataset.map(_parse_function)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:04.721473Z","iopub.execute_input":"2023-11-30T12:57:04.722335Z","iopub.status.idle":"2023-11-30T12:57:07.906660Z","shell.execute_reply.started":"2023-11-30T12:57:04.722300Z","shell.execute_reply":"2023-11-30T12:57:07.905666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Gathering the tfrec Photos:\nphoto_dataset = tf.data.Dataset.list_files(photo_tfrec_path + '/*.tfrec')\nphoto_dataset = photo_dataset.interleave(tf.data.TFRecordDataset, cycle_length=4)\nphoto_dataset = photo_dataset.map(_parse_function)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:07.908223Z","iopub.execute_input":"2023-11-30T12:57:07.908516Z","iopub.status.idle":"2023-11-30T12:57:07.947575Z","shell.execute_reply.started":"2023-11-30T12:57:07.908489Z","shell.execute_reply":"2023-11-30T12:57:07.946843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BUFFER_SIZE = 400\nBATCH_SIZE = 32\nmonet_dataset = monet_dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)\nphoto_dataset = photo_dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)\n\nmonet_dataset, photo_dataset","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:07.948594Z","iopub.execute_input":"2023-11-30T12:57:07.948861Z","iopub.status.idle":"2023-11-30T12:57:07.963979Z","shell.execute_reply.started":"2023-11-30T12:57:07.948837Z","shell.execute_reply":"2023-11-30T12:57:07.963137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building The Model:","metadata":{}},{"cell_type":"code","source":"## Generator:\ndef make_generator_model():\n    # Reshaping the images\n    inputs = tf.keras.layers.Input(shape=[256, 256, 3])\n    \n    # Encoder\n    down1 = tf.keras.layers.Conv2D(64, (4, 4), strides=2, padding='same', activation='relu')(inputs)\n    down2 = tf.keras.layers.Conv2D(128, (4, 4), strides=2, padding='same', activation='relu')(down1)\n    down3 = tf.keras.layers.Conv2D(256, (4, 4), strides=2, padding='same', activation='relu')(down2)\n    \n    # Decoder\n    up1 = tf.keras.layers.Conv2DTranspose(128, (4, 4), strides=2, padding='same', activation='relu')(down3)\n    up2 = tf.keras.layers.Conv2DTranspose(64, (4, 4), strides=2, padding='same', activation='relu')(up1)\n    \n    outputs = tf.keras.layers.Conv2DTranspose(3, (4, 4), strides=2, padding='same', activation='tanh')(up2)\n    \n    return tf.keras.Model(inputs=inputs, outputs=outputs)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:10.617366Z","iopub.execute_input":"2023-11-30T12:57:10.618211Z","iopub.status.idle":"2023-11-30T12:57:10.627081Z","shell.execute_reply.started":"2023-11-30T12:57:10.618178Z","shell.execute_reply":"2023-11-30T12:57:10.625969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Discriminator:\ndef make_discriminator_model():\n    inputs = tf.keras.layers.Input(shape=[256, 256, 3])\n    \n    d1 = tf.keras.layers.Conv2D(64, (4, 4), strides=2, padding='same', activation='relu')(inputs)\n    d2 = tf.keras.layers.Conv2D(128, (4, 4), strides=2, padding='same', activation='relu')(d1)\n    d3 = tf.keras.layers.Conv2D(256, (4, 4), strides=2, padding='same', activation='relu')(d2)\n    \n    outputs = tf.keras.layers.Conv2D(1, (4, 4), padding='same')(d3)\n    \n    return tf.keras.Model(inputs=inputs, outputs=outputs)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:11.422499Z","iopub.execute_input":"2023-11-30T12:57:11.422907Z","iopub.status.idle":"2023-11-30T12:57:11.430751Z","shell.execute_reply.started":"2023-11-30T12:57:11.422876Z","shell.execute_reply":"2023-11-30T12:57:11.429691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building The Loss:","metadata":{}},{"cell_type":"code","source":"loss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:12.212931Z","iopub.execute_input":"2023-11-30T12:57:12.213294Z","iopub.status.idle":"2023-11-30T12:57:12.217925Z","shell.execute_reply.started":"2023-11-30T12:57:12.213265Z","shell.execute_reply":"2023-11-30T12:57:12.216954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def discriminator_loss(real, generated):\n    real_loss = loss_object(tf.ones_like(real), real)\n    generated_loss = loss_object(tf.zeros_like(generated), generated)\n    total_disc_loss = real_loss + generated_loss\n    return total_disc_loss","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:12.603070Z","iopub.execute_input":"2023-11-30T12:57:12.603406Z","iopub.status.idle":"2023-11-30T12:57:12.608509Z","shell.execute_reply.started":"2023-11-30T12:57:12.603378Z","shell.execute_reply":"2023-11-30T12:57:12.607454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generator_loss(generated):\n    return loss_object(tf.ones_like(generated), generated)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:12.980050Z","iopub.execute_input":"2023-11-30T12:57:12.980343Z","iopub.status.idle":"2023-11-30T12:57:12.985002Z","shell.execute_reply.started":"2023-11-30T12:57:12.980316Z","shell.execute_reply":"2023-11-30T12:57:12.984033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calc_cycle_loss(real_image, cycled_image, LAMBDA=10):\n    loss = tf.reduce_mean(tf.abs(real_image - cycled_image))\n    return LAMBDA * loss","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:13.403293Z","iopub.execute_input":"2023-11-30T12:57:13.403665Z","iopub.status.idle":"2023-11-30T12:57:13.408517Z","shell.execute_reply.started":"2023-11-30T12:57:13.403636Z","shell.execute_reply":"2023-11-30T12:57:13.407466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Building Model's Parameters:","metadata":{}},{"cell_type":"code","source":"generator_g_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ngenerator_f_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.3)\ndiscriminator_x_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_y_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.3)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:14.052130Z","iopub.execute_input":"2023-11-30T12:57:14.052477Z","iopub.status.idle":"2023-11-30T12:57:14.070218Z","shell.execute_reply.started":"2023-11-30T12:57:14.052450Z","shell.execute_reply":"2023-11-30T12:57:14.069323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"generator_g = make_generator_model()\ngenerator_f = make_generator_model()\ndiscriminator_x = make_discriminator_model()\ndiscriminator_y = make_discriminator_model()","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:14.390224Z","iopub.execute_input":"2023-11-30T12:57:14.390584Z","iopub.status.idle":"2023-11-30T12:57:14.663197Z","shell.execute_reply.started":"2023-11-30T12:57:14.390554Z","shell.execute_reply":"2023-11-30T12:57:14.662182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@tf.function\ndef train_step(real_x, real_y, generator_g, generator_f, discriminator_x, discriminator_y, \n               generator_g_optimizer, generator_f_optimizer, discriminator_x_optimizer, discriminator_y_optimizer):\n    with tf.GradientTape(persistent=True) as tape:\n        # Generate images\n        fake_y = generator_g(real_x, training=True)\n        cycled_x = generator_f(fake_y, training=True)\n\n        fake_x = generator_f(real_y, training=True)\n        cycled_y = generator_g(fake_x, training=True)\n\n        # Discriminator outputs\n        disc_real_x = discriminator_x(real_x, training=True)\n        disc_real_y = discriminator_y(real_y, training=True)\n\n        disc_fake_x = discriminator_x(fake_x, training=True)\n        disc_fake_y = discriminator_y(fake_y, training=True)\n\n        # Generator losses\n        gen_g_loss = generator_loss(disc_fake_y)\n        gen_f_loss = generator_loss(disc_fake_x)\n\n        # Total cycle consistency loss\n        total_cycle_loss = calc_cycle_loss(real_x, cycled_x) + calc_cycle_loss(real_y, cycled_y)\n\n        # Total generator loss\n        total_gen_g_loss = gen_g_loss + total_cycle_loss\n        total_gen_f_loss = gen_f_loss + total_cycle_loss\n\n        # Discriminator losses\n        disc_x_loss = discriminator_loss(disc_real_x, disc_fake_x)\n        disc_y_loss = discriminator_loss(disc_real_y, disc_fake_y)\n\n    # Calculate gradients and apply them\n    generator_g_gradients = tape.gradient(total_gen_g_loss, generator_g.trainable_variables)\n    generator_f_gradients = tape.gradient(total_gen_f_loss, generator_f.trainable_variables)\n\n    discriminator_x_gradients = tape.gradient(disc_x_loss, discriminator_x.trainable_variables)\n    discriminator_y_gradients = tape.gradient(disc_y_loss, discriminator_y.trainable_variables)\n\n    generator_g_optimizer.apply_gradients(zip(generator_g_gradients, generator_g.trainable_variables))\n    generator_f_optimizer.apply_gradients(zip(generator_f_gradients, generator_f.trainable_variables))\n\n    discriminator_x_optimizer.apply_gradients(zip(discriminator_x_gradients, discriminator_x.trainable_variables))\n    discriminator_y_optimizer.apply_gradients(zip(discriminator_y_gradients, discriminator_y.trainable_variables))\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:14.664750Z","iopub.execute_input":"2023-11-30T12:57:14.665031Z","iopub.status.idle":"2023-11-30T12:57:14.675693Z","shell.execute_reply.started":"2023-11-30T12:57:14.665007Z","shell.execute_reply":"2023-11-30T12:57:14.674783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Take a sample of photos for visualization\nsample_photos = next(iter(photo_dataset))\nNUM_SAMPLES = 4  # Number of samples to visualize\n\ndef generate_and_save_images(model, epoch, test_input):\n    predictions = model(test_input, training=False)\n    \n    fig = plt.figure(figsize=(12, 12))\n    \n    for i in range(predictions.shape[0]):\n        plt.subplot(4, 4, i + 1)\n        plt.imshow((predictions[i] + 1) / 2.0)\n        plt.axis('off')\n\n    plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:14.926104Z","iopub.execute_input":"2023-11-30T12:57:14.926427Z","iopub.status.idle":"2023-11-30T12:57:15.541903Z","shell.execute_reply.started":"2023-11-30T12:57:14.926399Z","shell.execute_reply":"2023-11-30T12:57:15.540852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 100\nfor epoch in range(EPOCHS):\n    for photo, monet in tf.data.Dataset.zip((photo_dataset, monet_dataset)):\n        train_step(photo, monet, generator_g, generator_f, discriminator_x, discriminator_y, \n                   generator_g_optimizer, generator_f_optimizer, discriminator_x_optimizer, discriminator_y_optimizer)\n    # Save generated images to visualize progress\n    if epoch % 5 == 0 or epoch == EPOCHS - 1:  # Save images every 5 epochs\n        generate_and_save_images(generator_g, epoch, sample_photos[:NUM_SAMPLES])\n        generator_g.save('generator_g_model_{}.h5'.format(epoch))","metadata":{"execution":{"iopub.status.busy":"2023-11-30T12:57:15.940359Z","iopub.execute_input":"2023-11-30T12:57:15.941345Z","iopub.status.idle":"2023-11-30T13:05:49.424477Z","shell.execute_reply.started":"2023-11-30T12:57:15.941307Z","shell.execute_reply":"2023-11-30T13:05:49.423549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"generator_g = tf.keras.models.load_model('generator_g_model_99.h5')","metadata":{"execution":{"iopub.status.busy":"2023-11-30T13:07:49.792038Z","iopub.execute_input":"2023-11-30T13:07:49.792984Z","iopub.status.idle":"2023-11-30T13:07:49.913501Z","shell.execute_reply.started":"2023-11-30T13:07:49.792951Z","shell.execute_reply":"2023-11-30T13:07:49.912777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_image(image_path):\n    image = tf.io.read_file(image_path)\n    image = tf.io.decode_jpeg(image)\n    image = tf.image.resize(image, [256, 256])\n    image = (tf.cast(image, tf.float32) / 127.5) - 1  # Normalize to [-1, 1]\n    image = tf.expand_dims(image, 0)  # Add batch dimension\n    return image\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T13:07:51.995119Z","iopub.execute_input":"2023-11-30T13:07:51.995486Z","iopub.status.idle":"2023-11-30T13:07:52.001274Z","shell.execute_reply.started":"2023-11-30T13:07:51.995456Z","shell.execute_reply":"2023-11-30T13:07:52.000353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Converting the Photos to Monet Paintings:","metadata":{}},{"cell_type":"code","source":"photo_directory = '/kaggle/input/gan-getting-started/photo_jpg'\noutput_directory = 'converted'\nos.makedirs(output_directory, exist_ok=True)\n\nfor filename in os.listdir(photo_directory):\n    if filename.endswith(\".jpg\"):\n        image_path = os.path.join(photo_directory, filename)\n        input_image = preprocess_image(image_path)\n        transformed_image = generator_g.predict(input_image)\n        transformed_image = (transformed_image + 1) * 127.5  # Denormalize to [0, 255]\n        transformed_image = tf.squeeze(transformed_image).numpy().astype(np.uint8)  # Remove batch dimension and convert to uint8\n\n        # Save the transformed image\n        output_path = os.path.join(output_directory, 'monet_' + filename)\n        tf.keras.preprocessing.image.save_img(output_path, transformed_image)\n","metadata":{"_kg_hide-output":true,"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-11-30T13:07:55.119164Z","iopub.execute_input":"2023-11-30T13:07:55.119539Z","iopub.status.idle":"2023-11-30T13:15:10.431522Z","shell.execute_reply.started":"2023-11-30T13:07:55.119498Z","shell.execute_reply":"2023-11-30T13:15:10.430555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ls converted/","metadata":{"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving The Pictures:","metadata":{}},{"cell_type":"code","source":"!zip -r images.zip converted","metadata":{"execution":{"iopub.status.busy":"2023-11-30T13:15:22.066053Z","iopub.execute_input":"2023-11-30T13:15:22.066980Z","iopub.status.idle":"2023-11-30T13:15:26.872022Z","shell.execute_reply.started":"2023-11-30T13:15:22.066943Z","shell.execute_reply":"2023-11-30T13:15:26.870952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'images.zip')","metadata":{"execution":{"iopub.status.busy":"2023-11-30T13:15:33.687308Z","iopub.execute_input":"2023-11-30T13:15:33.687735Z","iopub.status.idle":"2023-11-30T13:15:33.695260Z","shell.execute_reply.started":"2023-11-30T13:15:33.687698Z","shell.execute_reply":"2023-11-30T13:15:33.694272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## After the training, let's see how they perform:","metadata":{}},{"cell_type":"code","source":"def preprocess_image(image_path):\n    img = image.load_img(image_path, target_size=(256, 256))\n    img = image.img_to_array(img)\n    img = np.expand_dims(img, axis=0)\n    img = (img / 127.5) - 1.0  # Normalize to the range [-1, 1]\n    return img\n\ngenerator_g = tf.keras.models.load_model('/kaggle/working/generator_g_model_99.h5')\nphoto_image_path = '/kaggle/input/gan-getting-started/photo_jpg/00068bc07f.jpg'\ninput_image = preprocess_image(photo_image_path)\ntransformed_image = generator_g.predict(input_image)\ntransformed_image = (transformed_image + 1.0) * 127.5\ntransformed_image = np.clip(transformed_image, 0, 255)\noriginal_image = image.load_img(photo_image_path)\nplt.figure(figsize=(10, 5))\nplt.subplot(1, 2, 1)\nplt.title('Original Photo')\nplt.imshow(original_image)\nplt.axis('off')\nplt.subplot(1, 2, 2)\nplt.title('Monet Style')\nplt.imshow(transformed_image[0].astype(np.uint8))\nplt.axis('off')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T13:15:55.448585Z","iopub.execute_input":"2023-11-30T13:15:55.448950Z","iopub.status.idle":"2023-11-30T13:15:56.147034Z","shell.execute_reply.started":"2023-11-30T13:15:55.448915Z","shell.execute_reply":"2023-11-30T13:15:56.146083Z"},"trusted":true},"execution_count":null,"outputs":[]}]}