{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30823,"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,"execution":{"iopub.status.busy":"2024-12-27T14:14:54.467834Z","iopub.execute_input":"2024-12-27T14:14:54.468102Z","iopub.status.idle":"2024-12-27T14:15:03.375241Z","shell.execute_reply.started":"2024-12-27T14:14:54.468080Z","shell.execute_reply":"2024-12-27T14:15:03.374398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport glob\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport itertools\nfrom torch import nn\nfrom torch.optim import Adam","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:15:03.376070Z","iopub.execute_input":"2024-12-27T14:15:03.376492Z","iopub.status.idle":"2024-12-27T14:15:03.380607Z","shell.execute_reply.started":"2024-12-27T14:15:03.376469Z","shell.execute_reply":"2024-12-27T14:15:03.379617Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 定义数据集类\nclass MonetDataset(Dataset):\n    def __init__(self, photo_dir, monet_dir, transform=None):\n        self.photo_paths = glob.glob(os.path.join(photo_dir, \"*.jpg\"))\n        self.monet_paths = glob.glob(os.path.join(monet_dir, \"*.jpg\"))\n        self.transform = transform\n\n    def __len__(self):\n        return max(len(self.photo_paths), len(self.monet_paths))\n\n    def __getitem__(self, idx):\n        photo_path = self.photo_paths[idx % len(self.photo_paths)]\n        monet_path = self.monet_paths[idx % len(self.monet_paths)]\n        \n        photo_image = Image.open(photo_path).convert(\"RGB\")\n        monet_image = Image.open(monet_path).convert(\"RGB\")\n        \n        if self.transform:\n            photo_image = self.transform(photo_image)\n            monet_image = self.transform(monet_image)\n        \n        return photo_image, monet_image\n\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])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:15:03.381565Z","iopub.execute_input":"2024-12-27T14:15:03.381866Z","iopub.status.idle":"2024-12-27T14:15:03.395302Z","shell.execute_reply.started":"2024-12-27T14:15:03.381835Z","shell.execute_reply":"2024-12-27T14:15:03.394455Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 数据集路径\nphoto_dir = \"/kaggle/input/gan-getting-started/photo_jpg\"\nmonet_dir = \"/kaggle/input/gan-getting-started/monet_jpg\"\n\n# 数据加载器\ndataset = MonetDataset(photo_dir, monet_dir, transform)\ndataloader = DataLoader(dataset, batch_size=64, shuffle=True, num_workers=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:15:03.396233Z","iopub.execute_input":"2024-12-27T14:15:03.396529Z","iopub.status.idle":"2024-12-27T14:15:03.427571Z","shell.execute_reply.started":"2024-12-27T14:15:03.396498Z","shell.execute_reply":"2024-12-27T14:15:03.426920Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 定义生成器网络\nclass Generator(nn.Module):\n    def __init__(self):\n        super(Generator, self).__init__()\n        self.main = nn.Sequential(\n            nn.Conv2d(3, 64, kernel_size=4, stride=2, padding=1),\n            nn.ReLU(),\n            # 更多层...\n            nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1),\n            nn.Tanh()\n        )\n\n    def forward(self, x):\n        return self.main(x)\n\n# 定义判别器网络\nclass Discriminator(nn.Module):\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        self.main = nn.Sequential(\n            nn.Conv2d(3, 64, kernel_size=4, stride=2, padding=1),\n            nn.LeakyReLU(0.2),\n            # 更多层...\n            nn.Conv2d(64, 1, kernel_size=4, stride=1, padding=1)\n        )\n\n    def forward(self, x):\n        return self.main(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:15:14.572117Z","iopub.execute_input":"2024-12-27T14:15:14.572462Z","iopub.status.idle":"2024-12-27T14:15:14.578806Z","shell.execute_reply.started":"2024-12-27T14:15:14.572435Z","shell.execute_reply":"2024-12-27T14:15:14.577873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 初始化模型\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nG_photo2monet = Generator().to(device)\nD_monet = Discriminator().to(device)\n\n# 多 GPU 并行\nif torch.cuda.device_count() > 1:\n    G_photo2monet = nn.DataParallel(G_photo2monet)\n    D_monet = nn.DataParallel(D_monet)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:16:34.737449Z","iopub.execute_input":"2024-12-27T14:16:34.737765Z","iopub.status.idle":"2024-12-27T14:16:34.744543Z","shell.execute_reply.started":"2024-12-27T14:16:34.737737Z","shell.execute_reply":"2024-12-27T14:16:34.743871Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm import tqdm\n\n\n# 损失函数和优化器\ncriterion = nn.MSELoss()\noptimizer_G = Adam(G_photo2monet.parameters(), lr=0.0002, betas=(0.5, 0.999))\noptimizer_D_monet = Adam(D_monet.parameters(), lr=0.0002, betas=(0.5, 0.999))\n\n# 训练循环\nnum_epochs = 100\nfor epoch in range(num_epochs):\n    epoch_loss_G = 0\n    epoch_loss_D_monet = 0\n\n    with tqdm(dataloader, desc=f\"Epoch {epoch+1}/{num_epochs}\") as pbar:\n        for photo, monet in pbar:\n            photo, monet = photo.to(device), monet.to(device)\n\n            # 生成假图像\n            fake_monet = G_photo2monet(photo)\n\n            # 更新判别器 D_monet\n            optimizer_D_monet.zero_grad()\n            real_loss = criterion(D_monet(monet), torch.ones_like(D_monet(monet)))\n            fake_loss = criterion(D_monet(fake_monet.detach()), torch.zeros_like(D_monet(fake_monet)))\n            loss_D_monet = real_loss + fake_loss\n            loss_D_monet.backward()\n            optimizer_D_monet.step()\n\n            # 更新生成器 G_photo2monet\n            optimizer_G.zero_grad()\n            loss_G = criterion(D_monet(fake_monet), torch.ones_like(D_monet(fake_monet)))\n            loss_G.backward()\n            optimizer_G.step()\n\n            # 累积损失\n            epoch_loss_G += loss_G.item()\n            epoch_loss_D_monet += loss_D_monet.item()\n\n            # 更新进度条描述\n            pbar.set_postfix({\n                \"Loss G\": loss_G.item(),\n                \"Loss D_monet\": loss_D_monet.item()\n            })\n\n    print(f\"Epoch {epoch+1}/{num_epochs}, Loss G: {epoch_loss_G/len(dataloader):.4f}, \"\n          f\"Loss D_monet: {epoch_loss_D_monet/len(dataloader):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:16:36.020394Z","iopub.execute_input":"2024-12-27T14:16:36.020706Z","iopub.status.idle":"2024-12-27T14:17:22.225732Z","shell.execute_reply.started":"2024-12-27T14:16:36.020685Z","shell.execute_reply":"2024-12-27T14:17:22.224477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom PIL import Image\nimport torch\nfrom torchvision import transforms\n\n# 定义图像转换\ntransform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))  # [-1, 1] 归一化\n])\n\n# 输入文件夹和输出文件夹\ninput_dir = \"/kaggle/input/gan-getting-started/photo_jpg\"  # 替换为 photo 文件夹路径\noutput_dir = \"/kaggle/working/images\"\nos.makedirs(output_dir, exist_ok=True)\n\n# 加载 photo 文件夹中的所有图像\nphoto_files = [f for f in os.listdir(input_dir) if f.endswith(('jpg', 'png', 'jpeg'))]\n\n# 将图像转为 Monet 风格\nG_photo2monet.eval()  # 切换到评估模式\nfor i, file_name in enumerate(photo_files):\n    photo_path = os.path.join(input_dir, file_name)\n    photo = Image.open(photo_path).convert(\"RGB\")\n    photo = transform(photo).unsqueeze(0).to(device)  # 转换为模型输入格式\n\n    with torch.no_grad():\n        fake_monet = G_photo2monet(photo)\n\n    # 将生成的图像保存为 JPEG 格式\n    fake_monet_image = (fake_monet.squeeze(0).permute(1, 2, 0).cpu().detach().numpy() + 1) / 2  # 反归一化到 [0, 1]\n    fake_monet_image = (fake_monet_image * 255).astype('uint8')\n    Image.fromarray(fake_monet_image).save(f\"{output_dir}/monet_{i}.jpg\")\n\nprint(f\"所有图片已保存至 {output_dir}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-27T14:17:27.256429Z","iopub.execute_input":"2024-12-27T14:17:27.256742Z","iopub.status.idle":"2024-12-27T14:17:39.671172Z","shell.execute_reply.started":"2024-12-27T14:17:27.256718Z","shell.execute_reply":"2024-12-27T14:17:39.669797Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 打包生成的图像，直接保存图片到 ZIP 文件中\n!cd /kaggle/working/images && zip -r ../images.zip ./*","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}