{"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":"# Generative Adversarial Networks for Monet Paintings:","metadata":{}},{"cell_type":"markdown","source":"Generative Models are kind of unsupervised models that are trained to mimic the patterns in a dataset and produce examples very similar to those of training set. Generative models are of two sub models. These two submodels are called generators and discriminators. The role of the generator is to make fake example that look like the real example. On the other hand, the role of discriminator is to distinguish the real example from the fake example. These two sub models compete with each other up to the point when a balance between them established.","metadata":{}},{"cell_type":"markdown","source":"## Structure of this notebook:\n\n* Description of the problem and data\n* Exploratory data analysis (EDA)\n* Analysis - model building and training\n* Result\n* Conclusion","metadata":{}},{"cell_type":"code","source":"# importing required libraries:\n\nimport numpy as np\nimport pandas as pd\nimport random\nimport shutil\nimport glob\nimport os\nfrom scipy import stats\nimport time\n\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\n\nimport tensorflow as tf\nfrom tensorflow import keras\nimport tensorflow_addons  as tfa\nfrom tensorflow.keras import Sequential, Model, layers, regularizers\nfrom tensorflow.keras.layers import Conv2D, Dense, Input, Dropout, Activation, LeakyReLU, ReLU, BatchNormalization, Reshape, Flatten, Conv2DTranspose\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom keras.losses import binary_crossentropy\nfrom keras.activations import relu, tanh\nfrom keras.initializers import RandomNormal","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:32.160854Z","iopub.execute_input":"2023-03-06T03:09:32.161140Z","iopub.status.idle":"2023-03-06T03:09:40.567739Z","shell.execute_reply.started":"2023-03-06T03:09:32.161079Z","shell.execute_reply":"2023-03-06T03:09:40.566319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Description of the problem and data:\n\nThe Monet paintings have a unique style. Without having Claude Monet it might be difficult to repeat his painting style for the new scenes. The main goal of this competition/project is to apply the style of Monet painting to a new given photo so that it look like it has been painted by Claude Monet. This project uses special type Generative Adversarial Networks (GAN) which is mainly used for image translation. Images are initially different sizes. We are not given a dataframe to view or plot values. Instead, we will move on to the EDA and view some images. Prior to training, we will set our training data (images) and we will normalize all images.","metadata":{}},{"cell_type":"code","source":"# Input data:\n\nprint(os.listdir('../input'))","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:40.568741Z","iopub.execute_input":"2023-03-06T03:09:40.570252Z","iopub.status.idle":"2023-03-06T03:09:40.577149Z","shell.execute_reply.started":"2023-03-06T03:09:40.570198Z","shell.execute_reply":"2023-03-06T03:09:40.575838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Input data:\n\nmonet_tfrec_path = '../input/gan-getting-started/monet_tfrec'\nmonet_jpg_path = '../input/gan-getting-started/monet_jpg'\n\nphoto_tfrec_path = '../input/gan-getting-started/photo_tfrec'\nphoto_jpg_path = '../input/gan-getting-started/photo_jpg'","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:40.578651Z","iopub.execute_input":"2023-03-06T03:09:40.579025Z","iopub.status.idle":"2023-03-06T03:09:40.591448Z","shell.execute_reply.started":"2023-03-06T03:09:40.578988Z","shell.execute_reply":"2023-03-06T03:09:40.590157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saving the names of all the files with .jpg format and .tfrec format in a list:\n\nmonet_tfrec = tf.io.gfile.glob(monet_tfrec_path+'/*.tfrec')\nmonet_jpg = tf.io.gfile.glob(monet_jpg_path+'/*.jpg')\nphoto_tfrec = tf.io.gfile.glob(photo_tfrec_path+'/*.tfrec')\nphoto_jpg = tf.io.gfile.glob(photo_jpg_path+'/*.jpg')\n\n# checking the number of monet examples and photo examples:\nprint(len(monet_tfrec), len(photo_tfrec))\nprint(len(monet_jpg), len(photo_jpg))","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:40.595397Z","iopub.execute_input":"2023-03-06T03:09:40.595777Z","iopub.status.idle":"2023-03-06T03:09:46.915017Z","shell.execute_reply.started":"2023-03-06T03:09:40.595746Z","shell.execute_reply":"2023-03-06T03:09:46.914283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Exploratory data analysis (EDA):\n\nThis sections explores the datasets by plotting some training examples. In addition, some histograms for different color channels in the training set are displayed. After cropping the images, we visualize them below.","metadata":{}},{"cell_type":"code","source":"# Loading an image files by its path:\ndef Load_Image(path):\n    image_path = tf.io.read_file(path)\n    image_path = tf.image.decode_image(image_path, channels = 3)\n    image_path = tf.image.convert_image_dtype(image_path, tf.float32)\n    image_path = tf.reshape(image_path, [256, 256, 3])\n    return image_path\n\n\n# The function below decode image, rescales and reshape the images: \ndef Decode_Image(path):\n    images = tf.image.decode_image(path, channels = 3)\n    images = (tf.cast(images, tf.float32) /127.5) - 1\n    images = tf.reshape(images, [256, 256, 3])\n    return images\n\n\n# The function below decode image, rescales and reshape the images: \ndef Process_Image(path):\n    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    paths = tf.io.parse_single_example(path, format)\n    image = Decode_Image(paths['image'])\n    return image\n\n\n# Loads the whole dataset to a tensorflow dataset object:\ndef Load_Data(name):\n    dataset = tf.data.TFRecordDataset(name)\n    dataset = dataset.map(Process_Image, num_parallel_calls = tf.data.experimental.AUTOTUNE)\n    return dataset\n\n\n# To crop the images:\ndef Crop_Image(image, box):\n    img = Image.open(image)\n    img = img.crop(box)\n    return img\n","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:46.916150Z","iopub.execute_input":"2023-03-06T03:09:46.917097Z","iopub.status.idle":"2023-03-06T03:09:46.927276Z","shell.execute_reply.started":"2023-03-06T03:09:46.917060Z","shell.execute_reply":"2023-03-06T03:09:46.926097Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Loading the whole dataset:\n\nmonet_data = Load_Data(monet_tfrec).batch(1)\nphoto_data = Load_Data(photo_tfrec).batch(1)","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:46.928514Z","iopub.execute_input":"2023-03-06T03:09:46.928843Z","iopub.status.idle":"2023-03-06T03:09:47.175671Z","shell.execute_reply.started":"2023-03-06T03:09:46.928816Z","shell.execute_reply":"2023-03-06T03:09:47.174493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visulaization of Some Images:","metadata":{}},{"cell_type":"code","source":"# Visualization:\n\nsample = next(iter(monet_data))\nplt.imshow(sample[0]*0.5 + 0.5)\nplt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:47.177194Z","iopub.execute_input":"2023-03-06T03:09:47.177598Z","iopub.status.idle":"2023-03-06T03:09:47.583839Z","shell.execute_reply.started":"2023-03-06T03:09:47.177557Z","shell.execute_reply":"2023-03-06T03:09:47.582749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display images from the monet dataset:\n\nfig, ax = plt.subplots(4, 5, figsize = (20, 20))\n\njpg = random.sample(monet_jpg, 20)\n\nfor idx, name in enumerate(jpg):\n    img = Load_Image(name)\n    ax[idx//5, idx%5].imshow(img)","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:47.585243Z","iopub.execute_input":"2023-03-06T03:09:47.585563Z","iopub.status.idle":"2023-03-06T03:09:51.215130Z","shell.execute_reply.started":"2023-03-06T03:09:47.585534Z","shell.execute_reply":"2023-03-06T03:09:51.214114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display images from the photo dataset:\n\nfig, ax = plt.subplots(4, 5, figsize = (20, 20))\n\njpg = random.sample(photo_jpg, 20)\n\nfor idx, name in enumerate(jpg):\n    img = Load_Image(name)\n    ax[idx//5, idx%5].imshow(img)","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:51.216418Z","iopub.execute_input":"2023-03-06T03:09:51.217554Z","iopub.status.idle":"2023-03-06T03:09:54.397137Z","shell.execute_reply.started":"2023-03-06T03:09:51.217513Z","shell.execute_reply":"2023-03-06T03:09:54.395722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Analysis - model building and training:\n\n#### Model Architecture:\n\n* Used Architecture : The architecture chosen for this project is DCGAN.\n\n#### Hyperparameter Tuning:\n\nThe hyperparemeter tuning for the chosen model could be performed by using the advice from experts or in trial-and-error fashion.","metadata":{}},{"cell_type":"code","source":"# Create a function to build the generator model:\n\ndef generator_model():\n    initializer  = RandomNormal(mean = 0, stddev = 0.02)\n    \n    model = Sequential()\n    \n    model.add(Conv2D(filters = 64, kernel_size = (4, 4), strides = (2, 2), padding = 'same', use_bias = False, input_shape = [256, 256, 3], kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n\n    #model.add(Reshape((8, 8, 512)))\n\n    model.add(Conv2D(filters = 128, kernel_size = (4, 4), strides = (2, 2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())    \n    model.add(Dropout(0.3))\n\n    model.add(Conv2D(filters = 256, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n    model.add(Dropout(0.3))\n\n\n    model.add(Conv2DTranspose(filters = 265, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n    model.add(Dropout(0.3))\n\n    model.add(Conv2DTranspose(filters = 128, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n    model.add(Dropout(0.3))\n    \n    model.add(Conv2DTranspose(filters = 3, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n    model.add(Dropout(0.3))\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:54.398653Z","iopub.execute_input":"2023-03-06T03:09:54.398989Z","iopub.status.idle":"2023-03-06T03:09:54.414399Z","shell.execute_reply.started":"2023-03-06T03:09:54.398947Z","shell.execute_reply":"2023-03-06T03:09:54.412369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function to build the discriminator model:\n\ndef discriminator_model():\n    initializer  = RandomNormal(mean = 0, stddev = 0.02)\n    model = Sequential()\n    \n    model.add(Conv2D(filters = 64, kernel_size = (4, 4), strides = (2,2), padding = 'same', input_shape = [256,256,3], kernel_initializer = initializer, use_bias = False))\n    model.add(ReLU())\n    model.add(BatchNormalization())\n    model.add(Dropout(0.2))\n    \n    model.add(Conv2D(filters = 128, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(ReLU())\n    model.add(BatchNormalization())\n    model.add(Dropout(0.2))\n    \n    model.add(Conv2D(filters = 256, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(ReLU())\n    model.add(BatchNormalization())\n    model.add(Dropout(0.2))\n    \n    model.add(Conv2D(filters = 1, kernel_size = (4, 4), strides = (2,2), padding = 'same', use_bias = False, kernel_initializer = initializer))\n    model.add(BatchNormalization())\n    model.add(LeakyReLU())\n    model.add(Dropout(0.3))\n    \n\n    model.add(Flatten())\n    model.add(Dense(1, activation = 'sigmoid'))\n    model.add(Flatten())\n       \n    return model\n    ","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:54.416216Z","iopub.execute_input":"2023-03-06T03:09:54.416557Z","iopub.status.idle":"2023-03-06T03:09:54.435624Z","shell.execute_reply.started":"2023-03-06T03:09:54.416528Z","shell.execute_reply":"2023-03-06T03:09:54.434390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Summary:\n\noptimizer = Adam(0.0001)\ngenerator = generator_model()\ngenerator.compile(loss = 'binarycrossentropy', optimizer = optimizer, metrics = ['accuracy'])\ngenerator.summary()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:54.436723Z","iopub.execute_input":"2023-03-06T03:09:54.436996Z","iopub.status.idle":"2023-03-06T03:09:54.695348Z","shell.execute_reply.started":"2023-03-06T03:09:54.436972Z","shell.execute_reply":"2023-03-06T03:09:54.694452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Summary:\n\ndiscriminator = discriminator_model()\ndiscriminator.compile(loss = 'binarycrossentropy', optimizer = optimizer, metrics = ['accuracy'])\ndiscriminator.summary()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:54.701170Z","iopub.execute_input":"2023-03-06T03:09:54.701566Z","iopub.status.idle":"2023-03-06T03:09:54.867651Z","shell.execute_reply.started":"2023-03-06T03:09:54.701533Z","shell.execute_reply":"2023-03-06T03:09:54.866501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Combining both generator and discriminatir:\n\noptimizer = Adam(0.0001)\n\ndef gan_model(generator, discriminator):\n    model = Sequential()\n    model.add(generator)\n    model.add(discriminator)\n    return model\n\n\ngenerator = generator_model()\ndiscriminator = discriminator_model()\n\nGAN = gan_model(generator, discriminator)\nGAN.compile(loss = 'binarycrossentropy', optimizer = optimizer, metrics = ['accuracy'])\nGAN.summary()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:54.869407Z","iopub.execute_input":"2023-03-06T03:09:54.869807Z","iopub.status.idle":"2023-03-06T03:09:55.265154Z","shell.execute_reply.started":"2023-03-06T03:09:54.869773Z","shell.execute_reply":"2023-03-06T03:09:55.264284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualize one sample example and make sure its working correct:\n\nnoise = tf.random.normal([1,256, 256, 3])\nimage = generator(noise)\ngenerated_image = generator(noise, training = False)\nprint(generated_image.shape)\nprint(generated_image[0, :, :, 0].shape)\n\ndef generate_images(row = 1,col = 1, is_norm = False):\n    plt.figure(figsize = (4*row, 5*col))    \n    for ele in range(1,1+row*col):        \n        noise = tf.random.normal([1, 256, 256, 3])\n        plt.subplot(row, col, ele)\n        if(is_norm):\n            plt.imshow(generator(noise)[0, :, :, :]*255)\n        else:            \n            plt.imshow(generator(noise)[0, :, :, :]*0.5 + 0.5)\n        plt.axis('off')\n        \ngenerate_images()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:55.266059Z","iopub.execute_input":"2023-03-06T03:09:55.266313Z","iopub.status.idle":"2023-03-06T03:09:55.752209Z","shell.execute_reply.started":"2023-03-06T03:09:55.266289Z","shell.execute_reply":"2023-03-06T03:09:55.751092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training step and Training loop:\n\ndiscriminator = discriminator_model()\ngen_pred = discriminator(generated_image, training = False)\nprint(gen_pred)","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:55.753573Z","iopub.execute_input":"2023-03-06T03:09:55.754366Z","iopub.status.idle":"2023-03-06T03:09:55.910070Z","shell.execute_reply.started":"2023-03-06T03:09:55.754330Z","shell.execute_reply":"2023-03-06T03:09:55.909179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = iter(photo_data)\nfor ele in range(2):\n        example_sample = next(df)\n        generated_sample = generator(example_sample)\n        \n        f = plt.figure(figsize=(5, 5))\n        \n        plt.subplot(121)\n        plt.title('Input image')\n        plt.imshow(example_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        \n        plt.subplot(122)\n        plt.title('Generated image')\n        plt.imshow(generated_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:55.911397Z","iopub.execute_input":"2023-03-06T03:09:55.911774Z","iopub.status.idle":"2023-03-06T03:09:56.613970Z","shell.execute_reply.started":"2023-03-06T03:09:55.911730Z","shell.execute_reply":"2023-03-06T03:09:56.612832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create two separate loss functions for the generator and discriminator:\n\ncross_entropy = keras.losses.BinaryCrossentropy(from_logits = True)\n\ndef generator_loss(fake_output):\n    return cross_entropy(tf.ones_like(fake_output), fake_output)\n\ndef discriminator_loss(real_output, fake_output):\n    real_loss = cross_entropy(tf.ones_like(real_output), real_output)\n    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)\n    total_loss = real_loss + fake_loss\n    return total_loss","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:56.615320Z","iopub.execute_input":"2023-03-06T03:09:56.615688Z","iopub.status.idle":"2023-03-06T03:09:56.621752Z","shell.execute_reply.started":"2023-03-06T03:09:56.615661Z","shell.execute_reply":"2023-03-06T03:09:56.620776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set the hyperparameters to be used for training:\n\nEPOCHS = 3\nsample_interval = EPOCHS / 10\nBATCH_SIZE = 32","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:56.623007Z","iopub.execute_input":"2023-03-06T03:09:56.624293Z","iopub.status.idle":"2023-03-06T03:09:56.638039Z","shell.execute_reply.started":"2023-03-06T03:09:56.624232Z","shell.execute_reply":"2023-03-06T03:09:56.637190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function that trains one step of a GAN:\n\n@tf.function\ndef train_step(image_batch):\n    noise = tf.random.normal([1,256, 256, 3])\n    \n    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: \n        \n        generated_image = generator(noise, training=True)\n\n        discriminator_pred_gen = discriminator(generated_image, training=True)\n\n        discriminator_pred_ori= discriminator(image_batch, training=True)\n\n\n        discriminator_loss = cross_entropy(tf.ones_like(discriminator_pred_ori),discriminator_pred_ori) + cross_entropy(tf.zeros_like(discriminator_pred_gen), discriminator_pred_gen)\n        generator_loss = cross_entropy(tf.ones_like(discriminator_pred_gen), discriminator_pred_gen)\n        \n    generator_grad = gen_tape.gradient(generator_loss, generator.trainable_variables)\n    discriminator_grad = disc_tape.gradient(discriminator_loss, discriminator.trainable_variables)\n\n    optimizer.apply_gradients(zip(generator_grad,generator.trainable_variables))\n    optimizer.apply_gradients(zip(discriminator_grad,discriminator.trainable_variables))    ","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:56.640120Z","iopub.execute_input":"2023-03-06T03:09:56.640831Z","iopub.status.idle":"2023-03-06T03:09:56.650704Z","shell.execute_reply.started":"2023-03-06T03:09:56.640794Z","shell.execute_reply":"2023-03-06T03:09:56.649825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function that trains the GAN on multiple epochs:\n\ndef train(dataset, epochs):\n    for epoch in range(epochs):\n        start = time.time()\n        \n        for image_batch in dataset:\n            train_step(image_batch)\n        \n        print(f\"Time for epoch {epoch+ 1} is : {time.time()-start}\")","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:56.652875Z","iopub.execute_input":"2023-03-06T03:09:56.655028Z","iopub.status.idle":"2023-03-06T03:09:56.663498Z","shell.execute_reply.started":"2023-03-06T03:09:56.655001Z","shell.execute_reply":"2023-03-06T03:09:56.662890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train(monet_data, EPOCHS)","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:09:56.665953Z","iopub.execute_input":"2023-03-06T03:09:56.666277Z","iopub.status.idle":"2023-03-06T03:16:14.369750Z","shell.execute_reply.started":"2023-03-06T03:09:56.666252Z","shell.execute_reply":"2023-03-06T03:16:14.369038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create new directory and generate images:\n\nimport PIL\nfrom PIL import Image\n\nSAVE_PATH = './Monet_output'\n\nif not os.path.exists(SAVE_PATH ):\n    os.mkdir(SAVE_PATH )\nelse:\n    shutil.rmtree(SAVE_PATH )\n    os.mkdir(SAVE_PATH )\n\nfor index, photo in enumerate(photo_data):\n\n    prediction = generator(photo, training = False)[0].numpy()\n    prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n\n    PIL.Image.fromarray(prediction).save(SAVE_PATH  + f'/image {index+1}.jpg')\n\nshutil.make_archive('images', 'zip', SAVE_PATH )\n","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:16:14.370858Z","iopub.execute_input":"2023-03-06T03:16:14.371682Z","iopub.status.idle":"2023-03-06T03:27:12.747736Z","shell.execute_reply.started":"2023-03-06T03:16:14.371651Z","shell.execute_reply":"2023-03-06T03:27:12.746675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_iter = iter(photo_data)\nfor n_sample in range(2):\n        example_sample = next(ds_iter)\n        generated_sample = generator(example_sample)\n        \n        f = plt.figure(figsize=(5, 5))\n        \n        plt.subplot(121)\n        plt.title('Input image')\n        plt.imshow(example_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        \n        plt.subplot(122)\n        plt.title('Generated image')\n        plt.imshow(generated_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-06T03:27:12.748892Z","iopub.execute_input":"2023-03-06T03:27:12.749719Z","iopub.status.idle":"2023-03-06T03:27:13.161667Z","shell.execute_reply.started":"2023-03-06T03:27:12.749689Z","shell.execute_reply":"2023-03-06T03:27:13.160839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Conclusion:\n\nOur model did learn and begin to take shape. However, it is obvious our model did not create convincing images. There are a few suggestions: increase the number of epochs, modify the architecture and try transfer learning. \n\nSomething that I would have liked to try was transfer learning during the generator part so that the model doesn't have to learn from 0. In addition, I think increasing the number of epochs would have useful. \n\n This project just scrapes the surface of GANs and how much they can accomplish.","metadata":{}},{"cell_type":"markdown","source":"GitHub like: https://github.com/shriyutha/Monet-paintings-DCGAN-Deeplearning","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}