3.1 生成模型
3.1.1 生成模型简介
1. 什么是生成模型
在开始介绍生成对抗网络之前,我们先看一下什么是生成模型。在概率统计理论中,生成模型是指能够在给定某些隐含参数的条件下随机生成观测数据的模型,它给观测值和标注数据序列指定一个联合概率分布。在机器学习中,生成模型可以用来直接对数据建模,例如根据某个变量的概率密度函数进行数据采样,也可以用来建立变量间的条件概率分布,条件概率分布可以由生成模型根据贝叶斯定理形成。
如图3-1所示为生成模型的概念示意图,对于输入的随机样本能够产生我们期望数据分布的生成数据。举一个例子,一个生成模型可以通过视频的某一帧预测出下一帧的输出。另一个例子是搜索引擎,在输入的同时,搜索引擎已经在推断你可能搜索的内容了。可以发现,生成模型的特点在于学习训练数据,并根据训练数据的特点来产生特定分布的输出数据。
图3-1 生成模型概念图
对于生成模型来说,可以分为两个类型,第一种类型的生成模型可以完全表示出数据确切的分布函数。第二种类型的生成模型只能做到新数据的生成,而数据分布函数则是模糊的。本书讨论的生成对抗网络属于第二种,第二种类型生成新数据的功能也通常是大部分生成模型的主要核心目标。
2. 生成模型的作用是什么
生成模型做的事情似乎就是为了产生那些不真实的数据,那我们究竟为何要研究生成模型呢?
虽说生成模型的功能在于生成假数据,但在科学界和工业界中确实可以起到各种各样的作用。Ian在NIPS2016的演讲中给出了很多生成模型的研究意义所在[2]。
首先,生成模型具备了表现和处理高维度概率分布的能力,而这种能力可以有效运用在数学或工程领域。其次,生成模型,尤其是生成对抗网络可以与强化学习领域相结合,形成更多有趣的研究。此外,生成模型亦可通过提供生成数据来优化半监督式学习。
当然,生成模型也已经在业内有了非常多的应用点,比如将生成模型用于超高解析度成像,可以将低分辨率的照片还原成高分辨率,此类应用非常有用,对于大量不清晰的老照片,我们可以采用这项技术加以还原,或者对于各类低分辨率的摄像头等,也可以在不更换硬件的情况下提升其成像能力。
使用生成模型进行艺术创作也是非常流行的一种应用方式,可以通过用户交互的方式,输入简单的内容从而产生艺术作品的创作。
此外还有图像到图像的转换、文字到图像的转换等。这些内容都非常有趣,不仅可以应用于工业与学术领域,也可应用于消费级市场。更多关于应用方面的详细介绍会在本书的后半部分中展开详述。
3.1.2 自动编码器
我们已经清楚了生成模型其实要做的事情就是让机器学习大量的训练数据,从而具备能够产生同类型新数据的能力。那现在我们来看一下,究竟有哪些方法可以实现上述功能呢?从本小节开始,我们来看一下实际可用的生成模型。
首先在这里介绍一个叫作自动编码器(auto-encoder)的方法。自动编码器是一种神经网络模型,该模型的最初意义是为了能够对数据进行压缩。如图3-2所示是一个标准的自动编码器,它的基本结构是一个多层感知器的神经网络,从输入层到输出层之间有多个隐含层,它的结构特点在于输入层与输出层拥有相同的节点数量,中间编码层的节点数量需要小于输入层与输出层的节点数。
图3-2 自动编码器示意图
该网络结构希望能够在输出层产生的数据X′良好地还原出输入层的数据X,由于中间的编码层数据z拥有的维度数量低于输入层与输出层的维度,所以如果输出层可以还原输入层,相当于对输入数据进行了降维,也就是前面所说的数据压缩。
在自动编码器中,我们把输入层到编码层的网络部分(也就是整个神经网络的前半部分)称为编码器,把编码层到输出层的网络部分(图3-2中后半部分)称为解码器。编码器可以实现数据的压缩,将高维度数据压缩成低维度数据,解码器则可以将压缩数据还原成原始数据,当然由于对数据进行了降维处理,所以在还原的过程中数据会有一些损失。
自动编码器的训练过程需要将编码器与解码器绑定在一起进行训练,训练数据一般是无标签数据,因为我们会把数据本身作为它自身的标签。大致训练过程的伪代码参见伪代码3-1:
伪代码3-1 自动编码器训练过程
while循环输入数据X do
前向传输通过所有隐含层,得到输出层数据X′;
计算X′与X的偏差程度;
反向传输误差值,从而更新网络参数;
end while
除了数据压缩的功能以外,研究人员也使用自动编码器来实现生成模型的功能。当我们使用如上训练过程对自动编码器进行了某类型数据的训练后,编码器与解码器分别具备了此类型数据的编码/解码能力。在训练之后,我们可以单独使用解码器作为生成模型,在编码层输入任意数据,解码器都可以产生对应的生成数据。
图3-3展示的是自动编码器在手写数字数据集上的应用,可以看到原始输入数据的手写数字“2”在经过编码器后形成了一组压缩形式的编码,而这项编码经过解码器之后输出了一个与原始数据非常接近的输出图像,虽然有些许模糊,但是基本还原了手写数字“2”的形态。
图3-3 自动编码器在手写数据集上的应用
如图3-3所示,在生成模型的应用中我们仅使用模型的后半部分,当我们对解码器输入任意编码时,解码器会给出相应的输出数据。由于受到训练数据集的限制,生成的数据往往也是和输入数据相关的内容。
我们可以在网络上找到自动编码器的具体实现方法,比如Keras的官方博客[1]给出了自动编码器在Keras上的实现,本书不做过多介绍。
自动编码器看起来似乎是生成模型的一个不错的实现方案,但是在实际使用中存在很多问题,导致自动编码器其实并不太适合用来做数据生成,现在的自动编码器网络结构仅仅能够记录数据,除了通过编码器以外无法产生任何隐含编码(latent code)来生成数据,如图3-4所示。
图3-4 生成模型的应用
还是以手写数字数据集作为例子,对于每一个手写数字我们会产生一个相应的编码,当我们对解码器输入相应的编码时往往能够很好地还原出当时的手写数字,然而当我们对解码器输入一个训练集中未出现过的编码时,可能会发现输出的内容居然是噪声,也就是说和手写数字数据集完全没有关系。这不是我们想要的结果,我们希望生成模型能够对于任意的输入编码产生有相关意义的数据。针对这个问题,研究人员提出了自动编码器的升级版本——变分自动编码器(Variational Auto-Encoder,VAE)。
3.1.3 变分自动编码器
相比于普通的自动编码器,变分自动编码器(VAE)其实才算得上是真正的生成模型。
为了解决前文中叙述的自动编码器存在的不能通过新编码生成数据的问题,VAE在普通的自动编码器上加入了一些限制,要求产生的隐含向量能够遵循高斯分布,这个限制帮助自动编码器真正读懂训练数据的潜在规律,让自动编码器能够学习到输入数据的隐含变量模型。如果说普通自动编码器通过训练数据学习到的是某个确定的函数的话,那么VAE希望能够基于训练数据学习到参数的概率分布。
我们可以通过图3-5看一下VAE具体的实现方法,在编码阶段我们将编码器输出的结果从一个变成两个,两个向量分别对应均值向量和标准差向量。通过均值向量和标准差向量可以形成一个隐含变量模型,而隐含编码向量正是通过对于这个概率模型随机采样获得的。最终我们通过解码器将采样获得的隐含编码向量还原成原始图片。
图3-5 VAE实现方法
在实际的训练过程中,我们需要权衡两个问题,第一个是网络整体的准确程度,第二个是隐含变量是否可以很好地吻合高斯分布。对应这两个问题也就形成了两个损失函数:第一个是描述网络还原程度的损失函数,具体的方法是求输出数据与输入数据之间的均方距离;第二个是隐含变量与高斯分布相近程度的损失函数。
在这里我们需要介绍一个概念,叫作KL散度(Kullback–Leibler divergence),也可以称作相对熵。KL散度的理论意义在于度量两个概率分布之间的差异程度,当KL散度越高的时候,说明两者的差异程度越大;而当KL散度低的时候,则说明两者的差异程度越小。如果两者相同的话,则该KL散度应该为0。这里我们正是采用了KL散度来计算隐含变量与高斯分布的接近程度。
下面的公式代码将两个损失函数相加,由VAE网络在训练过程中决定如何调节这两个损失函数,通过优化这个整体损失函数来使得模型能够达到最优的结果。
generation_loss = mean(square(generated_image−real_image)) (3-1)
latent_loss = KL−Divergence(latent_variable, unit_gaussian) (3-2)
loss = generation_loss + latent_loss (3-3)
在使用了VAE以后,生成数据就显得非常简单了,我们只需要从高斯分布中随机采样一个隐含编码向量,然后将其输入解码器即可生成全新的数据。如果将手写数字数据集编码成二维数据,我们可以尝试将二维数据能够生成的数据在平面上展现出来,如图3-6所示是从二位数据(−15,−15)到(15,15)之间数据点生成的数据,可以看到随着隐含编码的变化,手写数字也会逐渐从左下角的手写数字0逐渐演变成右上角的手写数字1。
图3-6 隐含编码与对应生成之间的关系
当然VAE也存在缺陷,VAE的缺点在于训练过程中最终模型的目的是使得输出数据与输入数据的均方误差最小化,这使得VAE其实本质上并非学会了如何生成数据,而是更倾向于生成与真实数据更为接近的数据,甚至于为了让数据越接近越好,模型基本会复制真实数据。
为了解决VAE的缺点,也为了让生成模型更加优秀,就让我们请出本书的主角——生成对抗网络(GAN)。让我们来看一下GAN究竟是什么,是通过什么样的方法来实现生成模型的建立的。
[1] https://blog.keras.io/building-autoencoders-in-keras.html