GAN 是以很难训练而闻名的,我们接下来介绍一些其中的原因和训练GAN的小技巧。 首先,我们回顾一下判别器和生成器都在做些什么。判别器的目标是要分辨真的图片与产生 出来的假图片间的差异,而生成器在做的事情是要去产生假的图片,骗过判别器。而事实上 这两个网络,生成器和判别器它们是互相砥砺才能互相成长的,如图1所示。因为如果判 别器太强了,那么生成器就会很难骗过它,生成器就会很难产生出真的图片。但是如果生成 器太强了,那么判别器就会很难分辨真图片和假图片。只要其中一者发生什么问题停止训练, 另外一个就会跟着停下训练就会跟着变差。假设在训练判别器的时候一下子没有训练好,那 么判别器没有办法分辨真的跟产生出来的图片的差异,同时生成器就失去了可以进步的目标, 生成器就没有办法再进步了。那么判别器也会跟着停下来,所以这两个网络是互相砥砺才能互相成长的。所以这也是为什么GAN很难训练的原因,因为这两个网络必须要同时训练,而 且必须要同时训练到一个比较好的状态。
图1 GAN 训练的难点
所以GAN 本质上它的训练仍然不是一件容易的事情,当然它是一个非常重要的前瞻技 术。有一些训练GAN的小技巧,例如Soumith、DCGAN、BigGAN等等。大家可以自己看 看相关文献进行尝试。
训练GAN 最难的一个领域其实是要拿GAN来生成文字。如果要生成一段文字那需要 一个序列到序列的模型,其中的一个解码器会产生一段文字,如图2所示。这个序列到序 列的模型就是我们的生成器。著名的Transformer就是一个解码器,它现在在GAN里面,就 扮演了生成器的角色,负责产生我们要它产生的东西,比如说一段文字。那这个序列到序列的 GAN 和原来的用于图像中的GAN有什么不同呢?就最高层次来看,就算法来讲它们没有太 大的不同。因为本质上就是训练一个判别器,判别器把这段文字读进去,去判断说这段文字是 真正的文字还是机器产生出来的文字。而解码器就是想办法去骗过判别器,生成器就是想办 法去骗过判别器,我们来调整生成器的参数,想办法让判别器觉得生成器产生出来的东西是 真正的文字。所以从算法的角度来讲,它们没有太大的不同。对于序列到序列的模型其真正 的难点在于,如果要用梯度下降去训练解码器,去让判别器输出得分越大越好,你会发现很 难做到。我们来思考下,假设我们改变了解码器的参数,这个生成器,也就是解码器的参数, 有一点小小的变化的时候,到底对判别器的输出有什么样的影响。如果解码器的参数有一点 小小的变化,那它现在输出的分布也会有小小的变化,那因为这个变化很小,所以它对于输出 的词元不会有很大的影响。
图 2 序列生成的GAN
其中词元就是现在在处理产生这个序列的单位。假设我们今天,在产生一个中文的句子 的时候,我们是每次产生一个汉字,那这每一个汉字就是我们的词元。在处理英文的时候,每 次产生一个英文的字母,那字母就是你的词元。所以词元就是你产生一个序列的单位,那这个 单位是你自己定义的。假设你一次是产生一个英文的词,英文的词和词之间是以空白分开的, 那就是词就是你的词元。
我们回到刚才的讨论,假设输出的分布只有小小的变化,并且在取最大值的时候,或者 说在找分数最大那个词元的时候,你会发现分数最大的那个词元是没有改变的。输出的分布 只有小小的变化,所以分数最大的那个词元是同一个。那对于判别器来说,它输出的分数是没有改变的。判别器输出也不会改变,所以你根本就没有办法算微分,也根本就没有办法做 梯度下降。当然就算是不能做梯度下降,我们还是可以用强化学习的方法来训练生成器。但 是强化学习本身是以难训练而闻名,GAN也是以难训练而闻名,这样的东西加在一起,就会 非常非常地难训练。所以要用GAN产生一段文字,在过去一直被认为是一个非常大的难题。 所以有很长一段时间,没有人可以成功地把生成器训练起来产生文字。
直到有一篇文章叫做ScratchGAN,不需要预训练(pre-training),可以直接从随机的 初始化参数开始,训练生成器,然后让生成器可以产生文字。它的方法是调节超参数,并且 加上一些训练技巧,就可以从零开始训练生成器。里面的技巧比如说要用SeqGAN-Step的技 术,并且将训练批大小设置的很大,要上千,然后要用强化学习的方法,要改一下强化学习的 参数,同时加一些正则化等等技巧,就可以从真的把GAN训练起来,然后让它来产生序列。
此外,其实有关生成式的模型不是只有GAN而已,还有其他的比如VAE,比如流模型 等等,这些模型都有各自的优缺点。当然,就假设目前想要训练一个生成器,想让机器可以生 成一些东西还是那有很多方法,可以用GAN,可以VAE,也可以用流模型。但是如果我们想 要产生一些图片,那就最好用GAN,因为GAN是目前为止比较好的生成式的模型,它可以 产生最好的图片。但是如果想要产生一些文字,那就只有用VAE或者流模型,因为GAN在 产生文字的时候,还是有一些问题。从训练角度,你可能会觉得GAN从式子上看起来有一个 判别器和生成器,它们要互动。然后像流模型和VAE它们都比较像是直接训练一个一般的模 型,有一个很明确的目标,不过实际上训练时它们也没有那么容易成功地被训练起来。因为它 们的分类里面有很多项,它们的损失函数里面有很多项,然后把每一项都平衡才能够有好的 结果,但要达成平衡也非常地困难。
那为什么我们需要用生成式来做输出新图片的事情呢?如果我们今天的目标就是,输入 一个高斯分布的变量,然后使用采样出来的向量,直接输出一张照片,能不能直接用监督学习 的方式来实现呢?具体做法比如我有一堆图片,每一个图片都去配一个向量,这个向量来源于 从高斯分布中采样得到的向量,然后我就可以用监督学习的方式来训练一个网络,这个网络 的输入是这个向量,输出是这个图片。确实能这么做,也真的有这样的生成式模型。但是难点 在于,如果纯粹放随机的向量,那训练起来结果会很差。所以需要有一些特殊的方法例如生成 式潜在优化等方法,供大家参考