{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# I’m Something of a Painter Myself\nI wanted to be a picasso like painter, but haven't got enought talent to paint. So using the GAN I am noe transforming the photo images in this competition into a monet. I am using the tfrecords to get the better out of the model in training. I tried to explain every step to the best of my knowledge! Please do support if found interesting \n\nAlso I took some references from the following resources \n\n[Link 1](https://www.kaggle.com/ryanholbrook/tfrecords-basics)\n[Link 2](https://www.kaggle.com/drzhuzhe/monet-cyclegan-tutorial)\n[Link 3](https://kozodoi.me/python/deep%20learning/computer%20vision/competitions/2020/08/30/pre-training.html)","metadata":{"_uuid":"1f88e1dc-d4e2-4ef8-809e-a23c9ac9d3b4","_cell_guid":"f16371be-dbeb-48df-8625-c07f26a1bbdf","trusted":true}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport tensorflow as tf\nimport os\nimport re\nimport cv2\nimport math\nimport random","metadata":{"_uuid":"97ff9859-8f07-4754-bb09-ed75c36ef97e","_cell_guid":"169c5bcb-36a6-4d6c-8095-2e03e1d23603","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:42.086441Z","iopub.execute_input":"2021-05-25T02:57:42.086940Z","iopub.status.idle":"2021-05-25T02:57:48.118267Z","shell.execute_reply.started":"2021-05-25T02:57:42.086846Z","shell.execute_reply":"2021-05-25T02:57:48.117121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import keras\nfrom keras import *\nfrom keras.layers import *\nimport tensorflow_addons as tfa\n\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Device:', tpu.master())\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nexcept:\n    strategy = tf.distribute.get_strategy()","metadata":{"_uuid":"718333a9-d485-45f3-8333-1eef1f097f06","_cell_guid":"b5163907-fa97-46b8-92e8-75dd855757bd","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:48.119746Z","iopub.execute_input":"2021-05-25T02:57:48.120030Z","iopub.status.idle":"2021-05-25T02:57:54.116630Z","shell.execute_reply.started":"2021-05-25T02:57:48.120004Z","shell.execute_reply":"2021-05-25T02:57:54.115921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Data is stored as tfrecords for faster training and processing. `tf.io.gfile.glob` returns the list of files that manages the pattern given. For eg: \"*.tfrec\"","metadata":{"_uuid":"ed4f42a5-b78f-4c85-aab9-659ce404aa2d","_cell_guid":"5e700c98-4b99-4c41-80e6-0a99ea4f6522","trusted":true}},{"cell_type":"code","source":"\nmonet_names = tf.io.gfile.glob(r\"../input/gan-getting-started/monet_tfrec/*.tfrec\")\nprint(monet_names)\nphoto_names = tf.io.gfile.glob(r\"../input/gan-getting-started/photo_tfrec/*.tfrec\")","metadata":{"_uuid":"3b7002f5-8b03-4cf8-9616-ed4838f1876e","_cell_guid":"caa03fbd-c24d-4090-a5b9-d469f847487e","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.117874Z","iopub.execute_input":"2021-05-25T02:57:54.118132Z","iopub.status.idle":"2021-05-25T02:57:54.143158Z","shell.execute_reply.started":"2021-05-25T02:57:54.118108Z","shell.execute_reply":"2021-05-25T02:57:54.141716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def count_data_items(filenames):\n    n = [int(re.compile(r\"-([0-9]*)\\.\").search(filename).group(1)) \n         for filename in filenames]\n    return np.sum(n)\n\nprint(f\"Monet file tfrecords: {len(monet_names)}\")\nprint(f\"Photo file tfrecords: {len(photo_names)}\")\nprint(f\"Monet images: {count_data_items(monet_names)}\")\nprint(f\"Photo images: {count_data_items(photo_names)}\")","metadata":{"_uuid":"45325f9c-2770-42f9-972d-d6da325867de","_cell_guid":"f03dddc8-c5bf-48df-af09-0617d1aff3f1","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.144502Z","iopub.execute_input":"2021-05-25T02:57:54.144798Z","iopub.status.idle":"2021-05-25T02:57:54.152775Z","shell.execute_reply.started":"2021-05-25T02:57:54.144770Z","shell.execute_reply":"2021-05-25T02:57:54.152001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Loading the data\n- ***read_tfrecord()***:     takes a file and parse to get required variables.\n- ***prepare_image()***:     takes an image in tensor datatype and returns after reshaping and normalizing it.\n- ***get_dataset()***:       reads the TFRecords file and maps with the help of read_tfrecord function.\n- _**data_augment()**_:      as the name suggests augment the image data of tensor type for better accuracy.\n- _**get_gan_dataset()**_:   returns our main datasets which we will use for the training purposes","metadata":{"_uuid":"b893dc12-956f-4b01-9eb1-fa3f753fa7dd","_cell_guid":"9cdcd77f-7e40-4abf-b0a9-7d733dea04f9","trusted":true}},{"cell_type":"code","source":"def prepare_image(img, dim = 256):    \n    img = tf.image.decode_jpeg(img, channels = 3)\n    img = (tf.cast(img, tf.float32) / 255.0) - 1\n    img = tf.reshape(img, [dim, dim, 3])\n    return img\n\ndef read_tfrecord(example):\n    tfrec_format = {\n        'image' : tf.io.FixedLenFeature([], tf.string),\n        'image_name' : tf.io.FixedLenFeature([], tf.string),\n        \"target\": tf.io.FixedLenFeature([], tf.string)\n    }   \n    \n    example = tf.io.parse_single_example(example, tfrec_format)\n    image = prepare_image(example['image'])\n    return image","metadata":{"_uuid":"d434e7d5-6dff-4be5-aab1-93e451a099ad","_cell_guid":"b394a2bc-4b89-45b0-a40d-63986b03b9fa","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.153854Z","iopub.execute_input":"2021-05-25T02:57:54.154299Z","iopub.status.idle":"2021-05-25T02:57:54.163339Z","shell.execute_reply.started":"2021-05-25T02:57:54.154272Z","shell.execute_reply":"2021-05-25T02:57:54.162383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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=tf.data.experimental.AUTOTUNE)\n    return dataset","metadata":{"_uuid":"4f5ad4f1-27cd-435d-91b8-9065877721c5","_cell_guid":"f351cb07-5e9a-40d2-bba1-d29f71e2ac49","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.164858Z","iopub.execute_input":"2021-05-25T02:57:54.165250Z","iopub.status.idle":"2021-05-25T02:57:54.177037Z","shell.execute_reply.started":"2021-05-25T02:57:54.165210Z","shell.execute_reply":"2021-05-25T02:57:54.176003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_ds = load_dataset(monet_names, labeled=True).batch(1)\nphoto_ds = load_dataset(photo_names, labeled=True).batch(1)","metadata":{"_uuid":"22ddf34a-8757-4300-9607-0be6c332163a","_cell_guid":"071b2d17-6125-4275-8bd4-8c9583311fec","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.178281Z","iopub.execute_input":"2021-05-25T02:57:54.178654Z","iopub.status.idle":"2021-05-25T02:57:54.364394Z","shell.execute_reply.started":"2021-05-25T02:57:54.178627Z","shell.execute_reply":"2021-05-25T02:57:54.363647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset visualisation\n- batch_visualisation(): shows the given number of images in given path","metadata":{"_uuid":"768764fb-83cf-45b3-851b-23b8fb99e0e7","_cell_guid":"6d756951-047c-46c0-851e-3eaafcd20fd2","trusted":true}},{"cell_type":"code","source":"base_path = '../input/gan-getting-started/'\nmonet_path = os.path.join(base_path, 'monet_jpg')\nphoto_path = os.path.join(base_path, 'photo_jpg')","metadata":{"_uuid":"3d161c7b-d68e-4eda-bc26-69955c299f7e","_cell_guid":"03d22a4d-b35c-4d08-881e-8a7689558bc4","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.366357Z","iopub.execute_input":"2021-05-25T02:57:54.366752Z","iopub.status.idle":"2021-05-25T02:57:54.370147Z","shell.execute_reply.started":"2021-05-25T02:57:54.366723Z","shell.execute_reply":"2021-05-25T02:57:54.369524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def batch_visualization(path, n_images, is_random=True, figsize=(16, 16)):\n    plt.figure(figsize=figsize)\n    \n    w = int(n_images ** .5)\n    h = math.ceil(n_images / w)\n    \n    all_names = os.listdir(path)\n    \n    image_names = all_names[:n_images]\n    if is_random:\n        image_names = random.sample(all_names, n_images)\n    \n    for ind, image_name in enumerate(image_names):\n        img = cv2.imread(os.path.join(path, image_name))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) \n        plt.subplot(h, w, ind + 1)\n        plt.imshow(img)\n        plt.axis('off')\n    \n    plt.show()","metadata":{"_uuid":"89926a35-969f-4318-83c8-055e90a129a6","_cell_guid":"2132b3b3-fa08-4062-a72a-a86f3533bbb1","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.371570Z","iopub.execute_input":"2021-05-25T02:57:54.371877Z","iopub.status.idle":"2021-05-25T02:57:54.385512Z","shell.execute_reply.started":"2021-05-25T02:57:54.371851Z","shell.execute_reply":"2021-05-25T02:57:54.384424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_visualization(monet_path,6)","metadata":{"_uuid":"ef9a93eb-6437-46f6-bfe5-cac03476c904","_cell_guid":"8f38e542-db6b-44f1-97fd-7211ddbacf45","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:54.386956Z","iopub.execute_input":"2021-05-25T02:57:54.387263Z","iopub.status.idle":"2021-05-25T02:57:55.427523Z","shell.execute_reply.started":"2021-05-25T02:57:54.387236Z","shell.execute_reply":"2021-05-25T02:57:55.426519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_visualization(photo_path,6)","metadata":{"_uuid":"1de083ce-aec8-4ef8-98e0-0db2b02d7d88","_cell_guid":"1ef75f8c-e582-481d-a94c-260f69f74504","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:55.428758Z","iopub.execute_input":"2021-05-25T02:57:55.429042Z","iopub.status.idle":"2021-05-25T02:57:56.422065Z","shell.execute_reply.started":"2021-05-25T02:57:55.429017Z","shell.execute_reply":"2021-05-25T02:57:56.421151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Individual images\n- color_hist_visualization(): Gives the RGB bar graph of photo\n- channels_visualization(): Gives the RGB channel graph of photo\n- grayscale_visualization(): Converts the RGB channel to grayscale\n- color_graph(): Gives the RGB histogram graph","metadata":{"_uuid":"d056464e-d391-4081-981a-fafa9230c968","_cell_guid":"218373ef-b6ef-4cb2-bb80-c03a8f153f2d","trusted":true}},{"cell_type":"code","source":"rand_monet = r\"../input/gan-getting-started/monet_jpg/0260d15306.jpg\"\nrand_photo = r\"../input/gan-getting-started/photo_jpg/000ded5c41.jpg\"","metadata":{"_uuid":"c0f1c51e-1350-4e09-a2d4-fabf24c8b218","_cell_guid":"b6457742-9597-4704-960a-00da12c0ce8f","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:56.423206Z","iopub.execute_input":"2021-05-25T02:57:56.423467Z","iopub.status.idle":"2021-05-25T02:57:56.427031Z","shell.execute_reply.started":"2021-05-25T02:57:56.423441Z","shell.execute_reply":"2021-05-25T02:57:56.426224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def color_hist_visualization(image_path, figsize=(16, 4)):\n    plt.figure(figsize=figsize)\n    layers = ['red', 'green', 'blue']\n    \n    img = cv2.imread(image_path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) \n    plt.subplot(1, 4, 1)\n    plt.imshow(img)\n    plt.axis('off')\n    \n    for i in range(len(layers)):\n        plt.subplot(1, 4, i + 2)\n        plt.hist(\n            img[:, :, i].reshape(-1),\n            bins=25,\n            alpha=0.5,\n            color=layers[i],\n            density=True\n        )\n        plt.title(layers[i])\n        plt.xlim(0, 255)\n        plt.xticks([])\n        plt.yticks([])\n    plt.show()","metadata":{"_uuid":"8e55f6de-a5fc-4117-85aa-0fa1b9f050df","_cell_guid":"01570d0c-54e6-4dbc-9f57-14102e586f36","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:56.428161Z","iopub.execute_input":"2021-05-25T02:57:56.428420Z","iopub.status.idle":"2021-05-25T02:57:56.441708Z","shell.execute_reply.started":"2021-05-25T02:57:56.428394Z","shell.execute_reply":"2021-05-25T02:57:56.440755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Monet: \")\ncolor_hist_visualization(rand_monet)\nprint(\"\\nPhoto: \")\ncolor_hist_visualization(rand_photo)","metadata":{"_uuid":"c16cd515-e40d-47a3-a765-ac7f02b3e911","_cell_guid":"6a18ef6a-1c70-4736-ae2e-f5c6bf691dc3","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:56.442831Z","iopub.execute_input":"2021-05-25T02:57:56.443094Z","iopub.status.idle":"2021-05-25T02:57:57.192729Z","shell.execute_reply.started":"2021-05-25T02:57:56.443069Z","shell.execute_reply":"2021-05-25T02:57:57.191734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def channels_visualization(image_path, figsize=(16, 4)):\n    plt.figure(figsize=figsize)\n    \n    img = cv2.imread(image_path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) \n    plt.subplot(1, 4, 1)\n    plt.imshow(img)\n    plt.axis('off')\n    \n    for i in range(3):\n        plt.subplot(1, 4, i + 2)\n        tmp_img = np.full_like(img, 0)\n        tmp_img[:, :, i] = img[:, :, i]\n        plt.imshow(tmp_img)\n        plt.xlim(0, 255)\n        plt.xticks([])\n        plt.yticks([])\n    plt.show()","metadata":{"_uuid":"7fe0ba26-22df-4f14-86c8-dde750919e59","_cell_guid":"1fdaa986-3141-4ce4-bfdd-b254ee5eafe7","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:57.193934Z","iopub.execute_input":"2021-05-25T02:57:57.194208Z","iopub.status.idle":"2021-05-25T02:57:57.201588Z","shell.execute_reply.started":"2021-05-25T02:57:57.194181Z","shell.execute_reply":"2021-05-25T02:57:57.200319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Monet: \")\nchannels_visualization(rand_monet)\nprint(\"\\nPhoto: \")\nchannels_visualization(rand_photo)","metadata":{"_uuid":"490f431d-3ecb-4f18-8a03-851cb23c2f70","_cell_guid":"cdd561d4-c9c3-41e3-921c-228c0bd31b9b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:57.203300Z","iopub.execute_input":"2021-05-25T02:57:57.203812Z","iopub.status.idle":"2021-05-25T02:57:57.791125Z","shell.execute_reply.started":"2021-05-25T02:57:57.203763Z","shell.execute_reply":"2021-05-25T02:57:57.790055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def grayscale_visualization(image_path, figsize=(16, 4)):\n    plt.figure(figsize=figsize)\n    \n    img = cv2.imread(image_path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) \n    plt.subplot(1, 3, 1)\n    plt.imshow(img)\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 2)\n    tmp_img = np.full_like(img, 0)\n    for i in range(3):\n        tmp_img[:, :, i] = img.mean(axis=-1)\n    plt.imshow(tmp_img)\n    plt.axis('off')\n    \n    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    plt.subplot(1,3,3)\n    plt.imshow(img)\n    plt.axis(\"off\")\n    \n    plt.show()","metadata":{"_uuid":"eecb4e98-080d-4a71-9ece-9ba347660bef","_cell_guid":"c17c63c9-fdb5-48e1-b3ff-43712924e17a","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:57.792531Z","iopub.execute_input":"2021-05-25T02:57:57.793092Z","iopub.status.idle":"2021-05-25T02:57:57.802521Z","shell.execute_reply.started":"2021-05-25T02:57:57.793047Z","shell.execute_reply":"2021-05-25T02:57:57.801762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Monet: \")\ngrayscale_visualization(rand_monet)\nprint(\"\\nPhoto: \")\ngrayscale_visualization(rand_photo)","metadata":{"_uuid":"9f031445-6a41-458f-b119-1d49e8ecfdd6","_cell_guid":"a4a143be-b7ec-45d3-b2ea-079462a5fb19","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:57.803706Z","iopub.execute_input":"2021-05-25T02:57:57.803958Z","iopub.status.idle":"2021-05-25T02:57:58.381996Z","shell.execute_reply.started":"2021-05-25T02:57:57.803933Z","shell.execute_reply":"2021-05-25T02:57:58.380873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def color_graph(image_path, figsize=(16, 4)):\n    plt.figure(figsize=figsize)\n    \n    img = cv2.imread(image_path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) \n    plt.subplot(1, 2, 1)\n    plt.imshow(img)\n    plt.axis('off')\n    \n    chans = cv2.split(img)\n    colors = (\"b\", \"g\", \"r\")\n    plt.subplot(1, 2, 2)\n    plt.title(\"'Flattened' Color Histogram\")\n    plt.xlabel(\"Bins\")\n    plt.ylabel(\"# of Pixels\")\n    features = []\n    # loop over the image channels\n    for (chan, color) in zip(chans, colors):\n        # create a histogram for the current channel and\n        # concatenate the resulting histograms for each\n        # channel\n        hist = cv2.calcHist([chan], [0], None, [256], [0, 256])\n        features.extend(hist)\n        # plot the histogram\n        plt.plot(hist, color = color)\n        plt.xlim([0, 256])\n    \n    plt.show()","metadata":{"_uuid":"147f4eb8-01a3-4e86-8402-8913ad1e4eca","_cell_guid":"698967f1-8117-4f60-8c0e-0ee3fcbeae60","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:58.383308Z","iopub.execute_input":"2021-05-25T02:57:58.383621Z","iopub.status.idle":"2021-05-25T02:57:58.392942Z","shell.execute_reply.started":"2021-05-25T02:57:58.383592Z","shell.execute_reply":"2021-05-25T02:57:58.391752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Monet: \")\ncolor_graph(rand_monet)\nprint(\"\\nPhoto: \")\ncolor_graph(rand_photo)","metadata":{"_uuid":"c35bab5b-da26-4b5a-8c5c-d0f378f3b3c3","_cell_guid":"c4656079-168c-4d53-81a8-3d48b563d614","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:57:58.394564Z","iopub.execute_input":"2021-05-25T02:57:58.394940Z","iopub.status.idle":"2021-05-25T02:57:58.904800Z","shell.execute_reply.started":"2021-05-25T02:57:58.394909Z","shell.execute_reply":"2021-05-25T02:57:58.903698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training a CycleGAN\nIn the CycleGAN’s case, the architecture is complex, and as a result, we need a structure that allows us to keep accessing the original attributes and methods that we have defined. As a result, we will write out the CycleGAN as a Python class of its own with methods to build the Generator and Discriminator, and run the training.\n\nFor the training to execute we will need a seperate Generator() and discriminator() function which we will feed to CycleGAN as methods which in turn needs the upsample() and downsample() of image.\n\n- For downsampling we are using the Conv2D() as primary layer and LeakyReLU() as activation\n- For upsampling we are using the Conv2DTranspose() as primary layer and Dropout() at 0.3, ReLU() as secondary layers\n\nFor all of these I have made a utility script as this notebook kernel size was exceeding","metadata":{"_uuid":"c652cd97-b05b-43d5-86e0-06c3138f8af1","_cell_guid":"59669963-2036-4ec1-93e0-c0ced699afcd","trusted":true}},{"cell_type":"code","source":"from shutil import copyfile\ncopyfile(src = \"../usr/lib/monet_using_gan_utility/monet_using_gan_utility.py\", dst = \"../working/monet.py\")\nfrom monet import *","metadata":{"execution":{"iopub.status.busy":"2021-05-25T02:57:58.906430Z","iopub.execute_input":"2021-05-25T02:57:58.906885Z","iopub.status.idle":"2021-05-25T02:58:06.125655Z","shell.execute_reply.started":"2021-05-25T02:57:58.906844Z","shell.execute_reply":"2021-05-25T02:58:06.124775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From here we are declaring generator and discriminator spaces of GANs which will work the same as encoder and decoder of autoencoders. To know more about autoencoders, [click here](https://www.kaggle.com/discussion/240924)","metadata":{"_uuid":"675e14b8-7188-4534-9aeb-306e3cb3c0c6","_cell_guid":"30b8bdba-b4b4-483e-80c2-030de4fb8d01","trusted":true}},{"cell_type":"code","source":"generator_g = Generator()\ntf.keras.utils.plot_model(generator_g, dpi=48)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T02:58:06.126875Z","iopub.execute_input":"2021-05-25T02:58:06.127133Z","iopub.status.idle":"2021-05-25T02:58:08.579426Z","shell.execute_reply.started":"2021-05-25T02:58:06.127109Z","shell.execute_reply":"2021-05-25T02:58:08.578461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"discriminator_g = Discriminator()\ntf.keras.utils.plot_model(discriminator_g, dpi=48)","metadata":{"_uuid":"1b8ae826-0738-48b5-aaef-cdf316549902","_cell_guid":"286e8edb-00bb-45bb-ab94-e0ddb28e3357","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:08.583815Z","iopub.execute_input":"2021-05-25T02:58:08.584418Z","iopub.status.idle":"2021-05-25T02:58:08.915061Z","shell.execute_reply.started":"2021-05-25T02:58:08.584376Z","shell.execute_reply":"2021-05-25T02:58:08.913603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    monet_generator = Generator() # transforms photos to Monet-esque paintings\n    photo_generator = Generator() # transforms Monet paintings to be more like photos\n\n    monet_discriminator = Discriminator() # differentiates real Monet paintings and generated Monet paintings\n    photo_discriminator = Discriminator() # differentiates real photos and generated photos","metadata":{"_uuid":"be60c34a-b5c5-49c7-ab45-550170ad41ad","_cell_guid":"da001a4c-3681-4512-bb0b-02be2f4d5d71","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:08.917401Z","iopub.execute_input":"2021-05-25T02:58:08.917726Z","iopub.status.idle":"2021-05-25T02:58:17.815152Z","shell.execute_reply.started":"2021-05-25T02:58:08.917694Z","shell.execute_reply":"2021-05-25T02:58:17.814023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building the cycleGAN model\nImage-to-image translation frameworks are frequently difficult to train because of the need for perfect pairs; the CycleGAN solves this by making this an unpaired domain translation.\n\nThe CycleGAN has three losses:\n- Cycle-consistent, which measures the difference between the original image and an image translated into a different domain and back again\n- Adversarial, which ensures realistic images\n- Identity, which preserves the color space of the image\n\nPractical applications of the CycleGAN include self-driving car training and exten- sions that allow us to create different styles of images during the translation process.","metadata":{"_uuid":"2f3ecaf6-4cef-4835-9a1c-b31671d09eb5","_cell_guid":"c3f72181-5da5-4580-8f47-764af10d23bf","trusted":true}},{"cell_type":"code","source":"class CycleGan(keras.Model):\n    def __init__(\n        self,\n        monet_generator,\n        photo_generator,\n        monet_discriminator,\n        photo_discriminator,\n        lambda_cycle=10):\n        \n        super(CycleGan, self).__init__()\n        self.m_gen = monet_generator\n        self.p_gen = photo_generator\n        self.m_disc = monet_discriminator\n        self.p_disc = photo_discriminator\n        self.lambda_cycle = lambda_cycle\n        \n    def compile(\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\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, inputing 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, inputing 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,\n                                                  self.m_gen.trainable_variables)\n        photo_generator_gradients = tape.gradient(total_photo_gen_loss,\n                                                  self.p_gen.trainable_variables)\n\n        monet_discriminator_gradients = tape.gradient(monet_disc_loss,\n                                                      self.m_disc.trainable_variables)\n        photo_discriminator_gradients = tape.gradient(photo_disc_loss,\n                                                      self.p_disc.trainable_variables)\n\n        # Apply the gradients to the optimizer\n        self.m_gen_optimizer.apply_gradients(zip(monet_generator_gradients,\n                                                 self.m_gen.trainable_variables))\n\n        self.p_gen_optimizer.apply_gradients(zip(photo_generator_gradients,\n                                                 self.p_gen.trainable_variables))\n\n        self.m_disc_optimizer.apply_gradients(zip(monet_discriminator_gradients,\n                                                  self.m_disc.trainable_variables))\n\n        self.p_disc_optimizer.apply_gradients(zip(photo_discriminator_gradients,\n                                                  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        }","metadata":{"_uuid":"8f4feb5f-bac8-4eda-986b-e9152dcc960b","_cell_guid":"1bc75562-b230-4dd9-826b-4094d1fb58c1","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:35.784341Z","iopub.execute_input":"2021-05-25T02:58:35.784870Z","iopub.status.idle":"2021-05-25T02:58:35.807499Z","shell.execute_reply.started":"2021-05-25T02:58:35.784837Z","shell.execute_reply":"2021-05-25T02:58:35.806427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def discriminator_loss(real, generated):\n        real_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.ones_like(real), real)\n        generated_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.zeros_like(generated), generated)\n        total_disc_loss = real_loss + generated_loss\n        return total_disc_loss * 0.5","metadata":{"_uuid":"656a9e65-1be8-4b09-82cf-33181a6e0152","_cell_guid":"27b5cf67-973a-4138-a1c2-c95804274adf","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:36.628271Z","iopub.execute_input":"2021-05-25T02:58:36.628818Z","iopub.status.idle":"2021-05-25T02:58:36.635556Z","shell.execute_reply.started":"2021-05-25T02:58:36.628765Z","shell.execute_reply":"2021-05-25T02:58:36.634899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    def generator_loss(generated):\n        return tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)(tf.ones_like(generated), generated)\n    \nwith strategy.scope():\n    def calc_cycle_loss(real_image, cycled_image, LAMBDA):\n        loss1 = tf.reduce_mean(tf.abs(real_image - cycled_image))\n        return LAMBDA * loss1\n\nwith strategy.scope():\n    def identity_loss(real_image, same_image, LAMBDA):\n        loss = tf.reduce_mean(tf.abs(real_image - same_image))\n        return LAMBDA * 0.5 * loss","metadata":{"_uuid":"103c75df-4ff0-4cf1-8b1b-80faa20fdff9","_cell_guid":"6333b48e-221e-4dce-8d28-7fc1f6db811f","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:37.068905Z","iopub.execute_input":"2021-05-25T02:58:37.069489Z","iopub.status.idle":"2021-05-25T02:58:37.076723Z","shell.execute_reply.started":"2021-05-25T02:58:37.069454Z","shell.execute_reply":"2021-05-25T02:58:37.075738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Training","metadata":{"_uuid":"58f279e4-bb5b-46f8-9064-da9c879dc472","_cell_guid":"23d8d324-9006-4123-bedc-f6434d690fca","trusted":true}},{"cell_type":"code","source":"with strategy.scope():\n    monet_generator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n    photo_generator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n\n    monet_discriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n    photo_discriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)","metadata":{"_uuid":"a8aa356d-f122-42ca-8efe-9a1d17cadb7f","_cell_guid":"3b3f80e9-b982-430f-b4b3-fec7ec488e0d","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:39.520227Z","iopub.execute_input":"2021-05-25T02:58:39.520785Z","iopub.status.idle":"2021-05-25T02:58:39.526385Z","shell.execute_reply.started":"2021-05-25T02:58:39.520751Z","shell.execute_reply":"2021-05-25T02:58:39.525712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    cycle_gan_model = CycleGan(\n        monet_generator, photo_generator, monet_discriminator, photo_discriminator\n    )\n\n    cycle_gan_model.compile(\n        m_gen_optimizer = monet_generator_optimizer,\n        p_gen_optimizer = photo_generator_optimizer,\n        m_disc_optimizer = monet_discriminator_optimizer,\n        p_disc_optimizer = photo_discriminator_optimizer,\n        gen_loss_fn = generator_loss,\n        disc_loss_fn = discriminator_loss,\n        cycle_loss_fn = calc_cycle_loss,\n        identity_loss_fn = identity_loss\n    )","metadata":{"_uuid":"1b62bf9e-cbc7-4d41-8ade-fb20e2419707","_cell_guid":"836a6dd7-410a-43a5-bc56-c30305625f1c","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:40.700726Z","iopub.execute_input":"2021-05-25T02:58:40.701256Z","iopub.status.idle":"2021-05-25T02:58:40.753729Z","shell.execute_reply.started":"2021-05-25T02:58:40.701210Z","shell.execute_reply":"2021-05-25T02:58:40.752932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import clear_output","metadata":{"_uuid":"e113ce12-316f-44d7-b665-365eb2da49c2","_cell_guid":"97c67dc5-03a6-4d5e-a5a3-dc98c73c958b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:44.166061Z","iopub.execute_input":"2021-05-25T02:58:44.166443Z","iopub.status.idle":"2021-05-25T02:58:44.170908Z","shell.execute_reply.started":"2021-05-25T02:58:44.166408Z","shell.execute_reply":"2021-05-25T02:58:44.169863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    cycle_gan_model.fit(\n        tf.data.Dataset.zip((monet_ds, photo_ds)),\n        epochs=30)\nexcept:\n    clear_output()","metadata":{"_uuid":"6691657e-b195-4431-af00-700c8ff9f349","_cell_guid":"627e0c20-7fa5-4626-b672-326dceedc2bb","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T02:58:44.695977Z","iopub.execute_input":"2021-05-25T02:58:44.696317Z","iopub.status.idle":"2021-05-25T02:59:37.762738Z","shell.execute_reply.started":"2021-05-25T02:58:44.696289Z","shell.execute_reply":"2021-05-25T02:59:37.761783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Above fitting gives an error:\\nInvalidArgumentError: Unable to parse tensor proto [Op:DatasetCardinality]\")","metadata":{"_uuid":"4e3248cd-4cbf-4a7e-9122-01fa0cd9ead2","_cell_guid":"d949f587-110d-45b1-a8cf-46f1776ee02b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2021-05-25T03:00:07.842107Z","iopub.execute_input":"2021-05-25T03:00:07.842612Z","iopub.status.idle":"2021-05-25T03:00:07.847301Z","shell.execute_reply.started":"2021-05-25T03:00:07.842582Z","shell.execute_reply":"2021-05-25T03:00:07.846423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"All the solutions are cordially invited!","metadata":{"_uuid":"ab757b66-d8bf-48ad-a82e-adb59991127d","_cell_guid":"2632413d-025c-4053-a1f0-0fc47d2e4c76","trusted":true}},{"cell_type":"code","source":"","metadata":{"_uuid":"518c0ed8-c74f-403e-850f-6a89997be7ce","_cell_guid":"730df6b5-460b-4269-b45b-a1501837bcc8","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]}]}