白话GAN
GAN在2014年被提出,仅仅几年时间,GAN热潮就席卷了AI领域顶级会议,从ICLR到NIPS,大量高质量论文被发表和探讨。Yann LeCun曾评价GAN是“20年来机器学习领域最酷的想法”。可惜GAN的概念较为晦涩难懂,入门的门槛还是比较高的。
本文试图用最通俗易懂的语言来讲一个GAN的故事。里面绝大多数想法都来源于我们学习小分队成员:ZH、DY、PJ... 非常感谢大家!
一位漂亮小姐姐特别喜欢小狗,有一天她找到你说,她想找一些狗的图片,这些图片最好不要直接从网上下载,要有新意的。你非常乐意帮助她,那么问题来了,如何生成一些狗的图片呢?有一些deep learning基础的同学会想到说,我准备一些狗的图片,先把狗通过一个network来encode成一个向量,然后再用另一个network把向量decode成它自己,train这两个network就可以啦~ OK,这个想法就如同下图所示:
实际上,之前的确有学者做过相关的研究。但是这样做的效果一直不尽如人意,这种pixel2pixel做法的loss一般选用pixel error,而实际上,pixel error大的case,生成的效果不一定差;而pixel error小的case,生成的效果不一定好。我们看下图便一目了然:
左边两个图是生成数字0的任务,两个图的loss非常小,然而第二个图生成的并不是数字0;右边两个图是生成数字1的任务,两个图的loss挺大的,但是生成的数字1效果其实非常好~
我们仔细分析一下原因不难发现,用pixel粒度来衡量图片生成的效果是很不准确的,我们如果能从图片整体的视角来衡量图片生成的效果就更好啦。很自然的,我们想到可以再加一个判别模型来整体上做这件事。我们引出GAN的基本结构:
GAN里面也有两个network,G是生成网络部分、D是判别网络部分(下文都简称G和D)。接下来我们看下怎么训练他们:
首先,我们固定D的所有参数,通过D的输出反馈来训练G的参数。因为该任务我们生成的狗不需要有特定的风格等先导信息,所以输入部分(图中的I)可以初始化成一些随机的向量即可;那输出(图中的O)是什么呢?这个问题问的好,G的目的不就是想让自己生成的图片能以假乱真嘛,所以输出应该是“真狗”的label! (这点很重要!)我们画一下这个过程的简图:
接下来,当G训练完后,我们开始训练D。训练D的时候,我们就不需要G的参与啦。我们把G生成的那些“假狗”做为负样本,从网上下载的“真狗”做为正样本,把D的参数训练好。 草图如下:
训练完D后,我们再把D的参数固定,通过D的输出反馈来训练G,然后利用G生成的假狗和网上的真狗来训练D,然后去训练G,然后去训练D,然后去训练G,然后去训练D。。。。。终于终于,当G和D的参数都趋于稳定后,我们的GAN就训练完啦~~ 大功告成!!
把GAN用来生成狗就很简单啦,我们把一些随机向量喂给G,让G自己生成就好啦。
前面讲了一大堆,我想同学们可能会有疑惑,为什么用这种办法生成狗效果会好呢? 其实仔细想想不难发现,G和D表面看似合作的关系,实际是在不断的发生对抗。G的训练始终致力于让D认为G生成的狗是“真狗”,尽全力去“以假乱真”;而D的训练却始终致力于锻炼自己的火眼金睛,不管G生成的多像,D都要识别出来。。D和G相爱相杀,共同努力从而使得G生成的狗越来越逼近网上下载的“真狗”~~
故事基本讲完了,下面结个尾:
实际上,GAN的训练还是挺费钱的,训练速度很慢,很难收敛。大致上是因为真狗和假狗的分布差距太大啦。如下图所示:
理想中的情况应该是左图所绘,真狗和假狗的分布有一些共同区域。比如说当前在A点,G致力于从A点往B点走,使得D分不出开真假;而D致力于往反方向走,使得自己更容易区分真假。而现实中的情况往往是右图所绘,从A点应该往左呢还是往右呢?who knows...
几年来涌现的很多GAN衍生的模型,已经很大程度上解决了这些问题,不过都不在本文的范畴啦。
文本完。