{"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":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline\n!pip install GPUtil\n!pip install numba ","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:13.173679Z","iopub.execute_input":"2021-08-10T15:45:13.174340Z","iopub.status.idle":"2021-08-10T15:45:29.364839Z","shell.execute_reply.started":"2021-08-10T15:45:13.174283Z","shell.execute_reply":"2021-08-10T15:45:29.363933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\nimport itertools\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport os\nimport pandas as pd\nimport PIL\nfrom PIL import Image\n\nimport random\nimport shutil\nfrom sklearn.model_selection import GroupKFold\nfrom sklearn.metrics import roc_curve\nfrom sklearn import metrics\nimport time\nfrom tqdm.notebook import tqdm\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.nn.init as init\nfrom torch.utils.data import Dataset, random_split, DataLoader\n\nimport torchvision.models as models\nimport torchvision.transforms as transforms\n\n# for loading/processing the images  \nfrom keras.preprocessing.image import load_img \nfrom keras.preprocessing.image import img_to_array \nfrom keras.applications.vgg16 import preprocess_input \n\nfrom GPUtil import showUtilization as gpu_usage\nfrom numba import cuda ","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2021-08-10T15:45:29.368337Z","iopub.execute_input":"2021-08-10T15:45:29.368714Z","iopub.status.idle":"2021-08-10T15:45:37.043032Z","shell.execute_reply.started":"2021-08-10T15:45:29.368676Z","shell.execute_reply":"2021-08-10T15:45:37.042143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Seed","metadata":{}},{"cell_type":"code","source":"def set_seed(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:37.044530Z","iopub.execute_input":"2021-08-10T15:45:37.044931Z","iopub.status.idle":"2021-08-10T15:45:37.109275Z","shell.execute_reply.started":"2021-08-10T15:45:37.044889Z","shell.execute_reply":"2021-08-10T15:45:37.108057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = 'cuda' if torch.cuda.is_available() else 'cpu'\ndevice","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:37.110883Z","iopub.execute_input":"2021-08-10T15:45:37.111302Z","iopub.status.idle":"2021-08-10T15:45:37.216055Z","shell.execute_reply.started":"2021-08-10T15:45:37.111251Z","shell.execute_reply":"2021-08-10T15:45:37.215189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(719)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:37.220360Z","iopub.execute_input":"2021-08-10T15:45:37.220975Z","iopub.status.idle":"2021-08-10T15:45:37.282210Z","shell.execute_reply.started":"2021-08-10T15:45:37.220943Z","shell.execute_reply":"2021-08-10T15:45:37.281308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset and Dataloader","metadata":{}},{"cell_type":"code","source":"!mkdir monet_30","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:37.287857Z","iopub.execute_input":"2021-08-10T15:45:37.288154Z","iopub.status.idle":"2021-08-10T15:45:38.013805Z","shell.execute_reply.started":"2021-08-10T15:45:37.288126Z","shell.execute_reply":"2021-08-10T15:45:38.012684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Extract features using a trined model ","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom keras.applications.vgg16 import preprocess_input \nfrom keras.applications.vgg16 import VGG16 \nfrom keras.models import Model\nfrom keras.preprocessing.image import img_to_array \nfrom sklearn.cluster import KMeans\nfrom sklearn.decomposition import PCA\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:38.018093Z","iopub.execute_input":"2021-08-10T15:45:38.018414Z","iopub.status.idle":"2021-08-10T15:45:38.479322Z","shell.execute_reply.started":"2021-08-10T15:45:38.018380Z","shell.execute_reply":"2021-08-10T15:45:38.478284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = \"../input/gan-getting-started/monet_jpg/\"\n\n# this list holds all the image filename\nmonet_images = []\n\n# creates a ScandirIterator aliased as files\nwith os.scandir(path) as files:\n  # loops through each file in the directory\n    for file in files:\n        if file.name.endswith('.jpg'):\n          # adds only the image files to the monet_images list\n            monet_images.append(path + file.name)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:38.480614Z","iopub.execute_input":"2021-08-10T15:45:38.480960Z","iopub.status.idle":"2021-08-10T15:45:38.587824Z","shell.execute_reply.started":"2021-08-10T15:45:38.480926Z","shell.execute_reply":"2021-08-10T15:45:38.587122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load model\nmodel = VGG16()\n# remove the output layer\nmodel = Model(inputs=model.inputs, outputs=model.layers[-2].output)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:38.590690Z","iopub.execute_input":"2021-08-10T15:45:38.590959Z","iopub.status.idle":"2021-08-10T15:45:47.717387Z","shell.execute_reply.started":"2021-08-10T15:45:38.590925Z","shell.execute_reply":"2021-08-10T15:45:47.716614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the model first and pass as an argument\nmodel = VGG16()\nmodel = Model(inputs = model.inputs, outputs = model.layers[-2].output)\n\ndef extract_features(file, model):\n    # load the image as a 224x224 array\n    img = load_img(file, target_size=(224,224))\n    # convert from 'PIL.Image.Image' to numpy array\n    img = np.array(img) \n    # reshape the data for the model reshape(num_of_samples, dim 1, dim 2, channels)\n    reshaped_img = img.reshape(1,224,224,3) \n    # prepare image for model\n    imgx = preprocess_input(reshaped_img)\n    # get the feature vector\n    features = model.predict(imgx, use_multiprocessing=True)\n    return features","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:47.718710Z","iopub.execute_input":"2021-08-10T15:45:47.719059Z","iopub.status.idle":"2021-08-10T15:45:49.642912Z","shell.execute_reply.started":"2021-08-10T15:45:47.719023Z","shell.execute_reply":"2021-08-10T15:45:49.642022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = {}\np = \"monet_images.pkl\"\n\n# lop through each image in the dataset\nfor monet_image in monet_images:\n    # try to extract the features and update the dictionary\n    feat = extract_features(monet_image,model)\n    data[monet_image] = feat\n          \n \n# get a list of the filenames\nfilenames = np.array(list(data.keys()))\n\n# get a list of just the features\nfeat = np.array(list(data.values()))\nfeat.shape\n(210, 1, 4096)\n\n# reshape so that there are 210 samples of 4096 vectors\nfeat = feat.reshape(-1,4096)\nfeat.shape\n(210, 4096)\n\nunique_labels = list(set(list(range(30))))","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:45:49.644320Z","iopub.execute_input":"2021-08-10T15:45:49.644707Z","iopub.status.idle":"2021-08-10T15:46:05.353946Z","shell.execute_reply.started":"2021-08-10T15:45:49.644668Z","shell.execute_reply":"2021-08-10T15:46:05.352890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pca = PCA(n_components=100, random_state=22)\npca.fit(feat)\nx = pca.transform(feat)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:05.355595Z","iopub.execute_input":"2021-08-10T15:46:05.355957Z","iopub.status.idle":"2021-08-10T15:46:05.591131Z","shell.execute_reply.started":"2021-08-10T15:46:05.355917Z","shell.execute_reply":"2021-08-10T15:46:05.590233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kmeans = KMeans(n_clusters=len(unique_labels),n_jobs=-1, random_state=22)\nkmeans.fit(x)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:05.594915Z","iopub.execute_input":"2021-08-10T15:46:05.595207Z","iopub.status.idle":"2021-08-10T15:46:05.935933Z","shell.execute_reply.started":"2021-08-10T15:46:05.595178Z","shell.execute_reply":"2021-08-10T15:46:05.935004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# holds the cluster id and the images { id: [images] }\ngroups = {}\nfor file, cluster in zip(filenames,kmeans.labels_):\n    if cluster not in groups.keys():\n        groups[cluster] = []\n        groups[cluster].append(file)\n    else:\n        groups[cluster].append(file)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:05.937208Z","iopub.execute_input":"2021-08-10T15:46:05.937542Z","iopub.status.idle":"2021-08-10T15:46:06.003598Z","shell.execute_reply.started":"2021-08-10T15:46:05.937493Z","shell.execute_reply":"2021-08-10T15:46:06.002788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\n\nimgs = groups[0]\n\nplt.figure()\n\n#subplot(r,c) provide the no. of rows and columns\nf, axarr = plt.subplots(len(imgs),1, figsize = (len(imgs)*30,30))\n\nfor i, img_path in enumerate(imgs):\n    axarr[i].imshow(cv2.imread(imgs[i]))","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:06.005260Z","iopub.execute_input":"2021-08-10T15:46:06.005819Z","iopub.status.idle":"2021-08-10T15:46:07.771124Z","shell.execute_reply.started":"2021-08-10T15:46:06.005772Z","shell.execute_reply":"2021-08-10T15:46:07.769996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# we choose image 0 in every cluster as a representitive\nmonet_dataset_paths = []\nfor i in range(len(groups)):\n    monet_dataset_paths.append(groups[i][0].replace('../input/gan-getting-started/monet_jpg/', ''))\nprint(monet_dataset_paths)\nlen(monet_dataset_paths)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:07.772331Z","iopub.execute_input":"2021-08-10T15:46:07.772680Z","iopub.status.idle":"2021-08-10T15:46:07.851795Z","shell.execute_reply.started":"2021-08-10T15:46:07.772648Z","shell.execute_reply":"2021-08-10T15:46:07.850801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Select 30 monet images for training","metadata":{}},{"cell_type":"code","source":"FILENAMES = monet_dataset_paths\n#FILENAMES = ['3b262c6726.jpg','3c341ff93e.jpg','05b493ff42.jpg','5e357ad790.jpg','6c6cc46498.jpg','6e0429f92e.jpg','6ee7c39dbc.jpg','8b54448a07.jpg','8f02369f42.jpg','10c555c1b1.jpg','25c9904782.jpg','73f33a12c5.jpg','92c0ba8c0d.jpg','99d94af5dd.jpg','7017e6caa1.jpg','7239ba0b55.jpg','9843bc25c5.jpg','011835cfbf.jpg','064487d630.jpg','2581464ddc.jpg','88402296cc.jpg','a7977705be.jpg','b1ea5d5a7d.jpg','bf6db09354.jpg','c1dc1a85a4.jpg','cb9c553ded.jpg','cdddf326e3.jpg','dc33f0edbe.jpg','e510a74d3c.jpg','ee7adac58f.jpg']","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:07.853415Z","iopub.execute_input":"2021-08-10T15:46:07.854024Z","iopub.status.idle":"2021-08-10T15:46:07.915032Z","shell.execute_reply.started":"2021-08-10T15:46:07.853978Z","shell.execute_reply":"2021-08-10T15:46:07.914044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Clearing gpu memory\ngpu_usage()\nprint()\ndev = cuda.get_current_device()\ndev.reset()\ngpu_usage()","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:07.918602Z","iopub.execute_input":"2021-08-10T15:46:07.919055Z","iopub.status.idle":"2021-08-10T15:46:08.868811Z","shell.execute_reply.started":"2021-08-10T15:46:07.919024Z","shell.execute_reply":"2021-08-10T15:46:08.866548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Augment the data","metadata":{}},{"cell_type":"code","source":"\ndef sp_noise(image,prob):\n    image = image.convert('RGB') \n    image = np.array(image) \n    image = image[:, :, ::-1].copy() \n    '''\n    Add salt and pepper noise to image\n    prob: Probability of the noise\n    '''\n    output = np.zeros(image.shape,np.uint8)\n    thres = 1 - prob \n    for i in range(image.shape[0]):\n        for j in range(image.shape[1]):\n            rdn = random.random()\n            if rdn < prob:\n                output[i][j] = 0\n            elif rdn > thres:\n                output[i][j] = 125\n            else:\n                output[i][j] = image[i][j]\n    return Image.fromarray(output )\n","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:08.872658Z","iopub.execute_input":"2021-08-10T15:46:08.872989Z","iopub.status.idle":"2021-08-10T15:46:08.950437Z","shell.execute_reply.started":"2021-08-10T15:46:08.872955Z","shell.execute_reply":"2021-08-10T15:46:08.949662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import colorsys\n\ndef shift_hue(im, hue, sat):\n#     im = Image.open(filename)\n    ld = im.load()\n    width, height = im.size\n    for y in range(height):\n        for x in range(width):\n            r,g,b = ld[x,y]\n            h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)\n            h = (h + -hue/360.0) % 1.0\n            s = s**sat\n            r,g,b = colorsys.hsv_to_rgb(h, s, v)\n            ld[x,y] = (int(r * 255.9999), int(g * 255.9999), int(b * 255.9999))\n    return im","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:08.953741Z","iopub.execute_input":"2021-08-10T15:46:08.954031Z","iopub.status.idle":"2021-08-10T15:46:09.024251Z","shell.execute_reply.started":"2021-08-10T15:46:08.954005Z","shell.execute_reply":"2021-08-10T15:46:09.023232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom shutil import copyfile\nfrom skimage.util import random_noise\nfrom skimage.transform import rotate, AffineTransform, warp\n\ndirectory = '../input/gan-getting-started/monet_jpg/'\n\nsigma=0.1\ndst = '../input/gan-getting-started/monet_30'\nfor filename in FILENAMES:\n# for filename in monet_dataset_paths:\n        image = Image.open(f'{directory}{filename}')  \n#         image = Image.open(filename)  \n        im = np.fliplr(image) ###\n        flipLR = Image.fromarray(im) ###\n        hue_im = shift_hue(image, 25, 0.95) ###\n        noisyRandom = sp_noise(image,0.002) ###\n        flipLR = flipLR.save(f'monet_30/flipped_{filename}') ###\n        noisyRandom = noisyRandom.save(f'monet_30/noisy_{filename}') ###\n        hue_im = hue_im.save(f'monet_30/hue_{filename}') ###\n#         transform = AffineTransform(translation=(25,25))\n#         wrap_im = warp(image,transform,mode='wrap')\n#         wrap_im = Image.fromarray((wrap_im * 255).astype(np.uint8)) ###\n#         wrap_im = wrap_im.save(f'monet_30/wrap_{filename}') ###\n        copyfile(f'{directory}{filename}', f'monet_30/{filename}')","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:09.028309Z","iopub.execute_input":"2021-08-10T15:46:09.028663Z","iopub.status.idle":"2021-08-10T15:46:22.409360Z","shell.execute_reply.started":"2021-08-10T15:46:09.028628Z","shell.execute_reply":"2021-08-10T15:46:22.408534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls monet_30","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:22.410817Z","iopub.execute_input":"2021-08-10T15:46:22.411171Z","iopub.status.idle":"2021-08-10T15:46:23.194032Z","shell.execute_reply.started":"2021-08-10T15:46:22.411134Z","shell.execute_reply":"2021-08-10T15:46:23.193170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import matplotlib.image as mpimg\n# img = mpimg.imread(f'monet_30/hue_73f33a12c5.jpg')\n# imgplot = plt.imshow(img)\n# plt.show()\n# img = mpimg.imread(f'monet_30/73f33a12c5.jpg')\n# imgplot = plt.imshow(img)\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:23.196016Z","iopub.execute_input":"2021-08-10T15:46:23.196443Z","iopub.status.idle":"2021-08-10T15:46:23.267667Z","shell.execute_reply.started":"2021-08-10T15:46:23.196397Z","shell.execute_reply":"2021-08-10T15:46:23.266739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageDataset(Dataset):\n    def __init__(self, monet_dir, photo_dir, size=(256, 256), normalize=True):\n        super().__init__()\n        self.monet_dir = monet_dir\n        self.photo_dir = photo_dir\n        self.monet_idx = dict()\n        self.photo_idx = dict()\n        if normalize:\n            self.transform = transforms.Compose([\n                transforms.Resize(size),\n                transforms.ToTensor(),\n                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))                                \n            ])\n        else:\n            self.transform = transforms.Compose([\n                transforms.Resize(size),\n                transforms.ToTensor()                               \n            ])\n        for i, fl in enumerate(os.listdir(self.monet_dir)):\n            self.monet_idx[i] = fl\n        for i, fl in enumerate(os.listdir(self.photo_dir)):\n            self.photo_idx[i] = fl\n\n    def __getitem__(self, idx):\n        rand_idx = int(np.random.uniform(0, len(self.monet_idx.keys())))\n        photo_path = os.path.join(self.photo_dir, self.photo_idx[rand_idx])\n        monet_path = os.path.join(self.monet_dir, self.monet_idx[idx])\n        photo_img = Image.open(photo_path)\n        photo_img = self.transform(photo_img)\n        monet_img = Image.open(monet_path)\n        monet_img = self.transform(monet_img)\n        return photo_img, monet_img\n\n    def __len__(self):\n        return min(len(self.monet_idx.keys()), len(self.photo_idx.keys()))","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:23.269702Z","iopub.execute_input":"2021-08-10T15:46:23.270238Z","iopub.status.idle":"2021-08-10T15:46:23.344211Z","shell.execute_reply.started":"2021-08-10T15:46:23.270197Z","shell.execute_reply":"2021-08-10T15:46:23.343008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ds = ImageDataset('monet_30/', '../input/gan-getting-started/photo_jpg/')","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:23.346016Z","iopub.execute_input":"2021-08-10T15:46:23.346523Z","iopub.status.idle":"2021-08-10T15:46:23.691588Z","shell.execute_reply.started":"2021-08-10T15:46:23.346478Z","shell.execute_reply":"2021-08-10T15:46:23.690524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_dl = DataLoader(img_ds, batch_size=1, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:23.693321Z","iopub.execute_input":"2021-08-10T15:46:23.693833Z","iopub.status.idle":"2021-08-10T15:46:23.756862Z","shell.execute_reply.started":"2021-08-10T15:46:23.693788Z","shell.execute_reply":"2021-08-10T15:46:23.755881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"photo_img, monet_img = next(iter(img_dl))","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:23.758228Z","iopub.execute_input":"2021-08-10T15:46:23.758611Z","iopub.status.idle":"2021-08-10T15:46:25.669055Z","shell.execute_reply.started":"2021-08-10T15:46:23.758574Z","shell.execute_reply":"2021-08-10T15:46:25.668253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def unnorm(img, mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]):\n    for t, m, s in zip(img, mean, std):\n        t.mul_(s).add_(s)\n        \n    return img","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:25.670403Z","iopub.execute_input":"2021-08-10T15:46:25.670755Z","iopub.status.idle":"2021-08-10T15:46:25.731143Z","shell.execute_reply.started":"2021-08-10T15:46:25.670721Z","shell.execute_reply":"2021-08-10T15:46:25.730276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = plt.figure(figsize=(8, 8))\n\nf.add_subplot(1, 2, 1)\nplt.title('Photo')\nphoto_img = unnorm(photo_img)\nplt.imshow(photo_img[0].permute(1, 2, 0))\n\nf.add_subplot(1, 2, 2)\nplt.title('Monet')\nmonet_img = unnorm(monet_img)\nplt.imshow(monet_img[0].permute(1, 2, 0))","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:25.734461Z","iopub.execute_input":"2021-08-10T15:46:25.734732Z","iopub.status.idle":"2021-08-10T15:46:26.093868Z","shell.execute_reply.started":"2021-08-10T15:46:25.734706Z","shell.execute_reply":"2021-08-10T15:46:26.092980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Save and Load","metadata":{}},{"cell_type":"code","source":"def load_checkpoint(ckpt_path, map_location=None):\n    ckpt = torch.load(ckpt_path, map_location=map_location)\n    print(' [*] Loading checkpoint from %s succeed!' % ckpt_path)\n    return ckpt","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.095070Z","iopub.execute_input":"2021-08-10T15:46:26.095455Z","iopub.status.idle":"2021-08-10T15:46:26.157648Z","shell.execute_reply.started":"2021-08-10T15:46:26.095401Z","shell.execute_reply":"2021-08-10T15:46:26.156548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_checkpoint(state, save_path):\n    torch.save(state, save_path)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.159210Z","iopub.execute_input":"2021-08-10T15:46:26.159621Z","iopub.status.idle":"2021-08-10T15:46:26.220830Z","shell.execute_reply.started":"2021-08-10T15:46:26.159567Z","shell.execute_reply":"2021-08-10T15:46:26.220118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"def Upsample(in_ch, out_ch, use_dropout=True, dropout_ratio=0.5):\n    if use_dropout:\n        return nn.Sequential(\n            nn.ConvTranspose2d(in_ch, out_ch, 3, stride=2, padding=1, output_padding=1),\n            nn.InstanceNorm2d(out_ch),\n            nn.Dropout(dropout_ratio),\n            nn.GELU()\n        )\n    else:\n        return nn.Sequential(\n            nn.ConvTranspose2d(in_ch, out_ch, 3, stride=2, padding=1, output_padding=1),\n            nn.InstanceNorm2d(out_ch),\n            nn.GELU()\n        )","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.227990Z","iopub.execute_input":"2021-08-10T15:46:26.228277Z","iopub.status.idle":"2021-08-10T15:46:26.290781Z","shell.execute_reply.started":"2021-08-10T15:46:26.228251Z","shell.execute_reply":"2021-08-10T15:46:26.289873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Convlayer(in_ch, out_ch, kernel_size=3, stride=2, use_leaky=True, use_inst_norm=True, use_pad=True):\n    if use_pad:\n        conv = nn.Conv2d(in_ch, out_ch, kernel_size, stride, 1, bias=True)\n    else:\n        conv = nn.Conv2d(in_ch, out_ch, kernel_size, stride, 0, bias=True)\n\n    if use_leaky:\n        actv = nn.LeakyReLU(negative_slope=0.2, inplace=True)\n    else:\n        actv = nn.GELU()\n\n    if use_inst_norm:\n        norm = nn.InstanceNorm2d(out_ch)\n    else:\n        norm = nn.BatchNorm2d(out_ch)\n\n    return nn.Sequential(\n        conv,\n        norm,\n        actv\n    )","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.292360Z","iopub.execute_input":"2021-08-10T15:46:26.292781Z","iopub.status.idle":"2021-08-10T15:46:26.356020Z","shell.execute_reply.started":"2021-08-10T15:46:26.292741Z","shell.execute_reply":"2021-08-10T15:46:26.355223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Resblock(nn.Module):\n    def __init__(self, in_features, use_dropout=True, dropout_ratio=0.5):\n        super().__init__()\n        layers = list()\n        layers.append(nn.ReflectionPad2d(1))\n        layers.append(Convlayer(in_features, in_features, 3, 1, False, use_pad=False))\n        layers.append(nn.Dropout(dropout_ratio))\n        layers.append(nn.ReflectionPad2d(1))\n        layers.append(nn.Conv2d(in_features, in_features, 3, 1, padding=0, bias=True))\n        layers.append(nn.InstanceNorm2d(in_features))\n        self.res = nn.Sequential(*layers)\n\n    def forward(self, x):\n        return x + self.res(x)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.357397Z","iopub.execute_input":"2021-08-10T15:46:26.357799Z","iopub.status.idle":"2021-08-10T15:46:26.422552Z","shell.execute_reply.started":"2021-08-10T15:46:26.357756Z","shell.execute_reply":"2021-08-10T15:46:26.421597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, in_ch, out_ch, num_res_blocks=6):\n        super().__init__()\n        model = list()\n        model.append(nn.ReflectionPad2d(3))\n        model.append(Convlayer(in_ch, 64, 7, 1, False, True, False))\n        model.append(Convlayer(64, 128, 3, 2, False))\n        model.append(Convlayer(128, 256, 3, 2, False))\n        for _ in range(num_res_blocks):\n            model.append(Resblock(256))\n        model.append(Upsample(256, 128))\n        model.append(Upsample(128, 64))\n        model.append(nn.ReflectionPad2d(3))\n        model.append(nn.Conv2d(64, out_ch, kernel_size=7, padding=0))\n        model.append(nn.Tanh())\n\n        self.gen = nn.Sequential(*model)\n\n    def forward(self, x):\n        return self.gen(x)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.423865Z","iopub.execute_input":"2021-08-10T15:46:26.424276Z","iopub.status.idle":"2021-08-10T15:46:26.490826Z","shell.execute_reply.started":"2021-08-10T15:46:26.424232Z","shell.execute_reply":"2021-08-10T15:46:26.489984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, in_ch, num_layers=4):\n        super().__init__()\n        model = list()\n        model.append(nn.Conv2d(in_ch, 64, 4, stride=2, padding=1))\n        model.append(nn.LeakyReLU(0.2, inplace=True))\n        for i in range(1, num_layers):\n            in_chs = 64 * 2**(i-1)\n            out_chs = in_chs * 2\n            if i == num_layers -1:\n                model.append(Convlayer(in_chs, out_chs, 4, 1))\n            else:\n                model.append(Convlayer(in_chs, out_chs, 4, 2))\n        model.append(nn.Conv2d(512, 1, kernel_size=4, stride=1, padding=1))\n        self.disc = nn.Sequential(*model)\n\n    def forward(self, x):\n        return self.disc(x)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.492447Z","iopub.execute_input":"2021-08-10T15:46:26.492856Z","iopub.status.idle":"2021-08-10T15:46:26.557316Z","shell.execute_reply.started":"2021-08-10T15:46:26.492807Z","shell.execute_reply":"2021-08-10T15:46:26.556454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def init_weights(net, init_type='normal', gain=0.02):\n    def init_func(m):\n        classname = m.__class__.__name__\n        if hasattr(m, 'weight') and (classname.find('Conv') != -1 or classname.find('Linear') != -1):\n            init.normal_(m.weight.data, 0.0, gain)\n            if hasattr(m, 'bias') and m.bias is not None:\n                init.constant_(m.bias.data, 0.0)\n        elif classname.find('BatchNorm2d') != -1:\n            init.normal_(m.weight.data, 1.0, gain)\n            init.constant_(m.bias.data, 0.0)\n    net.apply(init_func)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.559018Z","iopub.execute_input":"2021-08-10T15:46:26.559415Z","iopub.status.idle":"2021-08-10T15:46:26.623471Z","shell.execute_reply.started":"2021-08-10T15:46:26.559376Z","shell.execute_reply":"2021-08-10T15:46:26.622617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Some additional classes and functions","metadata":{}},{"cell_type":"code","source":"def update_req_grad(models, requires_grad=True):\n    for model in models:\n        for param in model.parameters():\n            param.requires_grad = requires_grad","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.626721Z","iopub.execute_input":"2021-08-10T15:46:26.627014Z","iopub.status.idle":"2021-08-10T15:46:26.686238Z","shell.execute_reply.started":"2021-08-10T15:46:26.626965Z","shell.execute_reply":"2021-08-10T15:46:26.685398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://arxiv.org/pdf/1612.07828.pdf\n# Save 50 generated fake imgs and sample through them\n# to feed discriminators to avoid large oscillations \n# from iterations to iterations.\nclass sample_fake(object):\n    def __init__(self, max_imgs=50):\n        self.max_imgs = max_imgs\n        self.cur_img = 0\n        self.imgs = list()\n\n    def __call__(self, imgs):\n        ret = list()\n        for img in imgs:\n            if self.cur_img < self.max_imgs:\n                self.imgs.append(img)\n                ret.append(img)\n                self.cur_img += 1\n            else:\n                if np.random.ranf() > 0.5:\n                    idx = np.random.randint(0, self.max_imgs)\n                    ret.append(self.imgs[idx])\n                    self.imgs[idx] = img\n                else:\n                    ret.append(img)\n        return ret","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.687665Z","iopub.execute_input":"2021-08-10T15:46:26.688108Z","iopub.status.idle":"2021-08-10T15:46:26.753099Z","shell.execute_reply.started":"2021-08-10T15:46:26.688051Z","shell.execute_reply":"2021-08-10T15:46:26.752037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class lr_sched():\n    def __init__(self, decay_epochs=100, total_epochs=200):\n        self.decay_epochs = decay_epochs\n        self.total_epochs = total_epochs\n\n    def step(self, epoch_num):\n        if epoch_num <= self.decay_epochs:\n            return 1.0\n        else:\n            fract = (epoch_num - self.decay_epochs)  / (self.total_epochs - self.decay_epochs)\n            return 1.0 - fract","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.756515Z","iopub.execute_input":"2021-08-10T15:46:26.756800Z","iopub.status.idle":"2021-08-10T15:46:26.819709Z","shell.execute_reply.started":"2021-08-10T15:46:26.756773Z","shell.execute_reply":"2021-08-10T15:46:26.818917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AvgStats(object):\n    def __init__(self):\n        self.reset()\n        \n    def reset(self):\n        self.losses =[]\n        self.its = []\n        \n    def append(self, loss, it):\n        self.losses.append(loss)\n        self.its.append(it)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.820960Z","iopub.execute_input":"2021-08-10T15:46:26.821346Z","iopub.status.idle":"2021-08-10T15:46:26.883137Z","shell.execute_reply.started":"2021-08-10T15:46:26.821299Z","shell.execute_reply":"2021-08-10T15:46:26.882017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# GAN Class","metadata":{}},{"cell_type":"code","source":"class CycleGAN(object):\n    def __init__(self, in_ch, out_ch, epochs, device, start_lr=2e-4, lmbda=10, idt_coef=0.5, decay_epoch=0):\n        self.epochs = epochs\n        self.decay_epoch = decay_epoch if decay_epoch > 0 else int(self.epochs/2)\n        self.lmbda = lmbda\n        self.idt_coef = idt_coef\n        self.device = device\n        self.gen_mtp = Generator(in_ch, out_ch)\n        self.gen_ptm = Generator(in_ch, out_ch)\n        self.desc_m = Discriminator(in_ch)\n        self.desc_p = Discriminator(in_ch)\n        self.init_models()\n        self.mse_loss = nn.MSELoss()\n        self.l1_loss = nn.L1Loss()\n        self.adam_gen = torch.optim.Adam(itertools.chain(self.gen_mtp.parameters(), self.gen_ptm.parameters()),\n                                         lr = start_lr, betas=(0.5, 0.999))\n        self.adam_desc = torch.optim.Adam(itertools.chain(self.desc_m.parameters(), self.desc_p.parameters()),\n                                          lr=start_lr, betas=(0.5, 0.999))\n        self.sample_monet = sample_fake()\n        self.sample_photo = sample_fake()\n        gen_lr = lr_sched(self.decay_epoch, self.epochs)\n        desc_lr = lr_sched(self.decay_epoch, self.epochs)\n        self.gen_lr_sched = torch.optim.lr_scheduler.LambdaLR(self.adam_gen, gen_lr.step)\n        self.desc_lr_sched = torch.optim.lr_scheduler.LambdaLR(self.adam_desc, desc_lr.step)\n        self.gen_stats = AvgStats()\n        self.desc_stats = AvgStats()\n        \n    def init_models(self):\n        init_weights(self.gen_mtp)\n        init_weights(self.gen_ptm)\n        init_weights(self.desc_m)\n        init_weights(self.desc_p)\n        self.gen_mtp = self.gen_mtp.to(self.device)\n        self.gen_ptm = self.gen_ptm.to(self.device)\n        self.desc_m = self.desc_m.to(self.device)\n        self.desc_p = self.desc_p.to(self.device)\n        \n    def train(self, photo_dl):\n        for epoch in range(self.epochs):\n            start_time = time.time()\n            avg_gen_loss = 0.0\n            avg_desc_loss = 0.0\n            t = tqdm(photo_dl, leave=False, total=photo_dl.__len__())\n            for i, (photo_real, monet_real) in enumerate(t):\n                photo_img, monet_img = photo_real.to(device), monet_real.to(device)\n                update_req_grad([self.desc_m, self.desc_p], False)\n                self.adam_gen.zero_grad()\n\n                # Forward pass through generator\n                fake_photo = self.gen_mtp(monet_img)\n                fake_monet = self.gen_ptm(photo_img)\n\n                cycl_monet = self.gen_ptm(fake_photo)\n                cycl_photo = self.gen_mtp(fake_monet)\n\n                id_monet = self.gen_ptm(monet_img)\n                id_photo = self.gen_mtp(photo_img)\n\n                # generator losses - identity, Adversarial, cycle consistency\n                idt_loss_monet = self.l1_loss(id_monet, monet_img) * self.lmbda * self.idt_coef\n                idt_loss_photo = self.l1_loss(id_photo, photo_img) * self.lmbda * self.idt_coef\n\n                cycle_loss_monet = self.l1_loss(cycl_monet, monet_img) * self.lmbda\n                cycle_loss_photo = self.l1_loss(cycl_photo, photo_img) * self.lmbda\n\n                monet_desc = self.desc_m(fake_monet)\n                photo_desc = self.desc_p(fake_photo)\n\n                real = torch.ones(monet_desc.size()).to(self.device)\n\n                adv_loss_monet = self.mse_loss(monet_desc, real)\n                adv_loss_photo = self.mse_loss(photo_desc, real)\n\n                # total generator loss\n                total_gen_loss = cycle_loss_monet + adv_loss_monet\\\n                              + cycle_loss_photo + adv_loss_photo\\\n                              + idt_loss_monet + idt_loss_photo\n                \n                avg_gen_loss += total_gen_loss.item()\n\n                # backward pass\n                total_gen_loss.backward()\n                self.adam_gen.step()\n\n                # Forward pass through Descriminator\n                update_req_grad([self.desc_m, self.desc_p], True)\n                self.adam_desc.zero_grad()\n\n                fake_monet = self.sample_monet([fake_monet.cpu().data.numpy()])[0]\n                fake_photo = self.sample_photo([fake_photo.cpu().data.numpy()])[0]\n                fake_monet = torch.tensor(fake_monet).to(self.device)\n                fake_photo = torch.tensor(fake_photo).to(self.device)\n\n                monet_desc_real = self.desc_m(monet_img)\n                monet_desc_fake = self.desc_m(fake_monet)\n                photo_desc_real = self.desc_p(photo_img)\n                photo_desc_fake = self.desc_p(fake_photo)\n\n                real = torch.ones(monet_desc_real.size()).to(self.device)\n                fake = torch.zeros(monet_desc_fake.size()).to(self.device)\n\n                # Descriminator losses\n                # --------------------\n                monet_desc_real_loss = self.mse_loss(monet_desc_real, real)\n                monet_desc_fake_loss = self.mse_loss(monet_desc_fake, fake)\n                photo_desc_real_loss = self.mse_loss(photo_desc_real, real)\n                photo_desc_fake_loss = self.mse_loss(photo_desc_fake, fake)\n\n                monet_desc_loss = (monet_desc_real_loss + monet_desc_fake_loss) / 2\n                photo_desc_loss = (photo_desc_real_loss + photo_desc_fake_loss) / 2\n                total_desc_loss = monet_desc_loss + photo_desc_loss\n                avg_desc_loss += total_desc_loss.item()\n\n                # Backward\n                monet_desc_loss.backward()\n                photo_desc_loss.backward()\n                self.adam_desc.step()\n                \n                t.set_postfix(gen_loss=total_gen_loss.item(), desc_loss=total_desc_loss.item())\n\n            save_dict = {\n                'epoch': epoch+1,\n                'gen_mtp': gan.gen_mtp.state_dict(),\n                'gen_ptm': gan.gen_ptm.state_dict(),\n                'desc_m': gan.desc_m.state_dict(),\n                'desc_p': gan.desc_p.state_dict(),\n                'optimizer_gen': gan.adam_gen.state_dict(),\n                'optimizer_desc': gan.adam_desc.state_dict()\n            }\n            save_checkpoint(save_dict, 'current.ckpt')\n            \n            avg_gen_loss /= photo_dl.__len__()\n            avg_desc_loss /= photo_dl.__len__()\n            time_req = time.time() - start_time\n            \n            self.gen_stats.append(avg_gen_loss, time_req)\n            self.desc_stats.append(avg_desc_loss, time_req)\n            \n            print(\"Epoch: (%d) | Generator Loss:%f | Discriminator Loss:%f\" % \n                                                (epoch+1, avg_gen_loss, avg_desc_loss))\n      \n            self.gen_lr_sched.step()\n            self.desc_lr_sched.step()","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.885476Z","iopub.execute_input":"2021-08-10T15:46:26.886076Z","iopub.status.idle":"2021-08-10T15:46:26.980335Z","shell.execute_reply.started":"2021-08-10T15:46:26.886036Z","shell.execute_reply":"2021-08-10T15:46:26.979193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gan = CycleGAN(3, 3, 75, device)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:26.984114Z","iopub.execute_input":"2021-08-10T15:46:26.984398Z","iopub.status.idle":"2021-08-10T15:46:27.432756Z","shell.execute_reply.started":"2021-08-10T15:46:26.984371Z","shell.execute_reply":"2021-08-10T15:46:27.431964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save before train\nsave_dict = {\n    'epoch': 0,\n    'gen_mtp': gan.gen_mtp.state_dict(),\n    'gen_ptm': gan.gen_ptm.state_dict(),\n    'desc_m': gan.desc_m.state_dict(),\n    'desc_p': gan.desc_p.state_dict(),\n    'optimizer_gen': gan.adam_gen.state_dict(),\n    'optimizer_desc': gan.adam_desc.state_dict()\n}","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:27.434037Z","iopub.execute_input":"2021-08-10T15:46:27.434460Z","iopub.status.idle":"2021-08-10T15:46:27.496649Z","shell.execute_reply.started":"2021-08-10T15:46:27.434402Z","shell.execute_reply":"2021-08-10T15:46:27.495796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"save_checkpoint(save_dict, 'init.ckpt')","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:27.498098Z","iopub.execute_input":"2021-08-10T15:46:27.498551Z","iopub.status.idle":"2021-08-10T15:46:27.646053Z","shell.execute_reply.started":"2021-08-10T15:46:27.498504Z","shell.execute_reply":"2021-08-10T15:46:27.645214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gan.train(img_dl)","metadata":{"execution":{"iopub.status.busy":"2021-08-10T15:46:27.647400Z","iopub.execute_input":"2021-08-10T15:46:27.647830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.xlabel(\"Epochs\")\nplt.ylabel(\"Losses\")\nplt.plot(gan.gen_stats.losses, 'r', label='Generator Loss')\nplt.plot(gan.desc_stats.losses, 'b', label='Descriminator Loss')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_, ax = plt.subplots(5, 2, figsize=(12, 12))\nfor i in range(5):\n    photo_img, _ = next(iter(img_dl))\n    pred_monet = gan.gen_ptm(photo_img.to(device)).cpu().detach()\n    photo_img = unnorm(photo_img)\n    pred_monet = unnorm(pred_monet)\n    \n    ax[i, 0].imshow(photo_img[0].permute(1, 2, 0))\n    ax[i, 1].imshow(pred_monet[0].permute(1, 2, 0))\n    ax[i, 0].set_title(\"Input Photo\")\n    ax[i, 1].set_title(\"Monet-esque Photo\")\n    ax[i, 0].axis(\"off\")\n    ax[i, 1].axis(\"off\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Run Generator over all images","metadata":{}},{"cell_type":"code","source":"class PhotoDataset(Dataset):\n    def __init__(self, photo_dir, size=(256, 256), normalize=True):\n        super().__init__()\n        self.photo_dir = photo_dir\n        self.photo_idx = dict()\n        if normalize:\n            self.transform = transforms.Compose([\n                transforms.Resize(size),\n                transforms.ToTensor(),\n                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))                                \n            ])\n        else:\n            self.transform = transforms.Compose([\n                transforms.Resize(size),\n                transforms.ToTensor()                               \n            ])\n        for i, fl in enumerate(os.listdir(self.photo_dir)):\n            self.photo_idx[i] = fl\n\n    def __getitem__(self, idx):\n        photo_path = os.path.join(self.photo_dir, self.photo_idx[idx])\n        photo_img = Image.open(photo_path)\n        photo_img = self.transform(photo_img)\n        return photo_img\n\n    def __len__(self):\n        return len(self.photo_idx.keys())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ph_ds = PhotoDataset('../input/gan-getting-started/photo_jpg/')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ph_dl = DataLoader(ph_ds, batch_size=1, pin_memory=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir ../images","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trans = transforms.ToPILImage()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = tqdm(ph_dl, leave=False, total=ph_dl.__len__())\nfor i, photo in enumerate(t):\n    with torch.no_grad():\n        pred_monet = gan.gen_ptm(photo.to(device)).cpu().detach()\n    pred_monet = unnorm(pred_monet)\n    img = trans(pred_monet[0]).convert(\"RGB\")\n    img.save(\"../images/\" + str(i+1) + \".jpg\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}