{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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":30839,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport re\nimport io\nimport zipfile\nfrom PIL import Image\nimport shutil\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sb\n\nimport torch\nimport torch.nn as nn\nfrom torch.nn.utils import spectral_norm\nimport torch.optim as optim\nfrom torchvision import datasets, transforms\nfrom PIL import Image\nfrom torch.utils.data import DataLoader, Dataset\n\nfrom tqdm import tqdm\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:08.566279Z","iopub.execute_input":"2025-02-01T21:46:08.566576Z","iopub.status.idle":"2025-02-01T21:46:18.884822Z","shell.execute_reply.started":"2025-02-01T21:46:08.566549Z","shell.execute_reply":"2025-02-01T21:46:18.883712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMAGE_SIZE = (256, 256)\nBATCH_SIZE = 8\nLATENT_DIM = 100\nLR = 0.0002\nBETA1 = 0.5\nEPOCHS = 100","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:18.886322Z","iopub.execute_input":"2025-02-01T21:46:18.886909Z","iopub.status.idle":"2025-02-01T21:46:18.891636Z","shell.execute_reply.started":"2025-02-01T21:46:18.886868Z","shell.execute_reply":"2025-02-01T21:46:18.890555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PATH = '/kaggle/input/gan-getting-started/'\n\nmonet_files = os.listdir(PATH + 'monet_jpg')\nphoto_files = os.listdir(PATH + 'photo_jpg')\n\nn_monet_files = len(monet_files)\nn_photo_files = len(photo_files)\n\nprint(f\"Count Monet pictures: {n_monet_files}\")\nprint(f\"Count Photos: {n_photo_files}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:18.893692Z","iopub.execute_input":"2025-02-01T21:46:18.893968Z","iopub.status.idle":"2025-02-01T21:46:18.975998Z","shell.execute_reply.started":"2025-02-01T21:46:18.893943Z","shell.execute_reply":"2025-02-01T21:46:18.974800Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nprint(\"Device: \", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-02T03:27:03.452395Z","iopub.execute_input":"2025-02-02T03:27:03.452661Z","iopub.status.idle":"2025-02-02T03:27:03.541466Z","shell.execute_reply.started":"2025-02-02T03:27:03.452637Z","shell.execute_reply":"2025-02-02T03:27:03.539956Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomImageDataset(Dataset):\n    def __init__(self, img_dir, transform=None):\n        self.img_dir = img_dir\n        self.img_files = [f for f in os.listdir(img_dir) if os.path.isfile(os.path.join(img_dir, f))]\n        self.transform = transform\n        self.class_name = os.path.basename(img_dir)\n\n    def __len__(self):\n        return len(self.img_files)\n\n    def __getitem__(self, idx):\n        img_path = os.path.join(self.img_dir, self.img_files[idx])\n        try:\n            image = Image.open(img_path).convert(\"RGB\")\n            if self.transform:\n                image = self.transform(image)\n            return image, 0\n        except Exception as e:\n            print(f\"Error loading image {img_path}: {e}\")\n            return None, 0\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:18.987455Z","iopub.execute_input":"2025-02-01T21:46:18.987834Z","iopub.status.idle":"2025-02-01T21:46:19.003424Z","shell.execute_reply.started":"2025-02-01T21:46:18.987793Z","shell.execute_reply":"2025-02-01T21:46:19.002264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize(IMAGE_SIZE),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5,), (0.5,))\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:19.004308Z","iopub.execute_input":"2025-02-01T21:46:19.004610Z","iopub.status.idle":"2025-02-01T21:46:19.021762Z","shell.execute_reply.started":"2025-02-01T21:46:19.004574Z","shell.execute_reply":"2025-02-01T21:46:19.020692Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_monet = CustomImageDataset(img_dir=PATH + \"monet_jpg\", transform=transform)\ndataset_photo = CustomImageDataset(img_dir=PATH + \"photo_jpg\", transform=transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:19.022814Z","iopub.execute_input":"2025-02-01T21:46:19.023173Z","iopub.status.idle":"2025-02-01T21:46:34.304455Z","shell.execute_reply.started":"2025-02-01T21:46:19.023135Z","shell.execute_reply":"2025-02-01T21:46:34.303338Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataloader_monet = DataLoader(dataset_monet, batch_size=BATCH_SIZE, shuffle=True)\ndataloader_photo = DataLoader(dataset_photo, batch_size=BATCH_SIZE, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.305461Z","iopub.execute_input":"2025-02-01T21:46:34.305764Z","iopub.status.idle":"2025-02-01T21:46:34.310285Z","shell.execute_reply.started":"2025-02-01T21:46:34.305735Z","shell.execute_reply":"2025-02-01T21:46:34.309283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for real_images, _ in dataloader_monet:\n    print(\"Real image batch shape:\", real_images.shape)  # Should be torch.Size([BATCH_SIZE, 3, 256, 256])\n    break \n\nfor fake_images, _ in dataloader_photo:\n    print(\"Fake image batch shape:\", fake_images.shape)  # Should also be torch.Size([BATCH_SIZE, 3, 256, 256])\n    break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.313259Z","iopub.execute_input":"2025-02-01T21:46:34.313643Z","iopub.status.idle":"2025-02-01T21:46:34.541030Z","shell.execute_reply.started":"2025-02-01T21:46:34.313616Z","shell.execute_reply":"2025-02-01T21:46:34.540044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, latent_dim=100):\n        super(Generator, self).__init__()\n        self.model = nn.Sequential(\n            nn.Linear(latent_dim, 512 * 8 * 8), \n            nn.BatchNorm1d(512 * 8 * 8),\n            nn.ReLU(),\n            nn.Unflatten(1, (512, 8, 8)),  # 8x8 feature map\n\n            nn.ConvTranspose2d(512, 256, 4, stride=2, padding=1),  # 16x16\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1),  # 32x32\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),  # 64x64\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(64, 32, 4, stride=2, padding=1),  # 128x128\n            nn.BatchNorm2d(32),\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(32, 16, 4, stride=2, padding=1),  # 256x256\n            nn.BatchNorm2d(16),\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(16, 3, 3, stride=1, padding=1),  # Финальный слой\n            nn.Tanh()\n        )\n\n    def forward(self, x):\n        return self.model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.542568Z","iopub.execute_input":"2025-02-01T21:46:34.542946Z","iopub.status.idle":"2025-02-01T21:46:34.551526Z","shell.execute_reply.started":"2025-02-01T21:46:34.542910Z","shell.execute_reply":"2025-02-01T21:46:34.550137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        self.model = nn.Sequential(\n            spectral_norm(nn.Conv2d(3, 64, 4, stride=2, padding=1)),\n            nn.LeakyReLU(0.2),\n            nn.Dropout(0.3),\n            \n            spectral_norm(nn.Conv2d(64, 128, 4, stride=2, padding=1)),\n            nn.BatchNorm2d(128),\n            nn.LeakyReLU(0.2),\n            nn.Dropout(0.3),\n            \n            spectral_norm(nn.Conv2d(128, 256, 4, stride=2, padding=1)),\n            nn.BatchNorm2d(256),\n            nn.LeakyReLU(0.2),\n            nn.Dropout(0.3),\n\n            spectral_norm(nn.Conv2d(256, 512, 4, stride=2, padding=1)),\n            nn.BatchNorm2d(512),\n            nn.LeakyReLU(0.2),\n\n            nn.Conv2d(512, 1, 4, stride=2, padding=1),\n            nn.Flatten(),\n            nn.Sigmoid()\n        )\n\n    def forward(self, x):\n        output_before_flatten = self.model(x)\n        flattened_output = nn.Flatten()(output_before_flatten)\n        return nn.Sigmoid()(flattened_output)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:48:20.530091Z","iopub.execute_input":"2025-02-01T21:48:20.530529Z","iopub.status.idle":"2025-02-01T21:48:20.537977Z","shell.execute_reply.started":"2025-02-01T21:48:20.530495Z","shell.execute_reply":"2025-02-01T21:48:20.536894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"generator = Generator().to(device)\ndiscriminator = Discriminator().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:48:23.304738Z","iopub.execute_input":"2025-02-01T21:48:23.305064Z","iopub.status.idle":"2025-02-01T21:48:23.421096Z","shell.execute_reply.started":"2025-02-01T21:48:23.305037Z","shell.execute_reply":"2025-02-01T21:48:23.419972Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.BCELoss()\ng_optimizer = optim.Adam(generator.parameters(), lr=0.0002, betas=(BETA1, 0.999))\nd_optimizer = optim.Adam(discriminator.parameters(), lr=0.0001, betas=(BETA1, 0.999))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:48:25.324478Z","iopub.execute_input":"2025-02-01T21:48:25.324812Z","iopub.status.idle":"2025-02-01T21:48:25.330426Z","shell.execute_reply.started":"2025-02-01T21:48:25.324786Z","shell.execute_reply":"2025-02-01T21:48:25.329269Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for epoch in range(EPOCHS):\n    for real_images, _ in dataloader_monet:\n        real_images = real_images.to(device)\n        batch_size = real_images.size(0)\n\n        # === Обучение дискриминатора ===\n        noise = torch.randn(batch_size, LATENT_DIM, device=device)\n        fake_images = generator(noise).detach()\n\n        real_labels = torch.full((batch_size, 1), 0.9, device=device)  # Вместо 1.0\n        fake_labels = torch.full((batch_size, 1), 0.1, device=device)  # Вместо 0.0\n\n        real_labels = real_labels.expand(-1, 64)\n        fake_labels = fake_labels.expand(-1, 64)\n\n        real_output = discriminator(real_images)\n        fake_output = discriminator(fake_images)\n\n        d_real_loss = criterion(real_output, real_labels)\n        d_fake_loss = criterion(fake_output, fake_labels)\n        d_loss = (d_real_loss + d_fake_loss) / 2\n\n        d_optimizer.zero_grad()\n        d_loss.backward()\n        d_optimizer.step()\n\n        # === Обучение генератора (2 раза) ===\n        for _ in range(2):\n            noise = torch.randn(batch_size, LATENT_DIM, device=device)\n            fake_images = generator(noise)\n\n            g_loss = criterion(discriminator(fake_images), real_labels)  # Хочет обмануть дискриминатор\n            g_optimizer.zero_grad()\n            g_loss.backward()\n            g_optimizer.step()\n\n    print(f\"Epoch [{epoch+1}/{EPOCHS}], D Loss: {d_loss.item()}, G Loss: {g_loss.item()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:48:27.610029Z","iopub.execute_input":"2025-02-01T21:48:27.610423Z","iopub.status.idle":"2025-02-01T21:51:45.610492Z","shell.execute_reply.started":"2025-02-01T21:48:27.610387Z","shell.execute_reply":"2025-02-01T21:51:45.608994Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"noise = torch.randn(1, LATENT_DIM, device=device)\ngenerator.to(device)\ngenerator.eval()\n\nwith torch.no_grad():\n    generated_image = generator(noise).detach().cpu()\n\nprint(\"Output shape:\", generated_image.shape)\n\ngenerated_image = (generated_image[0].permute(1, 2, 0).numpy() + 1) / 2\nplt.imshow(generated_image)\nplt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.570480Z","iopub.status.idle":"2025-02-01T21:46:34.570795Z","shell.execute_reply":"2025-02-01T21:46:34.570668Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def generate_and_save_images(generator, num_images=8000, latent_dim=100, output_folder=\"/kaggle/working/images\", device=device):\n    if not os.path.exists(output_folder):\n        os.makedirs(output_folder)\n\n    generator.to(device)\n    generator.eval()\n    \n    noise = torch.randn(num_images, latent_dim, device=device)\n\n    for i in tqdm(range(num_images), desc=\"Generating Images\"):\n        with torch.no_grad(): \n            generated_image = generator(noise[i:i+1])\n        \n        generated_image = (generated_image.cpu().squeeze(0).permute(1, 2, 0).numpy() + 1) * 127.5\n        generated_image = np.clip(generated_image, 0, 255).astype(np.uint8)\n\n        img = Image.fromarray(generated_image)\n        img.save(f\"{output_folder}/monet_image_{i+1}.jpg\")\n\n    shutil.make_archive(\"/kaggle/working/images\", 'zip', output_folder)\n    print(f\"Saved and zipped {num_images} images in /kaggle/working/images.zip\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.571806Z","iopub.status.idle":"2025-02-01T21:46:34.572289Z","shell.execute_reply":"2025-02-01T21:46:34.572073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"generate_and_save_images(generator, num_images=8000, output_folder=\"/kaggle/working/images\", device=device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-01T21:46:34.573140Z","iopub.status.idle":"2025-02-01T21:46:34.573585Z","shell.execute_reply":"2025-02-01T21:46:34.573385Z"}},"outputs":[],"execution_count":null}]}