{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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)\n\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\nfor 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","trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:35.865111Z","iopub.execute_input":"2024-12-17T16:08:35.865547Z","iopub.status.idle":"2024-12-17T16:08:38.693454Z","shell.execute_reply.started":"2024-12-17T16:08:35.865507Z","shell.execute_reply":"2024-12-17T16:08:38.692052Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader, random_split\nfrom torchvision import transforms\nfrom torchvision.utils import save_image\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom pathlib import Path\nimport torch.optim as optim","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:38.695273Z","iopub.execute_input":"2024-12-17T16:08:38.695765Z","iopub.status.idle":"2024-12-17T16:08:41.812114Z","shell.execute_reply.started":"2024-12-17T16:08:38.695729Z","shell.execute_reply":"2024-12-17T16:08:41.810983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dataset Directories\ndata_path = '/kaggle/input/gan-getting-started'\nmonet_dir = 'monet_jpg'\nphoto_dir = 'photo_jpg'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.813739Z","iopub.execute_input":"2024-12-17T16:08:41.814517Z","iopub.status.idle":"2024-12-17T16:08:41.820695Z","shell.execute_reply.started":"2024-12-17T16:08:41.814462Z","shell.execute_reply":"2024-12-17T16:08:41.819344Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dataset Class\nclass MonetPhotoDataset(Dataset):\n    def __init__(self, root_dir, monet_folder, photo_folder, transform=None):\n        \"\"\"\n        Dataset for loading Monet-style paintings and photos.\n\n        Args:\n            root_dir (str): Root directory for the dataset.\n            monet_folder (str): Folder for Monet paintings.\n            photo_folder (str): Folder for photos.\n            transform (callable, optional): Transformations applied to images.\n        \"\"\"\n        self.root_dir = root_dir\n        self.monet_folder = monet_folder\n        self.photo_folder = photo_folder\n        self.monet_images = os.listdir(os.path.join(root_dir, monet_folder))\n        self.photo_images = os.listdir(os.path.join(root_dir, photo_folder))\n        self.transform = transform\n\n    def __len__(self):\n        return max(len(self.monet_images), len(self.photo_images))\n\n    def __getitem__(self, idx):\n        monet_img_path = os.path.join(self.root_dir, self.monet_folder, self.monet_images[idx % len(self.monet_images)])\n        photo_img_path = os.path.join(self.root_dir, self.photo_folder, self.photo_images[idx % len(self.photo_images)])\n        \n        monet_image = Image.open(monet_img_path)\n        photo_image = Image.open(photo_img_path)\n\n        if self.transform:\n            monet_image = self.transform(monet_image)\n            photo_image = self.transform(photo_image)\n\n        return monet_image, photo_image\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.823209Z","iopub.execute_input":"2024-12-17T16:08:41.823596Z","iopub.status.idle":"2024-12-17T16:08:41.835101Z","shell.execute_reply.started":"2024-12-17T16:08:41.823561Z","shell.execute_reply":"2024-12-17T16:08:41.833698Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Image Transforms\nimage_transforms = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.5], std=[0.5])\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.836510Z","iopub.execute_input":"2024-12-17T16:08:41.836842Z","iopub.status.idle":"2024-12-17T16:08:41.858141Z","shell.execute_reply.started":"2024-12-17T16:08:41.836810Z","shell.execute_reply":"2024-12-17T16:08:41.856825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dataset Initialization\ndataset = MonetPhotoDataset(data_path, monet_dir, photo_dir, transform=image_transforms)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.859960Z","iopub.execute_input":"2024-12-17T16:08:41.860492Z","iopub.status.idle":"2024-12-17T16:08:41.876023Z","shell.execute_reply.started":"2024-12-17T16:08:41.860414Z","shell.execute_reply":"2024-12-17T16:08:41.874737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# DataLoader\ntrain_loader = DataLoader(dataset, batch_size=16, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.877497Z","iopub.execute_input":"2024-12-17T16:08:41.878458Z","iopub.status.idle":"2024-12-17T16:08:41.885227Z","shell.execute_reply.started":"2024-12-17T16:08:41.878388Z","shell.execute_reply":"2024-12-17T16:08:41.884017Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# CycleGAN Models\nclass ResidualBlock(nn.Module):\n    def __init__(self, channels):\n        super().__init__()\n        self.block = nn.Sequential(\n            nn.Conv2d(channels, channels, kernel_size=3, padding=1),\n            nn.InstanceNorm2d(channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(channels, channels, kernel_size=3, padding=1),\n            nn.InstanceNorm2d(channels)\n        )\n\n    def forward(self, x):\n        return x + self.block(x)\n\nclass Generator(nn.Module):\n    def __init__(self, in_channels=3, out_channels=3, num_residuals=6):\n        super().__init__()\n        self.initial = nn.Sequential(\n            nn.Conv2d(in_channels, 64, kernel_size=7, stride=1, padding=3),\n            nn.InstanceNorm2d(64),\n            nn.ReLU(inplace=True)\n        )\n        self.downsampling = nn.Sequential(\n            nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1),\n            nn.InstanceNorm2d(128),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1),\n            nn.InstanceNorm2d(256),\n            nn.ReLU(inplace=True)\n        )\n        self.residual_blocks = nn.Sequential(*[ResidualBlock(256) for _ in range(num_residuals)])\n        self.upsampling = nn.Sequential(\n            nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1),\n            nn.InstanceNorm2d(128),\n            nn.ReLU(inplace=True),\n            nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1),\n            nn.InstanceNorm2d(64),\n            nn.ReLU(inplace=True)\n        )\n        self.final = nn.Conv2d(64, out_channels, kernel_size=7, stride=1, padding=3)\n        self.tanh = nn.Tanh()\n\n    def forward(self, x):\n        x = self.initial(x)\n        x = self.downsampling(x)\n        x = self.residual_blocks(x)\n        x = self.upsampling(x)\n        return self.tanh(self.final(x))\n\nclass Discriminator(nn.Module):\n    def __init__(self, in_channels=3):\n        super().__init__()\n        self.model = nn.Sequential(\n            nn.Conv2d(in_channels, 64, kernel_size=4, stride=2, padding=1),\n            nn.LeakyReLU(0.2, inplace=True),\n            nn.Conv2d(64, 128, kernel_size=4, stride=2, padding=1),\n            nn.InstanceNorm2d(128),\n            nn.LeakyReLU(0.2, inplace=True),\n            nn.Conv2d(128, 256, kernel_size=4, stride=2, padding=1),\n            nn.InstanceNorm2d(256),\n            nn.LeakyReLU(0.2, inplace=True),\n            nn.Conv2d(256, 512, kernel_size=4, stride=1, padding=1),\n            nn.InstanceNorm2d(512),\n            nn.LeakyReLU(0.2, inplace=True),\n            nn.Conv2d(512, 1, kernel_size=4, stride=1, padding=1)\n        )\n\n    def forward(self, x):\n        return self.model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.887142Z","iopub.execute_input":"2024-12-17T16:08:41.887657Z","iopub.status.idle":"2024-12-17T16:08:41.906227Z","shell.execute_reply.started":"2024-12-17T16:08:41.887605Z","shell.execute_reply":"2024-12-17T16:08:41.905065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Initialize Models\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\ngen_photo2monet = Generator().to(device)\ngen_monet2photo = Generator().to(device)\ndisc_photo = Discriminator().to(device)\ndisc_monet = Discriminator().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:41.907831Z","iopub.execute_input":"2024-12-17T16:08:41.908327Z","iopub.status.idle":"2024-12-17T16:08:42.246972Z","shell.execute_reply.started":"2024-12-17T16:08:41.908277Z","shell.execute_reply":"2024-12-17T16:08:42.245790Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Losses\nadversarial_loss = nn.MSELoss()\ncycle_loss = nn.L1Loss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:42.250355Z","iopub.execute_input":"2024-12-17T16:08:42.250770Z","iopub.status.idle":"2024-12-17T16:08:42.256275Z","shell.execute_reply.started":"2024-12-17T16:08:42.250734Z","shell.execute_reply":"2024-12-17T16:08:42.255001Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training Loop\nnum_epochs = 5\nfor epoch in range(num_epochs):\n    for real_monet, real_photo in tqdm(train_loader):\n        real_monet = real_monet.to(device)\n        real_photo = real_photo.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:08:42.257940Z","iopub.execute_input":"2024-12-17T16:08:42.258923Z","iopub.status.idle":"2024-12-17T16:11:44.943303Z","shell.execute_reply.started":"2024-12-17T16:08:42.258856Z","shell.execute_reply":"2024-12-17T16:11:44.942054Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define optimizers\ngen_optimizer = torch.optim.Adam(\n    list(gen_photo2monet.parameters()) + list(gen_monet2photo.parameters()),\n    lr=0.0002,\n    betas=(0.5, 0.999)\n)\n\ndisc_optimizer = torch.optim.Adam(\n    list(disc_monet.parameters()) + list(disc_photo.parameters()),\n    lr=0.0002,\n    betas=(0.5, 0.999)\n)\n\n# Train Generators\nfake_monet = gen_photo2monet(real_photo)\nfake_photo = gen_monet2photo(real_monet)\n\ncycle_photo = gen_monet2photo(fake_monet)\ncycle_monet = gen_photo2monet(fake_photo)\n\ngen_loss = (\n    adversarial_loss(disc_monet(fake_monet), torch.ones_like(disc_monet(fake_monet)))\n    + adversarial_loss(disc_photo(fake_photo), torch.ones_like(disc_photo(fake_photo)))\n    + cycle_loss(cycle_photo, real_photo) * 10\n    + cycle_loss(cycle_monet, real_monet) * 10\n)\ngen_optimizer.zero_grad()\ngen_loss.backward()\ngen_optimizer.step()\n\n# Train Discriminators\ndisc_loss = (\n    adversarial_loss(disc_monet(real_monet), torch.ones_like(disc_monet(real_monet)))\n    + adversarial_loss(disc_monet(fake_monet.detach()), torch.zeros_like(disc_monet(fake_monet)))\n    + adversarial_loss(disc_photo(real_photo), torch.ones_like(disc_photo(real_photo)))\n    + adversarial_loss(disc_photo(fake_photo.detach()), torch.zeros_like(disc_photo(fake_photo)))\n)\ndisc_optimizer.zero_grad()\ndisc_loss.backward()\ndisc_optimizer.step()\n\n# Print progress\nprint(f\"Epoch {epoch+1}/{num_epochs} - Gen Loss: {gen_loss.item()} - Disc Loss: {disc_loss.item()}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:14:58.043359Z","iopub.execute_input":"2024-12-17T16:14:58.043757Z","iopub.status.idle":"2024-12-17T16:18:31.616203Z","shell.execute_reply.started":"2024-12-17T16:14:58.043718Z","shell.execute_reply":"2024-12-17T16:18:31.614827Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile\n\n# Directory for saving images (in-memory for Kaggle)\noutput_zip_path = \"images.zip\"\n\n# Ensure the generator model is in evaluation mode\ngen_photo2monet.eval()\n\n# Open a zip file for writing\nwith zipfile.ZipFile(output_zip_path, 'w') as zipf:\n    image_count = 0  # Counter to track the number of generated images\n\n    # Iterate over the DataLoader\n    for real_photo, _ in tqdm(train_loader, desc=\"Generating Images\"):\n        real_photo = real_photo.to(device)\n\n        # Generate Monet-style images\n        with torch.no_grad():\n            fake_monet = gen_photo2monet(real_photo)\n\n        # Convert the tensor images to PIL format and save to the zip\n        for i in range(fake_monet.size(0)):\n            # Denormalize the image\n            img = fake_monet[i].cpu().detach()\n            img = img * 0.5 + 0.5  # Undo normalization\n            img = transforms.ToPILImage()(img)\n\n            # Save the image directly into the zip file\n            image_filename = f\"monet_image_{image_count + 1}.jpg\"\n            with zipf.open(image_filename, 'w') as img_file:\n                img.save(img_file, format=\"JPEG\")\n            \n            image_count += 1\n\n            # Stop once we reach the required number of images\n            if image_count >= 7000:  # Corrected typo here\n                break\n        \n        if image_count >= 7000:\n            break\n\nprint(f\"Successfully generated and zipped {image_count} Monet-style images into {output_zip_path}.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T16:36:32.400550Z","iopub.execute_input":"2024-12-17T16:36:32.401064Z","iopub.status.idle":"2024-12-17T18:20:47.827572Z","shell.execute_reply.started":"2024-12-17T16:36:32.401028Z","shell.execute_reply":"2024-12-17T18:20:47.826173Z"}},"outputs":[],"execution_count":null}]}