对抗学习原理与代码实战详解
背景介绍
对抗学习是近年来机器学习领域备受关注的新范式。它的出现源于对传统监督学习和无监督学习的补充,以及对生成模型日益增长的需求。对抗学习的核心思想是通过两个模型的相互博弈,迫使生成模型不断进化,最终生成逼真的数据。
自 2014 年 Goodfellow 等人提出生成对抗网络(GAN)以来,该技术已在图像生成、编辑、文本合成及强化学习等多个方向取得显著成果。尽管应用广泛,其理论完备性仍有提升空间,训练稳定性等问题也是当前研究的重点。
核心原理
对抗学习的基本架构包含两个部分:生成器(Generator)和判别器(Discriminator)。
- 生成器:负责从随机噪声中合成数据,目标是欺骗判别器。
- 判别器:负责区分真实数据和生成数据,目标是尽可能准确分类。
两者在训练中形成一种零和博弈关系。生成器试图最小化判别器的判断准确率,而判别器则试图最大化这一准确率。这种动态平衡推动双方性能共同提升。
数学上,这通常被建模为一个极小极大问题(Min-Max Game):
$$\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)))]$$
其中 $D$ 是判别器,$G$ 是生成器,$x$ 是真实样本,$z$ 是噪声输入。
代码实战
下面以 PyTorch 为例,展示一个简化的 GAN 实现框架。这里不依赖特定数据集,重点在于理解训练循环的逻辑。
import torch
import torch.nn as nn
import torch.optim as optim
# 定义生成器
class Generator(nn.Module):
def __init__(self, z_dim, out_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(z_dim, 256),
nn.ReLU(),
nn.Linear(256, 512),
nn.ReLU(),
nn.Linear(512, out_dim),
nn.Tanh() # 输出范围归一化
)
def forward(self, x):
return self.net(x)
# 定义判别器
class Discriminator(nn.Module):
def __init__():
().__init__()
.net = nn.Sequential(
nn.Linear(in_dim, ),
nn.LeakyReLU(),
nn.Linear(, ),
nn.LeakyReLU(),
nn.Linear(, ),
nn.Sigmoid()
)
():
.net(x)
z_dim =
img_dim =
G = Generator(z_dim, img_dim)
D = Discriminator(img_dim)
optimizer_G = optim.Adam(G.parameters(), lr=)
optimizer_D = optim.Adam(D.parameters(), lr=)
criterion = nn.BCELoss()
epoch (num_epochs):
real_imgs, _ dataloader:
batch_size = real_imgs.size()
optimizer_D.zero_grad()
labels = torch.ones(batch_size, )
noise = torch.randn(batch_size, z_dim)
outputs_real = D(real_imgs)
loss_real = criterion(outputs_real, labels)
fake_imgs = G(noise).detach()
labels_fake = torch.zeros(batch_size, )
outputs_fake = D(fake_imgs)
loss_fake = criterion(outputs_fake, labels_fake)
loss_D = (loss_real + loss_fake) /
loss_D.backward()
optimizer_D.step()
optimizer_G.zero_grad()
labels_gen = torch.ones(batch_size, )
outputs_gen = D(G(noise))
loss_G = criterion(outputs_gen, labels_gen)
loss_G.backward()
optimizer_G.step()

