{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"},{"sourceId":1217826,"sourceType":"datasetVersion","datasetId":298806},{"sourceId":3956508,"sourceType":"datasetVersion","datasetId":850761}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom PIL import Image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:33:41.712093Z","iopub.execute_input":"2024-11-05T09:33:41.712509Z","iopub.status.idle":"2024-11-05T09:33:41.717136Z","shell.execute_reply.started":"2024-11-05T09:33:41.712470Z","shell.execute_reply":"2024-11-05T09:33:41.716168Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"from PIL import Image\nimport os\n\ndef resize_images(folder_path, size=(256, 256)):\n    for filename in os.listdir(folder_path):\n        if filename.endswith(\".jpg\") or filename.endswith(\".png\"):\n            img = Image.open(os.path.join(folder_path, filename))\n            img = img.resize(size)\n            img.save(os.path.join(folder_path, filename))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:26:19.996303Z","iopub.execute_input":"2024-11-05T09:26:19.996952Z","iopub.status.idle":"2024-11-05T09:26:20.021702Z","shell.execute_reply.started":"2024-11-05T09:26:19.996884Z","shell.execute_reply":"2024-11-05T09:26:20.020532Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\n\nclass ImageDataset(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 __len__(self):\n        return len(self.files)\n\n    def __getitem__(self, idx):\n        img_path = os.path.join(self.root, self.files[idx])\n        image = Image.open(img_path)\n        if self.transform:\n            image = self.transform(image)\n        return image\n\n# Define transformations\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)),  # Normalize to [-1, 1]\n])\n\n# Load datasets\nvan_gogh_dataset = ImageDataset(\"/kaggle/input/van-gogh-paintings/VincentVanGogh\", transform=transform)\nmonet_dataset = ImageDataset(\"/kaggle/input/gan-getting-started/monet_jpg\", transform=transform)\nreal_images_dataset = ImageDataset(\"/kaggle/input/gan-getting-started/photo_jpg\", transform=transform)\n\n# DataLoaders\nvan_gogh_loader = DataLoader(van_gogh_dataset, batch_size=1, shuffle=True)\nmonet_loader = DataLoader(monet_dataset, batch_size=1, shuffle=True)\nreal_images_loader = DataLoader(real_images_dataset, batch_size=1, shuffle=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:29:54.453759Z","iopub.execute_input":"2024-11-05T09:29:54.454379Z","iopub.status.idle":"2024-11-05T09:30:00.069073Z","shell.execute_reply.started":"2024-11-05T09:29:54.454328Z","shell.execute_reply":"2024-11-05T09:30:00.068293Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nimport matplotlib.pyplot as plt\n\n# Sample image display function\ndef display_sample_images(image_paths, titles, max_images=3):\n    \"\"\"\n    Display a sample of images with titles.\n    \n    Parameters:\n        image_paths (list): List of paths to the images to display.\n        titles (list): List of titles for each image.\n        max_images (int): Maximum number of images to display.\n    \"\"\"\n    fig, axs = plt.subplots(1, min(max_images, len(image_paths)), figsize=(15, 5))\n    \n    for i, (img_path, title) in enumerate(zip(image_paths[:max_images], titles[:max_images])):\n        img = Image.open(img_path)\n        axs[i].imshow(img)\n        axs[i].set_title(title)\n        axs[i].axis('off')\n\n    plt.show()\n\n# Let's create placeholders to represent the dataset samples since the actual images are unavailable.\n# Normally, we would point to real image file paths, but here we’ll simulate sample image titles only.\nsample_van_gogh_images = [\"/kaggle/input/van-gogh-paintings/VincentVanGogh/Villege/Bulb Fields.jpg\", \"/kaggle/input/van-gogh-paintings/VincentVanGogh/Paris/Portrait of Pere Tanguy 2.jpg\", \"/kaggle/input/van-gogh-paintings/VincentVanGogh/Paris/Self-Portrait 2.jpg\"]\nsample_monet_images = [\"/kaggle/input/gan-getting-started/monet_jpg/011835cfbf.jpg\", \"/kaggle/input/gan-getting-started/monet_jpg/0e3b3292da.jpg\", \"/kaggle/input/gan-getting-started/monet_jpg/16dabe418c.jpg\"]\nsample_real_images = [\"/kaggle/input/gan-getting-started/photo_jpg/00f78547f0.jpg\", \"/kaggle/input/gan-getting-started/photo_jpg/03c5d1d098.jpg\", \"/kaggle/input/gan-getting-started/photo_jpg/03a17d96e1.jpg\"]\n\n# Titles for each group\ntitles_van_gogh = [\"Van Gogh Sample 1\", \"Van Gogh Sample 2\", \"Van Gogh Sample 3\"]\ntitles_monet = [\"Monet Sample 1\", \"Monet Sample 2\", \"Monet Sample 3\"]\ntitles_real = [\"Real World Sample 1\", \"Real World Sample 2\", \"Real World Sample 3\"]\n\n# Display samples\ndisplay_sample_images(sample_van_gogh_images, titles_van_gogh)\ndisplay_sample_images(sample_monet_images, titles_monet)\ndisplay_sample_images(sample_real_images, titles_real)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:40:39.518885Z","iopub.execute_input":"2024-11-05T09:40:39.519587Z","iopub.status.idle":"2024-11-05T09:40:42.723019Z","shell.execute_reply.started":"2024-11-05T09:40:39.519548Z","shell.execute_reply":"2024-11-05T09:40:42.722058Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Monet","metadata":{}},{"cell_type":"markdown","source":"## Generator","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass ResidualBlock(nn.Module):\n    def __init__(self, channels):\n        super(ResidualBlock, self).__init__()\n        self.conv_block = nn.Sequential(\n            nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1),\n            nn.InstanceNorm2d(channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1),\n            nn.InstanceNorm2d(channels)\n        )\n\n    def forward(self, x):\n        return x + self.conv_block(x)\n\nclass Generator(nn.Module):\n    def __init__(self, in_channels=3, out_channels=3, num_residual_blocks=6):\n        super(Generator, self).__init__()\n        \n        # Initial Convolution Block\n        model = [\n            nn.Conv2d(in_channels, 64, kernel_size=7, stride=1, padding=3),\n            nn.InstanceNorm2d(64),\n            nn.ReLU(inplace=True)\n        ]\n        \n        # Downsampling\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 *= 2\n        \n        # Residual Blocks\n        for _ in range(num_residual_blocks):\n            model += [ResidualBlock(in_features)]\n        \n        # Upsampling\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 //= 2\n        \n        # Output Layer\n        model += [nn.Conv2d(64, out_channels, kernel_size=7, stride=1, padding=3), nn.Tanh()]\n        \n        self.model = nn.Sequential(*model)\n    \n    def forward(self, x):\n        return self.model(x)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:44:04.793134Z","iopub.execute_input":"2024-11-05T09:44:04.793557Z","iopub.status.idle":"2024-11-05T09:44:04.807286Z","shell.execute_reply.started":"2024-11-05T09:44:04.793518Z","shell.execute_reply":"2024-11-05T09:44:04.806302Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Discieminator","metadata":{}},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, in_channels=3):\n        super(Discriminator, self).__init__()\n        \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        \n        model = []\n        in_filters = in_channels\n        out_filters = 64\n        for stride in [2, 2, 2, 1]:\n            model += discriminator_block(in_filters, out_filters, stride)\n            in_filters = out_filters\n            out_filters = min(out_filters * 2, 512)\n        \n        model += [nn.Conv2d(in_filters, 1, kernel_size=4, stride=1, padding=1)]\n        \n        self.model = nn.Sequential(*model)\n    \n    def forward(self, x):\n        return self.model(x)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:44:37.175615Z","iopub.execute_input":"2024-11-05T09:44:37.176007Z","iopub.status.idle":"2024-11-05T09:44:37.184668Z","shell.execute_reply.started":"2024-11-05T09:44:37.175968Z","shell.execute_reply":"2024-11-05T09:44:37.183785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn.functional as F\n\n# Adversarial loss (using MSE as a replacement for binary cross-entropy)\ndef adversarial_loss(pred, target):\n    return F.mse_loss(pred, target)\n\n# Cycle consistency loss (L1 loss for transformations)\ndef cycle_consistency_loss(real_image, reconstructed_image):\n    return F.l1_loss(real_image, reconstructed_image)\n\n# Identity loss (L1 loss to help retain content and color)\ndef identity_loss(real_image, generated_image):\n    return F.l1_loss(real_image, generated_image)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:48:03.655101Z","iopub.execute_input":"2024-11-05T09:48:03.655790Z","iopub.status.idle":"2024-11-05T09:48:03.661615Z","shell.execute_reply.started":"2024-11-05T09:48:03.655747Z","shell.execute_reply":"2024-11-05T09:48:03.660543Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.optim as optim\n\n# Initialize generators and discriminators\nG = Generator()  # Real to Van Gogh\nF = Generator()  # Real to Monet\nD_A = Discriminator()  # Discriminator for Van Gogh images\nD_B = Discriminator()  # Discriminator for Monet images\n\n# Optimizers for each model\noptimizer_G = optim.Adam(G.parameters(), lr=0.0002, betas=(0.5, 0.999))\noptimizer_F = optim.Adam(F.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\n# Target labels\nreal_label = torch.ones((1, 1, 30, 30))  # Real images\nfake_label = torch.zeros((1, 1, 30, 30))  # Fake images\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:48:19.617376Z","iopub.execute_input":"2024-11-05T09:48:19.617760Z","iopub.status.idle":"2024-11-05T09:48:19.837919Z","shell.execute_reply.started":"2024-11-05T09:48:19.617722Z","shell.execute_reply":"2024-11-05T09:48:19.836929Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_epochs = 200  # You can increase this for better quality\n\nfor epoch in range(num_epochs):\n    for real_A, real_B in dataloader:  # Assume real_A = real-world images, real_B = style images\n        # Move data to GPU if available\n        real_A, real_B = real_A.to(device), real_B.to(device)\n\n        # === Step 1: Train Generators ===\n        optimizer_G.zero_grad()\n        optimizer_F.zero_grad()\n        \n        # Adversarial loss for generator G (real_A -> fake_B)\n        fake_B = G(real_A)\n        pred_fake_B = D_B(fake_B)\n        loss_G_adv = adversarial_loss(pred_fake_B, real_label)\n        \n        # Adversarial loss for generator F (real_B -> fake_A)\n        fake_A = F(real_B)\n        pred_fake_A = D_A(fake_A)\n        loss_F_adv = adversarial_loss(pred_fake_A, real_label)\n        \n        # Cycle consistency loss\n        reconstructed_A = F(fake_B)\n        reconstructed_B = G(fake_A)\n        loss_cycle_A = cycle_consistency_loss(real_A, reconstructed_A)\n        loss_cycle_B = cycle_consistency_loss(real_B, reconstructed_B)\n        \n        # Identity loss\n        identity_A = G(real_A)\n        identity_B = F(real_B)\n        loss_identity_A = identity_loss(real_A, identity_A)\n        loss_identity_B = identity_loss(real_B, identity_B)\n        \n        # Total generator loss\n        loss_G = loss_G_adv + loss_F_adv + 10 * (loss_cycle_A + loss_cycle_B) + 5 * (loss_identity_A + loss_identity_B)\n        loss_G.backward()\n        optimizer_G.step()\n        optimizer_F.step()\n\n        # === Step 2: Train Discriminators ===\n        optimizer_D_A.zero_grad()\n        optimizer_D_B.zero_grad()\n        \n        # Train D_A on real and fake images\n        pred_real_A = D_A(real_A)\n        pred_fake_A_detached = D_A(fake_A.detach())\n        loss_D_A = (adversarial_loss(pred_real_A, real_label) + adversarial_loss(pred_fake_A_detached, fake_label)) * 0.5\n        loss_D_A.backward()\n        optimizer_D_A.step()\n        \n        # Train D_B on real and fake images\n        pred_real_B = D_B(real_B)\n        pred_fake_B_detached = D_B(fake_B.detach())\n        loss_D_B = (adversarial_loss(pred_real_B, real_label) + adversarial_loss(pred_fake_B_detached, fake_label)) * 0.5\n        loss_D_B.backward()\n        optimizer_D_B.step()\n    \n    print(f\"Epoch [{epoch}/{num_epochs}] - Generator Loss: {loss_G.item()} - D_A Loss: {loss_D_A.item()} - D_B Loss: {loss_D_B.item()}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-05T09:48:42.797447Z","iopub.execute_input":"2024-11-05T09:48:42.798067Z","iopub.status.idle":"2024-11-05T09:48:42.855601Z","shell.execute_reply.started":"2024-11-05T09:48:42.798027Z","shell.execute_reply":"2024-11-05T09:48:42.854544Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}