{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport torch\nfrom torch import nn\nfrom torchvision import transforms\nfrom torchvision.utils import make_grid\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image\nfrom tqdm.auto import tqdm\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-05-24T05:50:46.362043Z","iopub.execute_input":"2022-05-24T05:50:46.362521Z","iopub.status.idle":"2022-05-24T05:50:48.069518Z","shell.execute_reply.started":"2022-05-24T05:50:46.362428Z","shell.execute_reply":"2022-05-24T05:50:48.068753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageDataset(Dataset):\n    def __init__(self, pic_dir, photo_dir, transform=True):\n        super().__init__()\n        self.pic_dir = pic_dir\n        self.photo_dir = photo_dir\n        self.pic_idx = dict()\n        self.photo_idx = dict()\n        if transform:\n            self.transform = transforms.Compose([\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.5], std=[0.5])\n            ])\n        else:\n            self.transform = transforms.Compose([\n                transforms.ToTensor()\n            ])\n        \n        for i, pic in enumerate(os.listdir(self.pic_dir)):\n            self.pic_idx[i] = pic\n        for i, ph in enumerate(os.listdir(self.photo_dir)):\n            self.photo_idx[i] = ph\n        \n    def __len__(self):\n        return min(len(self.pic_idx.keys()), len(self.photo_idx.keys()))\n        \n    def __getitem__(self, idx):\n        rand_idx = int(np.random.uniform(0, len(self.pic_idx.keys()))) \n        photo_path = os.path.join(self.photo_dir, self.photo_idx[rand_idx])\n        pic_path = os.path.join(self.pic_dir, self.pic_idx[idx])\n        photo_img = Image.open(photo_path)\n        photo_img = self.transform(photo_img)\n        pic_img = Image.open(pic_path)\n        pic_img = self.transform(pic_img)\n        return photo_img, pic_img\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(mean=[0.5], std=[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 __len__(self):\n        return len(self.photo_idx.keys())    \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            \n            ","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:48.072718Z","iopub.execute_input":"2022-05-24T05:50:48.073109Z","iopub.status.idle":"2022-05-24T05:50:48.088815Z","shell.execute_reply.started":"2022-05-24T05:50:48.073073Z","shell.execute_reply":"2022-05-24T05:50:48.088159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 128\nimg_dataset = ImageDataset('../input/gan-getting-started/monet_jpg/', '../input/gan-getting-started/photo_jpg/')\ndataloader = DataLoader(img_dataset, batch_size=batch_size, pin_memory=True)  # faster data transfer to CUDA-enabled GPUs by pinned memory","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:48.090071Z","iopub.execute_input":"2022-05-24T05:50:48.090337Z","iopub.status.idle":"2022-05-24T05:50:48.347692Z","shell.execute_reply.started":"2022-05-24T05:50:48.090299Z","shell.execute_reply":"2022-05-24T05:50:48.346995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfor photo, pic in (dataloader):\n    plt.imshow(pic[0].numpy().transpose((1, 2, 0)))\n    break\n    \n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:48.349973Z","iopub.execute_input":"2022-05-24T05:50:48.350216Z","iopub.status.idle":"2022-05-24T05:50:53.792424Z","shell.execute_reply.started":"2022-05-24T05:50:48.350183Z","shell.execute_reply":"2022-05-24T05:50:53.791712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for photo, pic in (dataloader):\n    cur_batch_size = len(photo)\n    print(photo.shape)\n    photo = photo.view(cur_batch_size, -1)\n    print(photo.shape)\n    break\n    ","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:53.793346Z","iopub.execute_input":"2022-05-24T05:50:53.793599Z","iopub.status.idle":"2022-05-24T05:50:55.022180Z","shell.execute_reply.started":"2022-05-24T05:50:53.793569Z","shell.execute_reply":"2022-05-24T05:50:55.021421Z"},"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":"2022-05-24T05:50:55.024404Z","iopub.execute_input":"2022-05-24T05:50:55.024828Z","iopub.status.idle":"2022-05-24T05:50:55.028621Z","shell.execute_reply.started":"2022-05-24T05:50:55.024788Z","shell.execute_reply":"2022-05-24T05:50:55.027896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_generator_block(input_dim, output_dim):\n\n    return nn.Sequential(\n        nn.Linear(input_dim, output_dim),\n        nn.BatchNorm1d(output_dim),\n        nn.ReLU(inplace=True)\n    )\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.029721Z","iopub.execute_input":"2022-05-24T05:50:55.030350Z","iopub.status.idle":"2022-05-24T05:50:55.038134Z","shell.execute_reply.started":"2022-05-24T05:50:55.030316Z","shell.execute_reply":"2022-05-24T05:50:55.037503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Generator(nn.Module):\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        \n        return self.gen(image)","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.041052Z","iopub.execute_input":"2022-05-24T05:50:55.041253Z","iopub.status.idle":"2022-05-24T05:50:55.048644Z","shell.execute_reply.started":"2022-05-24T05:50:55.041231Z","shell.execute_reply":"2022-05-24T05:50:55.047979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_discriminator_block(input_dim, output_dim):\n\n    return nn.Sequential(\n         nn.Linear(input_dim, output_dim),\n         nn.LeakyReLU(0.2, inplace=True)\n    )","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.050158Z","iopub.execute_input":"2022-05-24T05:50:55.050619Z","iopub.status.idle":"2022-05-24T05:50:55.057565Z","shell.execute_reply.started":"2022-05-24T05:50:55.050585Z","shell.execute_reply":"2022-05-24T05:50:55.056751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Discriminator(nn.Module):\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        return self.disc(image)","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.060280Z","iopub.execute_input":"2022-05-24T05:50:55.060548Z","iopub.status.idle":"2022-05-24T05:50:55.067930Z","shell.execute_reply.started":"2022-05-24T05:50:55.060516Z","shell.execute_reply":"2022-05-24T05:50:55.067173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss() \nn_epochs = 700\ndisplay_step = 500 \nlr = 0.00001\n#choose gpu\ndevice = 'cuda'","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.069153Z","iopub.execute_input":"2022-05-24T05:50:55.069463Z","iopub.status.idle":"2022-05-24T05:50:55.077115Z","shell.execute_reply.started":"2022-05-24T05:50:55.069431Z","shell.execute_reply":"2022-05-24T05:50:55.076151Z"},"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\n#get the discriminator\ndisc = Discriminator().to(device) \ndisc_opt = torch.optim.Adam(disc.parameters(), lr=lr)\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:55.080161Z","iopub.execute_input":"2022-05-24T05:50:55.080385Z","iopub.status.idle":"2022-05-24T05:50:58.072328Z","shell.execute_reply.started":"2022-05-24T05:50:55.080343Z","shell.execute_reply":"2022-05-24T05:50:58.071498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_disc_loss(gen, disc, criterion, photo, num_images, monet, device):\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":"2022-05-24T05:50:58.073565Z","iopub.execute_input":"2022-05-24T05:50:58.073802Z","iopub.status.idle":"2022-05-24T05:50:58.078732Z","shell.execute_reply.started":"2022-05-24T05:50:58.073770Z","shell.execute_reply":"2022-05-24T05:50:58.078079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_gen_loss(gen, disc, criterion, num_images, photos, device):\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":"2022-05-24T05:50:58.080180Z","iopub.execute_input":"2022-05-24T05:50:58.080579Z","iopub.status.idle":"2022-05-24T05:50:58.090097Z","shell.execute_reply.started":"2022-05-24T05:50:58.080545Z","shell.execute_reply":"2022-05-24T05:50:58.089407Z"},"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    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()\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T05:50:58.091300Z","iopub.execute_input":"2022-05-24T05:50:58.091782Z","iopub.status.idle":"2022-05-24T05:50:58.100159Z","shell.execute_reply.started":"2022-05-24T05:50:58.091748Z","shell.execute_reply":"2022-05-24T05:50:58.099378Z"},"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            mean_loss = (mean_generator_loss + mean_discriminator_loss)/2\n            print(f\"Step {cur_step}: Generator loss: {mean_generator_loss}, discriminator loss: {mean_discriminator_loss}\")\n            print(f\"Mean loss: {mean_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":"2022-05-24T05:50:58.101313Z","iopub.execute_input":"2022-05-24T05:50:58.102073Z","iopub.status.idle":"2022-05-24T06:17:05.265951Z","shell.execute_reply.started":"2022-05-24T05:50:58.102039Z","shell.execute_reply":"2022-05-24T06:17:05.265222Z"},"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)\n!mkdir ../images\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T06:58:56.589646Z","iopub.execute_input":"2022-05-24T06:58:56.589897Z","iopub.status.idle":"2022-05-24T06:58:57.281275Z","shell.execute_reply.started":"2022-05-24T06:58:56.589869Z","shell.execute_reply":"2022-05-24T06:58:57.280305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"photo_dataset.__len__()","metadata":{"execution":{"iopub.status.busy":"2022-05-24T06:58:57.283122Z","iopub.execute_input":"2022-05-24T06:58:57.283414Z","iopub.status.idle":"2022-05-24T06:58:57.289929Z","shell.execute_reply.started":"2022-05-24T06:58:57.283387Z","shell.execute_reply":"2022-05-24T06:58:57.289195Z"},"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":"2022-05-24T06:59:19.764283Z","iopub.execute_input":"2022-05-24T06:59:19.764861Z","iopub.status.idle":"2022-05-24T06:59:19.769318Z","shell.execute_reply.started":"2022-05-24T06:59:19.764823Z","shell.execute_reply":"2022-05-24T06:59:19.768603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"topil = transforms.ToPILImage()","metadata":{"execution":{"iopub.status.busy":"2022-05-24T06:59:35.225261Z","iopub.execute_input":"2022-05-24T06:59:35.225946Z","iopub.status.idle":"2022-05-24T06:59:35.229976Z","shell.execute_reply.started":"2022-05-24T06:59:35.225901Z","shell.execute_reply":"2022-05-24T06:59:35.229099Z"},"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":"2022-05-24T07:01:01.425676Z","iopub.execute_input":"2022-05-24T07:01:01.426385Z","iopub.status.idle":"2022-05-24T07:02:56.035691Z","shell.execute_reply.started":"2022-05-24T07:01:01.426329Z","shell.execute_reply":"2022-05-24T07:02:56.034980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b = topil(pred_monet)","metadata":{"execution":{"iopub.status.busy":"2022-05-24T07:03:00.516708Z","iopub.execute_input":"2022-05-24T07:03:00.518548Z","iopub.status.idle":"2022-05-24T07:03:00.524073Z","shell.execute_reply.started":"2022-05-24T07:03:00.518500Z","shell.execute_reply":"2022-05-24T07:03:00.522847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(b)","metadata":{"execution":{"iopub.status.busy":"2022-05-24T07:03:01.639596Z","iopub.execute_input":"2022-05-24T07:03:01.639843Z","iopub.status.idle":"2022-05-24T07:03:01.867909Z","shell.execute_reply.started":"2022-05-24T07:03:01.639815Z","shell.execute_reply":"2022-05-24T07:03:01.867256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.array(b).shape","metadata":{"execution":{"iopub.status.busy":"2022-05-24T07:03:25.121334Z","iopub.execute_input":"2022-05-24T07:03:25.122104Z","iopub.status.idle":"2022-05-24T07:03:25.128761Z","shell.execute_reply.started":"2022-05-24T07:03:25.122060Z","shell.execute_reply":"2022-05-24T07:03:25.128061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.make_archive(\"/kaggle/working/images\", 'zip', \"/kaggle/images\")\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T07:03:27.435864Z","iopub.execute_input":"2022-05-24T07:03:27.436441Z","iopub.status.idle":"2022-05-24T07:03:30.299627Z","shell.execute_reply.started":"2022-05-24T07:03:27.436401Z","shell.execute_reply":"2022-05-24T07:03:30.298952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#save models\ntorch.save(gen.state_dict(), 'generator')\ntorch.save(disc.state_dict(), 'discriminator')\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-24T07:03:38.723892Z","iopub.execute_input":"2022-05-24T07:03:38.724328Z","iopub.status.idle":"2022-05-24T07:03:42.147972Z","shell.execute_reply.started":"2022-05-24T07:03:38.724288Z","shell.execute_reply":"2022-05-24T07:03:42.144747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}