{"metadata":{"accelerator":"GPU","colab":{"provenance":[{"file_id":"1BOQzvuzLLpeqG9nVcZ_SnztjXN8eJ4Sz","timestamp":1711052038871}],"gpuType":"V100","machine_shape":"hm"},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Import Dependencies","metadata":{"id":"hz4hcUHanTcv"}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport time\nimport os\nimport numpy as np\nfrom kaggle_datasets import KaggleDatasets","metadata":{"id":"49CEbidjLQ7K","executionInfo":{"status":"ok","timestamp":1711052733963,"user_tz":-120,"elapsed":10780,"user":{"displayName":"Ido","userId":"11603344171634062955"}},"outputId":"90976f9b-da95-49c4-d96a-09b33987bdc5","execution":{"iopub.status.busy":"2024-03-21T21:09:19.855089Z","iopub.execute_input":"2024-03-21T21:09:19.855541Z","iopub.status.idle":"2024-03-21T21:09:19.861646Z","shell.execute_reply.started":"2024-03-21T21:09:19.855507Z","shell.execute_reply":"2024-03-21T21:09:19.860495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Setup TPU strategy (For using TPU runtime)\nfor TPU runtimes, doesnt hurt GPU runtimes","metadata":{"id":"HlmSUctfnrer"}},{"cell_type":"code","source":"try:\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)\n   # strategy = tf.distribute.Strategy.experimental_run_v2(tpu)\nexcept:\n    strategy = tf.distribute.get_strategy()\nprint('Number of replicas:', strategy.num_replicas_in_sync)","metadata":{"id":"ojzzfqeq9Dxv","executionInfo":{"status":"ok","timestamp":1711052733964,"user_tz":-120,"elapsed":10,"user":{"displayName":"Ido","userId":"11603344171634062955"}},"outputId":"eb138dd4-0dae-41bd-bc27-a7557010cf24","execution":{"iopub.status.busy":"2024-03-21T21:09:19.865325Z","iopub.execute_input":"2024-03-21T21:09:19.865976Z","iopub.status.idle":"2024-03-21T21:09:19.87654Z","shell.execute_reply.started":"2024-03-21T21:09:19.865932Z","shell.execute_reply":"2024-03-21T21:09:19.875211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Load Images","metadata":{"id":"P7BkwG5On58K"}},{"cell_type":"code","source":"GCS_PATH = KaggleDatasets().get_gcs_path()\nMONET_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/monet_jpg/*.jpg'))\nprint('Monet JPG Files:', len(MONET_FILENAMES))\n\nPHOTO_FILENAMES = tf.io.gfile.glob(str(GCS_PATH + '/photo_jpg/*.jpg'))\nprint('Photo JPG Files:', len(PHOTO_FILENAMES))\n\n# Function to load and preprocess images\ndef load(image_file):\n    image = tf.io.read_file(image_file)\n    image = tf.image.decode_jpeg(image)\n    return image\n\n# Create TensorFlow datasets\nmonet_ds = tf.data.Dataset.list_files(str(GCS_PATH + '/monet_jpg/*.jpg')).map(load).take(100)\nphoto_ds = tf.data.Dataset.list_files(str(GCS_PATH + '/photo_jpg/*.jpg')).map(load).take(250)","metadata":{"id":"O7AxixgOPYVo","execution":{"iopub.status.busy":"2024-03-21T21:09:19.878162Z","iopub.execute_input":"2024-03-21T21:09:19.878675Z","iopub.status.idle":"2024-03-21T21:09:22.379967Z","shell.execute_reply.started":"2024-03-21T21:09:19.878646Z","shell.execute_reply":"2024-03-21T21:09:22.376803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{"id":"lkdD5cEd8rWQ"}},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\n\nfor i, img in enumerate(monet_ds.take(4)):\n  plt.subplot(2,4,i+1)\n  plt.imshow(img)\n\nfor i, img in enumerate(photo_ds.take(4)):\n  plt.subplot(2,4,i+5)\n  plt.imshow(img)\n\nplt.show()","metadata":{"id":"7YjNWqakP9C3","executionInfo":{"status":"ok","timestamp":1711052809686,"user_tz":-120,"elapsed":4732,"user":{"displayName":"Ido","userId":"11603344171634062955"}},"outputId":"d2db5bb8-d11f-4808-a689-a070d9a9e5b5","execution":{"iopub.status.busy":"2024-03-21T21:09:22.381614Z","iopub.execute_input":"2024-03-21T21:09:22.381975Z","iopub.status.idle":"2024-03-21T21:09:24.644546Z","shell.execute_reply.started":"2024-03-21T21:09:22.381945Z","shell.execute_reply":"2024-03-21T21:09:24.64339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Photo\nPHOTO_DATASET_SIZE = len(photo_ds)\n\ntrain_size = int(0.8 * PHOTO_DATASET_SIZE)\ntest_size = int(0.2 * PHOTO_DATASET_SIZE)\nBUFFER_SIZE = 1000\n\nphoto_ds = photo_ds.shuffle(BUFFER_SIZE)\n\ntrain_photo_ds = photo_ds.take(train_size)\n\ntest_photo_ds = photo_ds.skip(train_size)\ntest_photo_ds = photo_ds.take(test_size)\n\n\n# Monet\nMONET_DATASET_SIZE = len(monet_ds)\nBUFFER_SIZE = 1000\n\nmonet_ds = monet_ds.shuffle(BUFFER_SIZE)\n\ntrain_monet_ds = monet_ds\n","metadata":{"id":"9YZhov45U7jS","execution":{"iopub.status.busy":"2024-03-21T21:09:24.646895Z","iopub.execute_input":"2024-03-21T21:09:24.647785Z","iopub.status.idle":"2024-03-21T21:09:24.666209Z","shell.execute_reply.started":"2024-03-21T21:09:24.647753Z","shell.execute_reply":"2024-03-21T21:09:24.664938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Resize and preprocess images","metadata":{"id":"zRX-GYaLoDXG"}},{"cell_type":"code","source":"IMG_HEIGHT = 320\nIMG_WIDTH = 320\nBATCH_SIZE = 3\n\n\ndef resize(image):\n  image = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])\n  return image\n\n# normalizing the images to [-1, 1]\ndef normalize(image):\n  image = tf.cast(image, tf.float32)\n  image = (image / 127.5) - 1\n  return image\n\ndef denormalize(image):\n  image = tf.cast(image, tf.float32)\n  image = (image * 0.5 + 0.5) * 255 # Range 0 to 1 and then to range 0..255\n  image = tf.cast(image, tf.int32)\n  return image\n\ndef random_crop(image):\n  cropped_image = tf.image.random_crop(\n      image, size=[IMG_HEIGHT, IMG_WIDTH, 3])\n\n  return cropped_image\n\ndef random_jitter(image):\n  # resizing to 350 x 350 x 3\n  image = tf.image.resize(image, [350, 350],\n                          method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)\n\n  image = random_crop(image)\n\n  # random mirroring\n  image = tf.image.random_flip_left_right(image)\n\n  return image\n\ndef preprocess_image_train(image):\n  image = resize(image)\n  image = random_jitter(image)\n  image = normalize(image)\n  return image\n\ndef preprocess_image_test(image):\n  image = resize(image)\n  image = normalize(image)\n  return image","metadata":{"id":"10ukTYQOVoj-","execution":{"iopub.status.busy":"2024-03-21T21:09:24.667772Z","iopub.execute_input":"2024-03-21T21:09:24.668117Z","iopub.status.idle":"2024-03-21T21:09:24.679289Z","shell.execute_reply.started":"2024-03-21T21:09:24.668081Z","shell.execute_reply":"2024-03-21T21:09:24.678077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_photo_ds = train_photo_ds.map(\n    preprocess_image_train).cache().shuffle(\n    BUFFER_SIZE).batch(BATCH_SIZE)\n\ntest_photo_ds = test_photo_ds.map(\n    preprocess_image_test).cache().shuffle(\n    BUFFER_SIZE).batch(BATCH_SIZE)\n\ntrain_monet_ds = train_monet_ds.map(\n    preprocess_image_train).cache().shuffle(\n    BUFFER_SIZE).batch(BATCH_SIZE)","metadata":{"id":"ikmGxlFQVzZG","execution":{"iopub.status.busy":"2024-03-21T21:09:24.680719Z","iopub.execute_input":"2024-03-21T21:09:24.681145Z","iopub.status.idle":"2024-03-21T21:09:25.003685Z","shell.execute_reply.started":"2024-03-21T21:09:24.681088Z","shell.execute_reply":"2024-03-21T21:09:25.002651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\n\nfor i, img in enumerate(train_monet_ds.take(4)):\n  plt.subplot(2,4,i+1)\n  plt.imshow(denormalize(img[0,...]), vmin=0, vmax=255) # first dimension (batch) is eliminated and we denormalize the image\n\nfor i, img in enumerate(train_photo_ds.take(4)):\n  plt.subplot(2,4,i+5)\n  plt.imshow(denormalize(img[0,...]), vmin=0, vmax=255) # first dimension (batch) is eliminated and we denormalize the image\n\nplt.show()","metadata":{"id":"jDQaGTaZWl1d","execution":{"iopub.status.busy":"2024-03-21T21:09:25.00529Z","iopub.execute_input":"2024-03-21T21:09:25.006084Z","iopub.status.idle":"2024-03-21T21:09:50.187714Z","shell.execute_reply.started":"2024-03-21T21:09:25.006043Z","shell.execute_reply":"2024-03-21T21:09:50.186682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Build the Generator\nThe architecture of the generator consists of an encoder block and a decoder block, each of them is made up of simpler blocks of layers:\n\nEach block of the encoder, we call it downsample-k where k denotes the number of filters, this block performs an image compression operation (downsample). It consists of the following layers:\n* Convolution\n* Instance Normalization (not apply to the first block)\n* Leaky ReLU\n\nIn the decoder we can find two types of blocks, depending on whether a dropout operation is performed or not, we will call each one of them upsampleD-k and upsample-k, since they are performing a decompression. Each of these blocks is made up of:\n* Transposed Convolution\n* Instance Normalization\n* Dropout (applied to the first 3 blocks)\n* ReLU","metadata":{"id":"QXCu2MgNoN2B"}},{"cell_type":"markdown","source":"","metadata":{"id":"XhuA2BrmoNiy"}},{"cell_type":"code","source":"def downsample(filters, kernel_size=4, strides=2, apply_norm=True):\n  result = keras.Sequential()\n\n  initializer = tf.random_normal_initializer(0,0.02)\n\n  # Convolutional layer\n  result.add(layers.Conv2D(filters,\n                    kernel_size=kernel_size,\n                    strides=strides,\n                    padding=\"same\",\n                    kernel_initializer=initializer,\n                    use_bias=not apply_norm)) # when applying Normalization you already have the bias implicit\n\n  # Normalization layer\n\n  # Activation layer\n  result.add(layers.LeakyReLU())\n\n  return result","metadata":{"id":"gmNubw9MqiHF","execution":{"iopub.status.busy":"2024-03-21T21:09:50.188857Z","iopub.execute_input":"2024-03-21T21:09:50.189922Z","iopub.status.idle":"2024-03-21T21:09:50.196955Z","shell.execute_reply.started":"2024-03-21T21:09:50.189889Z","shell.execute_reply":"2024-03-21T21:09:50.195458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upsample(filters, kernel_size=4, strides=2, apply_dropout=True):\n  result = keras.Sequential()\n\n  initializer = tf.random_normal_initializer(0,0.02)\n\n  # Transpose convolutional layer\n  result.add(layers.Conv2DTranspose(filters,\n                            kernel_size=kernel_size,\n                            strides=strides,\n                            padding=\"same\",\n                            kernel_initializer=initializer,\n                            use_bias=False)) # when applying BatchNormalization already has implicit bias\n\n  # Normalization layer\n\n  # Dropout layer\n  if apply_dropout:\n    result.add(layers.Dropout(0.5))\n\n  # Activation layer\n  result.add(layers.ReLU())\n\n  return result\n","metadata":{"id":"m3-R-HazqppZ","execution":{"iopub.status.busy":"2024-03-21T21:09:50.198422Z","iopub.execute_input":"2024-03-21T21:09:50.198826Z","iopub.status.idle":"2024-03-21T21:09:50.215619Z","shell.execute_reply.started":"2024-03-21T21:09:50.198789Z","shell.execute_reply":"2024-03-21T21:09:50.214471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Generator():\n\n  inputs = layers.Input(shape=[IMG_HEIGHT,IMG_WIDTH,3])\n\n  down_stack = [\n                downsample(64, apply_norm=False),\n                downsample(128),\n                downsample(256),\n                downsample(512),\n                downsample(512),\n                downsample(512),\n                downsample(512, kernel_size=5, strides=5),\n  ]\n\n  up_stack = [\n                upsample(512, kernel_size=5, strides=5),\n                upsample(512),\n                upsample(512, apply_dropout=False),\n                upsample(256, apply_dropout=False),\n                upsample(128, apply_dropout=False),\n                upsample(64, apply_dropout=False),\n  ]\n\n  # Output layer\n  initializer = tf.random_normal_initializer(0,0.02)\n  last = layers.Conv2DTranspose(filters = 3, # Number of image channels\n                                kernel_size=4,\n                                strides=2,\n                                padding=\"same\",\n                                kernel_initializer=initializer,\n                                activation=\"tanh\" # output -1 to 1\n                                )\n\n  x = inputs\n  skips = []\n\n  # We add the Encoder blocks to the model and save the outputs to later perform the Skip Connections\n  for down in down_stack:\n    x = down(x)\n    skips.append(x)\n\n\n  # We eliminate the last layer of the Skips Connections,\n  # since it will be a direct input in the first block of the Decoder\n  # and we turn the Skips around since the second layer must connect\n  # with the penultimate output of the Encoder, the third with the penultimate .\n  # and so on successively\n  skips = reversed(skips[:-1])\n\n  # We add the Decoder blocks to the model and sthe Skip Connections\n  for up, skip in zip(up_stack, skips):\n    x = up(x)\n    x = layers.Concatenate()([x,skip])\n  x = last(x)\n\n  return keras.Model(inputs=inputs, outputs=x)\n","metadata":{"id":"QpCotwijqyim","execution":{"iopub.status.busy":"2024-03-21T21:09:50.221069Z","iopub.execute_input":"2024-03-21T21:09:50.221473Z","iopub.status.idle":"2024-03-21T21:09:50.232668Z","shell.execute_reply.started":"2024-03-21T21:09:50.221435Z","shell.execute_reply":"2024-03-21T21:09:50.231276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"generator_g = Generator()\ntf.keras.utils.plot_model(generator_g, show_shapes=True, dpi=64)","metadata":{"id":"HcBIaB9erCw4","execution":{"iopub.status.busy":"2024-03-21T21:09:50.233822Z","iopub.execute_input":"2024-03-21T21:09:50.234191Z","iopub.status.idle":"2024-03-21T21:09:51.00507Z","shell.execute_reply.started":"2024-03-21T21:09:50.234158Z","shell.execute_reply":"2024-03-21T21:09:51.003905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Build the Discriminator\nThe task of the discriminator is whether an input image is original or fake (the output of a generator)\n\nThe architecture of the discriminator is a convolution network of the PatchGAN type, instead of returning whether the image is real or not, this architecture returns whether pieces of the image can be considered real or false. consisting of an encoder blockmade up of simpler blocks of layers:\n\nAs in the generator, the encoder is made up of downsample-k blocks, this block performs an image compression operation (downsample). It consists of the following layers\n\n* Convolution\n* Instance Normalization (not apply to the first block)\n* Leaky ReLU\n\nSo the already implemented function is used \"downsample\", all convolutional layers of downsample, have the parameter strides = 2, which causes the dimensions to be reduced by half.","metadata":{"id":"97nfHBF_q7I4"}},{"cell_type":"code","source":"def Discriminator():\n\n  ini = layers.Input(shape=[IMG_HEIGHT, IMG_WIDTH, 3], name=\"input_img\")\n\n  down1 = downsample(64, apply_norm=False)(ini)\n  down2 = downsample(128)(down1)\n  down3 = downsample(256)(down2)\n\n  zero_pad1 = tf.keras.layers.ZeroPadding2D()(down3)\n\n  initializer = tf.random_normal_initializer(0., 0.02)\n  conv = tf.keras.layers.Conv2D(512,\n                                kernel_size=4,\n                                strides=1,\n                                kernel_initializer=initializer,\n                                use_bias=False)(zero_pad1)\n\n  gamma_init = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n\n  leaky_relu = tf.keras.layers.LeakyReLU()(conv)\n\n  zero_pad2 = tf.keras.layers.ZeroPadding2D()(leaky_relu)\n\n  last = tf.keras.layers.Conv2D(1,\n                                kernel_size=4,\n                                strides=1,\n                                kernel_initializer=initializer)(zero_pad2)\n\n  return keras.Model(inputs=ini, outputs=last)\n","metadata":{"id":"1hCFMhKtzrC_","execution":{"iopub.status.busy":"2024-03-21T21:09:51.006588Z","iopub.execute_input":"2024-03-21T21:09:51.006936Z","iopub.status.idle":"2024-03-21T21:09:51.016078Z","shell.execute_reply.started":"2024-03-21T21:09:51.006907Z","shell.execute_reply":"2024-03-21T21:09:51.014889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"discriminator_y = Discriminator()\ntf.keras.utils.plot_model(discriminator_y, show_shapes=True, dpi=64)","metadata":{"id":"ZCCREhOe0NvA","execution":{"iopub.status.busy":"2024-03-21T21:09:51.017571Z","iopub.execute_input":"2024-03-21T21:09:51.018745Z","iopub.status.idle":"2024-03-21T21:09:51.197965Z","shell.execute_reply.started":"2024-03-21T21:09:51.018698Z","shell.execute_reply":"2024-03-21T21:09:51.196778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Build the entire Model\nthe complete model consists of:  \n\n2 generators (generator_monet and generator_photo)\n* The generator_monet generator learns how to transform a photograph into a Monet painting\n\n* The generator_photo generator learns how to transform a Monet painting into a photograph\n\n* As the images are not paired, it is necessary to use two cycles\n  * Input Photo -> generator_monet -> Fake Monet -> generator_photo -> Cycle Photo\n  * Input Monet -> generator_photo -> Fake Photo -> generator_monet -> Cycle Monet  \n\n2 discriminators (discriminator_monet AND discriminator_photo)\n* The discriminator_monet discriminator learns to differentiate if a Monet painting is real or fake, serving to calculate the adversary loss and improve the generator_monet generator\n\n* The discriminator_photo discriminator learns to differentiate if a photo is real or fake, serving to calculate the adversary loss and improve the generator_photo generator\n\n* As the images are not paired, to calculate the loss of the discriminators, each one of them is executed twice, one with a real image and another with the fake image generated.","metadata":{"id":"pcLjQobMropT"}},{"cell_type":"code","source":"with strategy.scope():\n  generator_monet = Generator()\n  generator_photo = Generator()\n\n  discriminator_monet = Discriminator()\n  discriminator_photo = Discriminator()","metadata":{"id":"ZRa7xuEh0noO","execution":{"iopub.status.busy":"2024-03-21T21:09:51.199705Z","iopub.execute_input":"2024-03-21T21:09:51.200544Z","iopub.status.idle":"2024-03-21T21:09:52.604312Z","shell.execute_reply.started":"2024-03-21T21:09:51.20038Z","shell.execute_reply":"2024-03-21T21:09:52.603223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_object = keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)","metadata":{"id":"FiRCxtMi1YOp","execution":{"iopub.status.busy":"2024-03-21T21:09:52.605788Z","iopub.execute_input":"2024-03-21T21:09:52.606111Z","iopub.status.idle":"2024-03-21T21:09:52.611544Z","shell.execute_reply.started":"2024-03-21T21:09:52.606083Z","shell.execute_reply":"2024-03-21T21:09:52.61047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n  def discriminator_loss(disc_real_output, disc_generated_output):\n    #compare the real image with a matrix of 1. (All Ok)\n    real_loss = loss_object(tf.ones_like(disc_real_output), disc_real_output)\n\n    #compare the fake image with a matrix of 0 (All Fake)\n    generated_loss = loss_object(tf.zeros_like(disc_generated_output), disc_generated_output)\n\n    total_disc_loss = (real_loss + generated_loss) / 2\n\n    return total_disc_loss","metadata":{"id":"Y5DpMJL31dma","execution":{"iopub.status.busy":"2024-03-21T21:09:52.612951Z","iopub.execute_input":"2024-03-21T21:09:52.613858Z","iopub.status.idle":"2024-03-21T21:09:52.624875Z","shell.execute_reply.started":"2024-03-21T21:09:52.613827Z","shell.execute_reply":"2024-03-21T21:09:52.623589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n  def generator_adversarial_loss(disc_generated_output):\n    return loss_object(tf.ones_like(disc_generated_output), disc_generated_output)","metadata":{"id":"ArYKSU_f1mg6","execution":{"iopub.status.busy":"2024-03-21T21:09:52.626318Z","iopub.execute_input":"2024-03-21T21:09:52.62677Z","iopub.status.idle":"2024-03-21T21:09:52.637089Z","shell.execute_reply.started":"2024-03-21T21:09:52.626737Z","shell.execute_reply":"2024-03-21T21:09:52.636156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n  def generator_calc_cycle_loss(real_image, cycled_image, param_lambda):\n    loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))\n\n    return param_lambda * loss1","metadata":{"id":"O0G2UadR1pwp","execution":{"iopub.status.busy":"2024-03-21T21:09:52.638662Z","iopub.execute_input":"2024-03-21T21:09:52.639362Z","iopub.status.idle":"2024-03-21T21:09:52.649493Z","shell.execute_reply.started":"2024-03-21T21:09:52.639322Z","shell.execute_reply":"2024-03-21T21:09:52.648442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n  def generator_identity_loss(real_image, same_image, param_lambda):\n    loss = tf.reduce_mean(tf.abs(real_image - same_image))\n    return param_lambda * 0.5 * loss","metadata":{"id":"oyo7kpzw1s2u","execution":{"iopub.status.busy":"2024-03-21T21:09:52.651036Z","iopub.execute_input":"2024-03-21T21:09:52.651507Z","iopub.status.idle":"2024-03-21T21:09:52.665286Z","shell.execute_reply.started":"2024-03-21T21:09:52.651465Z","shell.execute_reply":"2024-03-21T21:09:52.664316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    generator_monet_optimizer = tf.keras.optimizers.Adam(1e-3, beta_1=0.5)\n    generator_photo_optimizer = tf.keras.optimizers.Adam(1e-3, beta_1=0.5)\n\n    discriminator_monet_optimizer = tf.keras.optimizers.Adam(1e-3, beta_1=0.5)\n    discriminator_photo_optimizer = tf.keras.optimizers.Adam(1e-3, beta_1=0.5)","metadata":{"id":"kik5VC4x1vzs","execution":{"iopub.status.busy":"2024-03-21T21:09:52.666671Z","iopub.execute_input":"2024-03-21T21:09:52.667205Z","iopub.status.idle":"2024-03-21T21:09:52.68101Z","shell.execute_reply.started":"2024-03-21T21:09:52.667175Z","shell.execute_reply":"2024-03-21T21:09:52.68013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CycleGan(keras.Model):\n    def __init__(\n        self,\n        generator_monet,\n        generator_photo,\n        discriminator_monet,\n        discriminator_photo,\n        lambda_cycle=10,\n        lambda_identity=10\n    ):\n        super(CycleGan, self).__init__()\n        self.generator_monet = generator_monet\n        self.generator_photo = generator_photo\n        self.discriminator_monet = discriminator_monet\n        self.discriminator_photo = discriminator_photo\n        self.lambda_cycle = lambda_cycle\n        self.lambda_identity = lambda_identity\n\n\n    def compile(\n        self,\n        generator_monet_optimizer,\n        generator_photo_optimizer,\n        discriminator_monet_optimizer,\n        discriminator_photo_optimizer,\n        discriminator_loss,\n        generator_adversarial_loss,\n        generator_calc_cycle_loss,\n        generator_identity_loss\n    ):\n        super(CycleGan, self).compile()\n        self.generator_monet_optimizer = generator_monet_optimizer\n        self.generator_photo_optimizer = generator_photo_optimizer\n        self.discriminator_monet_optimizer = discriminator_monet_optimizer\n        self.discriminator_photo_optimizer = discriminator_photo_optimizer\n        self.discriminator_loss = discriminator_loss\n        self.generator_adversarial_loss = generator_adversarial_loss\n        self.generator_calc_cycle_loss = generator_calc_cycle_loss\n        self.generator_identity_loss = generator_identity_loss\n\n\n\n    def train_step(self, batch_data):\n\n        monet, photo = batch_data\n\n        with tf.GradientTape(persistent=True) as tape:\n            # Get Predictions\n            # from photo we generate Monet (fake) and regenerate the photo again (cycle)\n            gen_output_monet_fake = self.generator_monet(photo, training=False)\n            gen_output_photo_cycle = self.generator_photo(gen_output_monet_fake, training=False)\n\n            # from Monet we generate photo (fake) and regenerate Monet again (cycle)\n            gen_output_photo_fake = self.generator_photo(monet, training=False)\n            gen_output_monet_cycle = self.generator_monet(gen_output_photo_fake, training=False)\n\n            # generating itself are used for identity loss.\n            gen_output_monet_same = self.generator_monet(monet, training=False)\n            gen_output_photo_same = self.generator_photo(photo, training=False)\n\n\n            # Run the discriminator for real Monet (input) and generated Monet (fake)\n            disc_out_monet_real = self.discriminator_monet(monet, training=False)\n            disc_out_monet_fake = self.discriminator_monet(gen_output_monet_fake, training=False)\n\n            # Run the discriminator for Real Photo (input) and Photo (fake)\n            disc_out_photo_real = self.discriminator_photo(photo, training=False)\n            disc_out_photo_fake = self.discriminator_photo(gen_output_photo_fake, training=False)\n\n            # Calculate the loss\n            gen_monet_adversarial_loss = self.generator_adversarial_loss(disc_out_monet_fake)\n            gen_photo_adversarial_loss = self.generator_adversarial_loss(disc_out_photo_fake)\n\n            # evaluates total cycle consistency loss\n            total_cycle_loss = (self.generator_calc_cycle_loss(monet, gen_output_monet_cycle, self.lambda_cycle)\n                                + self.generator_calc_cycle_loss(photo, gen_output_photo_cycle, self.lambda_cycle))\n\n            gen_monet_identity_loss = self.generator_identity_loss(monet, gen_output_monet_same, self.lambda_identity)\n            gen_photo_identity_loss = self.generator_identity_loss(photo, gen_output_photo_same, self.lambda_identity)\n\n            # Total generator loss = adversarial loss + cycle loss + identity loss\n            total_gen_monet_loss = (gen_monet_adversarial_loss + total_cycle_loss + gen_monet_identity_loss)\n            total_gen_photo_loss = (gen_photo_adversarial_loss + total_cycle_loss + gen_photo_identity_loss)\n\n\n            disc_monet_loss = self.discriminator_loss(disc_out_monet_real, disc_out_monet_fake)\n            disc_photo_loss = self.discriminator_loss(disc_out_photo_real, disc_out_photo_fake)\n\n\n        # Calculate the gradients for generator and discriminator\n        gen_monet_gradients = tape.gradient(total_gen_monet_loss,\n                                            self.generator_monet.trainable_variables)\n        gen_photo_gradients = tape.gradient(total_gen_photo_loss,\n                                            self.generator_photo.trainable_variables)\n\n\n        disc_monet_gradients = tape.gradient(disc_monet_loss,\n                                                self.discriminator_monet.trainable_variables)\n        disc_photo_gradients = tape.gradient(disc_photo_loss,\n                                               self.discriminator_photo.trainable_variables)\n\n        # Apply the gradients to the optimizer\n\n\n        self.generator_monet_optimizer.apply_gradients(zip(gen_monet_gradients,\n                                                      self.generator_monet.trainable_variables))\n        self.generator_photo_optimizer.apply_gradients(zip(gen_photo_gradients,\n                                                     self.generator_photo.trainable_variables))\n\n        self.discriminator_monet_optimizer.apply_gradients(zip(disc_monet_gradients,\n                                                         self.discriminator_monet.trainable_variables))\n        self.discriminator_photo_optimizer.apply_gradients(zip(disc_photo_gradients,\n                                                        self.discriminator_photo.trainable_variables))\n\n        return {\n            \"total_gen_monet_loss\": total_gen_monet_loss,\n            \"total_gen_photo_loss\": total_gen_photo_loss,\n            \"disc_monet_loss\": disc_monet_loss,\n            \"disc_photo_loss\": disc_photo_loss\n        }\n","metadata":{"id":"i0AqyUU111Bf","execution":{"iopub.status.busy":"2024-03-21T21:09:52.682537Z","iopub.execute_input":"2024-03-21T21:09:52.682897Z","iopub.status.idle":"2024-03-21T21:09:52.701074Z","shell.execute_reply.started":"2024-03-21T21:09:52.682867Z","shell.execute_reply":"2024-03-21T21:09:52.699564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n  cycle_gan_model = CycleGan(\n      generator_monet, generator_photo, discriminator_monet, discriminator_photo\n  )\n\n  cycle_gan_model.compile(\n      generator_monet_optimizer = generator_monet_optimizer,\n      generator_photo_optimizer = generator_photo_optimizer,\n      discriminator_monet_optimizer = discriminator_monet_optimizer,\n      discriminator_photo_optimizer = discriminator_photo_optimizer,\n      discriminator_loss = discriminator_loss,\n      generator_adversarial_loss = generator_adversarial_loss,\n      generator_calc_cycle_loss = generator_calc_cycle_loss,\n      generator_identity_loss = generator_identity_loss\n  )","metadata":{"id":"QScxQuIn143b","execution":{"iopub.status.busy":"2024-03-21T21:09:52.702358Z","iopub.execute_input":"2024-03-21T21:09:52.70274Z","iopub.status.idle":"2024-03-21T21:09:52.722476Z","shell.execute_reply.started":"2024-03-21T21:09:52.70271Z","shell.execute_reply":"2024-03-21T21:09:52.72133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\n\nt1 = time.process_time()\n\nhistory = cycle_gan_model.fit(\n    tf.data.Dataset.zip((train_photo_ds, train_monet_ds)),\n    epochs=1,\n)\n\nt2 = time.process_time()\n\nprint (\"Accelerator =  ----- Computation time = \" + str(1000*(t2 - t1)) + \"ms\")","metadata":{"id":"QBcBN9sO1-m4","execution":{"iopub.status.busy":"2024-03-21T21:09:52.723968Z","iopub.execute_input":"2024-03-21T21:09:52.724719Z","iopub.status.idle":"2024-03-21T21:19:12.214359Z","shell.execute_reply.started":"2024-03-21T21:09:52.724675Z","shell.execute_reply":"2024-03-21T21:19:12.213549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_images(model, test_input):\n  prediction = model(test_input)\n\n  plt.figure(figsize=(12, 12))\n\n  plt.subplot(1, 2, 1)\n  plt.imshow(test_input[0] * 0.5 + 0.5)\n  plt.title('Input Image')\n  plt.axis('off')\n\n  plt.subplot(1, 2, 2)\n  plt.imshow(prediction[0] * 0.5 + 0.5)\n  plt.title('Predicted Image')\n  plt.axis('off')\n\n  plt.show()","metadata":{"id":"u4MolfuJaqZT","execution":{"iopub.status.busy":"2024-03-21T21:20:35.244135Z","iopub.execute_input":"2024-03-21T21:20:35.244616Z","iopub.status.idle":"2024-03-21T21:20:35.252279Z","shell.execute_reply.started":"2024-03-21T21:20:35.244584Z","shell.execute_reply":"2024-03-21T21:20:35.250795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Assuming 'test_photo_ds' yields images of shape (320, 320, 3)\nimage = next(iter(test_photo_ds))\n\n# Ensure the image is of shape (320, 320, 3) and add a batch dimension\n# Now 'image_batch' has the correct shape for the model\ngenerate_images(generator_monet, image)","metadata":{"id":"XExO23oXatJC","execution":{"iopub.status.busy":"2024-03-21T21:20:37.659505Z","iopub.execute_input":"2024-03-21T21:20:37.660903Z","iopub.status.idle":"2024-03-21T21:20:56.353006Z","shell.execute_reply.started":"2024-03-21T21:20:37.66085Z","shell.execute_reply":"2024-03-21T21:20:56.351803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL\n! mkdir -p ../images","metadata":{"id":"b89WmLsAuerz","execution":{"iopub.status.busy":"2024-03-21T21:21:17.442684Z","iopub.execute_input":"2024-03-21T21:21:17.443153Z","iopub.status.idle":"2024-03-21T21:21:18.643263Z","shell.execute_reply.started":"2024-03-21T21:21:17.443119Z","shell.execute_reply":"2024-03-21T21:21:18.641546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i = 1\nphoto_ds = tf.data.Dataset.list_files(str(GCS_PATH + '/photo_jpg/*.jpg')).map(load).take(7038)\npre_processed_photo_ds = photo_ds.map(\n    preprocess_image_train).cache().shuffle(\n    BUFFER_SIZE).batch(BATCH_SIZE)\n\nfor img in pre_processed_photo_ds:\n    prediction = generator_monet(img, training=False)[0].numpy()\n    prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n    im = PIL.Image.fromarray(prediction)\n    im.save(\"../images/\" + str(i) + \".jpg\")\n    i += 1","metadata":{"id":"Tw3-nEdauhj2","execution":{"iopub.status.busy":"2024-03-21T21:21:22.807668Z","iopub.execute_input":"2024-03-21T21:21:22.808088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")","metadata":{"id":"Xe_vyd00vE_Y","execution":{"iopub.status.busy":"2024-03-21T21:19:12.273306Z","iopub.status.idle":"2024-03-21T21:19:12.273691Z","shell.execute_reply.started":"2024-03-21T21:19:12.273503Z","shell.execute_reply":"2024-03-21T21:19:12.273518Z"},"trusted":true},"execution_count":null,"outputs":[]}]}