{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1. Import libraries "},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import tensorflow as tf \nimport tensorflow_addons as tfa \n\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg \nimport cv2 \nimport os\n\nimport numpy as np\nimport pandas as pd","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2. Set up the input pipeline"},{"metadata":{"trusted":true},"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)\nexcept:\n  strategy = tf.distribute.get_strategy()\n\nprint('Number of replicas:', strategy.num_replicas_in_sync)\n\nprint(tf.__version__)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 3. Hyperparameter config"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMG_WIDTH = 256\nIMG_HEIGTH = 256\nCHANNELS = 3\n\nBATCH_SIZE = 1\nBUFFER_SIZE = 1000\n\n\nAUTOTUNE = tf.data.experimental.AUTOTUNE","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 4. Helper functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"def resize(image):\n  image = tf.image.resize(image, [IMG_HEIGTH, IMG_WIDTH])\n  return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Random Crop \ndef random_crop(image):\n  cropped_image = tf.image.random_crop(image, size = [IMG_HEIGTH, IMG_WIDTH, CHANNELS])\n  return cropped_image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Normalize the pictures to [-1, 1]\ndef normalize(image):\n  image = tf.cast(image, tf.float32)\n  image = (image / 127.5) - 1\n  return image ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def 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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def random_jitter(image):\n  # resize the image to 286 x 286 x 3\n  image = tf.image.resize(image, [286,286], method = tf.image.ResizeMethod.NEAREST_NEIGHBOR)\n\n  # randomly cropping 256 x 256 x 3\n  image = random_crop(image)\n\n  # random mirroring\n  image = tf.image.random_flip_left_right(image)\n\n  return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocess_image_train(image):\n  \"\"\"\n  For preprocessing training images \n  \"\"\"\n  image = resize(image)\n  image = random_jitter(image)\n  image = normalize(image)\n\n  return image ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocess_image_test(image):\n  \"\"\"\n  For preprocessing test images \n  \"\"\"\n  image = resize(image)\n  image = normalize(image)\n\n  return image ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def count_data_items(filenames):\n  \"\"\"\n  Getting the number of files inside your image folder\n  \"\"\"\n  n = [filename for filename in filenames]\n  return len(n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def 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\n  example = tf.io.parse_single_example(example, tfrecord_format)\n  image = tf.image.decode_jpeg(example['image'], channels = 3)\n  return image ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 5. Input Pipeline"},{"metadata":{"trusted":true},"cell_type":"code","source":"MONET_TF_PATH = '../input/gan-getting-started/monet_tfrec'\nPHOTO_TF_PATH = '../input/gan-getting-started/photo_tfrec'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MONET_FILENAMES = tf.io.gfile.glob(MONET_TF_PATH + '/*.tfrec')\nPHOTO_FILENAMES = tf.io.gfile.glob(PHOTO_TF_PATH + '/*.tfrec')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"monet_ds = load_dataset(MONET_FILENAMES, labeled=True)\nphoto_ds = load_dataset(PHOTO_FILENAMES, labeled=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MONET_JPG_PATH = '../input/gan-getting-started/monet_jpg'\nPHOTO_JPG_PATH = '../input/gan-getting-started/photo_jpg'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MONET_DATA_SIZE = count_data_items(tf.io.gfile.glob(MONET_JPG_PATH + '/*.jpg'))\nPHOTO_DATA_SIZE = count_data_items(tf.io.gfile.glob(PHOTO_JPG_PATH + '/*.jpg'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_size = int(0.7 * PHOTO_DATA_SIZE)\ntest_size = int(0.15 * PHOTO_DATA_SIZE)\nval_size = int(0.15 * PHOTO_DATA_SIZE)\nBUFFER_SIZE = 1000\n\nphoto_ds = photo_ds.shuffle(BUFFER_SIZE)\n\ntrain_photo = photo_ds.take(train_size)\ntest_photo = photo_ds.skip(train_size)\ntest_photo = photo_ds.take(test_size)\n\nval_photo = photo_ds.skip(train_size+test_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_size = int(0.7 * MONET_DATA_SIZE)\ntest_size = int(0.15 * MONET_DATA_SIZE)\nval_size = int(0.15 * MONET_DATA_SIZE)\nBUFFER_SIZE = 1000\n\nmonet_ds = monet_ds.shuffle(BUFFER_SIZE)\n\ntrain_monet = monet_ds\n\ntrain_monet = monet_ds.take(train_size)\n\ntest_monet = monet_ds.skip(train_size)\ntest_monet = monet_ds.take(test_size)\n\nval_monet = monet_ds.skip(train_size+test_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_monet = train_monet.map(preprocess_image_train, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)\n\ntest_monet = test_monet.map(preprocess_image_test, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)\n\nval_monet = val_monet.map(preprocess_image_test, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)\n\ntrain_photo = train_photo.map(preprocess_image_train, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)\n\ntest_photo = test_photo.map(preprocess_image_test, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)\n\nval_photo = val_photo.map(preprocess_image_test, \n                              num_parallel_calls=AUTOTUNE).cache().shuffle(BUFFER_SIZE).batch(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(10,10))\n\nfor i, img in enumerate(train_monet.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.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()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 6. Loss function"},{"metadata":{"trusted":true},"cell_type":"code","source":"LAMBDA = 10","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss_obj = tf.keras.losses.BinaryCrossentropy(from_logits=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Discriminator_loss\ndef discriminator_loss(real, generated):\n  real_loss = loss_obj(tf.ones_like(real), real)\n\n  generated_loss = loss_obj(tf.zeros_like(generated), generated)\n\n  total_disc_loss = real_loss + generated_loss\n\n  return total_disc_loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def generated_loss(generated):\n  return loss_obj(tf.ones_like(generated), generated)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def cal_cycle_loss(real_image, cycled_image):\n\n    loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))\n\n    return LAMBDA * loss1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def identity_loss(real_image, same_image):\n\n    loss = tf.reduce_mean(tf.abs(real_image - same_image))\n    \n    return LAMBDA * 0.5 * loss","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 7. Build the Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"def downsample(filters, apply_norm = True):\n\n  result = tf.keras.Sequential()\n\n  initializer = tf.random_normal_initializer(0, 0.02)\n\n  # Convolutional layer \n  result.add(tf.keras.layers.Conv2D(filters, \n                                    kernel_size = 4, \n                                    strides = 2, \n                                    padding = 'same', \n                                    kernel_initializer = initializer, \n                                    use_bias = not apply_norm)) # When applying Normalization you have already have the bias implicit\n  # Normalization layer \n  if apply_norm:\n    gamma_init = tf.keras.initializers.RandomNormal(mean=0.0, stddev = 0.02)\n    result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n\n  # Activation layer \n  result.add(tf.keras.layers.LeakyReLU())\n\n  return result ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def upsample(filters, apply_dropout=True):\n\n  result = tf.keras.Sequential()\n\n  initializer = tf.random_normal_initializer(0, 0.02)\n\n  # Transpose convolutional layer \n  result.add(tf.keras.layers.Conv2DTranspose(filters, \n                                             kernel_size = 4, \n                                             strides = 2,\n                                             padding = 'same',\n                                             kernel_initializer = initializer,\n                                             use_bias = False))\n\n  # Normalization layer \n  gamma_init = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.02)\n  result.add(tfa.layers.InstanceNormalization(gamma_initializer=gamma_init))\n\n  # Dropout layer\n  if apply_dropout:\n    result.add(tf.keras.layers.Dropout(0.5))\n\n  # Activation layer \n  result.add(tf.keras.layers.ReLU())\n\n  return result \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Generator(tf.keras.Model):\n\n  def __init__(self):\n    super(Generator, self).__init__()\n    self.downstack = [downsample(64, apply_norm=False),\n                      downsample(128),\n                      downsample(256),\n                      downsample(512),\n                      downsample(512),\n                      downsample(512),\n                      downsample(512),\n                      downsample(512)]\n\n    self.upstack = [upsample(512),\n                    upsample(512),\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    self.last = tf.keras.layers.Conv2DTranspose(filters = 3,\n                                                kernel_size = 4,\n                                                strides = 2,\n                                                padding = 'same',\n                                                kernel_initializer = tf.random_normal_initializer(0,0.02),\n                                                activation = 'tanh')\n\n  def call(self, inputs, training=False):\n    x = inputs\n    skips = []\n\n    # Add the Encoder blocks to the model and save the outputs to later perform the Skip Connections\n    for down in self.downstack:\n      x = down(x)\n      skips.append(x)\n\n    # We eliminate the last layer of the Skips connections, since it will be a direct input in the first block of Encoder,\n    # and we turn the Skips around since the second layer must connect \n    skips = reversed(skips[:-1])\n\n    # We add the Decoder blocks to the model and the Skips connection\n    for up, skip in zip(self.upstack, skips):\n      x = up(x)\n      x = tf.keras.layers.Concatenate()([x, skip])\n\n    return self.last(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"generator = Generator()\ngenerator.build((None, 256, 256, 3))\ngenerator.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 8. Build the discriminator"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Discriminator(tf.keras.Model):\n\n  def __init__(self):\n    super(Discriminator, self).__init__()\n    self.down1 = downsample(64, apply_norm=False)\n    self.down2 = downsample(128)\n    self.down3 = downsample(256)\n    self.zero_pad1 = tf.keras.layers.ZeroPadding2D()\n    self.conv = tf.keras.layers.Conv2D(filters = 512,\n                                       kernel_size = 4,\n                                       strides = 1,\n                                       kernel_initializer = tf.random_normal_initializer(0., 0.02),\n                                       use_bias = False)\n    self.norm1 = tfa.layers.InstanceNormalization(gamma_initializer=tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.02))\n    self.leaky_relu = tf.keras.layers.LeakyReLU()\n    self.zero_pad2 = tf.keras.layers.ZeroPadding2D()\n    self.last = tf.keras.layers.Conv2D(filters = 1,\n                                       kernel_size = 4,\n                                       strides = 1,\n                                       kernel_initializer = tf.random_normal_initializer(0., 0.02))\n\n  def call(self, inputs, training=False):\n    x = inputs\n    down_x = self.down3(self.down2(self.down1(x)))\n    zero_pad1 = self.zero_pad1(down_x)\n    conv = self.conv(zero_pad1)\n    norm1 = self.norm1(conv)\n\n    return self.last(self.zero_pad2(self.leaky_relu(norm1)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"discriminator = Discriminator()\ndiscriminator.build((None, 256, 256, 3))\ndiscriminator.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 9. Build the CycleGAN model"},{"metadata":{"trusted":true},"cell_type":"code","source":"class CycleGAN(tf.keras.Model):\n  \n  def __init__(self, generator_monet, generator_photo, discrimator_monet, discriminator_photo):\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\n\n  def compile(self, generator_monet_optimizer, generator_photo_optimizer, discriminator_monet_optimizer, discriminator_photo_optimizer, discriminator_loss, adversarial_loss, calc_cycle_loss, identity_loss):\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.adversarial_loss = adversarial_loss\n    self.calc_cycle_loss = cal_cycle_loss\n    self.identity_loss = identity_loss\n\n  def train_step(self, batch_data):\n    monet, photo =  batch_data\n\n    with tf.GradientTape(persistent=True) as tape:\n\n      # monet generator\n      fake_monet = self.generator_monet(photo)\n      cycled_photo = self.generator_photo(fake_monet)\n\n      # photo generator\n      fake_photo = self.generator_photo(monet)\n      cycled_monet = self.generator_monet(fake_photo)\n\n      # monet discriminator \n      fake_monet_disc = self.discriminator_monet(fake_monet)\n      real_monet_disc = self.discriminator_monet(monet)\n\n      # photo discriminator \n      fake_photo_disc = self.discriminator_photo(fake_photo)\n      real_photo_disc = self.discriminator_photo(photo)\n\n      # generating itself are used for identity loss\n      same_monet = self.generator_monet(monet)\n      same_photo = self.generator_photo(photo)\n\n      # calculate the loss\n      gen_monet_adversarial_loss = self.adversarial_loss(fake_monet_disc)\n      gen_photo_adversarial_loss = self.adversarial_loss(fake_photo_disc)\n\n      # evaluates total cycle consistency loss\n      total_cycle_loss = self.calc_cycle_loss(monet, same_monet) + self.calc_cycle_loss(photo, same_photo)\n\n      # identity loss\n      gen_monet_identity_loss = self.identity_loss(monet, same_monet)\n      gen_photo_identity_loss = self.identity_loss(photo, same_photo)\n\n      # Total_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      # discriminator loss \n      disc_monet_loss = self.discriminator_loss(real_monet_disc, fake_monet_disc)\n      disc_photo_loss = self.discriminator_loss(real_photo_disc, fake_photo_disc)\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    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    self.generator_monet_optimizer.apply_gradients(zip(gen_monet_gradients,\n                                                   self.generator_monet.trainable_variables))\n    \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    }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"generator_monet = Generator()\ngenerator_monet.build((None, 256, 256, 3))\ngenerator_photo = Generator()\ngenerator_photo.build((None, 256, 256, 3))\ndiscriminator_monet = Discriminator()\ndiscriminator_monet.build((None, 256, 256, 3))\ndiscriminator_photo = Discriminator()\ndiscriminator_photo.build((None, 256, 256, 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"generator_monet_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ngenerator_photo_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_monet_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_photo_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cycle_gan_model = CycleGAN(generator_monet, generator_photo, discriminator_monet, discriminator_photo)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cycle_gan_model.compile(generator_monet_optimizer,\n                        generator_photo_optimizer,\n                        discriminator_monet_optimizer,\n                        discriminator_photo_optimizer,\n                        discriminator_loss,\n                        generated_loss,\n                        cal_cycle_loss,\n                        identity_loss)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import time\n\nt1 = time.process_time()\n\ncycle_gan_model.fit(\n    tf.data.Dataset.zip((train_photo, train_monet)),\n    epochs=5\n)\n\nt2 = time.process_time()\n\nprint (\"Accelerator =  ----- Computation time = \" + str(1000*(t2 - t1)) + \"ms\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 10. Test the model"},{"metadata":{"trusted":true},"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()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}