{"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 DCGAN in Pytorch","metadata":{}},{"cell_type":"markdown","source":"In this Notebook we will create a DCGAN with tips from the Paper as well as the author's github page https://github.com/soumith/ganhacks, to compare with Basic GAN and alter WGAN and Cycle GAN.\n\nWe follow the improvements suggested in the DCGAN Paper:\n\n* Batchnormalize everywhere\n* tanh for generator output between -1 and 1\n* LeakyRelu in the Discriminator\n* Relu in the Generator\n* Feed Gaussian Noise (modified to having last conv layer in Generator be without Relu)\n* initialize Gaussian Weights\n* use label smoothing\n\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 import flatten\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-23T09:52:33.556438Z","iopub.execute_input":"2021-10-23T09:52:33.557079Z","iopub.status.idle":"2021-10-23T09:52:33.562755Z","shell.execute_reply.started":"2021-10-23T09:52:33.557041Z","shell.execute_reply":"2021-10-23T09:52:33.562042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#choose gpu\ndevice = 'cuda'","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.564762Z","iopub.execute_input":"2021-10-23T09:52:33.565158Z","iopub.status.idle":"2021-10-23T09:52:33.57366Z","shell.execute_reply.started":"2021-10-23T09:52:33.565114Z","shell.execute_reply":"2021-10-23T09:52:33.573033Z"},"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-23T09:52:33.574669Z","iopub.execute_input":"2021-10-23T09:52:33.575319Z","iopub.status.idle":"2021-10-23T09:52:33.584352Z","shell.execute_reply.started":"2021-10-23T09:52:33.575287Z","shell.execute_reply":"2021-10-23T09:52:33.583696Z"},"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    plt.figure(figsize = (20, 10))\n    try:\n        plt.imshow(image_tensor.numpy().transpose(1,2,0))\n        plt.show()\n    except:\n        print(\"can't show image\")","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.585822Z","iopub.execute_input":"2021-10-23T09:52:33.586343Z","iopub.status.idle":"2021-10-23T09:52:33.594617Z","shell.execute_reply.started":"2021-10-23T09:52:33.586299Z","shell.execute_reply":"2021-10-23T09:52:33.593957Z"},"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_conv_transpose(in_channels = 3, out_channels = 3, kernel_size = 3, stride = 2, padding = 0):\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.ConvTranspose2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding = padding),\n                nn.BatchNorm2d(out_channels),\n                nn.ReLU()\n            )","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.596497Z","iopub.execute_input":"2021-10-23T09:52:33.597173Z","iopub.status.idle":"2021-10-23T09:52:33.60564Z","shell.execute_reply.started":"2021-10-23T09:52:33.597136Z","shell.execute_reply":"2021-10-23T09:52:33.604781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_conv(in_channels = 3, out_channels = 3, kernel_size = 3, stride = 2, padding = 0, activation = True):\n    #use relu unless final\n    if activation:\n    \n        return nn.Sequential(\n                    nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding = padding),\n                    nn.BatchNorm2d(out_channels),\n                    nn.ReLU()\n                )\n    #dcgan suggests a gaussian latent space\n    else:\n        return nn.Sequential(\n                    nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding = padding),\n                    nn.BatchNorm2d(out_channels),\n                )\n        \n","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.607177Z","iopub.execute_input":"2021-10-23T09:52:33.607565Z","iopub.status.idle":"2021-10-23T09:52:33.619328Z","shell.execute_reply.started":"2021-10-23T09:52:33.607534Z","shell.execute_reply":"2021-10-23T09:52:33.618553Z"},"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, hidden_dim=32):\n        super(Generator, self).__init__()\n        # Build the CNN\n        self.conv1 = nn.Sequential(\n            get_conv(in_channels = 3, out_channels = hidden_dim, padding = 1),\n            get_conv(in_channels = hidden_dim, out_channels = hidden_dim*2, padding = 0),\n            get_conv(in_channels = hidden_dim*2, out_channels = hidden_dim*4, padding = 0),\n            #leave me gaussian\n            get_conv(in_channels = hidden_dim*4, out_channels = hidden_dim*8, padding = 0, activation = False)\n        )\n        self.gen = nn.Sequential(\n            #in flattened image of dimension 3*(256**2) out 128\n            get_conv_transpose(hidden_dim*8, hidden_dim*4),\n            get_conv_transpose(hidden_dim*4, hidden_dim*2), \n            #in 128 out 256\n            get_conv_transpose(hidden_dim*2, hidden_dim, padding = 0), \n            #in 1024, out flattened image\n            nn.ConvTranspose2d(in_channels = hidden_dim, out_channels = 3, kernel_size = 3, stride = 2, output_padding = 1),\n            nn.Tanh()\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        image = self.conv1(image)\n        #image = image.view(len(image), 1024, 1, 1)\n        \n        return self.gen(image)\n    ","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.620765Z","iopub.execute_input":"2021-10-23T09:52:33.621145Z","iopub.status.idle":"2021-10-23T09:52:33.631724Z","shell.execute_reply.started":"2021-10-23T09:52:33.621103Z","shell.execute_reply":"2021-10-23T09:52:33.631009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# UNQ_C3 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n# GRADED FUNCTION: Discriminator\nclass Discriminator(nn.Module):\n    '''\n    Discriminator Class\n    Values:\n        im_chan: the number of channels of the output image, a scalar\n              (MNIST is black-and-white, so 1 channel is your default)\n    hidden_dim: the inner dimension, a scalar\n    '''\n    def __init__(self, im_chan=3, hidden_dim=16):\n        super(Discriminator, self).__init__()\n        self.disc = nn.Sequential(\n            self.make_disc_block(im_chan, hidden_dim),\n            self.make_disc_block(hidden_dim, hidden_dim * 2),\n            self.make_disc_block(hidden_dim * 2, 1, final_layer=True),\n        )\n\n    def make_disc_block(self, input_channels = 3, output_channels = 3, kernel_size=3, stride=2, final_layer=False):\n        '''\n        Function to return a sequence of operations corresponding to a discriminator block of DCGAN, \n        corresponding to a convolution, a batchnorm (except for in the last layer), and an activation.\n        Parameters:\n            input_channels: how many channels the input feature representation has\n            output_channels: how many channels the output feature representation should have\n            kernel_size: the size of each convolutional filter, equivalent to (kernel_size, kernel_size)\n            stride: the stride of the convolution\n            final_layer: a boolean, true if it is the final layer and false otherwise \n                      (affects activation and batchnorm)\n        '''\n        #     Steps:\n        #       1) Add a convolutional layer using the given parameters.\n        #       2) Do a batchnorm, except for the last layer.\n        #       3) Follow each batchnorm with a LeakyReLU activation with slope 0.2.\n        \n        # Build the neural block\n        if not final_layer:\n            return nn.Sequential(\n                #### START CODE HERE #### #\n                nn.Conv2d(input_channels, output_channels, kernel_size, stride),\n                nn.BatchNorm2d(output_channels),\n                nn.LeakyReLU(0.2, inplace=True)\n                #### END CODE HERE ####\n            )\n        else: # Final Layer\n            return nn.Sequential(\n                #### START CODE HERE #### #\n                nn.Conv2d(input_channels, output_channels, kernel_size, stride)\n                #### END CODE HERE ####\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        disc_pred = self.disc(image)\n        return disc_pred.view(len(disc_pred), -1)","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.633151Z","iopub.execute_input":"2021-10-23T09:52:33.634075Z","iopub.status.idle":"2021-10-23T09:52:33.646496Z","shell.execute_reply.started":"2021-10-23T09:52:33.63403Z","shell.execute_reply":"2021-10-23T09:52:33.645453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss()\ndisplay_step = 500\nbatch_size = 32\n# A learning rate of 0.0002 works well on DCGAN\nlr = 0.000005\nn_epochs = 900\n\nbeta_1 = 0.5 \nbeta_2 = 0.999","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.647917Z","iopub.execute_input":"2021-10-23T09:52:33.648398Z","iopub.status.idle":"2021-10-23T09:52:33.661585Z","shell.execute_reply.started":"2021-10-23T09:52:33.648358Z","shell.execute_reply":"2021-10-23T09:52:33.660994Z"},"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-23T09:52:33.662877Z","iopub.execute_input":"2021-10-23T09:52:33.663392Z","iopub.status.idle":"2021-10-23T09:52:33.682998Z","shell.execute_reply.started":"2021-10-23T09:52:33.663355Z","shell.execute_reply":"2021-10-23T09:52:33.681875Z"},"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-23T09:56:53.261991Z","iopub.execute_input":"2021-10-23T09:56:53.264333Z","iopub.status.idle":"2021-10-23T09:56:53.282506Z","shell.execute_reply.started":"2021-10-23T09:56:53.264241Z","shell.execute_reply":"2021-10-23T09:56:53.281343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#get the generator\ngen = Generator(hidden_dim = 32).to(device)\ngen_opt = torch.optim.Adam(gen.parameters(), lr=lr)\n\n#get the discriminator\ndisc = Discriminator().to(device) \ndisc_opt = torch.optim.Adam(disc.parameters(), lr=lr)\n\ndef weights_init(m):\n    if isinstance(m, nn.Conv2d) or isinstance(m, nn.ConvTranspose2d):\n        torch.nn.init.normal_(m.weight, 0.0, 0.02)\n    if isinstance(m, nn.BatchNorm2d):\n        torch.nn.init.normal_(m.weight, 0.0, 0.02)\n        torch.nn.init.constant_(m.bias, 0)\ngen = gen.apply(weights_init)\ndisc = disc.apply(weights_init)","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.707485Z","iopub.execute_input":"2021-10-23T09:52:33.707833Z","iopub.status.idle":"2021-10-23T09:52:33.770779Z","shell.execute_reply.started":"2021-10-23T09:52:33.707799Z","shell.execute_reply":"2021-10-23T09:52:33.770143Z"},"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.to(device))\n    disc_fake_pred = disc(fake.detach())\n    #smoothing\n    #disc_fake_loss = criterion(disc_fake_pred, torch.zeros_like(disc_fake_loss)) #hard loss\n    disc_fake_loss = criterion(disc_fake_pred, torch.from_numpy(np.random.uniform(0, 0.2, disc_fake_pred.shape)).to(device))\n    disc_real_pred = disc(monet.to(device))\n    #smoothing\n    #disc_real_loss = criterion(disc_real_pred, torch.ones_like(disc_real_pred)) #hard loss\n    disc_real_loss = criterion(disc_real_pred, torch.from_numpy(np.random.uniform(0.8, 1.2, disc_real_pred.shape)).to(device))\n    disc_loss = (disc_fake_loss + disc_real_loss) / 2\n    return disc_loss","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:58:00.311454Z","iopub.execute_input":"2021-10-23T09:58:00.311806Z","iopub.status.idle":"2021-10-23T09:58:00.320143Z","shell.execute_reply.started":"2021-10-23T09:58:00.31177Z","shell.execute_reply":"2021-10-23T09:58:00.319092Z"},"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.to(device))\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-23T09:58:00.725537Z","iopub.execute_input":"2021-10-23T09:58:00.726233Z","iopub.status.idle":"2021-10-23T09:58:00.732065Z","shell.execute_reply.started":"2021-10-23T09:58:00.726197Z","shell.execute_reply":"2021-10-23T09:58:00.731044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n#for photo, monet in tqdm(dataloader):\n#    plt.imshow(monet[0].numpy().transpose((1, 2, 0)))\n#    break","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:58:00.908748Z","iopub.execute_input":"2021-10-23T09:58:00.909949Z","iopub.status.idle":"2021-10-23T09:58:00.914257Z","shell.execute_reply.started":"2021-10-23T09:58:00.909891Z","shell.execute_reply":"2021-10-23T09:58:00.913133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gen.cuda()\ndisc.cuda()","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:58:01.077823Z","iopub.execute_input":"2021-10-23T09:58:01.078159Z","iopub.status.idle":"2021-10-23T09:58:01.108202Z","shell.execute_reply.started":"2021-10-23T09:58:01.078125Z","shell.execute_reply":"2021-10-23T09:58:01.106926Z"},"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.to(device))\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-23T09:58:01.253812Z","iopub.execute_input":"2021-10-23T09:58:01.254772Z","iopub.status.idle":"2021-10-23T09:58:18.961158Z","shell.execute_reply.started":"2021-10-23T09:58:01.254714Z","shell.execute_reply":"2021-10-23T09:58:18.959761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#np.random.uniform(0, 0.2, (3, 256, 256))","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:58:18.962771Z","iopub.status.idle":"2021-10-23T09:58:18.96332Z","shell.execute_reply.started":"2021-10-23T09:58:18.963048Z","shell.execute_reply":"2021-10-23T09:58:18.963076Z"},"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-23T09:56:21.042715Z","iopub.execute_input":"2021-10-23T09:56:21.043156Z","iopub.status.idle":"2021-10-23T09:56:21.051699Z","shell.execute_reply.started":"2021-10-23T09:56:21.043124Z","shell.execute_reply":"2021-10-23T09:56:21.050859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir ../images","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:56:21.258621Z","iopub.execute_input":"2021-10-23T09:56:21.259211Z","iopub.status.idle":"2021-10-23T09:56:22.054652Z","shell.execute_reply.started":"2021-10-23T09:56:21.259166Z","shell.execute_reply":"2021-10-23T09:56:22.053435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir()","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:56:23.867114Z","iopub.execute_input":"2021-10-23T09:56:23.867517Z","iopub.status.idle":"2021-10-23T09:56:23.87358Z","shell.execute_reply.started":"2021-10-23T09:56:23.867463Z","shell.execute_reply":"2021-10-23T09:56:23.873048Z"},"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-23T09:52:33.796603Z","iopub.status.idle":"2021-10-23T09:52:33.797136Z","shell.execute_reply.started":"2021-10-23T09:52:33.796821Z","shell.execute_reply":"2021-10-23T09:52:33.796845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"topil = transforms.ToPILImage()","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.798417Z","iopub.status.idle":"2021-10-23T09:52:33.798842Z","shell.execute_reply.started":"2021-10-23T09:52:33.798684Z","shell.execute_reply":"2021-10-23T09:52:33.798701Z"},"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        pred_monet = gen(photo.to(device)).detach()\n    pred_monet = unnorm(pred_monet) #I don't think this is necessary\n    pred_monet = torch.squeeze(pred_monet)\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-23T09:52:33.799654Z","iopub.status.idle":"2021-10-23T09:52:33.800094Z","shell.execute_reply.started":"2021-10-23T09:52:33.799895Z","shell.execute_reply":"2021-10-23T09:52:33.799911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_monet.shape","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.800872Z","iopub.status.idle":"2021-10-23T09:52:33.801319Z","shell.execute_reply.started":"2021-10-23T09:52:33.80116Z","shell.execute_reply":"2021-10-23T09:52:33.801176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b = topil(pred_monet)","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.8021Z","iopub.status.idle":"2021-10-23T09:52:33.802502Z","shell.execute_reply.started":"2021-10-23T09:52:33.802338Z","shell.execute_reply":"2021-10-23T09:52:33.802354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.array(b).shape","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.803273Z","iopub.status.idle":"2021-10-23T09:52:33.803676Z","shell.execute_reply.started":"2021-10-23T09:52:33.803519Z","shell.execute_reply":"2021-10-23T09:52:33.803535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(b)","metadata":{"execution":{"iopub.status.busy":"2021-10-23T09:52:33.804488Z","iopub.status.idle":"2021-10-23T09:52:33.804886Z","shell.execute_reply.started":"2021-10-23T09:52:33.80473Z","shell.execute_reply":"2021-10-23T09:52:33.804746Z"},"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-23T09:52:33.805678Z","iopub.status.idle":"2021-10-23T09:52:33.806086Z","shell.execute_reply.started":"2021-10-23T09:52:33.805917Z","shell.execute_reply":"2021-10-23T09:52:33.805944Z"},"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-23T09:52:33.806884Z","iopub.status.idle":"2021-10-23T09:52:33.807293Z","shell.execute_reply.started":"2021-10-23T09:52:33.807138Z","shell.execute_reply":"2021-10-23T09:52:33.807153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}