{"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":"# Monet-ifying photos with Basic (original) GAN in Pytorch","metadata":{}},{"cell_type":"markdown","source":"In this Notebook we will create a basic GAN true to the original paper, in the later Notebooks I will compare how improvements on GAN (DCGAN, WGAN, CycleGAN etc) stack up on this task.\nThis is part of a handout I'll do for a presentation at school. \nPlease let me know if anything is unclear or you have ideas for improvements.","metadata":{}},{"cell_type":"code","source":"#importing relevant packages\nimport numpy as np\nimport pandas as pd\nimport torch\nfrom torch import nn\nimport os\nfrom tqdm.auto import tqdm\nfrom torchvision import transforms\nfrom torchvision.utils import make_grid\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-10-21T13:44:28.534684Z","iopub.execute_input":"2021-10-21T13:44:28.535192Z","iopub.status.idle":"2021-10-21T13:44:33.099429Z","shell.execute_reply.started":"2021-10-21T13:44:28.535067Z","shell.execute_reply":"2021-10-21T13:44:33.098628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#choose gpu\ndevice = 'cuda'","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.101253Z","iopub.execute_input":"2021-10-21T13:44:33.101491Z","iopub.status.idle":"2021-10-21T13:44:33.106674Z","shell.execute_reply.started":"2021-10-21T13:44:33.101458Z","shell.execute_reply":"2021-10-21T13:44:33.10596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## for TPU\n#!curl https://raw.githubusercontent.com/pytorch/xla/master/contrib/scripts/env-setup.py -o pytorch-xla-env-setup.py\n#!python pytorch-xla-env-setup.py --apt-packages libomp5 libopenblas-dev","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.1081Z","iopub.execute_input":"2021-10-21T13:44:33.108497Z","iopub.status.idle":"2021-10-21T13:44:33.115922Z","shell.execute_reply.started":"2021-10-21T13:44:33.108461Z","shell.execute_reply":"2021-10-21T13:44:33.115063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_tensor_images(image_tensor, num_images=5, size=(3, 256, 256)):\n    '''\n    Function for visualizing images: Given a tensor of images, number of images, and\n    size per image, plots and prints the images in a uniform grid.\n    '''\n    image_unflat = image_tensor.detach().cpu().view(-1, *size)\n    image_grid = make_grid(image_unflat[:num_images], nrow=5)\n    plt.figure(figsize = (20, 10))\n    plt.imshow(image_grid.permute(1, 2, 0).squeeze())\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.117248Z","iopub.execute_input":"2021-10-21T13:44:33.117658Z","iopub.status.idle":"2021-10-21T13:44:33.125279Z","shell.execute_reply.started":"2021-10-21T13:44:33.117622Z","shell.execute_reply":"2021-10-21T13:44:33.124348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#basic gan only takes 1D Vectors\n#this is it's dimension\nflatten_dim = 256*256*3","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.129187Z","iopub.execute_input":"2021-10-21T13:44:33.129422Z","iopub.status.idle":"2021-10-21T13:44:33.13485Z","shell.execute_reply.started":"2021-10-21T13:44:33.12939Z","shell.execute_reply":"2021-10-21T13:44:33.134165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# *Generator*\n","metadata":{}},{"cell_type":"markdown","source":"The generator tries to learn the distribution of Monet Paintings, i.e. given a photo x, it will try to output the most likely monet painting y.\nI.e. it tries to match the two distributions as closely as possible.\n\n![What the generator attempts](https://i.imgur.com/t9zb0Cn.png)\n","metadata":{}},{"cell_type":"code","source":"def get_generator_block(input_dim, output_dim):\n    '''\n    Function for returning a block of the generator's neural network\n    given input and output dimensions.\n    Parameters:\n        input_dim: the dimension of the input vector, a scalar\n        output_dim: the dimension of the output vector, a scalar\n    Returns:\n        a generator neural network layer, with a linear transformation \n          followed by a batch normalization and then a relu activation\n    '''\n    return nn.Sequential(\n        nn.Linear(input_dim, output_dim),\n        nn.BatchNorm1d(output_dim),\n        nn.ReLU(inplace=True)\n    )","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.135923Z","iopub.execute_input":"2021-10-21T13:44:33.138278Z","iopub.status.idle":"2021-10-21T13:44:33.145132Z","shell.execute_reply.started":"2021-10-21T13:44:33.13824Z","shell.execute_reply":"2021-10-21T13:44:33.144476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Generator(nn.Module):\n    '''\n    Generator Class\n    Values:\n        im_dim: the dimension of the images 256*256 acts as noise vector\n    '''\n    def __init__(self, im_dim=flatten_dim, hidden_dim=128):\n        super(Generator, self).__init__()\n        # Build the neural network\n        self.gen = nn.Sequential(\n            #in flattened image of dimension 3*(256**2) out 128\n            get_generator_block(im_dim, hidden_dim), \n            #in 128 out 256\n            get_generator_block(hidden_dim, hidden_dim * 2), \n            #in 256 out 512\n            get_generator_block(hidden_dim * 2, hidden_dim * 4), \n            #in 512 out 1024\n            get_generator_block(hidden_dim * 4, hidden_dim * 8),\n            #in 1024, out flattened image\n            nn.Linear(hidden_dim*8, im_dim), \n            #scale pixel intensities to between 0 and 1\n            nn.Sigmoid() \n        )\n    def forward(self, image):\n        '''\n        Function for completing a forward pass of the generator: Given a noise tensor (photos), \n        returns generated images.\n        Parameters:\n            noise: a noise tensor with dimensions (n_samples, z_dim)\n        '''\n        \n        return self.gen(image)\n    ","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.146446Z","iopub.execute_input":"2021-10-21T13:44:33.147018Z","iopub.status.idle":"2021-10-21T13:44:33.155288Z","shell.execute_reply.started":"2021-10-21T13:44:33.146946Z","shell.execute_reply":"2021-10-21T13:44:33.154574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_discriminator_block(input_dim, output_dim):\n    '''\n    Discriminator Block\n    Function for returning a neural network of the discriminator given input and output dimensions.\n    Parameters:\n        input_dim: the dimension of the input vector, a scalar\n        output_dim: the dimension of the output vector, a scalar\n    Returns:\n        a discriminator neural network layer, with a linear transformation \n          followed by an nn.LeakyReLU activation with negative slope of 0.2 \n          (https://pytorch.org/docs/master/generated/torch.nn.LeakyReLU.html)\n    '''\n    return nn.Sequential(\n         nn.Linear(input_dim, output_dim),\n        #LeakyRelu to hopefully prevent dying Relus\n         nn.LeakyReLU(0.2, inplace=True)\n    )","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.157305Z","iopub.execute_input":"2021-10-21T13:44:33.158096Z","iopub.status.idle":"2021-10-21T13:44:33.167044Z","shell.execute_reply.started":"2021-10-21T13:44:33.158061Z","shell.execute_reply":"2021-10-21T13:44:33.166307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    '''\n    Discriminator Class\n    Values:\n        im_dim: flatten_img dimension\n        hidden_dim: the inner dimension, a scalar\n    '''\n    def __init__(self, im_dim=flatten_dim, hidden_dim=128):\n        super(Discriminator, self).__init__()\n        self.disc = nn.Sequential(\n            get_discriminator_block(im_dim, hidden_dim * 4),\n            get_discriminator_block(hidden_dim * 4, hidden_dim * 2),\n            get_discriminator_block(hidden_dim * 2, hidden_dim),\n            nn.Linear(hidden_dim, 1)\n            #could add sigmoid here, but we'll have it in the scoring\n        )\n\n    def forward(self, image):\n        '''\n        Function for completing a forward pass of the discriminator: Given an image tensor, \n        returns a 1-dimension tensor representing fake/real.\n        Parameters:\n            image: a flattened image tensor with dimension (im_dim)\n        '''\n        return self.disc(image)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.170174Z","iopub.execute_input":"2021-10-21T13:44:33.17067Z","iopub.status.idle":"2021-10-21T13:44:33.177409Z","shell.execute_reply.started":"2021-10-21T13:44:33.170584Z","shell.execute_reply":"2021-10-21T13:44:33.176569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set your parameters\ncriterion = nn.BCEWithLogitsLoss()\nn_epochs = 700\ndisplay_step = 500\nbatch_size = 128\nlr = 0.00001","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.17855Z","iopub.execute_input":"2021-10-21T13:44:33.179241Z","iopub.status.idle":"2021-10-21T13:44:33.188748Z","shell.execute_reply.started":"2021-10-21T13:44:33.179205Z","shell.execute_reply":"2021-10-21T13:44:33.188003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#taken from https://www.kaggle.com/nachiket273/cyclegan-pytorch by @NACHIKET273\n#changed a little for understandability\n#creates dataset that feeds photo/monet noise, label\nclass ImageDataset(Dataset):\n    def __init__(self, monet_dir, photo_dir, normalize=True):\n        super().__init__()\n        #folder with monets\n        self.monet_dir = monet_dir\n        #folder with photos\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.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.ToTensor()                               \n            ])\n        #iterate over all monets and store them in dict by index\n        for i, monet in enumerate(os.listdir(self.monet_dir)):\n            self.monet_idx[i] = monet\n            \n        #iterate over all photos and store them in dict by index\n        for i, photo in enumerate(os.listdir(self.photo_dir)):\n            self.photo_idx[i] = photo\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()))\n    \n    \nclass 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":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.190748Z","iopub.execute_input":"2021-10-21T13:44:33.191363Z","iopub.status.idle":"2021-10-21T13:44:33.208328Z","shell.execute_reply.started":"2021-10-21T13:44:33.191325Z","shell.execute_reply":"2021-10-21T13:44:33.207471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#create dataset and dataloader to feed to GAN\nimg_ds = ImageDataset('../input/gan-getting-started/monet_jpg/', '../input/gan-getting-started/photo_jpg/')\ndataloader = DataLoader(img_ds, batch_size=batch_size, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:33.20954Z","iopub.execute_input":"2021-10-21T13:44:33.209995Z","iopub.status.idle":"2021-10-21T13:44:33.64471Z","shell.execute_reply.started":"2021-10-21T13:44:33.209943Z","shell.execute_reply":"2021-10-21T13:44:33.643921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#get the generator\ngen = Generator(im_dim = flatten_dim, hidden_dim = 128).to(device)\ngen_opt = torch.optim.Adam(gen.parameters(), lr=lr)\n#gen_rlr = torch.optim.lr_scheduler.ReduceLROnPlateau(gen_opt, mode = 'min')\n\n#get the discriminator\ndisc = Discriminator().to(device) \ndisc_opt = torch.optim.Adam(disc.parameters(), lr=lr)\n#disc_rlr = torch.optim.lr_scheduler.ReduceLROnPlateau(disc_opt, mode = 'min')","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:51:13.987108Z","iopub.execute_input":"2021-10-21T13:51:13.987457Z","iopub.status.idle":"2021-10-21T13:51:17.004942Z","shell.execute_reply.started":"2021-10-21T13:51:13.987421Z","shell.execute_reply":"2021-10-21T13:51:17.0041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_disc_loss(gen, disc, criterion, photo, num_images, monet, device):\n    '''\n    Return the loss of the discriminator given inputs.\n    Parameters:\n        gen: the generator model, which returns an image given photo of dimensions im_dim\n        disc: the discriminator model, which returns a single-dimensional prediction of real/fake\n        criterion: the loss function, which should be used to compare \n               the discriminator's predictions to the ground truth reality of the images \n               (e.g. fake = 0, real = 1)\n        real: a batch of real images\n        num_images: the number of images the generator should produce, \n                which is also the length of the real images\n        z_dim: the dimension of the photo\n        device: the device type\n    Returns:\n        disc_loss: a torch scalar loss value for the current batch\n    '''\n    fake = gen(photo)\n    disc_fake_pred = disc(fake.detach())\n    disc_fake_loss = criterion(disc_fake_pred, torch.zeros_like(disc_fake_pred))\n    disc_real_pred = disc(monet)\n    disc_real_loss = criterion(disc_real_pred, torch.ones_like(disc_real_pred))\n    disc_loss = (disc_fake_loss + disc_real_loss) / 2\n    return disc_loss","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:51:25.663898Z","iopub.execute_input":"2021-10-21T13:51:25.664611Z","iopub.status.idle":"2021-10-21T13:51:25.670693Z","shell.execute_reply.started":"2021-10-21T13:51:25.664573Z","shell.execute_reply":"2021-10-21T13:51:25.670017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_gen_loss(gen, disc, criterion, num_images, photos, device):\n    '''\n    Return the loss of the generator given inputs.\n    Parameters:\n        gen: the generator model, which returns an image given z-dimensional noise\n        disc: the discriminator model, which returns a single-dimensional prediction of real/fake\n        criterion: the loss function, which should be used to compare \n               the discriminator's predictions to the ground truth reality of the images \n               (e.g. fake = 0, real = 1)\n        num_images: the number of images the generator should produce, \n                which is also the length of the real images\n        z_dim: the dimension of the noise vector, a scalar\n        device: the device type\n    Returns:\n        gen_loss: a torch scalar loss value for the current batch\n    '''\n    fake = gen(photos)\n    disc_fake_pred = disc(fake)\n    gen_loss = criterion(disc_fake_pred, torch.ones_like(disc_fake_pred))\n    return gen_loss","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:51:25.846779Z","iopub.execute_input":"2021-10-21T13:51:25.847608Z","iopub.status.idle":"2021-10-21T13:51:25.853431Z","shell.execute_reply.started":"2021-10-21T13:51:25.84756Z","shell.execute_reply":"2021-10-21T13:51:25.852635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfor photo, monet in tqdm(dataloader):\n    plt.imshow(monet[0].numpy().transpose((1, 2, 0)))\n    break","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:51:26.01471Z","iopub.execute_input":"2021-10-21T13:51:26.014997Z","iopub.status.idle":"2021-10-21T13:51:28.8394Z","shell.execute_reply.started":"2021-10-21T13:51:26.014953Z","shell.execute_reply":"2021-10-21T13:51:28.838474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cur_step = 0\nmean_generator_loss = 0\nmean_discriminator_loss = 0\ngen_loss = False\nerror = False\nfor epoch in range(n_epochs):\n  \n    # Dataloader returns the batches\n    for photo, monet in dataloader:\n        cur_batch_size = len(photo)\n\n        # Flatten the batch of real images from the dataset\n        photo = photo.view(cur_batch_size, -1).to(device)\n        monet = monet.view(cur_batch_size, -1).to(device)\n\n        ### Update discriminator ###\n        # Zero out the gradients before backpropagation\n        disc_opt.zero_grad()\n\n        # Calculate discriminator loss\n        disc_loss = get_disc_loss(gen, disc, criterion, photo, cur_batch_size, monet, device)\n\n        # Update gradients\n        disc_loss.backward(retain_graph=True)\n\n        # Update optimizer\n        disc_opt.step()\n        \n        #backpropagation\n        gen_opt.zero_grad()\n        gen_loss = get_gen_loss(gen, disc, criterion, cur_batch_size, photo, device)\n        gen_loss.backward()\n        gen_opt.step()\n\n        # Keep track of the average discriminator loss\n        mean_discriminator_loss += disc_loss.item() / display_step\n\n        # Keep track of the average generator loss\n        mean_generator_loss += gen_loss.item() / display_step\n\n        #show images every display_step\n        if cur_step % display_step == 0 and cur_step > 0:\n            print(f\"Step {cur_step}: Generator loss: {mean_generator_loss}, discriminator loss: {mean_discriminator_loss}\")\n            fake = gen(photo)\n            show_tensor_images(fake)\n            show_tensor_images(photo)\n            mean_generator_loss = 0\n            mean_discriminator_loss = 0\n        cur_step += 1","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:51:28.840725Z","iopub.execute_input":"2021-10-21T13:51:28.84124Z","iopub.status.idle":"2021-10-21T14:02:38.72593Z","shell.execute_reply.started":"2021-10-21T13:51:28.8412Z","shell.execute_reply":"2021-10-21T14:02:38.725164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"photo_dataset = PhotoDataset('../input/gan-getting-started/photo_jpg/')\ndataloader = DataLoader(photo_dataset, batch_size=1, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:02:38.727265Z","iopub.execute_input":"2021-10-21T14:02:38.727521Z","iopub.status.idle":"2021-10-21T14:02:38.737142Z","shell.execute_reply.started":"2021-10-21T14:02:38.727491Z","shell.execute_reply":"2021-10-21T14:02:38.736339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir ../images","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:02:38.739094Z","iopub.execute_input":"2021-10-21T14:02:38.739429Z","iopub.status.idle":"2021-10-21T14:02:39.462233Z","shell.execute_reply.started":"2021-10-21T14:02:38.739394Z","shell.execute_reply":"2021-10-21T14:02:39.461175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir()","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:02:39.464984Z","iopub.execute_input":"2021-10-21T14:02:39.465573Z","iopub.status.idle":"2021-10-21T14:02:39.473884Z","shell.execute_reply.started":"2021-10-21T14:02:39.46553Z","shell.execute_reply":"2021-10-21T14:02:39.473228Z"},"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-10-21T14:02:39.475307Z","iopub.execute_input":"2021-10-21T14:02:39.475812Z","iopub.status.idle":"2021-10-21T14:02:39.482717Z","shell.execute_reply.started":"2021-10-21T14:02:39.475773Z","shell.execute_reply":"2021-10-21T14:02:39.481878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"topil = transforms.ToPILImage()","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:02:39.48403Z","iopub.execute_input":"2021-10-21T14:02:39.484375Z","iopub.status.idle":"2021-10-21T14:02:39.492012Z","shell.execute_reply.started":"2021-10-21T14:02:39.484252Z","shell.execute_reply":"2021-10-21T14:02:39.491112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = tqdm(dataloader, leave=False, total=dataloader.__len__())\ngen.eval()\nfor i, photo in enumerate(t):\n    with torch.no_grad():\n        photo = photo.view(1, -1).to(device)\n        pred_monet = gen(photo.to(device)).detach()\n    pred_monet = unnorm(pred_monet) #I don't think this is necessary\n    pred_monet = torch.reshape(pred_monet, (3, 256, 256))\n    img = topil(pred_monet)\n    #print(type(img))\n    img = img.convert(\"RGB\")\n    img.save(\"../images/\" + str(i+1) + \".jpg\")","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:02:39.493197Z","iopub.execute_input":"2021-10-21T14:02:39.493399Z","iopub.status.idle":"2021-10-21T14:04:30.100042Z","shell.execute_reply.started":"2021-10-21T14:02:39.493369Z","shell.execute_reply":"2021-10-21T14:04:30.099314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b = topil(pred_monet)","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:09:47.213384Z","iopub.execute_input":"2021-10-21T14:09:47.213665Z","iopub.status.idle":"2021-10-21T14:09:47.221646Z","shell.execute_reply.started":"2021-10-21T14:09:47.21363Z","shell.execute_reply":"2021-10-21T14:09:47.220908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.array(b).shape","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:09:47.817554Z","iopub.execute_input":"2021-10-21T14:09:47.817806Z","iopub.status.idle":"2021-10-21T14:09:47.823836Z","shell.execute_reply.started":"2021-10-21T14:09:47.817777Z","shell.execute_reply":"2021-10-21T14:09:47.823171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(b)","metadata":{"execution":{"iopub.status.busy":"2021-10-21T14:09:48.377603Z","iopub.execute_input":"2021-10-21T14:09:48.378059Z","iopub.status.idle":"2021-10-21T14:09:48.621819Z","shell.execute_reply.started":"2021-10-21T14:09:48.378004Z","shell.execute_reply":"2021-10-21T14:09:48.621153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:41.185572Z","iopub.status.idle":"2021-10-21T13:44:41.186128Z","shell.execute_reply.started":"2021-10-21T13:44:41.185878Z","shell.execute_reply":"2021-10-21T13:44:41.185903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#save your models\ntorch.save(gen.state_dict(), 'generator')\ntorch.save(disc.state_dict(), 'discriminator')","metadata":{"execution":{"iopub.status.busy":"2021-10-21T13:44:41.187166Z","iopub.status.idle":"2021-10-21T13:44:41.187709Z","shell.execute_reply.started":"2021-10-21T13:44:41.187468Z","shell.execute_reply":"2021-10-21T13:44:41.187493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}