生成对抗网络_生成对抗网络代码 - CSDN
生成对抗网络 订阅
生成式对抗网络(GAN, Generative Adversarial Networks )是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。原始 GAN 理论中,并不要求 G 和 D 都是神经网络,只需要是能拟合相应生成和判别的函数即可。但实用中一般均使用深度神经网络作为 G 和 D 。一个优秀的GAN应用需要有良好的训练方法,否则可能由于神经网络模型的自由性而导致输出不理想。 展开全文
生成式对抗网络(GAN, Generative Adversarial Networks )是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。原始 GAN 理论中,并不要求 G 和 D 都是神经网络,只需要是能拟合相应生成和判别的函数即可。但实用中一般均使用深度神经网络作为 G 和 D 。一个优秀的GAN应用需要有良好的训练方法,否则可能由于神经网络模型的自由性而导致输出不理想。
信息
属    于
无监督学习方法
简    称
GAN
构    成
生成模型和判别模型
中文名
生成式对抗网络
外文名
Generative Adversarial Networks
领    域
机器学习 / 深度学习
Gan发展历史
Ian J. Goodfellow等人于2014年10月在Generative Adversarial Networks中提出了一个通过对抗过程估计生成模型的新框架。框架中同时训练两个模型:捕获数据分布的生成模型G,和估计样本来自训练数据的概率的判别模型D。G的训练程序是将D错误的概率最大化。这个框架对应一个最大值集下限的双方对抗游戏。可以证明在任意函数G和D的空间中,存在唯一的解决方案,使得G重现训练数据分布,而D=0.5。在G和D由多层感知器定义的情况下,整个系统可以用反向传播进行训练。在训练或生成样本期间,不需要任何马尔科夫链或展开的近似推理网络。实验通过对生成的样品的定性和定量评估证明了本框架的潜力 [1]  。
收起全文
精华内容
参与话题
  • 生成对抗网络(GAN)简单梳理

    万次阅读 多人点赞 2017-09-25 09:45:14
    关于生成对抗网络的第一篇论文是Generative Adversarial Networks 0 前言GAN(Generative Adversarial Nets)是用对抗方法来生成数据的一种模型。和其他机器学习模型相比,GAN引人注目的地方在于给机器学习引入了对抗...

    作者:xg123321123 - 时光杂货店

    出处:http://blog.csdn.net/xg123321123/article/details/78034859

    声明:版权所有,转载请联系作者并注明出处

    网上已经贴满了关于GAN的博客,写这篇帖子只是梳理下思路,以便以后查阅。
    关于生成对抗网络的第一篇论文是Generative Adversarial Networks

    0 前言

    GAN(Generative Adversarial Nets)是用对抗方法来生成数据的一种模型。和其他机器学习模型相比,GAN引人注目的地方在于给机器学习引入了对抗这一理念。

    回溯地球生物的进化路线就会发现,万物都是在不停的和其他事物对抗中成长和发展的。
    生成对抗网络就像我们玩格斗游戏一样:学习过程就是不断找其他对手对抗,在对抗中积累经验,提升自己的技能。

    这里写图片描述

    GAN 是生成模型的一种,生成模型就是用机器学习去生成我们想要的数据,正规的说法是,获取训练样本并训练一个模型,该模型能按照我们定义的目标数据分布去生成数据。

    比如autoencoder自编码器,它的decoding部分其实就是一种生成模型,它是在生成原数据。又比如seq2seq序列到序列模型,其实也是生成另一个我们想要的序列。Neural style transfer的目标其实也是生成图片。

    这里写图片描述

    上图涵盖了基本的生成式模型的方法,主要按是否需要定义概率密度函数分为:

    • Explicit density models
      这之中又分为tractable explicit models和approximate explicit model,tractable explicit model通常可以直接通过数学方法来建模求解,而approximate explicit model通常无法直接对数据分布进行建模,可以利用数学里的一些近似方法来做数据建模, 通常基于approximate explicit model分为确定性(变分方法:如VAE的lower bound)和随机性的方法(马尔科夫链蒙特卡洛方法, MCMC)。

    • Implicit density models
      无需定义明确的概率密度函数,代表方法包括马尔科夫链、生成对抗式网络,该系列方法无需定义数据分布的描述函数。

    • GAN能够有效地解决很多生成式方法的缺点,主要包括:

      • 并行产生samples;
      • 生成式函数的限制少,比如无需合适马尔科夫采样的数据分布(Boltzmann machines),生成式函数无需可逆、latent code无需与sample同维度(nonlinear ICA);
      • 无需马尔科夫链的方法(Boltzmann machines, GSNs);
      • 相对于VAE的方法,无需variational bound;
      • GAN比其他方法一般来说性能更好。

    1 基本思想

    GAN 的核心思想源于博弈论的纳什均衡。

    设定参与游戏的双方分别为一个生成器(Generator)和一个判别器(Discriminator), 生成器捕捉真实数据样本的潜在分布, 并生成新的数据样本; 判别器是一个二分类器, 判别输入是真实数据还是生成的样本。
    为了取得游戏胜利, 这两个游戏参与者需要不断优化, 各自提高自己的生成能力和判别能力, 这个学习优化过程就是寻找二者之间的一个纳什均衡。

    GAN是一种二人零和博弈思想(two-player game),博弈双方的利益之和是一个常数。

    这里写图片描述

    GAN的计算流程与结构如上图所示。

    其中的生成器和判别器可以用任意可微分的函数, 这里我们用可微分函数D 和G 来分别表示判别器和生成器, 它们的输入分别为真实数据x 和随机变量z。
    G(z) 为由G 生成的尽量服从真实数据分布pdata的样本。
    如果判别器的输入来自真实数据, 标注为1.如果输入样本为G(z), 标注为0。

    这里D 的目标是实现对数据来源的二分类判别: 真(来源于真实数据x 的分布) 或者伪(来源于生成器的伪数据G(z))。
    而G 的目标是使自己生成的伪数据G(z) 在D 上的表现D(G(z)) 和真实数据x 在D 上的表现D(x)一致。

    这是一个图片栗子:

    这里写图片描述

    生成器和判别器都采用神经网络。

    这个栗子中,我们有的只是真实采集而来的人脸样本数据集,值得一提的是我们连人脸数据集的类标签都没有,也就是我们不知道那个人脸对应的是谁。

    最原始的GAN目的是想通过输入一个噪声,模拟得到一个人脸图像,这个图像可以非常逼真以至于以假乱真。(不同的任务想得到的东西不一样)

    上图右半部分的判别模型,是一个简单的神经网络结构,输入一幅图像,输出是一个概率值,用于判断真假使用(概率值大于0.5那就是真,小于0.5那就是假,人们定义的概率)
    左半部分的生成模型也是神经网络结构,输入是一组随机数Z,输出是一个图像,不再是一个数值。

    从图中可以看到,会存在两个数据集,一个是真实数据集,另一个是假的数据集,由生成网络生成的数据集。

    判别模型的目的:能判别出来属于的一张图它是来自真实样本集还是假样本集。假如输入的是真样本,网络输出就接近1,输入的是假样本,网络输出接近0。
    生成网络的目的:使得自己生成样本的能力尽可能强,强到判别网络没法判断自己生成的样本是真还是假。

    由此可见,生成模型与判别模型的目的正好相反,一个说我能判别得好,一个说我让你判别不好,所以叫做对抗,叫做博弈。

    而最后的结果到底是谁赢,就要归结于模型设计者希望谁赢了。作为设计者的我们,如果是要得到以假乱真的样本,那么就希望生成模型赢,希望生成的样本很真,判别模型能力不足以区分真假样本。

    2 训练过程

    • 在噪声数据分布中随机采样,输入生成模型,得到一组假数据,记为D(z)
    • 在真实数据分布中随机采样,作为真实数据,记做x
    • 将前两步中某一步产生的数据作为判别网络的输入(因此判别模型的输入为两类数据,真/假),判别网络的输出值为该输入属于真实数据的概率,real为1,fake为0.
    • 然后根据得到的概率值计算损失函数;
    • 根据判别模型和生成模型的损失函数,可以利用反向传播算法,更新模型的参数。(先更新判别模型的参数,然后通过再采样得到的噪声数据更新生成器的参数)

    这里写图片描述

    还是以前面那张图为栗子:

    这里写图片描述

    这里需要注意的是:生成模型与对抗模型是完全独立的两个模型,他们之间没有什么联系。那么训练采用的大原则是单独交替迭代训练

    因为是2个网络,不方便一起训练,所以才交替迭代训练。

    • 先是判别网络:

      • 假设现在有了生成网络(当然可能不是最好的),那么给一堆随机数组,就会得到一堆假的样本集(因为不是最终的生成模型,现在生成网络可能处于劣势,导致生成的样本不太好,很容易就被判别网络判别为假)。

      • 现在有了这个假样本集(真样本集一直都有),我们再人为地定义真假样本集的标签,很明显,这里我们默认真样本集的类标签为1,而假样本集的类标签为0,因为我们希望真样本集的输出尽可能为1,假样本集为0。

      • 现在有了真样本集以及它们的label(都是1)、假样本集以及它们的label(都是0)。这样一来,单就判别网络来说,问题变成了有监督的二分类问题了,直接送进神经网络中训练就好。

      • 判别网络训练完了。

    • 继续来看生成网络:

      • 对于生成网络,我们的目的是生成尽可能逼真的样本。

      • 而原始的生成网络生成的样本的真实程度只能通过判别网络才知道,所以在训练生成网络时,需要联合判别网络才能达到训练的目的。

      • 所以生成网络的训练其实是对生成-判别网络串接的训练,像上图显示的那样。因为如果只使用生成网络,那么无法得到误差,也就无法训练。

      • 当通过原始的噪声数组Z生成了假样本后,把这些假样本的标签都设置为1,即认为这些假样本在生成网络训练的时候是真样本。因为此时是通过判别器来生成误差的,而误差回传的目的是使得生成器生成的假样本逐渐逼近为真样本(当假样本不真实,标签却为1时,判别器给出的误差会很大,这就迫使生成器进行很大的调整;反之,当假样本足够真实,标签为1时,判别器给出的误差就会减小,这就完成了假样本向真样本逐渐逼近的过程),起到迷惑判别器的目的。

      • 现在对于生成网络的训练,有了样本集(只有假样本集,没有真样本集),有了对应的label(全为1),有了误差,就可以开始训练了。

      • 在训练这个串接网络时,一个很重要的操作是固定判别网络的参数,不让判别网络参数更新,只是让判别网络将误差传到生成网络,更新生成网络的参数。
    • 在生成网络训练完后,可以根据用新的生成网络对先前的噪声Z生成新的假样本了,不出意外,这次生成的假样本会更真实。

    • 有了新的真假样本集(其实是新的假样本集),就又可以重复上述过程了。

    • 整个过程就叫单独交替训练。可以定义一个迭代次数,交替迭代到一定次数后停止即可。不出意外,这时噪声Z生成的假样本就会很真实了。

    GAN设计的巧妙处之一,在于假样本在训练过程中的真假变换,这也是博弈得以进行的关键之处。

    3 目标函数

    上面提到,我们想要将一个随机高斯噪声z通过一个生成网络G得到一个和真的数据分布Pdata(x)差不多的生成分布PG(x;θ),其中的参数θ是网络的参数决定的,我们希望找到 θ 使得 PG(x;θ)Pdata(x) 尽可能接近。

    我们从真实数据分布 Pdata(x) 中取样m个点,x1,x2,,xm ,根据给定的参数 θ 我们可以计算如下的概率 PG(xi;θ) ,那么生成这m个样本数据的似然(likelihood)就是

    L=i=1mPG(xi;θ)

    我们要做的就是找到 θ^∗ 来最大化这个似然估计(关于最大似然估计,可见我这篇博客)

    θ=arg maxθi=1mpG(xi;θ)arg maxθlogi=1mPG(xi;θ)

    =arg maxθimlogPG(xi;θ)

    arg maxθExPdata[logPG(x;θ)]

    arg maxθxPdata(x)logPG(x;θ)dxxPdata(x)logPdata(x)dx

    这里多减去 xPdata(x)logPdata(x)dx没有影响,因为这相当于一个常数

    =arg maxθxPdata(x)logPG(x;θ)Pdata(x)dx

    =arg minθKL(Pdata(x)||PG(x;θ))

    这里在前面添加一个负号,将log里面的分数倒一下,就变成了KL divergence(关于KL散度,可见我这篇博客)

    PG(x;θ)该如何计算?

    PG(x)=zPprior(z)I[G(z)=x]dz

    里面的I表示示性函数,也就是

    IG(z)={01G(z)xG(z)=x

    尽管这样我们根本没办法求出这个 PG(x),但这就是生成模型的基本想法。

    进一步地

    G是生成器,给定先验分布 Pprior(z), 我们希望得到的生成分布是 Pz(z),这里很难通过极大似然估计得到结果;
    D是一个函数,可以衡量 Pz(z)Pdata(x) 之间的差距,被用来取代极大似然估计;

    定义函数V(G, D)如下:

    V(D,G)=ExPdata(x)[logD(X)]+EzPz(z)[log(1D(G(z)))]

    我们可以通过下面的式子求得最优的生成模型

    G=arg minGmaxDV(D,G)

    下面是论文中的目标函数:

    minGmaxDV(D,G)=ExPdata(x)[logD(X)]+EzPz(z)[log(1D(G(z)))]

    这是一个最大最小优化问题,先优化D,然后再优化G,本质上是两个优化问题,拆解后得到下面两个公式:

    优化D:

    maxDV(D,G)=Expdata(x)[log(D(x))]+Ezpz(z)[log(1D(G(z)))]

    优化G:

    minGV(D,G)=Ezpz(z)[log(1D(G(z)))]

    优化D(判别网络)时,不关生成网络的事,后面的G(z)相当于已经得到的假样本。优化D的公式的第一项,使的真样本x输入时,得到的结果越大越好,因为需要真样本的预测结果越接近于1越好。对于假样本,需要优化使其结果越小越好,也就是D(G(z))越小越好,因为它的标签为0。但是第一项越大,第二项就越小,这就矛盾了,所以把第二项改成1-D(G(z)),这样就是越大越好,两者合起来就是越大越好。

    优化G(生成网络)时,不关真样本的事,所以把第一项直接去掉,只剩下假样本,这时希望假样本的标签是1,所以D(G(z))越大越好,但为了统一成1-D(G(z))的形式,就变成最小化1-D(G(z)),本质上没有区别,只是为了形式的统一。

    这两个优化模型合并起来,就成了上面的最大最小目标函数了,里面既包含了判别模型的优化,同时也包含了生成模型的以假乱真的优化。

    4 探讨

    GAN强大之处在于能自动学习原始真实样本集的数据分布,不管这个分布多么的复杂,只要训练的足够好就可以学出来。

    传统的机器学习方法,一般会先定义一个模型,再让数据去学习。
    比如知道原始数据属于高斯分布,但不知道高斯分布的参数,这时定义高斯分布,然后利用数据去学习高斯分布的参数,得到最终的模型。
    再比如定义一个分类器(如SVM),然后强行让数据进行各种高维映射,最后变成一个简单的分布,SVM可以很轻易的进行二分类(虽然SVM放松了这种映射关系,但也给了一个模型,即核映射),其实也是事先知道让数据该如何映射,只是映射的参数可以学习。
    以上这些方法都在直接或间接的告诉数据该如何映射,只是不同的映射方法能力不一样。

    而GAN的生成模型最后可以通过噪声生成一个完整的真实数据(比如人脸),说明生成模型掌握了从随机噪声到人脸数据的分布规律。GAN一开始并不知道这个规律是什么样,也就是说GAN是通过一次次训练后学习到的真实样本集的数据分布。

    拿原论文中的一张图来解释:

    这里写图片描述

    上图表明的是GAN的生成网络如何一步步从均匀分布学习到正太分布的。

    黑色的点状线代表真实的数据分布,绿色的线代表生成模型G模拟的分布,蓝色的线代表判别模型D。

    • a图表示初始状态
    • b图表示,保持G不动,优化D,直到判别模型的准确率最高
    • c图表示保持D不动,优化G,直到混淆程度最高
    • d图表示,多次迭代后,终于使得G生成的数据分布能够完全与真实的数据分布一致,而D再也鉴别不出是原始数据还是由生成模型所产生的数据,从而认为G就是真实的。

    GAN的另一个强大之处在于可以自动定义潜在损失函数,即判别网络可以自动学习到一个好的判别方法(损失函数),来比较好或者不好的判别出来结果。
    虽然大的loss函数是模型设计者人为定义的,基本上对于多数GAN都这么定义就可以了,但是判别网络潜在学习到的损失函数隐藏在网络之中,不同的问题这个函数就不一样,所以说可以自动学习这个潜在的损失函数。

    5 优点 vs. 缺点

    • 优点:

      • 模型只用到了反向传播,而不需要马尔科夫链

      • 训练时不需要对隐变量做推断

      • 理论上,只要是可微分函数都可以用于构建D和G,因为能够与深度神经网络结合做深度生成式模型

      • G的参数更新不是直接来自数据样本,而是使用来自D的反向传播(这也是与传统方法相比差别较大的)

      • 从实际结果来看,GAN看起来能产生更好的生成样本

      • GAN框架可以训练任何一种生成器网络(理论上,然而在实践中,很难使用增强学习去训练有离散输出的生成器),大多数其他架构需要生成器有一些特定的函数形式,就像输出层必须是高斯化的.另外所有其他框架需要生成器整个都是非零权值(put non-zero mass everywhere),然而,GANs可以学习到一个只在靠近真实数据的地方(神经网络层)产生样本点的模型( GANs can learn models that generate points only on a thin manifold that goes near the data.)【指的是GAN学习到的分布十分接近真实分布,这里把分布密度函数看作高维流行当中的点,某个类型的真实分布,可能是这个高维空间中的低维流行,想象三维空间中一张卷曲的纸。GAN学习的G能够尽量的“收敛”到这张纸上,而别的生成模型不行,总是在真实的流行之外有一定的分布,不够收敛。非零的mass指的是分布的“密度”,或者分布的“微元”】

      • 没有必要遵循任何种类的因式分解去设计模型,所有的生成器和判别器都可以正常工作

      • 相比PixelRNN, GAN生成采样的运行时间更短,GANs一次产生一个样本,然而PixelRNNs需要一个像素一个像素的去产生样本

      • 相比VAE, GANs没有变分下界,如果鉴别器训练良好,那么生成器可以完美的学习到训练样本的分布.换句话说,GANs是渐进一致的,但是VAE是有偏差的

      • 相比深度玻尔兹曼机, GANs没有变分下界,也没有棘手的配分函数,样本是一次生成的,而不是重复的应用马尔科夫链来生成的

      • 相比GSNs, GANs产生的样本是一次生成的,而不是重复的应用马尔科夫链来生成的

      • 相比NICE和Real NVE,GANs没有对潜在变量(生成器的输入值)的大小进行限制

      • GANs是一种以半监督方式训练分类器的方法.在你没有很多带标签的训练集的时候,你可以不做任何修改的直接使用我们的代码,通常这是因为你没有太多标记样本

      • GANs可以比完全明显的信念网络(NADE,PixelRNN,WaveNet等)更快的产生样本,因为它不需要在采样序列生成不同的数据

      • GANs不需要蒙特卡洛估计来训练网络,人们经常抱怨GANs训练不稳定,很难训练,但是他们比训练依赖于蒙特卡洛估计和对数配分函数的玻尔兹曼机简单多了.因为蒙特卡洛方法在高维空间中效果不好,玻尔兹曼机从来没有拓展到像ImgeNet任务中.GANs起码在ImageNet上训练后可以学习去画一些以假乱真的狗

      • 相比于变分自编码器, GANs没有引入任何决定性偏置( deterministic bias),变分方法引入决定性偏置,因为他们优化对数似然的下界,而不是似然度本身,这看起来导致了VAEs生成的实例比GANs更模糊

      • 相比非线性ICA(NICE, Real NVE等,),GANs不要求生成器输入的潜在变量有任何特定的维度或者要求生成器是可逆的

      • 相比玻尔兹曼机和GSNs,GANs生成实例的过程只需要模型运行一次,而不是以马尔科夫链的形式迭代很多次

    • 缺点:

      • 可解释性差,生成模型的分布 Pg(G)没有显式的表达

      • 比较难训练,D与G之间需要很好的同步(例如D更新k次而G更新一次),GAN模型被定义为极小极大问题,没有损失函数,在训练过程中很难区分是否正在取得进展。GAN的学习过程可能发生崩溃问题(collapse problem),生成器开始退化,总是生成同样的样本点,无法继续学习。当生成模型崩溃时,判别模型也会对相似的样本点指向相似的方向,训练无法继续。

      • 网络难以收敛,目前所有的理论都认为GAN应该在纳什均衡上有很好的表现,但梯度下降只有在凸函数的情况下才能保证实现纳什均衡。

      • 训练GAN需要达到纳什均衡,有时候可以用梯度下降法做到,有时候做不到.还没有找到很好的达到纳什均衡的方法,所以训练GAN相比VAE或者PixelRNN是不稳定的,但在实践中它还是比训练玻尔兹曼机稳定的多

      • 它很难去学习生成离散的数据,就像文本

      • 相比玻尔兹曼机,GANs很难根据一个像素值去猜测另外一个像素值,GANs天生就是做一件事的,那就是一次产生所有像素, 你可以用BiGAN来修正这个特性,它能让你像使用玻尔兹曼机一样去使用Gibbs采样来猜测缺失值

    6 应用与改进

    先看几个GAN的应用:

    这里写图片描述

    再记录几个GAN的分支:

    • CGAN
      CGAN首次提出为GAN增加限制条件,从而增加GAN的准确率。原始的GAN产生的数据模糊不清,为了解决GAN太过自由这个问题,一个很自然的想法就是给GAN加一些约束,于是便有了这篇Conditional Generative Adversarial Nets,这篇工作的改进非常straightforward,在生成模型和判别模型分别为数据加上标签,也就是加上了限制条件。实验表明很有效。

    • DCGAN
      DCGAN全称为Deep convolutional generative adversarial networks,即将深度学习中的卷积神经网络应用到了对抗神经网络中,这篇文章在工程领域内的意义及其大,解决了很多工程性的问题,再加上其源码的开放,将其推向了一个高峰。

      这个模型为工业界具体使用CNN的对抗生成网络提供了非常完善的解决方案,并且生成的图片效果质量精细,为之后GAN的后续再应用领域的发展奠定了很好的基础,当然也可以说提供了一个标杆。

    • iGAN
      iGAN完美地将DCGAN和manifold learning融合在一起,很好的展现了一个DCGAN在实践应用方面的具体案例,将交互这种可能性实现,这对将来类似的应用提供了很好的模板。

    • LAPGAN
      江湖人称拉普拉斯对抗生成网络,主要致力于生成更加清晰,更加锐利的数据。

      LAPGAN事实上受启发与CGAN,同样在训练生成模型的时候加入了conditional variable,这也是本案例成功的一大重要原因。

    • SimGAN
      Apple出品的SimGAN本质地利用了GAN可以产生和训练数据质量一样的生成数据这个特性,通过GAN生成大量的和训练数据一样真实的数据,从而解决当前大规模的精确标注数据难以获取,人工标注成本过高等一系列问题。

    • InfoGAN
      InfoGAN是一种能够学习disentangled representation的GAN,比如人脸数据集中有各种不同的属性特点,如脸部表情、是否带眼镜、头发的风格眼珠的颜色等等,这些很明显的相关表示, InfoGAN能够在完全无监督信息(是否带眼镜等等)下能够学习出这些disentangled representation,而相对于传统的GAN,只需修改loss来最大化GAN的input的noise和最终输出之间的互信息。

    • AC-GAN
      AC-GAN即auxiliary classifier GAN。

    这里有个大神把各种GAN的paper都做了一个统计AdversarialNetsPapers
    另外还有大神用tensorflow实现了GAN和VAE的各种分支tensorflow-generative-model-collections
    generative-models

    7 WGAN-GP代码栗子

    数据集:MNIST
    环境:tensorflow 1.2.0
    模型:WGAN-GP

    注:GPU加速,CPU也行,但很慢,把batchsize改小后用cpu比较好训练,batchsize为64,save_images的参数是[8,8],如果batchsize为16,就相应改为[4,4];代码结尾是实验结果图。

    实验心得:开始用DCGAN,但怎么调都不收敛,DCGAN需要小心的平衡生成器和判别器的训练程度,换了好几个学习率,效果都不太理想,使用WGAN-GP后,头也不疼了,腰也不酸了,后者好训练很多,完全不用担心训练失衡的问题,用着很顺手。

    #coding:utf-8
    import os
    import numpy as np
    import scipy.misc
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data #as mnist_data
    
    def conv2d(name, tensor,ksize, out_dim, stddev=0.01, stride=2, padding='SAME'):
        with tf.variable_scope(name):
            w = tf.get_variable('w', [ksize, ksize, tensor.get_shape()[-1],out_dim], dtype=tf.float32,
                                initializer=tf.random_normal_initializer(stddev=stddev))
            var = tf.nn.conv2d(tensor,w,[1,stride, stride,1],padding=padding)
            b = tf.get_variable('b', [out_dim], 'float32',initializer=tf.constant_initializer(0.01))
            return tf.nn.bias_add(var, b)
    
    def deconv2d(name, tensor, ksize, outshape, stddev=0.01, stride=2, padding='SAME'):
        with tf.variable_scope(name):
            w = tf.get_variable('w', [ksize, ksize, outshape[-1], tensor.get_shape()[-1]], dtype=tf.float32,
                                initializer=tf.random_normal_initializer(stddev=stddev))
            var = tf.nn.conv2d_transpose(tensor, w, outshape, strides=[1, stride, stride, 1], padding=padding)
            b = tf.get_variable('b', [outshape[-1]], 'float32', initializer=tf.constant_initializer(0.01))
            return tf.nn.bias_add(var, b)
    
    def fully_connected(name,value, output_shape):
        with tf.variable_scope(name, reuse=None) as scope:
            shape = value.get_shape().as_list()
            w = tf.get_variable('w', [shape[1], output_shape], dtype=tf.float32,
                                        initializer=tf.random_normal_initializer(stddev=0.01))
            b = tf.get_variable('b', [output_shape], dtype=tf.float32, initializer=tf.constant_initializer(0.0))
    
            return tf.matmul(value, w) + b
    
    def relu(name, tensor):
        return tf.nn.relu(tensor, name)
    
    def lrelu(name,x, leak=0.2):
        return tf.maximum(x, leak * x, name=name)
    
    
    DEPTH = 28
    OUTPUT_SIZE = 28
    batch_size = 64
    def Discriminator(name,inputs,reuse):
        with tf.variable_scope(name, reuse=reuse):
            output = tf.reshape(inputs, [-1, 28, 28, 1])
            output1 = conv2d('d_conv_1', output, ksize=5, out_dim=DEPTH)
            output2 = lrelu('d_lrelu_1', output1)
    
            output3 = conv2d('d_conv_2', output2, ksize=5, out_dim=2*DEPTH)
            output4 = lrelu('d_lrelu_2', output3)
    
            output5 = conv2d('d_conv_3', output4, ksize=5, out_dim=4*DEPTH)
            output6 = lrelu('d_lrelu_3', output5)
    
            # output7 = conv2d('d_conv_4', output6, ksize=5, out_dim=8*DEPTH)
            # output8 = lrelu('d_lrelu_4', output7)
    
            chanel = output6.get_shape().as_list()
            output9 = tf.reshape(output6, [batch_size, chanel[1]*chanel[2]*chanel[3]])
            output0 = fully_connected('d_fc', output9, 1)
            return output0
    
    
    def generator(name, reuse=False):
        with tf.variable_scope(name, reuse=reuse):
            noise = tf.random_normal([batch_size, 128])#.astype('float32')
    
            noise = tf.reshape(noise, [batch_size, 128], 'noise')
            output = fully_connected('g_fc_1', noise, 2*2*8*DEPTH)
            output = tf.reshape(output, [batch_size, 2, 2, 8*DEPTH], 'g_conv')
    
            output = deconv2d('g_deconv_1', output, ksize=5, outshape=[batch_size, 4, 4, 4*DEPTH])
            output = tf.nn.relu(output)
            output = tf.reshape(output, [batch_size, 4, 4, 4*DEPTH])
    
            output = deconv2d('g_deconv_2', output, ksize=5, outshape=[batch_size, 7, 7, 2* DEPTH])
            output = tf.nn.relu(output)
    
            output = deconv2d('g_deconv_3', output, ksize=5, outshape=[batch_size, 14, 14, DEPTH])
            output = tf.nn.relu(output)
    
            output = deconv2d('g_deconv_4', output, ksize=5, outshape=[batch_size, OUTPUT_SIZE, OUTPUT_SIZE, 1])
            # output = tf.nn.relu(output)
            output = tf.nn.sigmoid(output)
            return tf.reshape(output,[-1,784])
    
    
    def save_images(images, size, path):
        # 图片归一化
        img = (images + 1.0) / 2.0
        h, w = img.shape[1], img.shape[2]
        merge_img = np.zeros((h * size[0], w * size[1], 3))
        for idx, image in enumerate(images):
            i = idx % size[1]
            j = idx // size[1]
            merge_img[j * h:j * h + h, i * w:i * w + w, :] = image
        return scipy.misc.imsave(path, merge_img)
    
    
    LAMBDA = 10
    EPOCH = 40
    def train():
        # print  os.getcwd()
        with tf.variable_scope(tf.get_variable_scope()):
            # real_data = tf.placeholder(dtype=tf.float32, shape=[-1, OUTPUT_SIZE*OUTPUT_SIZE*3])
            path = os.getcwd()
            data_dir = path + "/train.tfrecords"#准备使用自己的数据集
            # print data_dir
            '''获得数据'''
            z = tf.placeholder(dtype=tf.float32, shape=[batch_size, 100])#build placeholder
            real_data = tf.placeholder(tf.float32, shape=[batch_size,784])
    
            with tf.variable_scope(tf.get_variable_scope()):
                fake_data = generator('gen',reuse=False)
                disc_real = Discriminator('dis_r',real_data,reuse=False)
                disc_fake = Discriminator('dis_r',fake_data,reuse=True)
    
    #下面这三句话去掉也没有影响
            t_vars = tf.trainable_variables()
            d_vars = [var for var in t_vars if 'd_' in var.name]
            g_vars = [var for var in t_vars if 'g_' in var.name]
    
            '''计算损失'''
            gen_cost = tf.reduce_mean(disc_fake)
            disc_cost = -tf.reduce_mean(disc_fake) + tf.reduce_mean(disc_real)
    
            alpha = tf.random_uniform(
                shape=[batch_size, 1],minval=0.,maxval=1.)
            differences = fake_data - real_data
            interpolates = real_data + (alpha * differences)
            gradients = tf.gradients(Discriminator('dis_r',interpolates,reuse=True), [interpolates])[0]
            slopes = tf.sqrt(tf.reduce_sum(tf.square(gradients), reduction_indices=[1]))
            gradient_penalty = tf.reduce_mean((slopes - 1.) ** 2)
            disc_cost += LAMBDA * gradient_penalty
    
            with tf.variable_scope(tf.get_variable_scope(), reuse=None):
                gen_train_op = tf.train.AdamOptimizer(
                    learning_rate=1e-4,beta1=0.5,beta2=0.9).minimize(gen_cost,var_list=g_vars)
                disc_train_op = tf.train.AdamOptimizer(
                    learning_rate=1e-4,beta1=0.5,beta2=0.9).minimize(disc_cost,var_list=d_vars)
    
            saver = tf.train.Saver()
    
            # os.environ['CUDA_VISIBLE_DEVICES'] = str(0)#gpu环境
            # config = tf.ConfigProto()
            # config.gpu_options.per_process_gpu_memory_fraction = 0.5#调用50%GPU资源
            # sess = tf.InteractiveSession(config=config)
            sess = tf.InteractiveSession()
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    
    
            init = tf.global_variables_initializer()
            # init = tf.initialize_all_variables()
            sess.run(init)
            mnist = input_data.read_data_sets("data", one_hot=True)
            # mnist = mnist_data.read_data_sets("data", one_hot=True, reshape=False, validation_size=0)
            for epoch in range (1, EPOCH):
                idxs = 1000
                for iters in range(1, idxs):
                    _, g_loss = sess.run([gen_train_op, gen_cost])
                    img, _ = mnist.train.next_batch(batch_size)
    
                    # img2 = tf.reshape(img, [batch_size, 784])
                    for x in range (0,5):
                        _, d_loss = sess.run([disc_train_op, disc_cost], feed_dict={real_data: img})
    
                    # print "fake_data:%5f disc_real:%5f disc_fake:%5f "%(tf.reduce_mean(fake_data)
                    #                         ,tf.reduce_mean(disc_real),tf.reduce_mean(disc_fake))
                    print("[%4d:%4d/%4d] d_loss: %.8f, g_loss: %.8f"%(epoch, iters, idxs, d_loss, g_loss))
    
                with tf.variable_scope(tf.get_variable_scope()):
                    samples = generator('gen', reuse=True)
                    samples = tf.reshape(samples, shape=[batch_size, 28,28,1])
                    samples=sess.run(samples)
                    save_images(samples, [8,8], os.getcwd()+'/img/'+'sample_%d_epoch.png' % (epoch))
    
                if epoch>=39:
                    checkpoint_path = os.path.join(os.getcwd(),
                                                   'my_wgan-gp.ckpt')
                    saver.save(sess, checkpoint_path, global_step=epoch)
                    print '*********    model saved    *********'
    
            coord.request_stop()
            coord.join(threads)
            sess.close()
    if __name__ == '__main__':
        train()

    这里写图片描述       这里写图片描述
    第1个epoch生成结果                         第39个epoch生成结果

    当然,这里还有一篇对代码讲解比较详细的帖子GAN入门教程|从0开始,手把手教你学会最火的神经网络


    本篇博客整理自以下博客:

    深入探索生成对抗网络
    tensorflow学习之最简单的GAN 实现
    简单理解与实验生成对抗网络GAN
    对抗生成网络详解
    tensorflow 实现wgan-gp mnist图片生成
    火热的生成对抗网络(GAN),你究竟好在哪里
    GAN生成对抗网络
    GAN理解与TF实现
    Gan的数学推导

    展开全文
  • 生成对抗网络(GAN)教程 - 多图详解

    万次阅读 多人点赞 2018-08-30 14:15:04
    生成对抗网络简介 1.生成对抗网络模型主要包括两部分:生成模型和判别模型。 生成模型是指我们可以根据任务、通过模型训练由输入的数据生成文字、图像、视频等数据。  [1]比如RNN部分讲的用于生成奥巴马演讲稿的...

    一.生成对抗网络简介

    1.生成对抗网络模型主要包括两部分:生成模型和判别模型。 生成模型是指我们可以根据任务、通过模型训练由输入的数据生成文字、图像、视频等数据。            

        [1]比如RNN部分讲的用于生成奥巴马演讲稿的RNN模型,通过输入开头词就能生成下来。

        [2]或者由有马赛克的图像通过模型变成清晰的图像,第一张是真实,第四张是合成的。    

                     

         [3]或者我们为了生成一类图像时会通过输入指定的分布形态数据,这样经过训练数据和输入分布形态后,就可以将分布形态输入网络获得这一类的图像(可用于数据集的扩展,图片的合成,思路等下介绍),左图是看了大量街景记录生成的未见过的场景。

    二生成对抗网络 —— 基本机构

    1.生成模型从本质上是一种极大似然估计,用于产生指定分布数据的模型,生成模型的作用是捕捉样本数据的分布、将原输入信息的分布情况经过极大似然估计中参数的转化来将训练偏向转换为指定分布的样本。

    2.判别模型实际上是个二分类,会对生成模型生成的图像等数据进行判断,判断其是否是真实的训练数据中的数据。

    二生成对抗网络 —— 模型介绍

    1.对于GAN,一个简单的理解是可以将其看做博弈的过程,我们可以将生成模型和判别模型看作博弈的双方,比如在犯罪分子造假币和警察识别假币的过程中:            

         [1]生成模型G相当于制造假币的一方,其目的是根据看到的钱币情况和警察的识别技术,去尽量生成更加真实的、警察识别不出的假币。            

         [2]判别模型D相当于识别假币的一方,其目的是尽可能的识别出犯罪分子制造的假币。 这样通过造假者和识假者双方的较量和朝目的的改进,使得最后能达到生成模型能尽可能真的钱币、识假者判断不出真假的纳什均衡效果(真假币概率都为0.5)。

    2.我们可以将上面的场景映射成图片之间生成模型和判别模型之间的博弈过程,博弈的简单模式如下:生成模型生成一些图片->判别模型学习区分生成的图片和真实图片->生成模型根据判别模型改进自己,生成新的图片->判别模型再学习区分生成的图片和真实图片.....

    上面的博弈场景会一直继续下去,直到生成模型和判别模型别无法提升自己,这样生成模型就会成为一个比较完美的模型。

    3.下图是基本GAN网络的模型结构,我们现在开始由下往上介绍,先看右图,右图是生成模型函数的训练网络。          

          [1]首先我们先将正态分布的噪声数据z(必须统一的一类分布数据,因为训练模型是按分布情况转换的,模型作用是将一类分布转化为任务需要的数据分布情况)输入到网络中。

             

          [2]噪音数据会通过生成模型网络G(z)生成造假的图像数据,因为我们的目的是制造尽可能让判别模型分不清往图像,所以会结合判别网络进行模型训练,通过这种训练来使生成模型有更好的造假效果。(结合判别模型知道误差)

      [3]接下来会将生成模型输出的造假图片数据输入到判别模型网络D(x)中,之后进行网络的参数计算得到最后的判别输出,输出0-1之间的参数值,0表示是造假信息,1表示是真实数据,对于生成模型产生的造假信息,我们希望判别模型能够输出接近0的输出值,从而有效判断真假。        

             在下面网络进行生成模型训练时,在判别模型部分生成误差后,我们在训练时判别网络的网络参数并不需要发生变化,只是把最后按生成模型目标函数计算的误差往前一直传,传到生成网络来更新生成网络的参数,这样就可以完成生成网络的训练。

     

    4.下图中上半部分是判别模型的训练模型,我们会结合真实样本集和造假样本集按批次进行判别模型网络的训练,根据其目标函数进行梯度下降:

     

    三 生成对抗网络 —— 模型训练

    1.进行网络训练时,判别模型的目标函数是:

           

           其中D(x)是判别模型的输出结果,是一个0-1范围内的实数值,用来判断图片是真实图片的概率,其中Pr和Pg分别代表真实图像的分布与生成图像的数据分布情况,可以看出目标函数是找到使得后面两个式子之和最大的判别模型函数D(z),后面两个式子是一个加和形式,其中:        

           [1]是指使得真实数据放入到判别模型D(x)输出的计算值和整个式子值尽可能大,        

           [2] 是指使得造假数据放入到判别模型D(x)输出的计算值尽可能小和整个式子值尽可能大,这样整合下来就是使得目标函数尽可能大,因此在训练时就可以根据目标函数进行梯度提升。

    2.生成模型的目标是让判别模型无法区分真实图片和生成图片,其目标函数是:        

    也就是找到生成函数g(z)使得生成模型的目标函数尽量小,所以两者是对抗的。

    3.下图是GAN的一个算法流程,我们会使用目标函数在两个网络中进行参数的梯度改变。

    4.对于上面的最大最小化目标函数进行优化时,我们最直观的处理方式是将生成网络模型D和判别网络模型G进行交替迭代,在一段时间内,固定G网络内的参数,来优化网络D,另一段时间固定D网络中的参数,来优化G网络中的参数(这样的话,上图俩部分就是两个网络)。

    5.我们举个优化效果的例子,假设刚开始的真实样本分布、生成样本分布、判别模型分别对应左图的黑线、绿线、蓝线。那么:             [1]当我们固定生成模型,而优化判别模型时,我们发现判别模型会变得有很好的对黑线和蓝线的区分效果。(偏向于在两者中间)

          [2]当我们固定判别模型,改进生成模型时,我们发现生成模型生成的数据分布(绿线)会不断往真实数据分布(黑线)靠拢,也就如第三幅图,使得判别模型很难分离判断。          

          [3]进行1、2过程进行大量迭代后,我们会得到最后图的效果,生成样本数据分布和真实数据分布基本吻合,判别模型处于纳什均衡,做不了判断。

    四 生成对抗网络 —— 模型应用

    1.对于GAN的应用,我们可以分为两大类:            

            [1]一类是学后联想任务,这类任务特点是只有大量的目标样例[y1,y2,y3...],这类任务我们只知道我们想让网络模仿的东西,比如我们使用大量毕加索的画像去训练GAN,让其模仿生成毕加索的画像,此时生成模型网络的输入是正态分布即可,网络会学着把正态分布转成猫的图像的数据分布情况(可用于数据生成)。          

     

           [2]另一类是目标引导的训练任务,这类任务是有目标指定的,训练数据是{[x1,y1],[x2,y2]...}这种形式,我们会学着让生成网络学会去除图片的马赛克、图像风格变化等任务。此时生成模型的输入应该是原始转换前的图片(按批次放,每批次数据称为一个噪音,噪音维度越小,图片共性越大)。

    2.早期的GAN模型中,生成模型输入的是一些服从某一简单分布(例如高斯分布)的随机噪声z,输出是训练图像相同尺寸的生成图像。 如能实现数据量的扩充,比如对手写数字图像的扩充,如下图输入高斯分布,将大量0数据放入生成对抗网络进行训练,我们就能获得很像9的右面的图片。再比如我们使用大量人类的脸或者猫的图片,GAN就能通过对高斯分布转成猫图像数据分布学习来想想生成新的猫的图像、或者合成场景、脸等数据。

    3.应用于图像方面,更强的改进模型是DCGAN(convolutional nn for Gan),DCGAN中生成模型用到的神经网络是与卷积神经网络相反的网络形式(反卷积),判别是正卷积,网络形式如下图。

    为什么是这种形式,他与通常的CNN网络比较可以考虑成是画画和理解画两个不同的过程。            

             [1]我们在画画时是先考虑构图(高维联想),之后开始画轮廓、画线条、填充颜色。  

             

             [2]而我们在理解画时,是按照视觉皮层的理解思路,先看到边缘的即视的东西,之后将这些低维的东西组合进行抽象信息的联想。 所以我们现在也是按照初始分布数据画出一幅画的过程,所以与普通CNN是相反的。

    所以我们现在也是按照初始分布数据画出一幅画的过程,所以与普通CNN是相反的。

    5.使用DCGAN我们可以实现图像合成的功能,如左图我们可以将左边的图像作为生成模型的输入(将图像像素不断按行输入到生成模型中,在生成模型的输出部分再拼合成造假的图片x),进行输入时会先将三个图片(x1,x2,x3)进行加减合成得到合成的图片分布z,之后将z输入到生成模型得到对应的造假图像x,x和y图像通过判别模型得到D(x)和D(y)结果,再根据目函数计算梯度值实现对生成模型和判别模型参数的更新,。

    还可以进行图像还原、生成卡通图片等。。。

    五 生成对抗网络 —— 模型特点

    1.生成对抗网络仍存在的问题有:        

           [1]解决不收敛的问题。所有的理论都认为 GAN 应该在纳什均衡上有卓越的表现,但梯度下降只有在凸函数的情况下才能保证实现纳什均衡。当博弈双方都由神经网络表示时,在没有实际达到均衡的情况下,让它们永远保持对自己策略的调整是可能的。        [2]难以训练(目标函数难构建)。GAN模型被定义为极小极大问题,没有损失函数,在训练过程中很难区分是否正在取得进展。GAN的学习过程可能发生崩溃问题,生成器开始退化,会生成同样的样本点,无法继续学习。当生成模型崩溃时,判别模型也会对相似的样本点指向相似的方向,训练无法继续。    

           [3]判别器D效果越好,生成器梯度消失越严重,最后难训练。

    2.对于GAN模型最难的是对目标函数的构建,构建的式子非常影响最后优化出模型的效果,而且要解决各种梯度消失和梯度爆炸问题。

    所以很多改进模型都是在目标函数的构造上动手脚,如著名的wGAN方法,进行了以下几点的改进:              

           [1]判别器的最后一层去掉sigmoid函数。              

          [2]生成器和判别器的目标函数中不用log函数包装。            

          [3]不要急于动量的优化算法,而是使用SGD、RMSprop等方法。            

          [4]对判别器加上Lipschitz限制,当输入的样本稍微变化后,判别器给出的分数不能发生太过剧烈的变化。

         

    展开全文
  • 了解生成对抗网络(GAN)

    千次阅读 2019-01-16 08:09:17
    什么是Generative Adversarial Networks(生成对抗网络)?本文中,我们将看到对抗性训练是一种很有启发性的想法,其简单而实用,这代表了机器学习的真正概念进展,尤其是生成模型。 在进入细节之前,让我们快速...

     

     

    2019-01-08 23:29:25

    介绍

    什么是Generative Adversarial Networks(生成对抗性网络)?本文中,我们将看到对抗性训练是一种很有启发性的想法,其简单而实用,这代表了机器学习的真正概念进展,尤其是生成模型。

    在进入细节之前,让我们快速概述一下GANs的用途。生成对抗性网络属于一组生成模型集。这意味着他们能够生成新的内容。为了说明这种“生成模型”的概念,我们可以看一些用GANs获得结果的著名的例子。

    了解生成对抗网络(GAN)

    这些是由GANs在对两个数据集进行训练后生成的样本:MNIST和TFD。

    当然,这种生成新内容的能力使GANs看起来有点“神奇”。在以下部分中,我们将深入了解这些模型背后的想法,数学和建模。我们不仅会讨论GANs所依赖的基本概念,我们还会一步一步地构建这些概念,并从一开始就对这些概念进行推理。

    注意:尽管我们试图使本文尽可能独立,但仍需要具备机器学习的基本先验知识。

    目录

    1、我们将讨论从给定的分布生成随机变量的过程。

    2、我们将通过一个例子展示GANs试图解决的问题可以表示为随机变量生成问题。

    3、我们将讨论基于匹配的生成网络。

    4、我们将呈现带有损失函数的通用架构,并且与之前的所有部分建立连接。

    生成随机变量

    我们先讨论生成随机变量的方法:逆变换方法,它允许从简单的均匀随机变量生成复杂的随机变量。我们将在后面看到与生成模型存在的深层联系。

    随机变量可以是伪随机生成的

    从理论上讲,生成真正随机的数字是不可能的。但是,可以定义生成数字序列的算法,其特征非常接近理论随机数序列的属性。特别是,计算机能够使用伪随机数生成器生成一个数字序列,该数字序列近似地遵循0和1之间的均匀随机分布。均匀的情况是非常简单的,可以以不同的方式建立更复杂的随机变量。

    随机变量表示的是运算或过程的结果

    有不同的技术可以生成更复杂的随机变量。我们可以找到逆变换方法,拒绝采样法,Metropolis-Hasting算法等。所有这些方法都依赖于不同的数学技巧,这些技巧主要包括表示我们希望作为运算或过程的结果生成的随机变量。

    拒绝采样是针对复杂问题的一种随机采样方法,拒绝采样是指不从复杂分布中采样,而是从已知的简单分布中采样,并根据一定条件接受或拒绝采样值的过程的结果。重复这个过程直到采样值被接受,我们可以证明在接受的条件正确的情况下,有效采样的值将遵循正确的分布。

    在Metropolis-Hasting算法中,使用的是马尔可夫链蒙特卡罗(MCMC)方法,用于从难以直接采样的概率分布中获得随机样本序列。该序列可用于近似分布或计算积分。我们可以使用马尔科夫链(MC),使得MC的平稳分布对应于我们需要从中抽样的随机变量的分布,一旦找到这个MC,考虑到我们已经达到了一个稳定的状态,我们就可以在这个MC上模拟出足够长的轨迹,然后我们以这种方式获得的最后一个值可以被认为是从有用的分布中得出的。

    逆变换 方法

    逆变换方法的概念仅仅是为了表示我们的复杂,而不是数学意义中的随机变量最为函数应用于一个我们知道如何生成的均匀随机变量的结果。

    在下面的一维例子中。设X是我们想要从中采样的复杂随机变量,U是[0,1]上的均匀随机变量,我们知道如何从中采样。我们赋予随机变量由其累积分布函数(CDF)完全定义。随机变量的CDF是从随机变量的定义域到区间[0,1]的函数,并且在一个维度中定义,例如:

    了解生成对抗网络(GAN)

     

    在特定情况下U是我们的均匀随机变量:

    了解生成对抗网络(GAN)

     

    为简单起见,我们假设函数CDF_X是可逆的:

    了解生成对抗网络(GAN)

     

    (这个方法可以通过使用泛化的逆函数来简单地扩展到非可逆的例子但这并不是我们想要关注的重点)。然后:

    了解生成对抗网络(GAN)

     

    我们可以得到:

    了解生成对抗网络(GAN)

     

    我们可以看到,Y和X具有相同的CDF,然后定义相同的随机变量。因此,通过如上定义Y(作为均匀随机变量的函数),我们设法定义了具有目标分布的随机变量。

    综上所述,逆变换方法是通过使均匀随机变量经过精心设计的“变换函数”(逆CDF)来生成遵循给定分布的随机变量的方式。事实上,这种“逆变换方法”的概念可以扩展到“变换方法”的概念,“变换方法”更简单地说,在生成随机变量作为一些更简单的随机变量的函数时(不一定是均匀的,然后变换函数是不再是逆CDF)。从概念上讲,“变换函数”的目的是使初始概率分布变形/重塑:变换函数从初始概率分布相对于目标概率分布过高的位置,并将其置于初始概率分布过低的位置。

    了解生成对抗网络(GAN)

    逆变换方法的图示。蓝色:均匀分布在[0,1]上。橙色:标准高斯分布。灰色:从均匀到高斯分布的映射(逆

    生成模型

    我们试图生成非常复杂的随机变量......

    假设我们生成大小为n*n像素的狗的黑白方形图像。我们可以将每个数据重新塑造为N = n×n维向量(通过在彼此之上堆叠),使得狗的图像可以由向量表示。然而,这并不意味着所有的向量都代表了曾经被塑造成方形的狗!因此,我们可以说,在N维空间的向量空间中,可以有效地生成一种看起来像条狗的图形,这是根据一种特定的概率分布在整个N维向量空间上的。本着同样的精神,在这个N维向量空间上存在猫,鸟等图像的概率分布。

    然后,生成狗的新图像的问题等同于在N维向量空间上按照“狗概率分布”生成一个的新向量的问题。事实上,我们面临的问题是根据特定的概率分布生成一个随机变量。

    在这一点上,我们可以提到两件重要的事情。首先,我们提到的“狗概率分布”是在非常大的空间内非常复杂的分布。其次,即使我们可以假设存在这样的基础分布,但我们显然不知道如何明确地表达这种分布。之前的两点都使得从该分布生成随机变量的过程非常困难。但让我们尝试着解决这两个问题。

    使用神经网络的变换方法作为函数!

    当我们尝试生成狗的新图像时,我们的第一个问题是N维向量空间上的“狗概率分布”是一个非常复杂的问题,我们不知道如何直接生成复杂的随机变量。然而,正如我们非常清楚如何生成N个不相关的均匀随机变量,我们可以利用变换方法。为此,我们需要将N维随机变量表示为将非常复杂的函数应用于简单的N维随机变量的结果!

    这里,我们可以强调的事实是,发现变换函数并不像我们在描述逆变换方法时所做的那样简单。变换函数无法明确表达,因此,我们必须从数据中学习它。

    在大多数情况下,非常复杂的函数自然意味着神经网络建模。然后,通过神经网络对变换函数进行建模,该神经网络将一个简单的N维均匀随机变量作为输入,并将其作为输出返回另一个N维随机变量,该随机变量在训练后应遵循正确的“dog概率分布” 。网络架构设计完成后,我们仍然需要对其进行训练。后面,我们将讨论训练这些生成网络的两种方法,包括GANs背后的对抗训练的概念。

    了解生成对抗网络(GAN)

    使用神经网络的生成模型概念的图。显然,我们真正谈论的维度远高于此处所表示的维度。

    生成匹配网络

    训练生成模型

    到目前为止,我们已经证明了我们生成狗的新图像的问题可以被重新描述为在N维向量空间中生成遵循“狗概率分布”的随机向量的问题,并且我们建议使用变换方法,用神经网络来模拟变换函数。

    现在,我们仍然需要训练(优化)网络以表达正确的变换函数。我们选择两种不同的训练方法:直接训练方法和间接训练方法。直接训练方法是比较真实概率分布和生成的概率分布,并通过网络反向传播差异(误差)。这是规则生成匹配网络(GMNs)的想法。对于间接训练方法,我们不直接比较真实和生成的概率分布。相反,我们训练生成网络,让这两个分布通过选择一个下游任务,这样生成网络相对于下游任务的优化过程将强制生成的分布接近真实的分布。

    比较基于样本的两个概率分布

    如上所述,GMN的概念是通过直接比较生成分布和真实分布来训练生成网络。如果我们有一种比较基于样本的概率分布的方法,我们可以使用它来训练网络。实际上,我们有一个真实数据样本,我们可以在训练过程的每次迭代中生成一个生成数据的样本。

    虽然理论上可以使用任何基于样本的距离(或相似性度量)来有效地比较两个分布,但我们可以特别提到最大均值差异(MMD)方法。MMD定义了可以基于这些分布的样本计算(估计)的两个概率分布之间的距离。

    分布匹配误差的反向传播

    如果我们定义了一种基于样本比较两种分布的方法,我们就可以定义GMN中生成网络的训练过程。给定具有均匀概率分布的随机变量作为输入,我们希望所生成的输出的概率分布是“狗概率分布”。然后,GMN的想法是通过重复以下步骤来优化网络:

    • 产生一些统一的输入
    • 使这些输入通过网络并收集生成的输出
    • 比较真实的“狗概率分布”和基于可用样本生成的一个
    • 使用反向传播来进行梯度下降的一个步骤,以降低真实分布和生成分布之间的距离(例如MMD)

    如上所述,当遵循这些步骤时,我们在网络上应用梯度下降,其具有损失函数,该函数是当前迭代时真实分布与生成分布之间的距离。

    了解生成对抗网络(GAN)

    生成匹配网络采用简单的随机输入,生成新数据,直接比较生成数据的分布与真实数据的分布,并反向传播匹配误

    生成对抗网络

    “间接”训练方法

    上面提出的“直接”方法在训练生成网络时直接比较生成分布与真实分布。规则GAN的好处在于用间接的比较替换这种直接比较,后者采用这两种分布的下游任务的形式,然后对该任务进行生成网络的训练,使得它迫使所生成的分布越来越接近真实分布。

    GANs的下游任务是区分真样本和生成样本的任务。因此,在GAN架构中,我们有一个鉴别器,它从真实的和生成的数据中提取样本并尽可能地对它们进行分类,还有一个生成器,它被训练成尽可能地欺骗鉴别器。

    理想的情况:完美的生成器和鉴别器

    为了更好地理解为什么训练生成器来欺骗鉴别器会得到与直接训练生成器匹配目标分布相同的结果,让我们采用一个简单的一维示例。我们暂时忘记掉如何表示生成器和鉴别器,并将它们视为抽象概念。此外,两者都被认为是“完美的”,因为它们不受任何类型(参数化)模型的约束。

    假设我们有一个真正的分布,例如一维高斯分布,并且我们想要一个从这个概率分布中采样的生成器。我们所谓的“直接”训练方法将包括迭代地调整生成器(梯度下降迭代)以校正真实分布和生成分布之间的测量差异/误差。最后,假设优化过程完美,我们应该最终得到与真实分布完全匹配的生成分布。

    了解生成对抗网络(GAN)

    直接匹配方法的概念的例证。蓝色的分布是真实的,而生成的分布用橙色表示。通过逐次迭代,我们比较两个分布

    对于“间接”方法,我们还必须考虑一个鉴别器。我们现在假设这个鉴别器是一种oracle,它确切知道什么是真实和生成的分布,并且能够根据这些信息预测任何给定点的类(“真”或“生成”)。如果这两个分布很明显,那么鉴别器将能够轻松地进行分类,并且可以对我们提供给它的大多数点进行分类。如果我们想欺骗鉴别器,我们必须使生成的分布接近真实的分布。当两个分布在所有点上相等时,鉴别器将很难预测类:

    了解生成对抗网络(GAN)

    对抗性方法的直觉。

    蓝色分布是真实的,橙色是生成的分布。在灰色中,右边有相应的y轴,如果它选择每个点中密度较高的类(假设“真实”和“生成”数据的比例相等),我们就会显示鉴别器的概率为真。两个分布越接近,鉴别器就越容易出错。在训练时,目标是将“绿色区域”移向“红色区域”。

    在这一点上,似乎有理由怀疑这种间接方法是否真的是一个好方法。实际上,它似乎更复杂。对于第一点,直接比较基于样本的两个概率分布的难度抵消了间接方法的明显较高的复杂性。对于第二点,很明显,鉴别器是未知的。

    对抗性神经网络

    现在让我们描述采用GANs架构中的生成器和鉴别器的具体形式。生成器是一个模拟转换函数的神经网络。它将一个简单的随机变量作为输入,并且必须在训练后返回一个遵循目标分布的随机变量。由于鉴别器结构复杂且未知,我们决定用另一种神经网络对其进行建模。这个神经网络模型具有辨别功能。它将一个点作为输入,并将该点的概率作为输出返回为“真”。

    现在我们强加一个参数化模型来表达生成器和鉴别器,实际上并没有对上面给出的理论产生影响:我们只是在一些参数化空间而不是理想的空间中工作,因此,在理想情况下我们应达到的最佳点可以被看作是“圆”,是由参数化模型的精确性来判定的。

    一旦确定,这两个网络就可以(同时)以相反的目标联合训练:

    • 生成器的目标是欺骗鉴别器,因此训练生成神经网络使最终分类误差最大化(真实数据和生成数据之间)
    • 鉴别器的目标是检测假的生成数据,因此训练判别神经网络使最终分类误差最小化

    因此,在训练过程的每次迭代中,生成网络的权重都会更新,以便增加分类误差,同时更新判别网络的权重以减少分类误差。

    了解生成对抗网络(GAN)

    生成性对抗网络表示

    生成器将简单随机变量作为输入并生成新数据。鉴别器采用“真实”和“生成”数据并尝试区分它们,构建分类器。生成器的目标是欺骗鉴别器(通过将尽可能多的生成数据与真实数据混合来增加分类错误),鉴别器的目标是区分真实数据和生成数据。

    这些相反的目标和两个网络的对抗性训练的隐含概念解释了“对抗性网络”的名称:两个网络都试图相互击败对方,这样做的目的是让对方都变得越来越好。他们之间的竞争使这两个网络在各自的目标方面“进步”。从博弈论的角度来看,我们可以将此设置视为极小极大双玩家游戏,其中均衡状态对应于发生器从精确目标分布产生数据并且鉴别器预测“真实”或“生成”的情况,它接收的任何一点的概率为1/2。

    关于GAN的数学方面

    神经网络建模本质上需要定义两件事:架构和损失函数。我们已经描述了GANs的架构。它包含两个网络:

    • 生成网络G,随机输入z定义为Pz,并返回一个输出Xg= G(z),该输出应该遵循(训练后)目标概率分布
    • 判别网络D,输入X可以是“ 真实”的(Xt,用Pt表示)或“生成的”Xg,(用Pg表示是由Pz经过G输出的)并将X的概率D(x)返回为“真实”数据

    现在让我们仔细看看GAN的“理论”损失函数。如果我们以相同的比例向鉴别器发送“真实”和“生成”的数据,则鉴别器的预期绝对误差可以表示为

    了解生成对抗网络(GAN)

     

    生成器的目标是欺骗鉴别器,其目标是能够区分真实数据和生成数据。因此,在训练生成器时,我们希望误差最大化,同时我们想要使鉴别器的误差最小化。

    了解生成对抗网络(GAN)

     

    对于任何给定的生成器G,最佳可能的鉴别器是最小化的鉴别器

    了解生成对抗网络(GAN)

     

    为了最小化(关于D)这个积分,我们可以最小化每个x值在积分内的函数,然后定义给定生成器的最佳鉴别器

    了解生成对抗网络(GAN)

     

    然后我们搜索G最大化

    了解生成对抗网络(GAN)

     

    同样,为了最大化G,我们可以最大化X的每个值的积分内的函数。

    了解生成对抗网络(GAN)

     

    当然,由于Pg是应该与1整合的,我们必然拥有最佳的G

    了解生成对抗网络(GAN)

     

    因此,我们已经证明,在具有无限容量生成器和鉴别器的理想情况下,对抗性设置的最佳点使得生成器产生与真实数据点相同的数据点,并且鉴别器不能比真实的更好。最后,还要注意G最大化

    了解生成对抗网络(GAN)

     

    在这种形式下,我们更好地看到G想要最大化鉴别器出错的预期概率。

    本文的主要内容是:

    • 计算机基本上可以生成简单的伪随机变量(例如,它们可以生成非常接近均匀分布的变量)
    • 存在不同的方法来生成更复杂的随机变量,包括“变换方法”的概念,其包括将随机变量表示为一些更简单的随机变量的函数。
    • 在机器学习中,生成模型试图从给定(复杂)概率分布生成数据
    • 深度学习生成模型被建模为神经网络(非常复杂的函数),它将一个简单的随机变量作为输入,并返回一个遵循目标分布的随机变量(“变换方法”)
    • 这些生成网络可以“直接”训练(通过比较生成数据与真实分布的分布):这就是生成匹配网络的想法
    • 这些生成网络也可以“间接”训练(通过试图欺骗同时训练的另一个网络来判断“生成的”数据和“真实”数据):这就是生成对抗网络的想法
    展开全文
  • 什么是生成对抗网络?生成式对抗网络(GAN, Generative Adversarial Networks )是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative ...

    什么是生成对抗网络?生成式对抗网络(GAN, Generative Adversarial Networks )是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。原始 GAN 理论中,并不要求 G D 都是神经网络,只需要是能拟合相应生成和判别的函数即可。但实用中一般均使用深度神经网络作为 G D 。一个优秀的GAN应用需要有良好的训练方法,否则可能由于神经网络模型的自由性而导致输出不理想。

    一个典型的生成对抗网络模型大概长这个样子:

     

    81ebac7551582049df9edad99126da79822.jpg

    我们先来理解下GAN的两个模型要做什么。

    首先判别模型,就是图中右半部分的网络,直观来看就是一个简单的神经网络结构,输入就是一副图像,输出就是一个概率值,用于判断真假使用(概率值大于0.5那就是真,小于0.5那就是假),真假也不过是人们定义的概率而已。

    其次是生成模型,生成模型要做什么呢,同样也可以看成是一个神经网络模型,输入是一组随机数Z,输出是一个图像,不再是一个数值而已。从图中可以看到,会存在两个数据集,一个是真实数据集,这好说,另一个是假的数据集,那这个数据集就是有生成网络造出来的数据集。好了根据这个图我们再来理解一下GAN的目标是要干什么:

    判别网络的目的:就是能判别出来属于的一张图它是来自真实样本集还是假样本集。假如输入的是真样本,网络输出就接近1,输入的是假样本,网络输出接近0,那么很完美,达到了很好判别的目的。

    生成网络的目的:生成网络是造样本的,它的目的就是使得自己造样本的能力尽可能强,强到什么程度呢,你判别网络没法判断我是真样本还是假样本。

    因此辨别网络的作用就是对噪音生成的数据辨别他为假的,对真实的数据辨别他为真的。

    而生成网络的损失函数就是使得对于噪音数据,经过辨别网络之后的辨别结果是真的,这样就能达到生成真实图像的目的。

    这里会感觉比较饶,这也是生成对抗网络的难点所在,理解了这点,整个生成对抗网络模型也就理解了。

     

    1. 工作模式

    一般的工作流程很简单直接:

    1. 采样训练样本的一个 minibatch,然后计算它们的鉴别器分数;

    2. 得到一个生成样本 minibatch,然后计算它们的鉴别器分数;

    3. 使用这两个步骤累积的梯度执行一次更新。

    下一个诀窍是避免使用稀疏梯度,尤其是在生成器中。只需将特定的层换成它们对应的「平滑」的类似层就可以了,比如:

    1.ReLU 换成 LeakyReLU

    2. 最大池化换成平均池化、卷积+stride

    3.Unpooling 换成去卷积

    两个主要网络模型,一个是生成器模型,一个是辨别器模型。

    辨别器模型要辨别两种数据源,一种是真实数据,一种是生成器生成的数据。这里可以分成两个辨别器模型,设置reuse=True来共享模型参数。

     

    2、代码

    import numpy as np
    import tensorflow as tf
    import matplotlib.pyplot as plt
    from tensorflow.examples.tutorials.mnist import input_data
    
    # TODO:数据准备
    mnist = input_data.read_data_sets('data')
    
    
    # TODO:获得输入数据
    def get_inputs(noise_dim, image_height, image_width, image_depth):
        # 真实数据
        inputs_real = tf.placeholder(tf.float32, [None, image_height, image_width, image_depth], name='inputs_real')
        # 噪声数据
        inputs_noise = tf.placeholder(tf.float32, [None, noise_dim], name='inputs_noise')
    
        return inputs_real, inputs_noise
    
    
    # TODO:生成器
    def get_generator(noise_img, output_dim, is_train=True, alpha=0.01):
        with tf.variable_scope("generator", reuse=(not is_train)):
            # 100 x 1 to 4 x 4 x 512
            # 全连接层
            layer1 = tf.layers.dense(noise_img, 4 * 4 * 512)
            layer1 = tf.reshape(layer1, [-1, 4, 4, 512])
            # batch normalization
            layer1 = tf.layers.batch_normalization(layer1, training=is_train)
            # Leaky ReLU
            layer1 = tf.maximum(alpha * layer1, layer1)
            # dropout
            layer1 = tf.nn.dropout(layer1, keep_prob=0.8)
    
            # 4 x 4 x 512 to 7 x 7 x 256
            layer2 = tf.layers.conv2d_transpose(layer1, 256, 4, strides=1, padding='valid')
            layer2 = tf.layers.batch_normalization(layer2, training=is_train)
            layer2 = tf.maximum(alpha * layer2, layer2)
            layer2 = tf.nn.dropout(layer2, keep_prob=0.8)
    
            # 7 x 7 256 to 14 x 14 x 128
            layer3 = tf.layers.conv2d_transpose(layer2, 128, 3, strides=2, padding='same')
            layer3 = tf.layers.batch_normalization(layer3, training=is_train)
            layer3 = tf.maximum(alpha * layer3, layer3)
            layer3 = tf.nn.dropout(layer3, keep_prob=0.8)
    
            # 14 x 14 x 128 to 28 x 28 x 1
            logits = tf.layers.conv2d_transpose(layer3, output_dim, 3, strides=2, padding='same')
            # MNIST原始数据集的像素范围在0-1,这里的生成图片范围为(-1,1)
            # 因此在训练时,记住要把MNIST像素范围进行resize
            outputs = tf.tanh(logits)
    
            return outputs
    
    
    # TODO:判别器
    def get_discriminator(inputs_img, reuse=False, alpha=0.01):
        with tf.variable_scope("discriminator", reuse=reuse):
            # 28 x 28 x 1 to 14 x 14 x 128
            # 第一层不加入BN
            layer1 = tf.layers.conv2d(inputs_img, 128, 3, strides=2, padding='same')
            layer1 = tf.maximum(alpha * layer1, layer1)
            layer1 = tf.nn.dropout(layer1, keep_prob=0.8)
    
            # 14 x 14 x 128 to 7 x 7 x 256
            layer2 = tf.layers.conv2d(layer1, 256, 3, strides=2, padding='same')
            layer2 = tf.layers.batch_normalization(layer2, training=True)
            layer2 = tf.maximum(alpha * layer2, layer2)
            layer2 = tf.nn.dropout(layer2, keep_prob=0.8)
    
            # 7 x 7 x 256 to 4 x 4 x 512
            layer3 = tf.layers.conv2d(layer2, 512, 3, strides=2, padding='same')
            layer3 = tf.layers.batch_normalization(layer3, training=True)
            layer3 = tf.maximum(alpha * layer3, layer3)
            layer3 = tf.nn.dropout(layer3, keep_prob=0.8)
    
            # 4 x 4 x 512 to 4*4*512 x 1
            flatten = tf.reshape(layer3, (-1, 4 * 4 * 512))
            logits = tf.layers.dense(flatten, 1)
            outputs = tf.sigmoid(logits)
    
            return logits, outputs
    
    
    # TODO: 目标函数
    def get_loss(inputs_real, inputs_noise, image_depth, smooth=0.1):
        g_outputs = get_generator(inputs_noise, image_depth, is_train=True)
        d_logits_real, d_outputs_real = get_discriminator(inputs_real)
        d_logits_fake, d_outputs_fake = get_discriminator(g_outputs, reuse=True)
    
        # 计算Loss
        g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,labels=tf.ones_like(d_outputs_fake) * (1 - smooth)))
    
        d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real,labels=tf.ones_like(d_outputs_real) * (1 - smooth)))
        d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,labels=tf.zeros_like(d_outputs_fake)))
        d_loss = tf.add(d_loss_real, d_loss_fake)
    
        return g_loss, d_loss
    
    
    # TODO:优化器
    def get_optimizer(g_loss, d_loss, learning_rate=0.001):
        train_vars = tf.trainable_variables()
    
        g_vars = [var for var in train_vars if var.name.startswith("generator")]
        d_vars = [var for var in train_vars if var.name.startswith("discriminator")]
    
        # Optimizer
        with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
            g_opt = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=g_vars)
            d_opt = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=d_vars)
    
        return g_opt, d_opt
    
    
    # 显示图片
    def plot_images(samples):
        fig, axes = plt.subplots(nrows=5, ncols=5, sharex=True, sharey=True, figsize=(7, 7))
        for img, ax in zip(samples, axes.flatten()):
            ax.imshow(img.reshape((28, 28)), cmap='Greys_r')
            ax.get_xaxis().set_visible(False)
            ax.get_yaxis().set_visible(False)
        fig.tight_layout(pad=0)
        plt.show()
    
    
    def show_generator_output(sess, n_images, inputs_noise, output_dim):
        noise_shape = inputs_noise.get_shape().as_list()[-1]
        # 生成噪声图片
        examples_noise = np.random.uniform(-1, 1, size=[n_images, noise_shape])
    
        samples = sess.run(get_generator(inputs_noise, output_dim, False),
                           feed_dict={inputs_noise: examples_noise})
    
        result = np.squeeze(samples, -1)
        return result
    
    
    # TODO:开始训练
    # 定义参数
    batch_size = 64
    noise_size = 100
    epochs = 5
    n_samples = 25
    learning_rate = 0.001
    
    
    def train(noise_size, data_shape, batch_size, n_samples):
        # 存储loss
        losses = []
        steps = 0
    
        inputs_real, inputs_noise = get_inputs(noise_size, data_shape[1], data_shape[2], data_shape[3])
        g_loss, d_loss = get_loss(inputs_real, inputs_noise, data_shape[-1])
        print("FUNCTION READY!!")
        g_train_opt, d_train_opt = get_optimizer(g_loss, d_loss, learning_rate)
        print("TRAINING....")
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            # 迭代epoch
            for e in range(epochs):
                for batch_i in range(mnist.train.num_examples // batch_size):
                    steps += 1
                    batch = mnist.train.next_batch(batch_size)
    
                    batch_images = batch[0].reshape((batch_size, data_shape[1], data_shape[2], data_shape[3]))
                    # scale to -1, 1
                    batch_images = batch_images * 2 - 1
    
                    # noise
                    batch_noise = np.random.uniform(-1, 1, size=(batch_size, noise_size))
    
                    # run optimizer
                    sess.run(g_train_opt, feed_dict={inputs_real: batch_images,
                                                     inputs_noise: batch_noise})
                    sess.run(d_train_opt, feed_dict={inputs_real: batch_images,
                                                     inputs_noise: batch_noise})
    
                    if steps % 101 == 0:
                        train_loss_d = d_loss.eval({inputs_real: batch_images,
                                                    inputs_noise: batch_noise})
                        train_loss_g = g_loss.eval({inputs_real: batch_images,
                                                    inputs_noise: batch_noise})
                        losses.append((train_loss_d, train_loss_g))
                        print("Epoch {}/{}....".format(e + 1, epochs),
                              "Discriminator Loss: {:.4f}....".format(train_loss_d),
                              "Generator Loss: {:.4f}....".format(train_loss_g))
    
                if e % 1 == 0:
                    # 显示图片
                    samples = show_generator_output(sess, n_samples, inputs_noise, data_shape[-1])
                    plot_images(samples)
    
    
    with tf.Graph().as_default():
        train(noise_size, [-1, 28, 28, 1], batch_size, n_samples)
        print("OPTIMIZER END!!")
    

     

    转载于:https://my.oschina.net/u/778683/blog/3100336

    展开全文
  • 深度学习(2)——生成对抗网络

    万次阅读 2018-12-08 17:35:59
    深度学习(2)——生成对抗网络 译文,如有错误请与笔者联系 摘要 本文提出一个通过对抗过程来预测生成模型的新框架,其中我们同时训练两个模型:一个用来捕捉数据分布的生成模型G和预测样本来自训练数据而...
  • 生成对抗网络——GAN(一)

    万次阅读 多人点赞 2019-03-18 18:51:51
    Generative adversarial network 据有关媒体统计:CVPR2018的论文里,有三分之一的论文与GAN有关!...生成对抗网络GAN,是当今的一大热门研究方向。在2014年,被Goodfellow大神提出来,当时的G...
  • 生成对抗网络

    千次阅读 2018-03-12 20:47:37
    之前 GAN网络是近两年深度学习领域的新秀,火的不行,本文旨在浅显理解传统GAN,分享学习心得。现有GAN网络大多数代码实现使用python、torch等语言,这里,后面用matlab搭建一个简单的GAN网...
  • CGAN(条件生成-对抗网络)简述教程

    万次阅读 多人点赞 2020-05-15 20:24:30
    一直以来提醒自己说,你要坚持,要坚持,要坚持更新,坚持读paper,要是现在都坚持不下去,还有将近...今天看的这篇论文其实很简单,名字叫《Conditional Generative Adversarial Nets》,简单来说就是条件生成-对抗...
  • 独家 | GAN之父NIPS 2016演讲现场直击:全方位解读生成对抗网络的原理及未来(附PPT) 原创: 加号 吴攀 机器之心 2016-12-10 机器之心原创 作者:机器之心分析师加号、吴攀 ... ...当地时间 12 月 5 日,机器学习...
  • 生成对抗网络GAN损失函数Loss的计算

    万次阅读 2017-09-22 14:53:02
    损失函数的计算辨别器对假数据的损失原理...生成器的目标是愚弄辨别器蒙混过关,需要达到的目标是对于生成的图片,输出为1.`d_loss_real = tf.reduce_mean( tf.nn.sigmoid_cross_entropy_with_logits(logits=d_log
  • 对抗样本与生成对抗网络

    万次阅读 2016-09-01 11:46:31
    最近一个月,人工智能领域听的最多的名词之一,莫过于对抗样本和对抗性网络,从最开始Yann LeCun在Quora上直播时表示生成对抗网络近期人工智能最值得期待的算法之一,到近日生成对抗网络的发明者Ian Goodfellow...
  • 【深度学习】生成对抗网络Generative Adversarial Nets

    万次阅读 热门讨论 2020-09-28 16:44:25
    介绍非监督深度学习经典论文GAN(Generative Adversarial Nets)
  • 对抗网络在文本生成图片中的应用

    千次阅读 2017-01-22 16:39:26
    1 简介利用神经网络可以从文本生成图片,即将文本的语义转化为图片; 也可以从图片生成文本,即生成的文本描述图片中的内容,例如一幅图片中有一直小鸟落在枝头。最后由图片生产的文本就可以能可爱的绿色小鸟落于枝头...
  • 深度学习项目实战-对抗生成网络

    千人学习 2020-06-24 14:45:35
    进入学习群,获取唐宇迪老师...后项目实战对抗生成网络的升级版DCGAN,大家都可以基于DCGAN生成出来任何你喜欢的数据。 课程代码基于Tensorflow框架,案例与项目课时会通过debug的形式详解代码中每行的用法。
  • 生成对抗网络GANs理解(附代码)

    万次阅读 多人点赞 2019-01-22 15:35:00
    对抗网络是14年Goodfellow Ian在论文Generative Adversarial Nets中提出来的。 记录下自己的理解,日后忘记了也能用于复习。生成模型和判别模型理解对抗网络,首先要了解生成模型和判别模型。判别模型比较好理解,...
  • 深度学习之对抗网络

    千次阅读 2017-06-14 22:27:57
    一. 对抗网络的由来  对抗网络 是个新词,全名叫 ... Ian Goodfellow(生成对抗性网络的发明者)定义了 对抗网络;  Yann LeCun(三巨头之一)在Quora上直播时表示生成对抗性网络近期人工智能最值得期待的算法之一;
  • 对抗生成网络(Generative Adversarial Net)

    万次阅读 多人点赞 2020-09-07 21:32:13
    现在,生成模型还没有体会到深度学习的利好,在Discriminative模型上,成果如雨后春笋,但在生成模型上,却并非如此。原因如下: - 在最大似然估计及相关策略上,很多概率计算的模拟非常难 - 将piecewise linear ...
  • 利用FGSM方法生成对抗样本的基本原理如下图所示,通过对原始图片添加噪声来使得网络对生成的图片X’进行误分类,需要注意的是,生成图片X’和原始图片X很像,人的肉眼无法进行辨别,生成的图片X’即为对抗样本!...
  • 深度学习之生成对抗网络(Gan)

    千次阅读 2018-07-14 20:35:32
    生成对抗网络(GAN,Generative Adversatial Networks)是一种深度学习模型,近年来无监督学习上最具前景的方法之一。 模型主要通用框架有(至少)两个模块:生成模型(generative)和判别模型(Discriminative)的...
  • 关于生成对抗网络(GAN)在先前的文章中已经提到了。请看我的前两篇博文。 https://blog.csdn.net/qq_21210467/article/details/81836976 https://blog.csdn.net/qq_21210467/article/details/81942447 现在来...
1 2 3 4 5 ... 20
收藏数 25,912
精华内容 10,364
关键字:

生成对抗网络