之前了解到的都是有监督学习(Supervised Learning):我们有数据x和标签y,目标是学习到一个函数可以将数据x映射到标签y,标签可以有很多形式。典型的有监督学习有:分类问题中输入一张图片,输出图片的分类;目标检测中输入一张图片,输出目标物体的边框;语义分割中,给每个像素都打上标签。
下面介绍一下无监督学习(Unsupervised Learning)。
本课重点:
-
无监督学习
-
生成模型
-
Pixel RNN/CNN
-
变分自编码器(VAE)
-
生成对抗网络(GAN)
-
1 无监督学习
无监督学习在我们只有一些没有标签的训练数据的情况下,学习数据中隐含的结构。无监督学习由于没有标签,数据获取也很容易。典型的无监督学习有以下几种:
聚类(k-Means)
聚类(Clustering)是找到数据的分组,组内数据在某种度量方式下是相似的。随机初始k个中心位置,将每个样本分配到最近的中心位置,然后根据分配的样本更新中心位置。重复直到中心位置不再变化。
PCA(主成分分析)
数据降维(Dimensionality reduction):找出一些轴,在这些轴上训练数据投影的方差最大。这些轴就是数据内潜在的结构。我们可以用这些轴来减少数据维度,数据在每个保留下来的维度上都有很大的方差。
特征学习(Feature Learning)
比如自编码(Autoencoders):
密度估计( Density Estimation)
估计数据的内在分布情况,比如下图上方有一些一维和二维的点,我们用高斯函数来拟合这一密度分布情况:
2 生成模型(Generative Models)
生成模型是一种无监督学习方法。其定义是给出一批由真实分布p-data(x) 产生的训练数据,我们的模型从中学习,然后以近似于真实的分布p-model(x) 来产生新样本。
为什么生成模型重要:生成样本,着色问题,强化学习应用,隐式表征推断等。下图左边为生成的图片,中间生成的人脸,还可以做超分辨率或者着色之类的任务。
生成模型分为显式和隐式的生成模型,往下分又可以分成很多子类。今天主要讨论三种模型:PixelRNN/CNN,变分自动编码器属于显示密度模型,生成对抗网络(GAN)属于隐式密度估计模型。
2.1 PixelRNN 和 PixelCNN
PixelRNN和PixelCNN使用概率链式法则来计算一张图片出现的概率。其中每一项为给定前 i-1 个像素点后第 i 个像素点的条件概率分布。这个分布通过神经网络 RNN 或 CNN 来建模,再通过最大化图片 x 的似然概率来学习出RNN或CNN的参数。
PixelRNN中,从左上角开始定义为“之前的像素”。由于RNN每个时间步的输出概率都依赖于之前所有输入,因此能够用来表示上面的条件概率分布。
训练这个RNN时,一次前向传播需要从左上到右下串行走一遍,然后根据上面的公式求出似然,并最大化似然以对参数做一轮更新。因此训练非常耗时。
PixelCNN中,使用一个CNN来接收之前的所有像素,并预测下一个像素的出现概率:
相比于PixelRNN,PixelCNN在训练时可以并行的求出公式中的每一项,然后进行参数更新,因此其训练速度要比pixelRNN快多了。
然而,无论是PixelRNN还是PixelCNN,其在测试时都需要从左上角开始逐个像素点地生成图片,因此测试阶段都比较慢。
PixelRNN和PixelCNN能显式地计算似然p(x),是一种可优化的显式密度模型,该方法给出了一个很好的评估度量,可以通过计算的数据的似然来度量出生成样本有多好。
2.2 变分自编码器(VAE)
PixelCNN定义了一个易于处理的密度函数,我们可以直接优化训练数据的似然;对于变分自编码器我们将定义一个不易处理的密度函数,现在我们通过附加的隐变量z对密度函数进行建模:我们数据的似然p(x)是等式右边的积分形式,即对所有可能的z值取期望,我们无法直接优化它,我们只能找出一个似然函数的下界然后再对该下界进行优化。
(1)自编码器
自编码器是为了无监督地学习出样本的特征表示,原理如下:
如上图,自编码器由编码器和解码器组成,编码器将样本x映射到特征z,解码器再将特征z映射到重构样本。为了能够使z解码后能够恢复出原来的x,我们最小化x与重构样本之间的L2损失,进而可以训练出编码器和解码器的参数。
编码器可以有多种形式,常用的是神经网络。最先提出的是非线性层的线性组合,然后有了深层的全连接网络,现在又出现了CNN,我们取得输入数据x然后将其映射到某些特征z,z的维度通常比x更小。降维是为了表示x中最重要的特征。第二个网络也就是解码器输出一些跟x有相同维度并和x相似的东西,也就是重构原始数据。解码器一般使用和编码器相同类型的网络(与编码器对称)。
训练好网络后,去掉解码器,使用训练好的编码器实现特征映射。通过编码器得到输入数据的特征,编码器顶部有一个分类器,如果是分类问题我们可以用它来输出一个类标签,在这里使用了外部标签和标准的损失函数如softmax:
此外,我们可以用很多无标签数据来学习到很多普适特征,可以用学习到的特征来初始化一个监督学习问题,因为在监督学习的时候可能只有很少的有标签训练数据,少量的数据很难训练模型,可能会出现过拟合等其他一些问题,通过使用上面得到的特征可以很好的初始化网络。
自动编码器具有重构数据、学习数据特征、初始化一个监督模型的能力。这些学习到的特征具有能捕捉训练数据中蕴含的变化因素的能力。我们获得了一个含有训练数据中变化因子的隐变量z。
(2)VAE的思想
VAE的思想是,既然我们无法直接获得样本x的分布,那么我们就假设存在一个x对应的隐式表征z,z的分布是一个先验分布比如高斯分布(或者其他简单的分布,总之是人为指定的)。例如我们想要生成微笑的人脸,z代表的就是眉毛的位置,嘴角上扬的弧度。z经过解码网络后,能够映射得到x的近似真实分布。这样的话我们就可以通过在标准正态分布上采样得到z,然后解码得到样本近似分布,再在此分布上采样来生成样本。对于这个采样过程,真实的参数是Θ*,是有关于先验假设和条件概率分布的参数,我们的目的在于获得一个样本生成式模型,从而利用它来生成新的数据,真实参数是我们想要估计并得出的。这个生成式模型如何表示呢?方法是选一个简单的关于z的先验分布,例如高斯分布,对于给定z的x的条件概率分布p(x|z)很复杂,所以我们选择用神经网络来对p(x|z)进行建模。
(3)如何训练VAE
现在的问题是,有一堆样本,我们如何从中学习出解码网络的参数,使得在标准高斯分布上采样得到的z,经过解码后得到的 x 的分布,刚好近似于x的真实分布呢?我们的方案是最大化样本 x 的似然P(x)。 在已经给定隐变量z的情况下,我们需要写出x的分布p并对所有可能的z值取期望,因为z值是连续的所以表达式是一个积分:
但如果利用求导来直接求最大化的似然,过程会很不好解。第一项是z的分布p(z),这里将它简单地设定为高斯分布,所以很容易求;p(x|z)是一个指定的神经网络解码器,也容易得到。但是计算所有的z对应的p(x|z)很困难,所以无法计算该积分。这样也导致p(z|x)是难解的。解决方法是,在使用神经网络解码器来定义一个对p(x|z)建模神经网络的同时,额外定义一个编码器q(z|x),将输入x编码为z,从而得到似然p(z|x)。也就是说我们定义该网络来估计出p(z|x),这个后验密度分布项仍然是难解的,我们用该附加网络来估计该后验分布,这将使我们得到一个数据似然的下界,该下界易解也能优化。
在变分自编码器中我们想得到一个生成数据的概率模型,将输入数据x送入编码器得到一些特征z,然后通过解码器网络把z映射到图像x。我们这里有编码器网络和解码器网络,将一切参数随机化。参数是Φ的编码器网络q(z|x)输出一个均值和一个对角协方差矩阵;解码器网络输入z,输出均值和关于x的对角协方差矩阵。为了得到给定x下的z和给定z下的x,我们会从这些分布(p和q)中采样,现在我们的编码器和解码器网络所给出的分别是z和x的条件概率分布,并从这些分布中采样从而获得值。
下面是推导过程:
这里引入了一个分布q(z|x),就是编码网络。这里我们暂时只把它当作一个符号,继续推导即可:
对第一项,我们有:
这样我们就得到了VAE的核心等式:
注意到这个式子的第三项中,含有p(z|x),而
由于这个积分无法求解出来,因此我们没办法求第三项的梯度。幸运的是,由于第三项是一个KL散度,其恒大于等于0,因此前两项的和是似然的一个下界。因此我们退而求其次,来最大化似然的下界,间接达到最大化似然的目的。
现在我们引入编码器网络来对q(z|x)建模,我们的训练框架如下:
如何得到下界:第一项是对所有采样的z取期望,z是x经过编码器网络采样得到,对z采样然后再求所有z对应的p(x|z)。让p(x|z)变大,就是最大限度地重构数据。第二项是让KL的散度变小,让我们的近似后验分布和先验分布变得相似,意味着我们想让隐变量z遵循我们期望的分布类型。
这个框架就非常类似于自编码器。其中最大化下界的第一项表示我们要能从解码器最大概率地重构出x,这一步等价于去最小化与样本x的均方误差。最小化下界的第二项则限定了z要遵循我们事先给它指定的分布。公式是我们要优化及最大化的下界,前向传播按如上流程处理,对输入数据x,让小批量的数据传递经过编码器网络的到q(z|x),通过q(z|x)来计算KL项,然后根据给定x的z分布对z进行采样,由此获得了隐变量的样本,这些样本可以根据x推断获得;然后把z传递给第二个解码器网络,通过解码器网络x在给定z的条件下的两个参数,均值和协方差,最终可以在给定z的条件下从这个分布中采样得到x。
训练时需要获得该分布,损失项是给定z条件下对训练像素值取对数,损失函数要做的是最大化被重构的原始输入数据的似然;对于每一个小批量的输入我们都计算这一个前向传播过程,取得所有我们需要的项,他们都是可微分的,接下来把他们全部反向传播回去并获得梯度,不断更新我们的参数,包括生成器和解码器网络的参数Θ和Φ从而最大化训练数据的似然。
训练好变分自编码器,当生成数据时只需要用解码器网络,我们在训练阶段就对z采样,而不用从后验分布中采样,在生成阶段会从真实的生成过程中采样。先从设定好的先验分布中采样,接下来对数据x采样。
需要注意的是,这个框架里面,梯度无法通过“采样“这个算子反向传播到编码器网络,因此我们使用一种叫做重采样的trick。即将z采样的算子分解为:
这样梯度不需要经过采样算子就能回流到编码器网络中。
(4)VAE的优缺点
VAE是在原来的自编码器上加了随机成分,那么在使用VAE的时候我们不是直接取得确定的输入x然后获得特征z最后再重构x,而是采用随机分布和采样的思想,这样我们就能生成数据。 为了训练模型VAEs,我们定义了一个难解的密度分布,我们推导出一个下界然后优化下界,下界是变化的,“变分”指的是用近似来解决这些难解的表达式,这是模型被称为变分自动编码器的原因。 VAEs优点:VAEs就生成式模型来说是一种有据可循的方法,它使得查询推断称为可能,如此一来便能够推断出像q(z|x)这样的分布,这些东西对其他任务来说会是很有用的特征表征。
2.3 生成对抗网络(Generative Adversarial Nets, GAN)
(1)理解GAN如何工作
我们之前的PixelCNN和PixelRNN定义了一个易于处理的密度函数,通过密度函数优化训练数据的似然;VAEs有一个额外定义的隐变量z,有了z以后获得了很多的有利性质但是我们也有了一个难解的密度函数,对于该函数我们不能直接优化,我们推到了一个似然函数的下界,然后对它进行优化。 现在我们放弃显式地对密度函数建模,我们想要得到的是从分布中采样并获得质量良好的样本。GANs中不再在显式的密度函数上花费精力,而是采用一个博弈论的方法,并且模型将会习得从训练分布中生成数据,而这一实现是基于一对博弈玩家。
相比变分自编码器,理解GAN如何工作非常简单。在GAN中我们定义了两个网络:生成器和判别器。判别器负责辨别哪些样本是生成器生成的假样本,哪些是从真实训练集中抽出来的真样本。生成器负责利用随机噪声z生成假样本,它的职责是生成尽可能真的样本以骗过判别器。
这种对抗形式的目标可以写成如下形式:
现在我们有两个玩家,通过一个mini max博弈公式联合训练这两个网络,该mini max目标函数就是如图所示的公式,我们的目标是让目标函数在Θg上取得最小值,Θg是指生成器网络g的参数;同时要在Θd上取得最大值,Θd指的是判别器网络的参数。 公式中各项的含义:第一项是在训练数据的分布上log(D(x))的期望,log(D(x))是判别器网络在输入为真实数据(训练数据)时的输出,该输出是真实数据从分布p-data中采样的似然概率;第二项是对z取期望,z是从p(z)中采样获得的,这意味着从生成器网络中采样,同时D(G(z))这一项代表了以生成的伪数据为输入判别器网路的输出,也就是判别器网络对于生成网络生成的数据给出的判定结果。 对该过程的解释:我们的判别器的目的是最大化目标函数也就是在Θd上取最大值,这样一来D(x)就会接近1,也就是使判别结果接近真,因而该值对于真实数据应该相当高,这样一来D(G(z))的值也就是判别器对伪造数据输出就会相应减小,我们希望这一值接近于0。因此如果我们能最大化这一结果,就意味着判别器能够很好的区别真实数据和伪造数据。对于生成器来说,我们希望它最小化该目标函数,也就是让D(G(z))接近1,如果D(G(z))接近1,那么用1减去它就会很小,判别器网络就会把伪造数据视为真实数据,也就意味着我们的生成器在生成真实样本。
这是一个无监督学习,所以不会人工给每个图片打上标签,但是生成器生成的图片我们标签为0或假,我们的训练集都是真实的图片,被标记为1或真。有了这些以后,对判别器的损失函数而言就会使用这些信息,判别器要做的就是对生成器生成的图片输出0,而对真实图片输出1,这其中没有外部标签。
如何训练:首先对判别器进行梯度上升,学习到θd来最大化该目标函数;对生成器进行梯度下降,θg进行梯度下降最小化目标函数,此时目标函数只取右边这一项,因为只有这一项与θg有关。
这里有个trick:我们观察生成器的损失函数形状如下:
发现当生成器效果不好(D(G(z)接近0)时,梯度非常平缓;当生成器效果好(D(G(z)接近1)时,梯度很陡峭。这就与我们期望的相反了,我们希望在生成器效果不好的时候梯度更陡峭,这样能学到更多。因此我们使用下面的目标函数来替代原来的生成器损失:
这样就使得在生成器效果不好时具有较大的梯度。此外,联合训练两个网络很有挑战,交替训练的方式不可能一次训练两个网络,还有损失函数的函数空间会影响训练的动态过程。
因此,GAN的训练过程如下:
- 在每一个训练迭代期都先训练判别器网络,然后训练生成器网络。
- 对于判别器网络的k个训练步,先从噪声先验分布z中采样得到一个小批量样本,接着从训练数据x中采样获得小批量的真实样本,下面要做的将噪声样本传给生成器网络,并在生成器的输出端获得生成的图像。此时我们有了一个小批量伪造图像和小批量真实图像,我们有这些小批量数据在判别器生进行一次梯度计算,接下来利用梯度信息更新判别器参数,按照以上步骤迭代几次来训练判别器。
- 之后训练生成器,在这一步采样获得一个小批量噪声样本,将它传入生成器,对生成器进行反向传播,来优化目标函数。
- 交替进行上述两个步骤。
训练完毕后,就可以用生成器来生成比较逼真的样本了。
(2)GAN的探索
- 传统的GAN生成的样本还不是很好,这篇论文在GAN中使用了CNN架构,取得了惊艳的生成效果:[Radford et al, “Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks”, ICLR 2016]
- Wasserstein GAN 一定程度解决了GAN训练中两个网络如何平衡的问题。
- 用GAN来做text->image
(3)GAN的优缺点以及热门研究方向
GAN不使用显式的密度函数,而是利用样本来隐式表达该函数,GAN通过一种博弈的方法来训练,通过两个玩家的博弈从训练数据的分布中学会生成数据。
GAN可以生成目前最好的样本,还可以做很多其他的事情。但是不好训练且不稳定,我们并不是直接优化目标函数,我们要努力地平衡两个网络。
总结
讲了三种目前最常用生成模型:
- PixelCNN和PixelRNN他们是显式密度模型,该模型优化的是一个显式的似然函数并产生良好的样本,但是效率很低,它是一个顺序的生成过程。
- VAE优化的是一个似然函数的下界,它会产生一个有用的隐式表征,可以用它来进行查询推断,生成的样本也不是特别好。
- GAN是目前能生成最好样本的模型,但是训练需要技巧且不稳定,查询推断上也有一些问题。
- 还有一些将模型的优点结合起来做的研究。