【深度之眼cs231n第七期】笔记(三十)


监督学习的数据需要标签,目标是学习一个函数把数据x映射成标签y。
监督学习的例子有:分类、回归、目标检测、语义分割、生成图像描述等等。

【深度之眼cs231n第七期】笔记(三十)
无监督学习则不需要标签,它想要学习数据的隐藏信息。
无监督学习的例子有:聚类、降维、密度估计(从大量的数据中估计数据的分布)等等。
【深度之眼cs231n第七期】笔记(三十)
训练图像是服从某个概率分布的,生成模型(一个无监督的模型)想要学习这个分布,这样就能从这个分布中生成新的数据。
生成模型有两大类,一种显式定义分布并解决它,另一类只学习如何从分布中生成新的数据,不需要显式地定义分布。
【深度之眼cs231n第七期】笔记(三十)
为什么要学习生成模型?

  • 生成艺术性图像、图像超分辨率、图片上色
  • 学习有用的特征为后续任务(比如分类)服务
  • 获取高维数据(比如物理、医学图像)间的联系
  • 为现实世界建模(机器人和强化学习)

【深度之眼cs231n第七期】笔记(三十)
会讲3种生成模型:PixelRNN/CNN(显式密度估计,能直接解决的)、变分自编码(显式密度估计,不能直接解决的)、GAN(隐式密度估计)
【深度之眼cs231n第七期】笔记(三十)

PixelRNN/CNN

使用链式法则表达图像x的似然函数。在前面所有像素确定的情况下,预测下一个像素的值。
【深度之眼cs231n第七期】笔记(三十)
在前面所有像素确定的情况下,预测下一个像素的值,这很容易想到RNN。
但是PixelRNN(每次生成一个像素)在训练阶段和应用阶段都非常慢
【深度之眼cs231n第七期】笔记(三十)
PixelCNN还是和PixelRNN一样,从图像的角落开始,每次生成一个像素。不过PixelCNN不使用前面的所有像素了,只使用附近的上下文信息。
在训练时PixelCNN比PixelRNN快,因为附近的上下文信息是知道的。但它依旧非常慢。
【深度之眼cs231n第七期】笔记(三十)
PixelRNN/CNN的优点:

  • 可以显式地表示图像x的似然函数
  • 易于优化
  • 生成的结果不错

缺点:

  • 由于是顺序生成像素,所以非常慢

【深度之眼cs231n第七期】笔记(三十)

变分自编码

这里有变分自编码的介绍。
变分自编码定义了一个关于图像x的(带隐变量z的)似然函数,但是这个似然函数不能直接优化,所以实际优化的是似然函数的下界。
【深度之眼cs231n第七期】笔记(三十)
在讲变分自编码之前,先讲一下自编码
自编码是一种无监督模型,它能学习无标签数据的特征z(维度通常比x的小,因为只想学习主要的特征)。

主要的训练过程是:

  1. 把数据x输入编码器,编码器输出图像的特征z
  2. 然后把特征z输入解码器,希望得到(输入数据)x作为输出
  3. 自编码器的损失是输入图像x和解码器的输出x^ 之间的相似度(两者相似,说明隐变量z获取到了x的主要特征)

训练后,可以丢掉解码器,然后用编码器输出图像的特征z。
【深度之眼cs231n第七期】笔记(三十)
自编码器可以用于初始化一个有监督的模型
以一个分类模型为例子:

  1. 把编码器作为分类模型的一部分,在编码器后面加上分类器
  2. 计算损失,训练分类器,微调编码器

【深度之眼cs231n第七期】笔记(三十)
从另一个角度来看,解码器能够用特征z重构数据x,如果输入一个新的z,就能生成一张新的图片,但是这个z怎么获取呢?这个问题并不好解决,因为我们并不知道特征空间的分布,也就没办法获取z。

研究人员从另一个方向解决了使用特征z生成数据x的问题——变分自编码:直接假设z服从某个分布(比如高斯分布),那么只需要训练一个类似于解码器的网络就可以了。
变分自编码和自编码类似,但是由于我们假设z服从特定分布(比如高斯分布),所以希望自编码器的隐变量z也服从该分布。因此,变分自编码的损失函数要加上一个KL散度(用于衡量隐变量z的分布和高斯分布的相似程度),剩下的部分和自编码相同。

训练完变分自编码后,就可以直接从高斯分布中采样得到z,然后生成新的图片数据。
使用MNIST训练的变分自编码中,隐变量z的维度为2,改变z的值后,能够生成不同的手写数字,如下图所示:
【深度之眼cs231n第七期】笔记(三十)
变分自编码的优点:

  • 生成模型的根本方法,假设z服从某个分布,从z生成数据
  • z所在的隐藏空间,有较好的可解释性
  • 允许从图像x推断出z( q(z|x) ),可用于其他任务的特征表示

缺点:

  • 优化似然函数的下界,估计的结果没有PixelRNN/CNN好
  • 生成图片的质量不够好,比不上GAN等

【深度之眼cs231n第七期】笔记(三十)

GAN

GAN的训练技巧
GAN不想显式定义密度函数,它希望能直接生成图像数据。但是图像数据的分布非常复杂,没办法直接从该分布里采样(也就是生成图片)。
解决办法是:从一个简单的分布中采样(比如随机均匀噪声),然后把采样得到的数据映射到图像数据(由于映射比较复杂,一般用神经网络),这样就能生成新的图像数据。
【深度之眼cs231n第七期】笔记(三十)
但是该如何训练从z到图像数据的映射呢?
解决办法是,再训练一个判别器,它能判断图像是否属于图像数据分布,如果生成的图像被认为属于图像数据分布,那么生成模型就学习到了从z到图像数据的映射。
所以生成器的梯度是从判别器里传回来的
【深度之眼cs231n第七期】笔记(三十)
GAN里有两个网络在博弈:
判别器:判断一张图像是否来自训练数据,还是生成器生成的
生成器:尽量生成真实的图片,让判别器认为是真的
【深度之眼cs231n第七期】笔记(三十)
关于GAN的损失函数

  1. 先来看判别器部分
    判别器使用的是二元交叉熵损失,公式如下:
    【深度之眼cs231n第七期】笔记(三十)
    由于判别器的输入包含两部分:真实数据(标签为1)和生成器生成的数据(标签为0),所以判别器的损失如下:
    【深度之眼cs231n第七期】笔记(三十)
    这个损失和下面的损失还差了一个负号,这是因为上面是对损失进行最小化,而下面的式子要进行最大化
  2. 生成器的损失:由于上面提到过,生成器并不能直接训练,所以求它的梯度时要用到判别器的损失。
    又由于整个表达式表达的是判别器分类正确的能力,所以生成器希望判别器的能力减弱(识别不出生成的数据),也就是说生成器希望最小化下图中的损失

【深度之眼cs231n第七期】笔记(三十)
把生成器和判别器的损失写开(因为每次只能更新其中一个)后,公式如下:
但是这个公式对生成器并不友好,如图中的右下角所示,生成器在结果不好的时候(被判别器判别为0附近),梯度平缓,每次更新变化不大,实际上想要梯度大一些;而在生成器结果比较好的时候,梯度反而很大,这就可能在最优点附近震荡甚至越过最优点。
【深度之眼cs231n第七期】笔记(三十)
所以对生成器的损失进行了修改(把最小化改为最大化),修改后的损失就满足我们的要求了。
【深度之眼cs231n第七期】笔记(三十)
GAN的训练过程:

  1. 更新k次判别器
    1.1. 采样m个噪声数据,使用生成器生成m张图片,标签为0
    1.2. 选取m张训练数据,标签为1
    1.3. 把这2m个数据输入判别器,训练并更新判别器
  2. 更新一次生成器
    2.1. 采样m个噪声数据,使用生成器生成m张图片,标签为1
    2.2. 把这m个数据输入判别器,得到关于生成器的梯度(判别器中包含生成器生成的数据),更新生成器

关于判别器的更新次数k,有很多争议,有人认为k=1就可以了,有人认为k>1会更稳定,不过Wasserstein GAN和BEGAN等缓解了这个问题,因为它们更稳定。
【深度之眼cs231n第七期】笔记(三十)
在训练完整个GAN网络后,就可以直接把随机噪声z输入生成器中生成新的图片了。
【深度之眼cs231n第七期】笔记(三十)
GAN的一些技巧:

  • 在判别器,使用步长较大的卷积代替所有池化层;在生成器,使用转置卷积
  • 在判别器和生成器中都使用BatchNorm
  • 在较深的结构中,去掉全连接隐藏层
  • 在生成器中,除了最后一层的**函数用Tanh以外,每一层的**函数都用ReLU
  • 判别器中的每一层的**函数都用LeakyReLU

【深度之眼cs231n第七期】笔记(三十)
在两个z中做插值,生成的图像也在缓慢过渡
【深度之眼cs231n第七期】笔记(三十)
z的可解释性,能生成带眼镜男人图像的z-能生成男人图像的z+能生成女人图像的z,最后得到的z能够生成带眼镜女人的图像。
【深度之眼cs231n第七期】笔记(三十)GAN Zoo里有很多训练GAN的技巧。

研究人员还在研究GAN的训练技巧和更稳定的GAN:
【深度之眼cs231n第七期】笔记(三十)
GAN的一些应用:把图片中的马变成斑马、从文字描述生成图片,为草图上色等等
【深度之眼cs231n第七期】笔记(三十)
GAN的优点:

  • 生成的结果很好

缺点:

  • 不稳定
  • 得不到数据的显式分布

【深度之眼cs231n第七期】笔记(三十)
其他有助于理解生成模型的资源:
【深度之眼cs231n第七期】笔记(三十)