文永亮作者华南理工大学学校目标检测、图像生成研究方向

LSGAN:最小二乘生成对抗网络

去几年发表于各大 AI 顶会论文提出的 400 多种算法中,公开算法代码的仅占 6%,其中三分之一的论文作者分享了测试数据,约 54% 的分享包含“伪代码”。这是今年 AAAI 会议上一个严峻的报告。 人工智能这个蓬勃发展的领域正面临着实验重现的危机,就像实验重现问题过去十年来一直困扰着心理学、医学以及其他领域一样。最根本的问题是研究人员通常不共享他们的源代码。 可验证的知识是科学的基础,它事关理解。随着人工智能领域的发展,打破不可复现性将是必要的。为此,PaperWeekly 联手百度 PaddlePaddle 共同发起了本次论文有奖复现,我们希望和来自学界、工业界的研究者一起接力,为 AI 行业带来良性循环。

笔者这次选择复现的是 Least Squares Generative Adversarial Networks,也就是LSGANs

近几年来 GAN 是十分火热的,由 Goodfellow 在 14 年发表论文 Generative Adversarial Nets [1] 开山之作以来,生成式对抗网络一直都备受机器学习领域的关注,这种两人零和博弈的思想十分有趣,充分体现了数学的美感。从 GAN 到 WGAN [2] 的优化,再到本文介绍的 LSGANs,再到最近很火的 BigGAN [3],可以说生成式对抗网络的魅力无穷,而且它的用处也是非常奇妙,如今还被用在例如无负样本的情况下如何训练分类器,例如 AnoGAN [4]。 

LSGANs 这篇经典的论文主要工作是交叉熵损失函数换做了最小二乘损失函数,这样做作者认为改善了传统 GAN 的两个问题,即传统 GAN 生成的图片质量不高,而且训练过程十分不稳定。

LSGANs 试图使用不同的距离度量来构建一个更加稳定而且收敛更快的,生成质量高的对抗网络。但是我看过 WGAN 的论文之后分析这一损失函数,其实并不符合 WGAN 作者的分析。在下面我会详细分析一下为什么 LSGANs 其实并没有那么好用。

论文复现代码: 

http://aistudio.baidu.com/aistudio/#/projectdetail/25767

LSGANs的优点

我们知道传统 GAN 生成的图片质量不高,传统的 GANs 使用的是交叉熵损失(sigmoid cross entropy)作为判别器的损失函数。 

在这里说一下我对交叉熵的理解,有两个分布,分别是真实分布 p 和非真实分布 q。

信息熵,就是按照真实分布 p 这样的样本空间表达能力强度的相反值,信息熵越大,不确定性越大,表达能力越弱,我们记作 H(p)。 交叉熵就是,可以理解为按照不真实分布 q 这样的样本空间表达能力强度的相反值,记作 H(p,q)。 

KL 散度就是 D(p||q) = H(p,q) - H(p),它表示的是两个分布的差异,因为真实分布 p 的信息熵固定,所以一般由交叉熵来决定,所以这就是为什么传统 GAN 会采用交叉熵的缘故,论文也证明了 GAN 损失函数与 KL 散度的关系。 

我们知道交叉熵一般都是拿来做逻辑分类的,而像最小二乘这种一般会用在线性回归中,这里为什么会用最小二乘作为损失函数的评判呢? 

使用交叉熵虽然会让我们分类正确,但是这样会导致那些在决策边界被分类为真的、但是仍然远离真实数据的假样本(即生成器生成的样本)不会继续迭代,因为它已经成功欺骗了判别器,更新生成器的时候就会发生梯度弥散的问题。 

论文指出最小二乘损失函数会对处于判别成真的那些远离决策边界的样本进行惩罚,把远离决策边界的假样本拖进决策边界,从而提高生成图片的质量。作者用下图详细表达了这一说法:

我们知道传统 GAN 的训练过程十分不稳定,这很大程度上是因为它的目标函数,尤其是在最小化目标函数时可能发生梯度弥散,使其很难再去更新生成器。而论文指出 LSGANs 可以解决这个问题,因为 LSGANs 会惩罚那些远离决策边界的样本,这些样本的梯度是梯度下降的决定方向。

论文指出因为传统 GAN 辨别器 D 使用的是 sigmoid 函数,并且由于 sigmoid 函数饱和得十分迅速,所以即使是十分小的数据点 x,该函数也会迅速忽略样本 x 到决策边界 w 的距离。这就意味着 sigmoid 函数本质上不会惩罚远离决策边界的样本,并且也说明我们满足于将 x 标注正确,因此辨别器 D 的梯度就会很快地下降到 0。

我们可以认为,交叉熵并不关心距离,而是仅仅关注于是否正确分类。正如论文作者在下图中所指出的那样,(a)图看到交叉熵损失很容易就达到饱和状态,而(b)图最小二乘损失只在一点达到饱和,作者认为这样训练会更加稳定。

LSGANs的损失函数

传统 GAN 的损失函数

LSGANs 的损失函数

其中 G 为生成器(Generator),D 为判别器(Discriminator),z 为噪音,它可以服从归一化或者高斯分布为真实数据 x 服从的概率分布,为 z 服从的概率分布。为期望值,同为期望值。

def generator(z, name="G"):
    with fluid.unique_name.guard(name+'_'):
        fc1 = fluid.layers.fc(input = z, size = 1024)
        fc1 = fluid.layers.fc(fc1, size = 128 * 7 * 7)
        fc1 = fluid.layers.batch_norm(fc1,act = 'tanh')
        fc1 = fluid.layers.reshape(fc1, shape=(-1, 128, 7, 7))


        conv1 = fluid.layers.conv2d(fc1, num_filters = 4*64,
                                    filter_size=5, stride=1, 
                                    padding=2, act='tanh')
        conv1 = fluid.layers.reshape(conv1, shape=(-1,64,14,14))

        conv2 = fluid.layers.conv2d(conv1, num_filters = 4*32, 
                                    filter_size=5, stride=1,
                                    padding=2, act='tanh')
        conv2 = fluid.layers.reshape(conv2, shape=(-1,32,28,28))

        conv3 = fluid.layers.conv2d(conv2, num_filters = 1, 
                                    filter_size=5, stride=1,
                                    padding=2,act='tanh')
#         conv3 = fluid.layers.reshape(conv3, shape=(-1,1,28,28))
        print("conv3",conv3)
        return conv3

▲ 生成器代码展示

def discriminator(image, name="D"):
    with fluid.unique_name.guard(name+'_'):
        conv1 = fluid.layers.conv2d(input=image, num_filters=32,
                                    filter_size=6, stride=2,
                                    padding=2)
        conv1_act = fluid.layers.leaky_relu(conv1)

        conv2 = fluid.layers.conv2d(conv1_act, num_filters=64, 
                                    filter_size=6, stride=2,
                                    padding=2)
        conv2 = fluid.layers.batch_norm(conv2)
        conv2_act = fluid.layers.leaky_relu(conv2)

        fc1 = fluid.layers.reshape(conv2_act, shape=(-1,64*7*7))
        fc1 = fluid.layers.fc(fc1, size=512)
        fc1_bn = fluid.layers.batch_norm(fc1)
        fc1_act = fluid.layers.leaky_relu(fc1_bn)

        fc2 = fluid.layers.fc(fc1_act, size=1)
        print("fc2",fc2)
        return fc2

▲ 判别器代码展示

作者提出了两种 abc 的取值方法: 

1. 使 b - c = 1,b - a = 2,例如 a = -1,b = 1,c = 0:

2. 使 c = b,用 0-1 二元标签,我们可以得到:

作者在文献中有详细推倒过程,详细说明了 LSGAN 与 f 散度之间的关系,这里简述一下。

通过对下式求一阶导可得到 D 的最优解:

代入:

其中另加项并不影响的值,因为它不包含参数 G。

最后我们设 b - c = 1,b - a =2 就可以得到:

其中就是皮尔森卡方散度。

LSGANs未能解决的地方

下面我会指出 LSGANs 给出的损失函数到底符不符合 WGAN 前作的理论。关于 WGAN 前作及 WGAN 论文的分析可以参考本文 [5]。

上面我们指出了 D 的最优解为公式(5),我们最常用的设 a=-1,b=1,c=0 可以得出:

把最优判别器带入上面加附加项的生成器损失函数可以表示为:

也就是优化上面说的皮尔森卡方散度,其实皮尔森卡方散度和 KL 散度、JS 散度有一样的问题,根据 WGAN 给出的理论,下面用 P1,P2 分别表示

当 P1 与 P2 的支撑集(support)是高维空间中的低维流形(manifold)时,P1 与 P2 重叠部分测度(measure)为 0 的概率为 1。也就是 P1 和 P2 不重叠或重叠部分可忽略的可能性非常大。

对于数据点 x,只可能发生如下四种情况:

1. P1(x)=0,P2(x)=0

2. P1(x)!=0,P2(x)!=0

3. P1(x)=0,P2(x)!=0

4. P1(x)!=0,P2(x)=0

可以想象成下面这幅图,假设 P1(x) 分布就是 AB 线段,P2(x) 分布就是 CD 线段,数据点要么在两条线段的其中一条,要么都不在,同时在两条线段上的可能性忽略不计。

情况 1 是没有意义的,而情况 2 由于重叠部分可忽略的可能性非常大所以对计算损失贡献为 0,情况 3 可以算出 D*=-1,损失是个定值 1,情况 4 类似。

所以我们可以得出结论,当 P1 和 P2 不重叠或重叠部分可忽略的可能性非常大时,当判别器达到最优时,生成器仍然是不迭代的,因为此时损失是定值,提供的梯度仍然为 0。同时我们也可以从另一个角度出发,WGAN 的 Wasserstein 距离可以变换如下:

它要求函数 f 要符合 Lipschitz 连续,可是最小二乘损失函数是不符合的,他的导数是没有上界的。所以结论就是 LSGANs 其实还是未能解决判别器足够优秀的时候,生成器还是会发生梯度弥散的问题。

两种模型架构和训练

模型的结构

作者也提出了两类架构:

第一种处理类别少的情况,例如 MNIST、LSUN。网络设计如下:

第二类处理类别特别多的情形,实际上是个条件版本的 LSGAN。针对手写汉字数据集,有 3740 类,提出的网络结构如下:

训练数据

论文中使用了很多场景的数据集,然后比较了传统 GANs 和 LSGANs 的稳定性,最后还通过训练 3740 个类别的手写汉字数据集来评价 LSGANs。

▲ 本文使用的数据集列表

在 LSUN 和 HWDB1.0 的这两个数据集上使用 LSGANs 的效果图如下,其中 LSUN 使用了里面的 bedroom, kitchen, church, dining room 和 conference room 五个场景,bedroom 场景还对比了 DCGANs 和 EBGANs 的效果在图 5 中,可以观察到 LSGANs 生成的效果要比那两种的效果好。

图 7 则体现了 LSGANs 和传统 GANs 生成的图片对比。

通过实验观察,作者发现 4 点技巧: 

1. 生成器 G 带有 batch normalization 批处理标准化(以下简称 BN)并且使用 Adam 优化器的话,LSGANs 生成的图片质量好,但是传统 GANs 从来没有成功学习到,会出现 mode collapse 现象;

2. 生成器 G 和判别器 D 都带有 BN 层,并且使用 RMSProp 优化器处理,LSGANs 会生成质量比 GANs 高的图片,并且 GANs 会出现轻微的 mode collapse 现象;

3. 生成器 G 带有 BN 层并且使用 RMSProp 优化器,生成器 G 判别器 D 都带有 BN 层并且使用 Adam 优化器时,LSGANs 与传统 GANs 有着相似的表现;

4. RMSProp 的表现比 Adam 要稳定,因为传统 GANs 在 G 带有 BN 层时,使用 RMSProp 优化可以成功学习,但是使用 Adam 优化却不行。

下面是使用 LSGANs 和 GANs 学习混合高斯分布的数据集,下图展现了生成数据分布的动态结果,可以看到传统 GAN 在 Step 15k 时就会发生 mode collapse 现象,但 LSGANs 非常成功地学习到了混合高斯分布

论文具体实现

笔者使用了 MNIST 数据集进行实验,具体实现效果如下:

LSGANs:

GAN:

从本次用 MNIST 数据训练的效果来看,LSGANs 生成的效果似乎是比 GAN 的要清晰高质量一些。

总结

LSGANs 是对 GAN 的一次优化,从实验的情况中,笔者也发现了一些奇怪的现象。我本来是参考论文把判别器 D 的损失值,按真假两种 loss 加起来一并放入 Adam 中优化,但是无论如何都学习不成功,梯度还是弥散了,最后把 D_fake_loss 和 D_real_loss 分为两个 program,放入不同的 Adam 中优化判别器D 的参数才达到预期效果。

这篇论文中的思想是非常值得借鉴的,从最小二乘的距离的角度考量,并不是判别器分类之后就完事了,但是 LSGANs 其实还是未能解决判别器足够优秀的时候,生成器梯度弥散的问题。

关于PaddlePaddle

笔者反馈:帮助文档有点少,而且我本来就直接写好了想改成使用 GPU 运算,没找到怎么改;

PaddlePaddle团队:关于如何使用 GPU 运行,可以看下执行器 Executor(单 GPU 或单线程 CPU 执行器)或 ParallelExecutor(多 GPU 或多线程 CPU 执行器,也可以单 GPU/线程 CPU 执行)的文档,前者指定 place 为 CUDAPlace,后者接口有个 use_cuda,具体请参考文档。也可以看 models repo 例子,比如 image_classification 或 text_classification 的例子。 

笔者反馈:Program 这个概念有点新颖,一个模型可以有多个 Program,但是我实现的 GAN 可以只用一个,也可以分别放进三个 Program,没有太了解到 Program 这个概念的优越之处,我还是像计算图那样使用了,官方也没给出与 TensorFlow 的对比。

PaddlePaddle团队:关于 Program 设计可以参考官方文档。这里提一点,在用户使用的直观感受中和 TensorFlow graph 不同的是,凡是放在一个 Program 里 op,只要运行该 Program,这些 op 就都会执行;而 TensorFlow,指定一个 variable,只运行以该 variable 为叶子节点的 graph,其他多余 node 不执行,这是最大的用户感受到的区别。 

至于一个 Program 还是多个 Program,看用户使用需求而定,多个 Program 时要注意的东西就比较多,例如是否要参数共享等,当然运行多次的时间代价也稍多。 如果是 GAN 也可以参考 models repo 的例子。

小道消息:听说全新版本的 PaddlePaddle 已于今日发布哦。

PaperWeekly
PaperWeekly

推荐、解读、讨论和报道人工智能前沿论文成果的学术平台。

理论LSGAN
31
相关数据
交叉熵技术

交叉熵(Cross Entropy)是Loss函数的一种(也称为损失函数或代价函数),用于描述模型预测值与真实值的差距大小

机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

高斯分布技术

正态分布是一个非常常见的连续概率分布。由于中心极限定理(Central Limit Theorem)的广泛应用,正态分布在统计学上非常重要。中心极限定理表明,由一组独立同分布,并且具有有限的数学期望和方差的随机变量X1,X2,X3,...Xn构成的平均随机变量Y近似的服从正态分布当n趋近于无穷。另外众多物理计量是由许多独立随机过程的和构成,因而往往也具有正态分布。

零和博弈技术

零和博弈,又称零和游戏或零和赛局,与非零和博弈相对,是博弈论的一个概念,属非合作博弈。零和博弈表示所有博弈方的利益之和为零或一个常数,即一方有所得,其他方必有所失。在零和博弈中,博弈各方是不合作的。非零和博弈表示在不同策略组合下各博弈方的得益之和是不确定的变量,故又称之为变和博弈。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

收敛技术

在数学,计算机科学和逻辑学中,收敛指的是不同的变换序列在有限的时间内达到一个结论(变换终止),并且得出的结论是独立于达到它的路径(他们是融合的)。 通俗来说,收敛通常是指在训练期间达到的一种状态,即经过一定次数的迭代之后,训练损失和验证损失在每次迭代中的变化都非常小或根本没有变化。也就是说,如果采用当前数据进行额外的训练将无法改进模型,模型即达到收敛状态。在深度学习中,损失值有时会在最终下降之前的多次迭代中保持不变或几乎保持不变,暂时形成收敛的假象。

损失函数技术

在数学优化,统计学,计量经济学,决策理论,机器学习和计算神经科学等领域,损失函数或成本函数是将一或多个变量的一个事件或值映射为可以直观地表示某种与之相关“成本”的实数的函数。

TensorFlow技术

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

张量技术

张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数,这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 维空间内,有 个分量的一种量,其中每个分量都是坐标的函数,而在坐标变换时,这些分量也依照某些规则作线性变换。称为该张量的秩或阶(与矩阵的秩和阶均无关系)。 在数学里,张量是一种几何实体,或者说广义上的“数量”。张量概念包括标量、矢量和线性算子。张量可以用坐标系统来表达,记作标量的数组,但它是定义为“不依赖于参照系的选择的”。张量在物理和工程学中很重要。例如在扩散张量成像中,表达器官对于水的在各个方向的微分透性的张量可以用来产生大脑的扫描图。工程上最重要的例子可能就是应力张量和应变张量了,它们都是二阶张量,对于一般线性材料他们之间的关系由一个四阶弹性张量来决定。

信息熵技术

在信息论中,熵是接收的每条消息中包含的信息的平均量,又被称为信息熵、信源熵、平均自信息量。这里,“消息”代表来自分布或数据流中的事件、样本或特征。熵的单位通常为比特,但也用Sh、nat、Hart计量,取决于定义用到对数的底。

线性回归技术

在现实世界中,存在着大量这样的情况:两个变量例如X和Y有一些依赖关系。由X可以部分地决定Y的值,但这种决定往往不很确切。常常用来说明这种依赖关系的最简单、直观的例子是体重与身高,用Y表示他的体重。众所周知,一般说来,当X大时,Y也倾向于大,但由X不能严格地决定Y。又如,城市生活用电量Y与气温X有很大的关系。在夏天气温很高或冬天气温很低时,由于室内空调、冰箱等家用电器的使用,可能用电就高,相反,在春秋季节气温不高也不低,用电量就可能少。但我们不能由气温X准确地决定用电量Y。类似的例子还很多,变量之间的这种关系称为“相关关系”,回归模型就是研究相关关系的一个有力工具。

梯度下降技术

梯度下降是用于查找函数最小值的一阶迭代优化算法。 要使用梯度下降找到函数的局部最小值,可以采用与当前点的函数梯度(或近似梯度)的负值成比例的步骤。 如果采取的步骤与梯度的正值成比例,则接近该函数的局部最大值,被称为梯度上升。

决策边界技术

在具有两类的统计分类问题中,决策边界或决策曲面是一个超曲面,它将底层的向量空间分成两组,每组一个。分类器会将决策边界一侧的所有点分为属于一个类,而另一侧属于另一个类。也即二元分类或多类别分类问题中,模型学到的类别之间的分界线。

逻辑技术

人工智能领域用逻辑来理解智能推理问题;它可以提供用于分析编程语言的技术,也可用作分析、表征知识或编程的工具。目前人们常用的逻辑分支有命题逻辑(Propositional Logic )以及一阶逻辑(FOL)等谓词逻辑。

噪音技术

噪音是一个随机误差或观测变量的方差。在拟合数据的过程中,我们常见的公式$y=f(x)+\epsilon$中$\epsilon$即为噪音。 数据通常包含噪音,错误,例外或不确定性,或者不完整。 错误和噪音可能会混淆数据挖掘过程,从而导致错误模式的衍生。去除噪音是数据挖掘(data mining)或知识发现(Knowledge Discovery in Database,KDD)的一个重要步骤。

目标函数技术

目标函数f(x)就是用设计变量来表示的所追求的目标形式,所以目标函数就是设计变量的函数,是一个标量。从工程意义讲,目标函数是系统的性能标准,比如,一个结构的最轻重量、最低造价、最合理形式;一件产品的最短生产时间、最小能量消耗;一个实验的最佳配方等等,建立目标函数的过程就是寻找设计变量与目标的关系的过程,目标函数和设计变量的关系可用曲线、曲面或超曲面表示。

卡方技术

卡方常常与卡方分布和卡方检验联系在一起: 卡方分布(chi-square distribution)是常用于概率论和统计检验中的一种概率分布;卡方检验是(chi-square test)是一种基于卡方分布的常用的统计检验,其统计量在原假设(null hypothesis)成立时服从卡方分布。

WGAN技术

就其本质而言,任何生成模型的目标都是让模型(习得地)的分布与真实数据之间的差异达到最小。然而,传统 GAN 中的判别器 D 并不会当模型与真实的分布重叠度不够时去提供足够的信息来估计这个差异度——这导致生成器得不到一个强有力的反馈信息(特别是在训练之初),此外生成器的稳定性也普遍不足。 Wasserstein GAN 在原来的基础之上添加了一些新的方法,让判别器 D 去拟合模型与真实分布之间的 Wasserstein 距离。Wassersterin 距离会大致估计出「调整一个分布去匹配另一个分布还需要多少工作」。此外,其定义的方式十分值得注意,它甚至可以适用于非重叠的分布。

优化器技术

优化器基类提供了计算梯度loss的方法,并可以将梯度应用于变量。优化器里包含了实现了经典的优化算法,如梯度下降和Adagrad。 优化器是提供了一个可以使用各种优化算法的接口,可以让用户直接调用一些经典的优化算法,如梯度下降法等等。优化器(optimizers)类的基类。这个类定义了在训练模型的时候添加一个操作的API。用户基本上不会直接使用这个类,但是你会用到他的子类比如GradientDescentOptimizer, AdagradOptimizer, MomentumOptimizer(tensorflow下的优化器包)等等这些算法。

推荐文章
请问这个模型在判别器网络的最后是没有使用任何非线性函数的吗? 直接把linear变换后的输出和标签的0和1算MSEloss???