深度卷积生成对抗网络(DCGAN)是GAN在图像生成领域的里程碑式改进。我第一次接触这个概念时,被它用卷积网络替代传统多层感知机的设计惊艳到了。简单来说,DCGAN就像两个互相较劲的艺术家:生成器(Generator)负责伪造名画,判别器(Discriminator)则扮演鉴定专家。两者通过对抗训练不断提升技艺,最终生成器能产出以假乱真的作品。
传统GAN的痛点在于生成图像质量差、训练不稳定。DCGAN通过四项关键技术解决这些问题:
实际项目中我验证过,加入这些改进后,MNIST生成效果提升显著。比如批归一化能让训练收敛速度加快约40%,而LeakyReLU的负斜率设为0.2时,判别器的稳定性最好。
搭建环境就像准备画家的颜料和画布。推荐使用conda创建虚拟环境:
bash复制conda create -n dcgan python=3.8
conda install pytorch torchvision -c pytorch
处理MNIST数据时要注意三个细节:
python复制transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)) # [-1,1]范围
])
dataset = datasets.MNIST('data', train=True, download=True, transform=transform)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=64, shuffle=True)
我曾遇到过显存不足的问题,解决方法有:
生成器的本质是反卷积的艺术。想象你有一张模糊的底片(随机噪声),通过多层反卷积逐渐还原出清晰图像。这里分享几个实战经验:
核心结构设计:
python复制class Generator(nn.Module):
def __init__(self, latent_dim=100, img_channels=1):
super().__init__()
self.main = nn.Sequential(
# 输入: latent_dim x 1 x 1
nn.ConvTranspose2d(latent_dim, 256, 4, 1, 0, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(True),
# 输出: 256 x 4 x 4
nn.ConvTranspose2d(256, 128, 3, 2, 1, bias=False),
nn.BatchNorm2d(128),
nn.ReLU(True),
# 128 x 7 x 7
nn.ConvTranspose2d(128, 64, 4, 2, 1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(True),
# 64 x 14 x 14
nn.ConvTranspose2d(64, img_channels, 4, 2, 1, bias=False),
nn.Tanh()
# 1 x 28 x 28
)
关键参数选择:
调试时发现,当隐变量维度小于50时生成质量明显下降。建议使用100-200维的噪声输入,这样能提供足够的创作空间。
判别器就像个火眼金睛的鉴宝专家,需要做到:
经典结构实现:
python复制class Discriminator(nn.Module):
def __init__(self, img_channels=1):
super().__init__()
self.main = nn.Sequential(
# 输入: 1 x 28 x 28
nn.Conv2d(img_channels, 64, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
# 64 x 14 x 14
nn.Conv2d(64, 128, 4, 2, 1, bias=False),
nn.BatchNorm2d(128),
nn.LeakyReLU(0.2, inplace=True),
# 128 x 7 x 7
nn.Conv2d(128, 256, 3, 2, 1, bias=False),
nn.BatchNorm2d(256),
nn.LeakyReLU(0.2, inplace=True),
# 256 x 4 x 4
nn.Conv2d(256, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
常见问题解决方案:
实测发现,在判别器的每个卷积层后添加谱归一化(spectral norm)能显著提升训练稳定性。
训练DCGAN就像调教两个互相竞争的运动员,需要平衡两者的进步速度。完整训练流程包含三个关键阶段:
1. 损失函数配置
python复制criterion = nn.BCELoss()
real_label = 0.9 # 标签平滑
fake_label = 0.1
# 优化器设置
d_optimizer = torch.optim.Adam(D.parameters(), lr=0.0002, betas=(0.5, 0.999))
g_optimizer = torch.optim.Adam(G.parameters(), lr=0.0002, betas=(0.5, 0.999))
2. 单轮训练步骤
python复制# 判别器训练
D.zero_grad()
real_images = batch[0].to(device)
batch_size = real_images.size(0)
labels = torch.full((batch_size,), real_label, device=device)
output = D(real_images)
errD_real = criterion(output, labels)
errD_real.backward()
# 生成假图像
noise = torch.randn(batch_size, latent_dim, 1, 1, device=device)
fake_images = G(noise)
labels.fill_(fake_label)
output = D(fake_images.detach())
errD_fake = criterion(output, labels)
errD_fake.backward()
errD = errD_real + errD_fake
d_optimizer.step()
# 生成器训练
G.zero_grad()
labels.fill_(real_label)
output = D(fake_images)
errG = criterion(output, labels)
errG.backward()
g_optimizer.step()
3. 训练监控技巧
在Colab上实测,使用T4 GPU训练约20分钟(100轮)就能看到清晰的数字生成。如果发现生成图像模糊,可以尝试:
评估生成质量不能只看损失曲线,我常用的三种方法:
定性评估
python复制with torch.no_grad():
test_noise = torch.randn(16, latent_dim, 1, 1, device=device)
generated = G(test_noise)
grid = torchvision.utils.make_grid(generated, nrow=4, normalize=True)
plt.imshow(grid.permute(1, 2, 0).cpu())
定量指标
调优技巧:
在MNIST上,好的DCGAN模型应达到:
掌握基础DCGAN后,可以尝试这些进阶方向:
架构改进
应用场景
部署时要注意:
有个实用技巧:在生成器最后一层前加入自适应实例归一化(AdaIN),可以轻松实现风格控制。我曾用这个方法在服装设计项目中,通过调节噪声向量的不同维度来控制衣服的款式和颜色。