生成对抗网络(GAN)

        为什么生成器与判别器的交互可以产生人脸图 片。首先,我们需要了解训练的目标是什么。在训练网络时,我们要确定一个损失函数,然后 使梯度下降策略来调整网络参数,并使得设定的损失函数的数值最小或最大即可。生成器的输入是一系列的从分布中采样出的向量,生成器就会产生一个比较复杂 的分布,如图1所示,我们称之为PG。另外我们还有一系列的数据,这些原始的数据本身 会形成另外一个分布,我们称之为Pdata。训练的效果是希望PG 和Pdata 尽可能的相似。

图1 GAN 的训练目标

         我们再举一个一维的简单例子说明PG和Pdata,我们假设生成器的输入是一个一维的向 量,如图1的橙色曲线,生成器的输出也是一维的向量,如图1的绿色曲线,真正的数 据同样是一个一维的向量,它的分布用蓝色曲线来表示。假设每次我们输入5个点,那每一 个点的位置就会随着训练次数而改变,就会产生一个新的分布。可能本来所有的点都集中在 中间,但是通过生成器,通过一个网络里面很复杂的训练后,这些点就分成两边,变成图片中 的分布的样子。而其中Pdata 就是指真正数据的分布,在实际应用中真正数据分布可能是更极 端的,比如左边的数据比较多,右边的数据比较少。我们训练的结果是希望两个分布PG 和Pdata 越接近越好,即图片中的公式所示,表达的是这两个分布之间的差异,我们可以将其视 为两个分布间的某种距离,如果这个距离越大,就代表这两个分布越不像;差异越小,代表这 两个分布越相近。所以差异就是衡量两个的分布相似度的一个指标。我们现在的目标就是训 练一组生成器模型中的网络参数,可以让生成的PG和Pdata之间的差异越小越好,这个最优 生成器称为G∗。

训练生成器的过程训练例如卷积神经网络等简单网络非常地像,相比于之前的找一组参 数最小化损失函数,我们现在其实也定义了生成器的损失函数,即PG 和Pdata 之间的差异。 对于一般的神经网络,其损失函数是可以计算的,但是对于生成器的差异,我们应该怎么处理 呢?对于连续的差异例如KL散度和JS散度是很复杂的,在实际离散的数据中,我们或许无 法计算其对应的积分。

        对于GAN,只要我们知道怎样从PG 和Pdata 中采样,就可以计算得到差异,而不需要 知道实际的公式。例如,我们对于图库进行随机采样时,就会得到Pdata。对于生成器,我们 需要从正态分布中采样出来的向量通过生成器生成一系列的图片,这些图片就是PG 采样出 来的结果。所以我们有办法从PG采样,也可以从Pdata 进行采样。接下来,我们将介绍如何 只做以上采样的前提下,即不知道PG 和Pdata 的形式以及公式的情况下,如何估算得到差 异,这其中要依靠判别器的力量。

        我们首先回顾下判别器的训练方式。首先,我们有一系列的真实数据,也就是从Pdata采 样得到的数据。同时,还有一系列的生成数据,从PG中采样出来的数据。根据真实数据和生成数据,我们会去训练一个判别器,其训练目标是看到真实数据就给它比较高的分数,看到 生成的数据就给它比较低的分数。我们可以把它当做是一个优化问题,具体来说,我们要训 练一个判别器,其可以最大化一个目标函数,当然如果我们最小化它就可以称它为损失函数。 这个目标函数如图8.16所示,其中有一些 y 是从 Pdata 中采样得到的,也就是真实的数据, 而我们把这个真正的数据输入到判别器中,得到一个分数。另一方面,我们还有一些y来源 于生成器,即从PG中采样出来的,将这些生成图片输入至判别器中同样得到一个分数,再取 Log(1 −D(Y))。

        我们希望目标函数V 越大越好,其中y如果是从Pdata 中采样得到的真实数据,它就要 越大越好;如果是从PG 采样得到的生成数据,它就要越小越好。这个过程在GAN提出之 初,人们将其写为这样其实还有一个缘由,就是为了让判别器和二分类产生联系,因为这个 目标函数本身就是一个交叉熵乘上一个负号。训练一个分类器时的操作就是要最小化交叉熵, 所以当我们最大化目标函数的时候,其实等同于最小化交叉熵,也就是等同于是在训练一个 分类器。这个它做的事情就是把图2中蓝色点,从Pdata 采样出的真实数据当作类别1,把 从PG 采样出的这些假的数据当作类别2。有两个类别的数据,训练一个二分类的分类器,训 练后就等同于是解了这个优化问题。而图中红框里面的数值,它本身就和JS散度有关。或许 最原始的GAN 的文章,它的出发点是从二分类开始的,一开始是把判别器写成二分类的分 类器然后有了这样的目标函数,然后再经过一番推导后发现这个目标函数的最大值和JS散度 是相关的。

图2 GAN 中判别器目标函数和优化过程 

        当然我们还是要直观理解下为什么目标函数的值会和散度有关。这里我们假设 PG 和 Pdata 的差距很小,就如图8.16 所示蓝色的星星和红色的星星混在一起。这里,判别器就是在 训练一个0、1 分类的分类器,但是因为这两组数据差距很小,所以在解决这个优化问题时, 就很难让目标函数V 达到最大值。但是当两组数据差距很大时,也就是蓝色的星星和红色的 星星并没有混在一起,那么就可以轻易地把它们分开。当判别器可以轻易把它们分开的时候, 目标的函数就可以变得很大。所以当两组数据差距很大的时候,目标函数的最大值就可以很 大。当然这里面有很多的假设,例如判别器的分类能力无穷大。

        我们再来看下计算生成器+判别器的过程,我们的目标是要找一个生成器去最小化两个 分布PG 和Pdata 的差异。这个差异就是使用训练好的判别器来最大化它的目标函数值来实 现。最小和最大的MinMax过程就像是生成器和判别器进行互动,互相“欺骗”的过程。注意, 这里的差异函数不一定使用KL或者JS等函数,可以尝试不同的函数来得到不同差异衡量指标。 

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成对抗网络(Generative Adversarial Networks, GANs)是由Ian Goodfellow等人在2014年提出的深度学习模型架构[^4]。GAN由两个主要组成部分组成:生成器(Generator)和判别器(Discriminator)。它们通过一种零和博弈的方式相互作用。 **生成器**:尝试学习从随机噪声(通常是高斯分布)中生成与训练数据相似的新样本。它的目标是尽可能地欺骗判别器,使其误认为生成的数据是真实的。 **判别器**:负责区分真实数据和生成的数据。它试图准确地判断输入是来自训练数据还是生成器。 GAN的工作流程如下: 1. **训练过程**:生成器接收随机噪声作为输入并生成假样本,判别器则对这些样本进行分类,判断是真样本还是假样本。生成器根据判别器的反馈更新参数以提高生成能力,判别器也相应地调整其参数以提高识别能力。 2. **对抗迭代**:这两个模型交替优化,直到达到平衡状态,即生成器可以生成足够逼真的样本,使得判别器无法准确区分开来。 **示例代码**(简化版): ```python import torch.nn as nn # 假设我们有简单的生成器和判别器结构 class Generator(nn.Module): def __init__(self): super(Generator, self).__init__() # ... def forward(self, noise): # 生成器的前向传播 pass class Discriminator(nn.Module): def __init__(self): super(Discriminator, self).__init__() # ... def forward(self, input): # 判别器的前向传播 pass # 初始化并训练GAN generator = Generator() discriminator = Discriminator() for _ in range(num_epochs): fake_data = generator(noise) real_labels = torch.ones(batch_size) fake_labels = torch.zeros(batch_size) discriminator.zero_grad() d_loss_real = discriminator(real_data).mean() d_loss_fake = discriminator(fake_data.detach()).mean() d_loss = (d_loss_real + d_loss_fake).backward() discriminator_optimizer.step() generator.zero_grad() g_loss = discriminator(generator(noise)).mean().backward() generator_optimizer.step() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值