AI-For-Beginners 课程精讲:生成对抗网络(GAN)从原理到实战 教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载生成对抗网络Generative Adversarial NetworkGAN是深度学习中最具代表性的生成模型架构之一。在《AI-For-Beginners》课程4-ComputerVision/10-GANs一课中你将系统理解 GAN 的对抗式训练思想、生成器与判别器的结构设计、训练两阶段流程、常见的训练失败模式并借助仓库内置的 TensorFlow/Keras 与 PyTorch 两份可运行 Notebook 亲手在 MNIST 上训练 GAN 与 DCGAN同时学习基于 CNN 特征与 Gram 矩阵的风格迁移技术。读完本文你将具备从零搭建并调优 GAN 的完整实战能力。为什么需要 GAN生成模型的意义瓶颈在前一节课程中我们学习了生成模型generative models这类模型能够生成与训练数据集相似的全新样本。变分自编码器VAE是生成模型的典型代表其结构可参阅仓库中的自动编码器课程。然而当我们试图用 VAE 生成真正有意义的内容例如一幅分辨率合理的画作时会发现训练难以收敛。原因在于纯基于重构误差的生成方式难以在低维潜空间与高维像素空间之间建立足够强的对应关系生成结果往往模糊、缺乏局部结构。这正是需要引入另一种面向生成任务专门设计的架构——**生成对抗网络GAN**的原因。GAN 的核心思想极其简洁而深刻同时训练两个相互博弈的神经网络让它们在一场持续的对抗中共同进步生成器Generator接收一个随机向量噪声将其映射为一张图像作为输出。判别器Discriminator接收一张图像判断它究竟是来自训练数据集的真实图像还是由生成器伪造的假图像。本质上判别器就是一个图像二分类器。本课内容基于 Dmitry Soshnikov 的课程设计。判别器Discriminator标准的图像分类器判别器的架构与普通图像分类网络并无本质区别。最简单的实现可以是全连接分类器但更常见、效果更好的实现是基于卷积网络的分类器。一个 CNN 判别器的典型层结构如下若干卷积 池化层空间尺寸逐层递减逐步提取从局部纹理到全局语义的特征一个或多个全连接层将高维特征图展平并压缩为特征向量最终的二元分类层输出该图像为真实图像的概率。✅ 这里所说的池化pooling是一种缩小图像尺寸的技术。池化层通过将某一层中一组神经元的输出合并到下一层的单个神经元来降低数据的维度。✅ 基于卷积网络的 GAN 被称为DCGANDeep Convolutional GAN其原始论文见 arXiv:1511.06434。本仓库的实践 Notebook 中也包含 DCGAN 的完整实现。在仓库的 Keras 版 NotebookGANTF.ipynb中判别器被实现为一个顺序模型输入 28×28 的图像经过Flatten展平后接两层Dense784 与 784//2均使用LeakyReLU最后通过sigmoid输出一个 0~1 之间的概率discriminator Sequential() discriminator.add(Flatten(input_shape(28,28))) discriminator.add(Dense(784)) discriminator.add(LeakyReLU(alpha0.2)) discriminator.add(Dense(784//2)) discriminator.add(LeakyReLU(alpha0.2)) discriminator.add(Dense(1, activationsigmoid)) discriminator.compile(lossbinary_crossentropy, optimizeroptimizer, metrics[accuracy])在 PyTorch 版 NotebookGANPyTorch.ipynb中判别器使用nn.Linear逐层压缩输入维度同样以LeakyReLU作为激活函数、Sigmoid输出二分类概率class Discriminator(nn.Module): def __init__(self): super().__init__() self.linear1 nn.Linear(784, 512) self.linear2 nn.Linear(512, 256) self.linear3 nn.Linear(256, 1) self.leaky_relu nn.LeakyReLU(0.2) self.sigmoid nn.Sigmoid() def forward(self, input): input input.view(input.shape[0], -1) hidden1 self.leaky_relu(self.linear1(input)) hidden2 self.leaky_relu(self.linear2(hidden1)) classififed self.sigmoid(self.linear3(hidden2)) return classififed生成器Generator被反转的判别器生成器要稍微复杂一些。你可以把它看作一个反向的判别器输入不再是特征向量而是潜向量latent vector——通常是从标准正态分布中采样得到的随机噪声首先通过一个全连接层将其转换为所需的大小/形状随后经过若干**反卷积 上采样deconvolution upscaling**操作逐步放大空间分辨率最终还原为图像。这一过程与自动编码器中的*解码器decoder*部分非常相似。✅ 由于卷积层本质上是一个在图像上滑动的线性滤波器反卷积在数学上可以看作卷积的转置操作因此可以用同一种层逻辑来实现。生成器中的三个实用技巧在仓库两份 Notebook 的生成器实现中反复出现了三个稳定训练的关键技巧使用 LeakyReLU 代替 ReLULeakyReLU 在输入为负时并非恒为 0而是乘以一个很小的斜率如alpha0.2。这保证了梯度即使在 ReLU 的死亡区负值区域也能继续传播对生成器的优化至关重要。使用批归一化BatchNormalization稳定各层输出的分布显著改善训练稳定性。最后一层使用tanh激活将输出压缩到[-1, 1]区间与将 MNIST 像素归一化到该区间的数据预处理方式相匹配。Keras 版生成器实现如下以 MNIST 为例generator Sequential() generator.add(Dense(256, input_shape(100,))) generator.add(LeakyReLU(alpha0.2)) generator.add(BatchNormalization(momentum0.8)) generator.add(Dense(512)) generator.add(LeakyReLU(alpha0.2)) generator.add(BatchNormalization(momentum0.8)) generator.add(Dense(1024)) generator.add(LeakyReLU(alpha0.2)) generator.add(BatchNormalization(momentum0.8)) generator.add(Dense(784, activationtanh)) generator.add(Reshape((28,28))) optimizer keras.optimizers.Adam(lr0.0002, decay8e-9) generator.compile(lossbinary_crossentropy, optimizeroptimizer, metrics[accuracy])PyTorch 版的生成器结构与之一一对应输出时通过.view(input.shape[0], 1, 28, 28)重塑为单通道图像张量class Generator(nn.Module): def __init__(self): super().__init__() self.linear1 nn.Linear(100, 256) self.bn1 nn.BatchNorm1d(256, momentum0.2) self.linear2 nn.Linear(256, 512) self.bn2 nn.BatchNorm1d(512, momentum0.2) self.linear3 nn.Linear(512, 1024) self.bn3 nn.BatchNorm1d(1024, momentum0.2) self.linear4 nn.Linear(1024, 784) self.tanh nn.Tanh() self.leaky_relu nn.LeakyReLU(0.2) def forward(self, input): hidden1 self.leaky_relu(self.bn1(self.linear1(input))) hidden2 self.leaky_relu(self.bn2(self.linear2(hidden1))) hidden3 self.leaky_relu(self.bn3(self.linear3(hidden2))) generated self.tanh(self.linear4(hidden3)).view(input.shape[0], 1, 28, 28) return generated训练 GAN两个阶段的军备竞赛GAN 之所以被称为**对抗性adversarial**网络是因为生成器与判别器之间存在持续的竞争判别器不断学习识破伪造图像生成器则不断学习制造更能骗过判别器的图像。在这种相互博弈中两个网络都在进步从而让生成器产出的图像质量螺旋上升。每次训练迭代分为两个阶段阶段一训练判别器。这个任务相对简单直接用生成器生成一批batch//2张假图像为其打上标签0表示假从输入数据集中取一批batch//2张真实图像打上标签1表示真将两类样本拼接后送入判别器计算**判别器损失discriminator loss**并执行反向传播。阶段二训练生成器。这一步稍显巧妙因为我们无法直接为生成器指定期望输出将整个 GAN 网络生成器 判别器串联视为一个整体向它输入一批随机向量并期望输出为1对应真实图像即骗过判别器冻结判别器的参数此阶段不希望判别器被更新执行反向传播只更新生成器的权重。在整个训练过程中生成器与判别器的损失都不会显著下降。理想情况下两者的损失应呈现振荡态势——这恰好对应两个网络在交替地提升各自的性能。Keras 版两阶段训练循环batch 32 for cnt in range(3000): # 阶段一训练判别器 random_index np.random.randint(0, len(X_train) - batch // 2) legit_images X_train[random_index : random_index batch // 2].reshape(batch // 2, 28, 28) gen_noise np.random.normal(0, 1, (batch // 2, 100)) syntetic_images generator.predict(gen_noise) x_combined_batch np.concatenate((legit_images, syntetic_images)) y_combined_batch np.concatenate((np.ones((batch // 2, 1)), np.zeros((batch // 2, 1)))) d_loss discriminator.train_on_batch(x_combined_batch, y_combined_batch) # 阶段二训练生成器经由判别器冻结的对抗网络 noise np.random.normal(0, 1, (batch, 100)) y_mislabled np.ones((batch, 1)) g_loss adversarial.train_on_batch(noise, y_mislabled)对应的对抗网络adversarial network由生成器后接判别器构成其中判别器被设置为不可训练discriminator.trainable False adversarial Sequential() adversarial.add(generator) adversarial.add(discriminator) adversarial.compile(lossbinary_crossentropy, optimizeroptimizer)PyTorch 版两阶段训练循环PyTorch 版的核心思想相同但实现方式更显式生成器损失为loss_fn(disc_preds, real_labels)判别器损失则由真实样本损失与伪造样本损失取平均得到for batch in train_dataloader: imgs, _ batch imgs imgs.to(device) # 生成器阶段期望伪造图像被判为真 gen.zero_grad() noise torch.FloatTensor(np.random.normal(0.0, 1.0, (imgs.shape[0], 100))).to(device) real_labels torch.ones((imgs.shape[0], 1)).to(device) fake_labels torch.zeros((imgs.shape[0], 1)).to(device) generated gen(noise) disc_preds disc(generated) g_loss loss_fn(disc_preds, real_labels) g_loss.backward() optim_gen.step() # 判别器阶段区分真实与伪造样本 disc.zero_grad() disc_real disc(imgs) disc_real_loss loss_fn(disc_real, real_labels) disc_fake disc(generated.detach()) disc_fake_loss loss_fn(disc_fake, fake_labels) d_loss (disc_real_loss disc_fake_loss) / 2.0 d_loss.backward() optim_disc.step()训练前需要按如下方式初始化模型与优化器PyTorch 示例lr 2e-4 weight_decay 8e-9 beta1 0.5 beta2 0.999 batch_size 256 epochs 100 generator Generator().to(device) discriminator Discriminator().to(device) optimizer_generator optim.Adam(generator.parameters(), lrlr, weight_decayweight_decay, betas(beta1, beta2)) optimizer_discriminator optim.Adam(discriminator.parameters(), lrlr, weight_decayweight_decay, betas(beta1, beta2)) loss_fn nn.BCELoss() 一个值得注意的细节MNIST 数据在送入 Keras 生成器之前需要通过(X_train.astype(np.float32) - 127.5) / 127.5归一化到[-1, 1]而在 PyTorch 版中使用transforms.Normalize(mean0.5, std0.5)达到同样目的从而与生成器输出端的tanh激活相匹配。DCGAN让卷积登场上述示例中生成器与判别器都采用了全连接网络。但我们知道处理图像时 CNN 往往表现更优。深度卷积生成对抗网络DCGAN与上述架构类似区别在于生成器和判别器都改用卷积层。DCGAN 生成器的主要难点在于它必须完成与传统 CNN相反的任务——从特征向量生成图像。某种意义上这类似于自动编码器的解码器部分因此我们在生成器中会使用Conv2DTransposeKeras或nn.ConvTranspose2dPyTorch层来实现上采样。PyTorch 版 DCGAN 生成器如下class DCGenerator(nn.Module): def __init__(self): super().__init__() self.conv1 nn.ConvTranspose2d(100, 256, kernel_size(3, 3), stride(2, 2), biasFalse) self.bn1 nn.BatchNorm2d(256) self.conv2 nn.ConvTranspose2d(256, 128, kernel_size(3, 3), stride(2, 2), biasFalse) self.bn2 nn.BatchNorm2d(128) self.conv3 nn.ConvTranspose2d(128, 64, kernel_size(3, 3), stride(2, 2), biasFalse) self.bn3 nn.BatchNorm2d(64) self.conv4 nn.ConvTranspose2d(64, 1, kernel_size(3, 3), stride(2, 2), padding(2, 2), output_padding(1, 1), biasFalse) self.tanh nn.Tanh() self.relu nn.ReLU() def forward(self, input): hidden1 self.relu(self.bn1(self.conv1(input))) hidden2 self.relu(self.bn2(self.conv2(hidden1))) hidden3 self.relu(self.bn3(self.conv3(hidden2))) generated self.tanh(self.conv4(hidden3)).view(input.shape[0], 1, 28, 28) return generatedDCGAN 判别器则与标准 CNN 分类器结构一致多层带步长的Conv2d卷积逐级压缩特征图配合LeakyReLU与BatchNorm2d最后经Sigmoid输出二分类结果。DCGAN 论文还给出了一个被广泛沿用的权重初始化方案仓库 Notebook 中亦有实现def weights_init(model): classname model.__class__.__name__ if classname.find(Conv) ! -1: nn.init.normal_(model.weight.data, 0.0, 0.02) elif classname.find(BatchNorm) ! -1: nn.init.normal_(model.weight.data, 1.0, 0.02) nn.init.constant_(model.bias.data, 0)进阶练习尝试使用 DCGAN 生成更复杂的彩色图像——例如取 CIFAR-10Keras或 PyTorch 版torchvision.datasets.CIFAR10数据集中的某一类进行训练观察彩色图像生成带来的新挑战。GAN 训练中公认的四大难题GAN 以尤其难训练而著称。本课总结了四个最常见的问题以及对应的调优策略1. 模式坍缩Mode Collapse指生成器偷懒地学会只生成一种能够骗过判别器的成功图像而不再产出多样化的样本。这是 GAN 训练中最著名的失败模式之一。2. 对超参数高度敏感经常可以看到 GAN 迟迟不收敛而一旦突然降低学习率训练便迅速收敛。这说明学习率等超参数对 GAN 的动力学影响极大需要谨慎选择。3. 生成器与判别器之间的平衡在许多情况下判别器损失会较快地降至 0导致生成器失去有效的梯度信号、无法继续训练。应对思路包括为生成器和判别器设置不同的学习率或者在判别器损失已经过低时跳过判别器的训练步骤。4. 高分辨率图像的训练这与自动编码器面临的同类问题一致卷积网络堆叠过多层之后重建过程会产生大量伪影artifacts。常用解法是渐进式增长progressive growing——先只在低分辨率图像上训练前几层随后逐步解锁或追加更多层。另一种思路是在层之间增加额外的连接并同时训练多个分辨率可参考 Multi-Scale Gradient GANs 论文。风格迁移Style TransferGAN 是生成艺术图像的绝佳工具但本课还介绍了另一项同样有趣的技术——风格迁移style transfer取一张内容图像content image应用来自另一张**风格图像style image**的滤镜将内容图像重新绘制成目标风格。其工作原理如下初始化从一张随机噪声图像开始也可以直接用内容图像初始化但从随机噪声出发更易于理解优化过程定义目标我们希望生成这样一张图像——它既与内容图像接近又与风格图像接近。这一目标由两个损失函数共同刻画内容损失content loss基于 CNN 在若干中间层上从当前图像与内容图像提取出的特征计算风格损失style loss以巧妙的方式利用Gram 矩阵Gram matrices在当前图像与风格图像之间计算更多细节见示例 Notebook。平滑约束为使图像更平滑、去除噪声还需要引入变化损失variation loss它计算相邻像素之间的平均距离优化循环主优化循环使用梯度下降或其他优化算法不断调整当前图像以最小化三个损失的加权和。仓库中提供了完整的风格迁移示例 Notebook以及 Keras 版 StyleTransfer_Keras.ipynb你可以直接运行并替换为自己的图片进行实验。小结与作业本课系统讲解了 GAN 的核心概念与训练方法生成器与判别器的角色与结构设计对抗式两阶段训练流程Keras 与 PyTorch 双版本实现DCGAN 的卷积化改造与权重初始化策略模式坍缩、超参数敏感、平衡性与高分辨率四大训练难题及应对方案基于内容损失、Gram 矩阵风格损失与变化损失三者加权组合的风格迁移方法。挑战使用你自己的图片运行风格迁移 Notebook观察不同内容与风格组合下的生成效果。作业重读本课附带的两个 GAN NotebookKeras 版与 PyTorch 版中的任意一个并在你自己的图像数据集上重新训练一个 GAN。看看你能创造出什么如果你想更深入学习可以继续阅读仓库中相关联的卷积网络课程与自动编码器课程它们为理解判别器的特征提取与生成器的解码结构提供了必要的前置知识。同时ImageNet 风格迁移与 GAN 相关的进阶 Notebook 可以作为风格迁移方向的延伸练习。赞分享教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载相关推荐AI-For-Beginners 实战解析从零理解生成对抗网络GAN的训练原理与实现AI For Beginners 实战解析从零理解生成对抗网络GAN的训练原理与实现 生成对抗网络Generative Adversarial Netw教程人工智能机器学习深度学习AI-For-Beginners 课程深度解析用 TensorFlow 与 PyTorch 构建生成对抗网络GAN与神经风格迁移AI For Beginners 课程深度解析用 TensorFlow 与 PyTorch 构建生成对抗网络GAN与神经风格迁移 本文是《AI For B教程人工智能机器学习深度学习生成对抗网络GAN原理与实现完整指南生成对抗网络GAN原理与实现完整指南 GitHub 加速计划 / ds / ds cheatsheets项目中的生成对抗网络GAN是一种强大的深度学习模型教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考