引言

本文主要探讨生成模型。在图片分类任务中,我们可以让机器知道猫和狗的不同,但它没有真正了解猫和狗是什么。也许当机器能自己画出一只猫的时候,那它才是真正知道猫是什么了。

关于这个主题有3个主要的方法:

  • PixelRNN
  • Variational Autoencoder(VAE)
  • Generative Adversarial Network(GAN)

先来了解下PixelRNN

PixelRNN

为了生成一张图片(eg,画出一只猫),每次只会一个像素点。

假设要画3 x 3的图片。

首先啥像素点都没有,那就随机给它一个颜色的像素点。

每个像素点都是一个3维的向量,R,G,B

假设是一个橙色的。

接下来就训练一个模型(神经网络模型,这里是循环神经网络,后面的文章会介绍),它的输入是刚才这个橙色的像素点,输出就是接下来要画的像素点。

假设它输出的是蓝色的像素点,就把它加到要画的图片上面。


现在图上有两个点了,那么再用同一个模型来生成下一个点,注意现在的输入是这两个点了。


假设它输出的是一个浅蓝色的点。

这里为什么可以输入两个点呢,因为RNN可以处理变长的输入。

现在图片上有三个点了,接下来就把这三个点做为输入,又可以得到一个点。

然后重复刚才的步骤,直到9点个全都生成完成。


假设最终生成的如上。PixelRNN主要做的事情就是这个。

看起来很简单,那它的表现会好吗。

这是真实世界的一只狗,假设把它的下半身挡住,让机器通过PixelRNN来生成它的下半身。

机器生成的狗图像是上面这三种。其实这表现已经很不错了。

它不仅可以用于图像上,还可以用在语音上。非常著名的例子就是wavenet,可以用来做语音合成。

红色框中的声音信号是已有的,蓝色框的都是生成的。

创造宝可梦

还是以宝可梦为例,现在我们看如何生成宝可梦。

我们可以得到792张宝可梦的小图,在让机器看完这些图片后,让它生成新的宝可梦。

原来的图像是40x40的,这里只取中间的20x20部分。

20x20的是这个样子。


每个像素用3个数字来描述。实际上这样做生成的像素点都偏向灰色。如果想产生非常鲜明的颜色,那么RGB里面需要某个特别高,其他都接近0。

但是在训练的时候往往做不到,如果把0-255正则化到0-1之间,如果输出用Sigmoid函数的话,Sigmoid函数的值往往都在0.5左右,很难生成0这种极端的值。所以生成的颜色RGB三个都差不多,看起来每张图片都是棕色或灰色的。

所以这里做了一下处理,把每个像素点都用一个1-of-N 编码的向量来表示。

在这个1-of-N编码中,每个维度都代表一个颜色。也就是说,不让它产色RGB三个去合成一个颜色,而是直接产色一个颜色。

比如说,绿色的话,只有绿色那个维度是1,其他都是0。
但是整个向量的长度是255x255x255,可能的颜色太多了。

怎么办呢,先做聚类,把接近的颜色聚到一起。

这样最终得到167个不同的颜色。

然后做PixelRNN得到一个模型,用这个模型来让机器预测它从来没看过的图像。

只给它看上半部分,让它生成下半部分。


上面是实际的图像,下面是机器生成的图像。看起来不错,但是实际上很难评价它好不好。

接下来尝试什么都不给,让机器生成一张完整的图像。为了让它每次画的图都不一样,在输出像素点的时候,我们增加个随机因素,不让它选概率最大的。

生成的图像是上面样子的。

Variational Autoencoder

在上篇文章中我们介绍过Autoencoder(自动编码器)


来回顾一下,输入一张图片,放到编码器中得到一个编码,然后再通过解码器输出一张图片,我们希望输出的图片和原图越接近越好。

在训练好这个模型后,我们可以拿出这个解码器(Decoder),再给它一个随机的编码,它的输出就是一张完整的图片。

但这样做的话得到的结果通常不会很好。

就引出了本节的主题VAE,用它来做结果就很不错。

VAE怎么做的呢?

从Auto-encoder中拿到编码器和解码器,在编码器的地方不直接输出编码,而是输出和输入向量同维度的两个向量{m,σ}\{m,\sigma\}{m,σ}。这里假设是3维的。

接下来用高斯分布来生成另外3维的向量eee,

然后通过ci=exp(σi)×ei+mic_i =exp(\sigma_i) \times e_i + m_ici​=exp(σi​)×ei​+mi​得到一个新的向量ccc。这个ccc才是编码code。

然后丢给解码器,希望解码器能最小化重构误差(reconstruction error)。

但是仅仅这样还不够,还需要最小化下式。

∑i=13−(exp(σi)−(1+σi)+(mi)2)\sum_{i=1}^3 -(exp(\sigma_i) - (1+\sigma_i) + (m_i)^2) i=1∑3​−(exp(σi​)−(1+σi​)+(mi​)2)


用VAE生成的图像是上面的样子。

那用VAE和PixelRNN有什么区别呢,用VAE理论上可以控制你要生成的图像。

假设我们用VAE来生成宝可梦,通过训练学好了一个vae 自动编码器后,得到一个10维的编码ccc。

我们再把解码器的部分拿出来,因为输出的向量也是10维,我固定其中8维,只随机生成2维的点。

我们选不同的点,和剩下的8维组成一个10维的向量当成输入,看输出的图像是什么样子。

这样我们就可以看出这个编码的每个维度分别代表什么意思,这样我们可以调整这个维度来生成我们想要的图像。

然后vae产生的图像是上面这个样子,它们都是变化了2个维度的结果。可以从这个变化看出来每个维度或许真的有些含义的。

我们可以看红框标出的那一列图像,上面好像是站着的东西,下面就变成趴着了。

下面是随机另外两个维度的例子。

从这些图片看,似乎都看的不太清除,都不像一个真正的宝可梦,但是这里还是可以找到一只比较像一点的。


看起来还是有头有尾巴的。

vaa还可以写诗,对,你没看错,吟的一首好诗。

写诗

我们把图像改成句子。


先随便拿两个句子,接下来通过这个encoder,转换成两个编码,然后画到这个二维图像中。

变成了两个点,把这两个点相连,中间等距间隔的取一些点。把这些新的点丢给Decoder,还原成句子。


大概就是这样子,其实生成的很多是一窍不通的。

为什么用VAE

我们先从直觉上来看为什么要用VAE

原来的自动编码器做的事情是把每张图片变成一个编码,假设这个编码是一维,可以在图上红线内表示。

满月和弦月的图分别得到两个编码,那假设在满月和弦月之间取一个点,再把这个点做解码,最终会得到怎样的图呢。我们期待它是满月和弦月中间的样子。
因为我们用的编码器和解码器都是NN ,都是非线性的,所以很难预测在满月和弦月之间到底是什么东西。

如果用VAE的好处是,当把满月的图变成编码后,它会在这个编码上增加噪声,在绿色箭头的范围内的编码重建后都应该还是一张满月。


弦月的图也一样。

但是你会发现,在红色光标的位置,同时希望重建为满月和弦月的图。但是只能产生一张图,在做训练的时候,需要最小化MSE,这样产生的图既像满月又像弦月,就能产生界于满月和弦月中间的图。


VAE的优势就体现出来了,我们再看下VAE的图,这个mmm代表的是原来的编码,ccc代表是加上噪声以后的编码,解码器要根据加上噪声后的编码把它重建回原来的图像。


σ\sigmaσ代表噪声的方差,代表噪声有多大。这里取指数为了确保它一定是正的。eee是从高斯分布中生成出来的值。 当你把σ\sigmaσ乘上eee再加到mmm的时候,就相当于把mmm加上了噪声。

这个eee的方差是固定的,因为是从一个确定参数的高斯分布中生成出来的。但是在乘上了σ\sigmaσ以后,它的大小就有所改变。这个σ\sigmaσ决定了噪声的大小,而这个σ\sigmaσ是从编码器产生的。

也就是说机器能自动学习这个值有多大。但是仅是这样是不够的。

因为让机器决定这个σ\sigmaσ的大小,机器可以说方差为0就好了,就等于是原来的编码,这样重构后的误差是最小的。

所以需要在这个方差上做一些限制,使得它不能太小。

∑i=13−(exp(σi)−(1+σi)+(mi)2)\sum_{i=1}^3 -(exp(\sigma_i) - (1+\sigma_i) + (m_i)^2) i=1∑3​−(exp(σi​)−(1+σi​)+(mi​)2)

exp(σi)exp(\sigma_i)exp(σi​)是蓝色的那条线,1+σi1+\sigma_i1+σi​是红色的那条线,蓝色的线减去红色的线得到的是绿色的这条线。

它的最低点是落在σ=0\sigma=0σ=0的地方,当σ=0\sigma=0σ=0时,方差就是111。最后的(mi)2(m_i)^2(mi​)2是正则化项。

这是直观上的理由,如果比较正式的解释要怎么做。

我们回归到我们要做的事情。

现在让机器做的事情是生成宝可梦的图的话,每张宝可梦的图都可以想成是高维空间中的一个点,

那现在要做的事情就是估计这个高维空间上的概率分布P(x)P(x)P(x),注意这里的xxx是一个向量。

只要我们知道这个P(x)P(x)P(x)的样子,就能生成像宝可梦样子的图。

那怎么估计这个分布的样子呢,我们可以用高斯混合模型(Gaussian Mixture Model)

我们现在有一个很复杂的分布(上图黑线),其实它是由很多个高斯用不同的权重叠加起来的结果。蓝色的线就是高斯分布。

只要高斯分布的数量够多,就可以产生很复杂的分布。

它的式子如下

P(x)=∑mP(m)P(x∣m)P(x) = \sum_mP(m)P(x|m) P(x)=m∑​P(m)P(x∣m)

假设你要从P(x)P(x)P(x)生成样本的时候,先决定从哪个高斯分布上生成样本,现在有很多高斯分布,每个高斯分布都有一个自己的权重。接下来根据每个权重来决定从哪个高斯上生成数据,然后再从你选择的高斯上生成数据。

那如何生成数据呢?


首先从多项分布中决定从哪个高斯分布中生成数据,mmm代表第几个高斯。

决定好了哪个高斯后,它会有自己的μ\muμ和Σ\SigmaΣ

这样就可以生成一个xxx出来,所以P(x)=∑mP(m)P(x∣m)P(x) = \sum_mP(m)P(x|m)P(x)=∑m​P(m)P(x∣m)是说那个高斯的权重P(m)P(m)P(m)乘以有了那个高斯后生成xxx的概率P(x∣m)P(x|m)P(x∣m),然后在求和。

在高斯混合模型中有很多问题,首先你要决定高斯分布的数量,在知道了数量后,还要知道每个高斯分布的参数和权重。

现在每个xxx都是从某个混合模型被生成的,这个和我们做分类是一样的,每个xxx都是来自于某个分类。

把数据做分类其实是不够的,更好的表示方式是用分布表示(distributional representation),也就是说每个xxx并不是属于某个类别,而是由一个向量来描述它的各个不同的面向的特性。

VAE其实就是高斯混合模型的分布表示的版本。

怎么说呢,首先我们要产生一个向量zzz,它是从高斯分布N(0,1)N(0,1)N(0,1)中出来的。这个向量的每个维度代表了你要生成的东西的某种特性。

假设zzz是这样的。

生成了zzz后,根据zzz可以决定高斯的μ(z),σ(z)\mu(z),\sigma(z)μ(z),σ(z)。这里的zzz是有一个这个高斯生成的,所以它有无穷种可能。所以μ,σ\mu,\sigmaμ,σ也有无穷多种可能。怎么给定一个zzz后,得到一个μ\muμ和σ\sigmaσ呢。

这里假设μ,σ\mu,\sigmaμ,σ都来自一个函数,把zzz代入产生μ\muμ的函数μ(z)\mu(z)μ(z)就能得到一个由zzz计算出来的μ\muμ。

所以xxx的产生式子是这样的:

实际上在产生zzz的高斯分布中每个点都可能被取样到,只不过生成中间部分点的概率比较大。

当你生成了一个点后,这个点会对应一个高斯分布。现在等于有无穷多个高斯分布。

现在的问题是我们如何找到这两个函数μ(z)\mu(z)μ(z)和σ(z)\sigma(z)σ(z)


我们可以说,NN就是一个函数,这个NN输入是zzz,输出就是两个向量。

现在P(X)P(X)P(X)就会变成这样子:

P(x)=∫zP(z)P(x∣z)dzP(x) =\int\limits_z P(z)P(x|z)dz P(x)=z∫​P(z)P(x∣z)dz

变成了P(z)P(z)P(z)的概率和知道zzz后xxx的概率P(x∣z)P(x|z)P(x∣z)对所有可能的zzz做积分,因为zzz是连续分布。


那我们要如何找到这个NN呢。

假设有了一笔xxx后,希望找到μ\muμ和σ\sigmaσ的函数,使得下式最大。

L=∑xlogP(x)L = \sum_x logP(x) L=x∑​logP(x)


调NN里面的参数使得LLL最大。

我们需要另一个分布q(z∣x)q(z|x)q(z∣x),它是给定xxx,决定在zzz上面的μ,σ\mu,\sigmaμ,σ,对应VAE的编码器。

和上面的NN不同,上面的NN是给定zzz,决定xxx的μ,σ\mu,\sigmaμ,σ,对应VAE的解码器。

也就是说,我们有另外一个NN,输入xxx后,它会告诉你zzz的μ,σ\mu,\sigmaμ,σ

回到最大化这个式子

L=∑xlogP(x)L = \sum_x logP(x) L=x∑​logP(x)


logP(x)=∫zq(z∣x)log⁡P(x)dzlogP(x) = \int\limits_z q(z|x)\log P(x)dz logP(x)=z∫​q(z∣x)logP(x)dz

因为q(z∣x)q(z|x)q(z∣x)是一个分布,相当于一个完备事件组,∫zq(z∣x)dz=1\int\limits_z q(z|x)dz=1z∫​q(z∣x)dz=1。

∫zq(z∣x)log⁡P(x)dz=∫zq(z∣x)log⁡(P(z,x)P(z∣x))dz\int\limits_z q(z|x)\log P(x)dz = \int\limits_z q(z|x)\log \left(\frac{P(z,x)}{P(z|x)}\right)dz z∫​q(z∣x)logP(x)dz=z∫​q(z∣x)log(P(z∣x)P(z,x)​)dz

这个是根据根据条件概率公式转换过来的

P(z∣x)=P(z,x)P(x)P(z|x) = \frac{P(z,x)}{P(x)} P(z∣x)=P(x)P(z,x)​

接下来上下式同乘以一个q(z∣x)q(z|x)q(z∣x)

∫zq(z∣x)log⁡(P(z,x)P(z∣x))dz=∫zq(z∣x)log⁡(P(z,x)q(z∣x)q(z∣x)P(z∣x))dz\int\limits_z q(z|x)\log \left(\frac{P(z,x)}{P(z|x)}\right)dz = \int\limits_z q(z|x)\log \left(\frac{P(z,x)}{q(z|x)}\frac{q(z|x)}{P(z|x)}\right)dz z∫​q(z∣x)log(P(z∣x)P(z,x)​)dz=z∫​q(z∣x)log(q(z∣x)P(z,x)​P(z∣x)q(z∣x)​)dz

因为它们在logloglog里面相乘,所以可以把它们转换成相加的形式:

∫zq(z∣x)log⁡(P(z,x)q(z∣x)q(z∣x)P(z∣x))dz=∫zq(z∣x)log⁡(P(z,x)q(z∣x))dz+∫zq(z∣x)log⁡(q(z∣x)P(z∣x))dz\int\limits_z q(z|x)\log \left(\frac{P(z,x)}{q(z|x)}\frac{q(z|x)}{P(z|x)}\right)dz = \int\limits_z q(z|x)\log \left(\frac{P(z,x)}{q(z|x)}\right)dz + \int\limits_z q(z|x)\log \left(\frac{q(z|x)}{P(z|x)}\right)dz z∫​q(z∣x)log(q(z∣x)P(z,x)​P(z∣x)q(z∣x)​)dz=z∫​q(z∣x)log(q(z∣x)P(z,x)​)dz+z∫​q(z∣x)log(P(z∣x)q(z∣x)​)dz


∫zq(z∣x)log⁡(q(z∣x)P(z∣x))dz\int\limits_z q(z|x)\log \left(\frac{q(z|x)}{P(z|x)}\right)dzz∫​q(z∣x)log(P(z∣x)q(z∣x)​)dz 就是相对熵KL(q(z∣x)∣∣p(z∣x))KL(q(z|x)||p(z|x))KL(q(z∣x)∣∣p(z∣x))(衡量两个分布间的距离,大于等于0)的形式。

所以

logP(x)≥∫zq(z∣x)log⁡(P(z,x)q(z∣x))dz=∫zq(z∣x)log⁡(P(x∣z)P(z)q(z∣x))dzlog P(x) \geq \int\limits_z q(z|x)\log \left(\frac{P(z,x)}{q(z|x)}\right)dz = \int\limits_z q(z|x)\log \left(\frac{P(x|z)P(z)}{q(z|x)}\right)dz logP(x)≥z∫​q(z∣x)log(q(z∣x)P(z,x)​)dz=z∫​q(z∣x)log(q(z∣x)P(x∣z)P(z)​)dz

我们把这项∫zq(z∣x)log⁡(P(x∣z)P(z)q(z∣x))dz\int\limits_z q(z|x)\log \left(\frac{P(x|z)P(z)}{q(z|x)}\right)dzz∫​q(z∣x)log(q(z∣x)P(x∣z)P(z)​)dz记作LbL_bLb​

现在有
logP(x)=Lb+KL(q(z∣x)∣∣p(z∣x))log P(x) = L_b +KL(q(z|x)||p(z|x)) logP(x)=Lb​+KL(q(z∣x)∣∣p(z∣x))

现在变成找P(x∣z)P(x|z)P(x∣z)和q(z∣x)q(z|x)q(z∣x)使得LbL_bLb​最大。

变成了突然要多找一项。如果我们只找P(x∣z)P(x|z)P(x∣z)这一项,来最大化LbL_bLb​的话。这样增加LbL_bLb​的时候,有可能会增加最大似然LLL,但是你不知道LLL和LbL_bLb​之间到底有什么样的关系。有可能会遇到当LbL_bLb​上升的时候,LLL反而下降。

引入q(z∣x)q(z|x)q(z∣x)可以解决这个问题。如果我们通过q(z∣x)q(z|x)q(z∣x)来最大化LbL_bLb​的话,首先q(z∣x)q(z|x)q(z∣x)和logP(x)logP(x)logP(x)是没关系的,logP(x)logP(x)logP(x)只和P(x∣z)P(x|z)P(x∣z)有关。所以不管q(z∣x)q(z|x)q(z∣x)怎么变化,logP(x)logP(x)logP(x)是不变的。上图中蓝线长度是一样的,但是我们现在最大化LbL_bLb​,也就是要最小化KLKLKL。也就是说会让LbL_bLb​和LLL越来越接近。

如果固定P(x∣z)P(x|z)P(x∣z),一直去调整q(z∣x)q(z|x)q(z∣x)的话,会让LbL_bLb​一直变大,最后KLKLKL会趋于0。
最后找到一个q(z∣x)q(z|x)q(z∣x),它和P(z∣x)P(z|x)P(z∣x)的分布一样的话,KLKLKL就会等于0,L=LbL=L_bL=Lb​。

这时,再增加LbL_bLb​的话,因为最大似然LLL一定会比LbL_bLb​大,所以这时可以确定LLL一定也会增大。这就是引入q(z∣x)q(z|x)q(z∣x)的原因。

当你在最大化q(z∣x)q(z|x)q(z∣x)的时候,会让KLKLKL越来越小。也就是说,会让q(z∣x)q(z|x)q(z∣x)和p(z∣x)p(z|x)p(z∣x)越来越接近。

所以接下来要做的事情是找P(x∣zP(x|zP(x∣z和q(z∣x)q(z|x)q(z∣x)让LbL_bLb​越大越好,而且最后会找到q(z∣x)q(z|x)q(z∣x)会和p(z∣x)p(z|x)p(z∣x)很接近。

我们继续化简下LbL_bLb​

Lb=∫zq(z∣x)log⁡(P(x∣z)P(z)q(z∣x))dz=∫zq(z∣x)log⁡(P(z)q(z∣x))dz+∫zq(z∣x)log⁡P(x∣z)dzL_b = \int\limits_z q(z|x)\log \left(\frac{P(x|z)P(z)}{q(z|x)}\right)dz \\ = \int\limits_z q(z|x)\log \left(\frac{P(z)}{q(z|x)}\right)dz + \int\limits_z q(z|x)\log P(x|z)dz Lb​=z∫​q(z∣x)log(q(z∣x)P(x∣z)P(z)​)dz=z∫​q(z∣x)log(q(z∣x)P(z)​)dz+z∫​q(z∣x)logP(x∣z)dz

观察发现这项也是P(z)P(z)P(z)和q(z∣x)q(z|x)q(z∣x)的KLKLKL距离表达式。

还记得吗, 这个q(z∣x)q(z|x)q(z∣x)是个NN,给定xxx就能得到qqq的参数。

所以现在如果要最小化KL(q(z∣x)∣∣p(z))KL(q(z|x)||p(z))KL(q(z∣x)∣∣p(z))(为什么是最小化,因为上式有个负号)

就是需要调qqq对应的这个NN,使得它产生的分布和高斯分布越近越好。

其实就是最小化

另外一项就是最大化

∫zq(z∣x)log⁡P(x∣z)dz=Eq(z∣x)[logP(x∣z)]\int\limits_z q(z|x)\log P(x|z)dz = E_{q(z|x)}[log P(x|z)]z∫​q(z∣x)logP(x∣z)dz=Eq(z∣x)​[logP(x∣z)]

就是logP(x∣z)log P(x|z)logP(x∣z)关于分布q(z∣x)q(z|x)q(z∣x)的期望。

相当于从q(z∣x)q(z|x)q(z∣x)去生成数据,使得logP(x∣z)log P(x|z)logP(x∣z)最大。这件事情其实就是自动编码器做的事情。

把xxx丢到NN中,它就会生成一个μ\muμ和σ\sigmaσ(q(z∣x)q(z|x)q(z∣x)),根据这两个参数,就得到了一个分布zzz,接下来就要最大化这个分布zzz产生xxx的概率,把这个zzz丢到另一个NN中,产生一个均值μ(x)\mu(x)μ(x)和方差σ(x)\sigma(x)σ(x)。一般在实际操作上,不会考虑方差,只考虑均值,只要让均值和xxx越接近越好。如果让这个NN输出的均值正好等于给定的输入xxx的话,那么这时候的logP(x∣z)logP(x|z)logP(x∣z)就最大。

所以其实就是自动编码器做的事情,让输入和输出越接近越好。

Conditional VAE

如果现在想让VAE产生手写数字,给它一个手写数字图片,然后它把这个数字的特性抽出来,接下来在丢进编码器的时候,可以同时给有关这个数字的特性的分布和这个数字是什么。就可以根据这个数字生成和它风格很相近的数字。

VAE的问题

VAE其实有个很严重的问题。
就是它没有真的学怎么产生一张看起来像真的图片。它所学到的事情是,它要产生一张图片和我们数据集中的某张图片越接近越好。

我们在评估它产生的图片和数据集中图片的相似度时,我们用像MSE这种方法来计算。

假设我们输出的图片和真的图片有一个像素点的差距,这个像素点在不同的位置其实会有不同的结果。VAE看这两张图片都是一样的好或不好。他没有办法产生新的图片。

所以接下来介绍另外一个方法,叫GAN(Generative Adversarial Netowrk,生成式对抗网络)

GAN

GAN是近年来复杂分布上无监督学习最具前景的方法之一。

GAN的概念有点像拟态的演化。

一种生物模拟另一种生物或模拟环境中的其他物体从而获得好处的现象叫拟态或称生物学拟态。

比如说这是一只枯叶蝶,它看起来就像一片枯叶。那它怎么会这么像枯叶呢,也许一开始它还是长得像正常的蝴蝶,但是它有类似像麻雀这种天敌,天敌会吃蝴蝶,它通常颜色来分辨蝴蝶,它知道蝴蝶不是棕色的。所以蝴蝶就演化了,变成了棕色的。

但是蝴蝶的天敌也跟着演化(进化,不进化的会饿死),它知道蝴蝶是没有叶脉的,它会吃没有叶脉的东西。

蝴蝶继续进化产生叶脉,它的天敌也会继续演化。知道最后无法分别枯叶蝶和枯叶为止。

GAN的概念是这样的,首先有第一代的生成器(Generator),它可能是随机初始的,生成的图像看上去不像真实的。


接下来有第一代的鉴别器(discriminator),它用真的图像和生成的图像做对比,调整参数,判断是否是产生的。

接下来生成器根据鉴别器来演化,它会调整参数,然后第二代的生成器产生的图像更像真的。

接下来第二代鉴别器会再次根据真实图像和生成器产生的图像来更新参数。

然后就有了第三代的生成器,它产生的图像更像真实的。第三代的生成器产生的图像可以骗过第二代的鉴别器,第二代的生成器可以骗过第一代的鉴别器。但是鉴别器也会进化,它可能可以分辨第三代产生的数字和真实的数字。

要注意的是,生成器从来没看过真正的图像是什么样的,它做的事情是要骗过看过真正图像的鉴别器。

因为生成器没有看过真正的图像,所以它可以产生出来数据集中从来没有见过的图像。
这比较像我们想要机器做的事情。

Discriminator

我们来看下分辨器是怎么训练的。

这个分辨器其实就是一个NN,它的输入是一个张图片,输出是1(真图片)或0(假图片)。

那生成器是什么呢,生成器在这里的架构和VAE的解码器一样。它也是一个NN,它的输入是从一个分部中生成出的一个向量,把这个向量丢到生成器中,就会产生一个数字样的图像。给它不同的向量可以产生不样子的图像。

先让生成器产生一堆假的图片,然后辨别器首先将这些产生的数字图片都标记为0,把真正的数字图像都标记为1,接下来就是一个二分类问题,就是训练一个辨别器。

接下来如何训练生成器呢

Generator

现在已经有了第一代的分辨器,怎么根据第一代的分辨器,来更新第一代的生成器。

首先随机输入一个向量,生成器会产生一张图片,这张图片可能无法骗过鉴别器。


接下来调整生成器的参数,让鉴别器认为现在产生的图片是真的。就是让鉴别器输出的值越接近1越好。

比如生成一个这样的图片就能骗过鉴别器。那么要如何做呢。

因为生成器和鉴别器都是NN,把生成器的输出,当成鉴别器的输入,然后让鉴别器产生一个标量(0~1)。

把它们看成一个整体的话,就像有个很大的神经网络,丢个随机的向量,就会产生一个数值标量。让这个输出标量接近于1是很容易的,只要做梯度下降,来更新参数就好了。

但是要注意的是,在更新这个NN的参数时,比如通过反向传播更新参数时,我们要固定鉴别器的参数,只能调整生成器的参数。

这里有个玩具例子,说的是现在有个一维的东西zzz,也就是解码器的输入。

把zzz丢到生成器中会产生另外一个一维的东西xxx,每个不同的zzz会得到不同的xxx。

就会有一个分布,xxx的分布就是绿色的,现在希望生成的输出越像真实数据越好,真实数据的分布是黑色的线,希望绿色的线能和黑色的线越接近越好。

如果按照GAN的概念,就是把生成的点和真实的点丢到鉴别器中,然后让鉴别器判断是真实数据的概率。鉴别器输出的就是绿色的曲线。

假设现在生成器还很弱,它生成的分布是这样的蓝色曲线。

这个分辨器根据真实数据,就会判断说,如果是这样的点,那么它们比较有可能是生成的。

接下来生成器就根据辨别器的结果去调整参数,因为在上图中左边的的点更像真实数据,调整参数的结果就把它的输出往左边移。

因为GAN是很难训练的,可能一次移动太多,过于偏左,因此要小心地调参数。这样绿色的分布曲线就会更加接近真正点的黑色分布曲线。

接下来分辨器会更新绿色曲线。

这个过程会反复进行,直到生成器产生的点分布和真实数据一样。

我们来看一个例子,下面哪个是机器产生的图片?

右边的是生成的,有21%的产生的图像能骗过人。

看起来不错是吧,实际上GAN很难去优化。因为无法衡量生成器真正的有多好。

参考

1.李宏毅机器学习

李宏毅机器学习——无监督学习(五)相关推荐

  1. 李宏毅机器学习笔记(五)-----Where does the error come from

    视频来源: 李宏毅机器学习(2017)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili https://www.bilibili.com/video/av10590361/?p=5 functio ...

  2. 机器学习-无监督学习-聚类:聚类方法(一)--- k-Means(k-均值)算法,k-Means++算法【使用最大期望值算法(EM算法)来求解】

    一.聚类算法 1.聚类算法概述 聚类算法:一种典型的无监督学习算法(没有目标值),主要用于将相似的样本自动归到一个类别中.在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,对于不同的相似度计 ...

  3. apriori算法_机器学习(无监督学习)关联规则Apriori算法原理与python实现

    关联规则Apriori算法 1.关联规则概述 关联规则算法是在一堆数据集中寻找数据之间的某种关联,通过该算法我们可以对数据集做关联分析--在大规模的数据中寻找有趣关系的任务.这些关系可以有两种形式:频 ...

  4. 算法——机器学习——无监督学习—— K均值(K-means)图解动画

    快速排序 简介 算法过程 算法过程详解 一:聚类 二:聚类中心移动 算法结束 简介 k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预 ...

  5. 机器学习-无监督学习-聚类:聚类方法(二)--- 基于密度的聚类算法【DBSCAN文本聚类算法,密度最大值文本聚类算法】

    密度聚类方法的指导思想是,只要样本点的密度大于某阀值,则将该样本添加到最近的簇中. 基于密度的聚类算法假设聚类结构能够通过样本分布的紧密程度确定,以数据集在空间分布上的稠密程度为依据进行聚类,即只要一 ...

  6. 吴恩达机器学习笔记-无监督学习

    机器学习-无监督学习 一.什么是无监督学习 二.聚类算法(无监督学习) 1.聚类算法的应用 2.K-Means算法 算法流程--图例 算法流程--文字描述 K-means分离不佳簇问题 K-means ...

  7. 机器学习两种方法——监督学习与无监督学习

    通俗讲解 一.前言 二.定义 1.监督学习 2.无监督学习 三.区别 四.范围 1.监督学习 2.无监督学习 五.选择 一.前言 在介绍监督学习和无监督学习之前,我们首先来了解一下什么是特征值和目标值 ...

  8. 入门机器学习(十五)--无监督学习(K均值)

    1.无监督学习-简介(Unsupervised Learning-Introduction) 如下图所示是一个典型的监督学习,训练集中的每一个样本都有标签,我们需要根据标签来拟合一个假设函数. 什么是 ...

  9. 【李宏毅机器学习】Unsupervised Learning - Word Embedding 无监督学习 - 词嵌入(p22) 学习笔记

    文章目录 Unsupervised Learning Word Embedding 用一个vector来表示一个word的几种方法 1-of-N Encoding Word Class Word Em ...

  10. 机器学习基础(五十七)—— 监督学习、无监督学习

    仅使用 inputs x(t)\mathbf x^{(t)} 用于学习: automatically extract meaningful features for your data leverag ...

最新文章

  1. exchange无法收发邮件_Python使用POP3和SMTP协议收发邮件!
  2. 导向滤波python_导向滤波(Guided Filter)简要介绍
  3. 省吃俭用 ,究竟祸害了多少人 ?
  4. 领域驱动设计和开发实战总结
  5. python读写不同编码txt文件
  6. 面试时,如何巧妙回答跳槽问题
  7. 怎么撤销工作表保护,没有密码?
  8. 梅特勒托利多xk3124电子秤说明书_梅特勒托利多电子称设置方法
  9. android gui工具,搞机助手简约易用的安卓ADB GUI玩机工具箱
  10. 【计算机组成原理——定点数原码一位乘法手算】
  11. Matplot pyplot绘制单图,多子图不同样式详解
  12. 鸿蒙支持ps4手柄吗,完美兼容PS4手柄!iPhone也能畅玩PS4,教程在此
  13. node之cookie-parser
  14. VTK错误解决合集(持续更新中......)
  15. [图形学] 延迟贴花渲染技术 (A Deffered Decal Rendering Technique)
  16. git pull指令报错:error: You have not concluded your merge (MERGE_HEAD exists).
  17. Mockito3.8 如何mock静态方法 (如何mock PageHelper)
  18. Android博通BCM libbt-vendor.so 分析蓝牙初始化流程
  19. HIVE优化的四种方法
  20. kafka报错The request included a message larger than the max message size the server will accept

热门文章

  1. 浏览器的控制台-----后期更新
  2. k8s资源对象及API群组
  3. 解决EasyDSS、EasyNVR流媒体RTMP、HLS(m3u8)、HTTP-FLV播放提示H5播放错误的问题
  4. oracle中nvarchar2查询结果显示总是少一位
  5. wamp3.1.0下载地址
  6. 可以在函数中间打点了,以分析bpf_prog_load函数为例
  7. Linux系统下安装Mysql
  8. .net为图片添加水印(转) jpg png和gif格式
  9. 在ECSHOP模板商品列表页 显示商品的评论等级和评论数量
  10. SVN Error: Unreadable path encountered; access denied;