{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30733,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport torch\nfrom torchvision import datasets, transforms\nfrom torch.utils.data import DataLoader\nfrom PIL import Image\n\ntransform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\nclass ImageDataset(torch.utils.data.Dataset):\n    def __init__(self, root, transform=None):\n        self.transform = transform\n        self.files = sorted(os.listdir(root))\n        self.root = root\n\n    def __getitem__(self, index):\n        img = Image.open(os.path.join(self.root, self.files[index])).convert('RGB')\n        if self.transform:\n            img = self.transform(img)\n        return img\n\n    def __len__(self):\n        return len(self.files)\n\nmonet_dataset = ImageDataset(root='/kaggle/input/gan-getting-started/monet_jpg', transform=transform)\nphoto_dataset = ImageDataset(root='/kaggle/input/gan-getting-started/photo_jpg', transform=transform)\n\nmonet_loader = DataLoader(monet_dataset, batch_size=1, shuffle=True)\nphoto_loader = DataLoader(photo_dataset, batch_size=1, shuffle=True)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-09T21:08:40.565972Z","iopub.execute_input":"2024-07-09T21:08:40.566344Z","iopub.status.idle":"2024-07-09T21:08:40.582614Z","shell.execute_reply.started":"2024-07-09T21:08:40.566315Z","shell.execute_reply":"2024-07-09T21:08:40.581700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\n\n\nclass ResidualBlock(nn.Module):\n    def __init__(self, in_features):\n        super(ResidualBlock, self).__init__()\n        self.block = nn.Sequential(\n            nn.Conv2d(in_features, in_features, kernel_size=3, stride=1, padding=1),\n            nn.InstanceNorm2d(in_features),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(in_features, in_features, kernel_size=3, stride=1, padding=1),\n            nn.InstanceNorm2d(in_features)\n        )\n\n    def forward(self, x):\n        return x + self.block(x)\n\nclass Generator(nn.Module):\n    def __init__(self):\n        super(Generator, self).__init__()\n    \n        model = [\n            nn.Conv2d(3, 64, kernel_size=7, stride=1, padding=3),\n            nn.InstanceNorm2d(64),\n            nn.ReLU(inplace=True)\n        ]\n        \n        in_features = 64\n        out_features = in_features * 2\n        for _ in range(2):\n            model += [\n                nn.Conv2d(in_features, out_features, kernel_size=3, stride=2, padding=1),\n                nn.InstanceNorm2d(out_features),\n                nn.ReLU(inplace=True)\n            ]\n            in_features = out_features\n            out_features = in_features * 2\n        \n        for _ in range(9):\n            model += [ResidualBlock(in_features)]\n        \n        out_features = in_features // 2\n        for _ in range(2):\n            model += [\n                nn.ConvTranspose2d(in_features, out_features, kernel_size=3, stride=2, padding=1, output_padding=1),\n                nn.InstanceNorm2d(out_features),\n                nn.ReLU(inplace=True)\n            ]\n            in_features = out_features\n            out_features = in_features // 2\n        \n        model += [nn.Conv2d(64, 3, kernel_size=7, stride=1, padding=3),\n                  nn.Tanh()]\n        self.model = nn.Sequential(*model)\n\n    def forward(self, x):\n        return self.model(x)\n\nclass Discriminator(nn.Module):\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        def discriminator_block(in_filters, out_filters, stride):\n            return [\n                nn.Conv2d(in_filters, out_filters, kernel_size=4, stride=stride, padding=1),\n                nn.InstanceNorm2d(out_filters),\n                nn.LeakyReLU(0.2, inplace=True)\n            ]\n        self.model = nn.Sequential(\n            *discriminator_block(3, 64, 2),\n            *discriminator_block(64, 128, 2),\n            *discriminator_block(128, 256, 2),\n            *discriminator_block(256, 512, 1),\n            nn.Conv2d(512, 1, kernel_size=4, stride=1, padding=1)\n        )\n\n    def forward(self, img):\n        return self.model(img)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import itertools\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nG_A2B = Generator().to(device)\nG_B2A = Generator().to(device)\nD_A = Discriminator().to(device)\nD_B = Discriminator().to(device)\n\ncriterion_GAN = nn.MSELoss().to(device)\ncriterion_cycle = nn.L1Loss().to(device)\ncriterion_identity = nn.L1Loss().to(device)\n\noptimizer_G = optim.Adam(itertools.chain(G_A2B.parameters(), G_B2A.parameters()), lr=0.0002, betas=(0.5, 0.999))\noptimizer_D_A = optim.Adam(D_A.parameters(), lr=0.0002, betas=(0.5, 0.999))\noptimizer_D_B = optim.Adam(D_B.parameters(), lr=0.0002, betas=(0.5, 0.999))\n\nnum_epochs = 200\nfor epoch in range(num_epochs):\n    for i, (real_A, real_B) in enumerate(zip(monet_loader, photo_loader)):\n        real_A = real_A.to(device)\n        real_B = real_B.to(device)\n\n        valid = torch.ones(real_A.size(0), 1, 30, 30).to(device)\n        fake = torch.zeros(real_A.size(0), 1, 30, 30).to(device)\n\n        optimizer_G.zero_grad()\n        \n        loss_id_A = criterion_identity(G_B2A(real_A), real_A)\n        loss_id_B = criterion_identity(G_A2B(real_B), real_B)\n\n        loss_identity = (loss_id_A + loss_id_B) / 2\n\n        fake_B = G_A2B(real_A)\n        loss_GAN_A2B = criterion_GAN(D_B(fake_B), valid)\n        fake_A = G_B2A(real_B)\n        loss_GAN_B2A = criterion_GAN(D_A(fake_A), valid)\n\n        loss_GAN = (loss_GAN_A2B + loss_GAN_B2A) / 2\n\n        recov_A = G_B2A(fake_B)\n        loss_cycle_A = criterion_cycle(recov_A, real_A)\n        recov_B = G_A2B(fake_A)\n        loss_cycle_B = criterion_cycle(recov_B, real_B)\n\n        loss_cycle = (loss_cycle_A + loss_cycle_B) / 2\n\n        loss_G = loss_GAN + 10.0 * loss_cycle + 5.0 * loss_identity\n\n        loss_G.backward()\n        optimizer_G.step()\n\n        optimizer_D_A.zero_grad()\n\n        loss_real = criterion_GAN(D_A(real_A), valid)\n        loss_fake = criterion_GAN(D_A(fake_A.detach()), fake)\n        loss_D_A = (loss_real + loss_fake) / 2\n\n        loss_D_A.backward()\n        optimizer_D_A.step()\n\n        optimizer_D_B.zero_grad()\n\n\n        loss_real = criterion_GAN(D_B(real_B), valid)\n        loss_fake = criterion_GAN(D_B(fake_B.detach()), fake)\n        loss_D_B = (loss_real + loss_fake) / 2\n\n        loss_D_B.backward()\n        optimizer_D_B.step()\n\n        print(f\"[Epoch {epoch}/{num_epochs}] [Batch {i}] [D loss: {loss_D_A.item() + loss_D_B.item()}] [G loss: {loss_G.item()}]\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-09T21:08:50.909501Z","iopub.execute_input":"2024-07-09T21:08:50.910160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import io\nimport zipfile\nimport torch\nimport torchvision.utils as vutils\n\nG_A2B.eval()\n\nbuffer = io.BytesIO()\n\nwith zipfile.ZipFile(buffer, 'w') as zip_file:\n    for i, photo in enumerate(photo_loader):\n        photo = photo.to(device)\n        fake_monet = G_A2B(photo).detach().cpu()\n        \n        image_buffer = io.BytesIO()\n        vutils.save_image(fake_monet, image_buffer, format='jpeg', normalize=True)\n        image_buffer.seek(0)\n        \n        zip_file.writestr(f'monet_{i}.jpg', image_buffer.read())\n        \n        if i >= 9999:\n            break\n\n# Save the zip file to disk\nwith open('images.zip', 'wb') as f:\n    f.write(buffer.getvalue())\n","metadata":{"execution":{"iopub.status.busy":"2024-07-09T21:06:19.055332Z","iopub.execute_input":"2024-07-09T21:06:19.055697Z","iopub.status.idle":"2024-07-09T21:08:08.023745Z","shell.execute_reply.started":"2024-07-09T21:06:19.055668Z","shell.execute_reply":"2024-07-09T21:08:08.022558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2024-07-09T19:46:32.688041Z","iopub.execute_input":"2024-07-09T19:46:32.688446Z","iopub.status.idle":"2024-07-09T19:46:33.716417Z","shell.execute_reply.started":"2024-07-09T19:46:32.688409Z","shell.execute_reply":"2024-07-09T19:46:33.714771Z"},"trusted":true},"execution_count":null,"outputs":[]}]}