天生对抗网络(GAN,Generative Adversarial Network)

[复制链接]
发表于 2026-1-10 22:55:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
天生对抗网络(GAN,Generative Adversarial Network)是一种深度学习模子,由两部门构成:天生器(Generator)和辨别器(Discriminator)。天生器的目标是天生逼真的样本,而辨别器的目标是区分真实样本与天生样本。它们通过对抗过程相互训练,终极使天生器可以大概天生高度逼真的数据。
根本概念


  • 天生器:从随机噪声(通常是高斯噪声)天生数据,表现为 G(z)G(z)G(z),此中 zzz 是埋伏变量(噪声)。
  • 辨别器:判定输入数据是否真实,表现为 D(x)D(x)D(x),此中 xxx 是输入数据。辨别器输出一个值,表现其对输入数据为真实的概率。
目标函数

GAN 的目标是通过最小化以下对抗丧失来训练天生器和辨别器:
min⁡Gmax⁡DV(D,G)=Ex∼pdata(x)[log⁡D(x)]+Ez∼pz(z)[log⁡(1−D(G(z)))]\min_G \max_D V(D, G) = \mathbb{E}_{x \sim p_{data}(x)}[\log D(x)] + \mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z)))]Gmin​Dmax​V(D,G)=Ex∼pdata​(x)​[logD(x)]+Ez∼pz​(z)​[log(1−D(G(z)))]

  • pdata(x)p_{data}(x)pdata​(x):真实数据分布。
  • pz(z)p_z(z)pz​(z):埋伏变量分布(通常为高斯分布)。
  • D(x)D(x)D(x):辨别器对真实样本的辨别概率。
  • G(z)G(z)G(z):天生器天生的样本。
训练过程


  • 辨别器训练:通过真实样本和天生样本的丧失来优化辨别器。
  • 天生器训练:通过辨别器的反馈,优化天生器,使得天生的样本更逼近真实样本。
通过不停的对抗训练,天生器终极可以大概天生靠近真实数据的样本,辨别器则不停进步其区分本领。
以下是一个使用 PyTorch 实现的简朴 GAN 案例,目标是天生手写数字(MNIST 数据集)。代码包罗天生器和辨别器的界说,以及训练过程。
GAN 案例代码

假如你要使用自界说的 MNISTDataset 类来加载数据,可以将它集成到之前的 GAN 示例中。以下是完备的代码示例,连合你的 MNISTDataset 实现。
完备的 GAN 示例代码

epoch设置为20,以作示例。
  1. import torch
  2. import torch.nn as nn
  3. import torch.optim as optim
  4. import numpy as np
  5. import os
  6. import matplotlib.pyplot as plt
  7. from torch.utils.data import Dataset, DataLoader
  8. # 自定义 MNIST 数据集类
  9. class MNISTDataset(Dataset):
  10.     def __init__(self, images_path, labels_path, transform=None):
  11.         self.images = self.load_images(images_path)
  12.         self.labels = self.load_labels(labels_path)
  13.         self.transform = transform
  14.     def load_images(self, path):
  15.         with open(path, 'rb') as f:
  16.             f.read(16)  # 跳过前16个字节
  17.             images = np.frombuffer(f.read(), np.uint8).reshape(-1, 1, 28, 28)
  18.         return torch.tensor(images, dtype=torch.float32) / 255.0  # 归一化到 [0, 1]
  19.     def load_labels(self, path):
  20.         with open(path, 'rb') as f:
  21.             f.read(8)  # 跳过前8个字节
  22.             labels = np.frombuffer(f.read(), np.uint8)
  23.         return labels
  24.     def __len__(self):
  25.         return len(self.labels)
  26.     def __getitem__(self, idx):
  27.         image = self.images[idx]
  28.         label = self.labels[idx]
  29.         if self.transform:
  30.             image = self.transform(image)
  31.         return image, label
  32. # 超参数
  33. latent_size = 100
  34. num_epochs = 20
  35. batch_size = 64
  36. learning_rate = 0.0002
  37. # 数据准备
  38. data_root = r'./MNIST'
  39. train_dataset = MNISTDataset(
  40.     images_path=os.path.join(data_root, 'train-images-idx3-ubyte'),
  41.     labels_path=os.path.join(data_root, 'train-labels-idx1-ubyte')
  42. )
  43. data_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
  44. # 生成器模型
  45. class Generator(nn.Module):
  46.     def __init__(self):
  47.         super(Generator, self).__init__()
  48.         self.model = nn.Sequential(
  49.             nn.Linear(latent_size, 256),
  50.             nn.ReLU(),
  51.             nn.Linear(256, 512),
  52.             nn.ReLU(),
  53.             nn.Linear(512, 1024),
  54.             nn.ReLU(),
  55.             nn.Linear(1024, 28 * 28),
  56.             nn.Tanh()  # 输出在[-1, 1]范围内
  57.         )
  58.     def forward(self, z):
  59.         return self.model(z).view(-1, 1, 28, 28)
  60. # 判别器模型
  61. class Discriminator(nn.Module):
  62.     def __init__(self):
  63.         super(Discriminator, self).__init__()
  64.         self.model = nn.Sequential(
  65.             nn.Linear(28 * 28, 1024),
  66.             nn.LeakyReLU(0.2),
  67.             nn.Linear(1024, 512),
  68.             nn.LeakyReLU(0.2),
  69.             nn.Linear(512, 256),
  70.             nn.LeakyReLU(0.2),
  71.             nn.Linear(256, 1),
  72.             nn.Sigmoid()  # 输出在[0, 1]范围内
  73.         )
  74.     def forward(self, x):
  75.         return self.model(x.view(-1, 28 * 28))
  76. # 初始化模型和优化器
  77. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  # 检查是否有 GPU
  78. generator = Generator().to(device)  # 移动到 GPU
  79. discriminator = Discriminator().to(device)  # 移动到 GPU
  80. criterion = nn.BCELoss()
  81. optimizer_G = optim.Adam(generator.parameters(), lr=learning_rate)
  82. optimizer_D = optim.Adam(discriminator.parameters(), lr=learning_rate)
  83. # 训练过程
  84. for epoch in range(num_epochs):
  85.     for i, (images, _) in enumerate(data_loader):
  86.         images = images.to(device)  # 移动输入数据到 GPU
  87.         # 标签
  88.         real_labels = torch.ones(images.size(0), 1).to(device)  # 移动到 GPU
  89.         fake_labels = torch.zeros(images.size(0), 1).to(device)  # 移动到 GPU
  90.         # 判别器训练
  91.         optimizer_D.zero_grad()
  92.         outputs = discriminator(images)
  93.         d_loss_real = criterion(outputs, real_labels)
  94.         z = torch.randn(images.size(0), latent_size).to(device)  # 随机噪声,移动到 GPU
  95.         fake_images = generator(z)
  96.         outputs = discriminator(fake_images.detach())
  97.         d_loss_fake = criterion(outputs, fake_labels)
  98.         d_loss = d_loss_real + d_loss_fake
  99.         d_loss.backward()
  100.         optimizer_D.step()
  101.         # 生成器训练
  102.         optimizer_G.zero_grad()
  103.         outputs = discriminator(fake_images)
  104.         g_loss = criterion(outputs, real_labels)
  105.         g_loss.backward()
  106.         optimizer_G.step()
  107.     if (epoch + 1) % 10 == 0:
  108.         print(f'Epoch [{epoch + 1}/{num_epochs}], d_loss: {d_loss.item():.4f}, g_loss: {g_loss.item():.4f}')
  109. # 可视化生成的图像
  110. with torch.no_grad():
  111.     z = torch.randn(64, latent_size).to(device)  # 随机噪声,移动到 GPU
  112.     fake_images = generator(z)
  113. # 显示生成的图像
  114. grid_img = fake_images.cpu().numpy()  # 移动到 CPU 以便绘图
  115. grid_img = grid_img.reshape(-1, 28, 28)
  116. plt.figure(figsize=(8, 8))
  117. for i in range(64):
  118.     plt.subplot(8, 8, i + 1)
  119.     plt.imshow(grid_img[i], cmap='gray')
  120.     plt.axis('off')
  121. plt.show()
复制代码

代码阐明


  • 自界说数据集:MNISTDataset 类用于从指定的路径加载 MNIST 数据。
  • 数据归一化:在 load_images 方法中,将图像数据归一化到 [0, 1] 范围。
  • 数据加载:使用 DataLoader 创建训练数据集的加载器。
  • GAN 模子:包罗天生器和辨别器的界说。
  • 训练过程:辨别器和天生器瓜代更新。
  • 可视化天生图像:训练竣事后天生并表现手写数字图像。
你可以运行这个代码,并观察天生的手写数字。确保 MNIST 数据集文件在指定的路径下。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表