原标题:CAA | 【智能自动化学科前沿讲习班第1期】国立台湾大学(位于中国台北)李宏毅教授:Anime Face Generation
整理:戴星原
演讲主要分为三个部分,第一部分是分享一下我对GAN的一些个人想法。第二部分讲二次元动漫人物头像生成,让机器根据输入的文字,产生动漫人物头像。第三部分讲一些自己的研究,主要是跟语言处理有关。
Part 1: My Two Cents about GAN
结构学习(structure learning)
GAN有什么用,我认为它是一种新的结构学习方法,接下来我会讲一下什么是结构学习。机器学习,是找一个函数f,输入X,输出Y。如果是回归问题,输出数值(scalar);如果是分类问题,输出类别(one-hot向量);结构学习是输出是一个序列(sequence),矩阵(matrix),图(graph)或树(tree)等,它们都是有结构的。
在结构学习问题里,输出可以看做是由很多小的部分(component)的组合,这些部分之间是有关联性的,它们单拿出来都不知道做得好不好,而要把所有的部分串在一起,才知道做的怎样。对于输出序列的情况,比如机器翻译,输出一个句子,这个句子由很多词汇构成,只有把所有的词汇串在一起,用正确的顺序摆对,才能说做好了翻译问题。对于输出矩阵的情况,比如生成图像,给一个简单的几何图像,画出真实图案,或给黑白图像上色,或是让机器根据一段文字叙述产生图像,这些生成的图像必须要从整体来看是好的。
为什么结构学习是一个有趣而且重要的问题?首先,我认为结构学习是one-shot/zero-shot的问题。在分类问题里,每一个类别都有一些样本,机器从中归纳出每个类别样本的共通性,然后做分类。结构学习不一样,在结构学习中里,因为输出是有结构的,它是一个非常大的空间,所以在测试阶段要输出的情况可能在训练的时候从没有出现过。假设做翻译问题,如果把每一个翻译可能的输出视为一个类别,类别1是hello,类别2是hi,类别3是fine,但在做翻译所要求的结果是good morning,这种情况训练时没有出现过,但是机器要想办法能够答对才算是解决问题。所以机器如果要解决结构学习的问题,必须比做分类更加智能,因为它必须在测试时创造训练时从来没有看到的东西,所以说结构学习是机器学习下一个阶段需要去研究克服的问题。
第二个有趣的地方就是如果进行结构学习,因为产生的是一个有结构的目标,所以它必须要学会规划(planning),要有大局观。例如,做图像或句子生成时,机器生成一个个像素组成图像,或是生成一个个单词组成句子,如果机器没有完整规划,结果将会很差。另外在结构学习中,输出部分有依赖(dependency),所以机器必须要对全局有足够的理解。
既然结构学习是一个有趣的问题,那能够对结构学习有新突破的GAN,就是很重要的技术,GAN对结构学习做了什么样的突破?
传统上结构学习有两个解法,一个是自底向上(Bottom Up)的解法,一个是自顶向下(Top Down)的解法。自底向上的解法中,component-by-component产生一个输出。在自顶向下的解法中,定义一个评价函数(evaluation function)去评价整个目标。而GAN就是同时结合这两个做法,它既有自底向上的生成器,也有自顶向下的判别器。
自底向上(Bottom Up)
自底向上是依次产生结果的每个部分。我们以句子生成为例,如果让机器学会写唐诗,首先要有一个循环神经网络(RNN),给它一个代表开始token,机器会输出“春”,给它开始的token+“春”,输出“眠”,输入“春”+“眠”,输出“不”……在测试中,机器不是从整首诗来学习,它只知道在第4步,看到“春眠不”就要输出“觉”。因为网络的容量(capacity)有限,不会把所有看过的句子背下来。现在机器只知道“春眠不”后面产生“觉”,但没有学到如果“春眠不”没有产生“觉”而是别的字,后面会发生什么,是生成一首差诗,还是把“觉”换成别的字也是一首好诗。在自底向上的做法中,模型只专注于把每个部分产生对,没有思考整个产生目标好不好。
刚才讲的是让机器随机生成句子,但在实际的应用中,只是让机器随机生成句子是不够的,我们更需要机器基于一定的条件生成句子,这叫做条件生成(conditional generation)。比如给机器一个输入,它根据你的输入产生适当的句子,这个输入就是条件。我们让机器做字幕生成(caption generation),给机器输入一张图像或一段影像,然后它告诉我们它看到了什么。机器输出的句子并不是一些随机的句子,这些句子必须符合它看到的那张图像。又比如在聊天机器人(chatbot)里面输入一个句子,机器人回一句话,它不是随机回每一句话,它不仅需要保证输出的语法对,而且要跟输入有关。
机器翻译或聊天机器人广泛使用的sequence-to-sequence是一种条件生成。做法是通过一个RNN把要翻译的句子或是一段文本编码为一个表征(representation),这个表征会输入给生成器,输出翻译结果或是对话内容。
自顶向下(Top Down)
自顶向下分为2个阶段,训练和推断(测试)。在训练时,要找一个评价函数。假设让机器生成目标(object)X,可以是句子或图像。我们定义一个函数F,输入X,它会输出一个数值,数值代表对X的评价。得到这个方程F以后,在推断时,我们的目标就是找到使F产生最大输出的X。
自顶向下方法也有conditional版本。我们希望机器输入一个X,输出Y。例如输入一个句子,输出一张图;或是输入中文,输出英文。我们定义一个评价函数F,输入(X,Y)组合,F输出(X,Y)组合有多合理(compatible)。推断时X给定,目标是找到Y使F(X, Y)最大。自顶向下的方法很多,如structured perception, structured SVM, Graphical model等。
自底向上和自顶向下方法各有优缺点。自底向上的优势是在测试时很快就能生成结果,不需要进行推断。它的缺点是没有考虑全局,学习过程是component-by-component。自顶向下的优势在于能够考虑全局,评价函数评价时考虑的是完整的图像或文本,以及各部分的关系。但缺点是在测试时要解argmax问题,解这个问题不总是可行(feasible)的,通常要做很多假设,才能够解出来。
GAN是学习一个自底向上的生成器和一个自顶向下的评价函数判别器。对于生成器,虽然它生成的样本是component-by-component,但它从判别器(评价函数)那里学到全局视图,判别器教导生成器产生好的东西,因此它生成的过程中会考虑全局,会知道各部分的关联。从另一个角度,判别器可以看做评价函数F,生成器希望产生的样本放到判别器产生大的值,因此生成器做的事就是在解argmax的问题,训练得到的生成器生成的试图骗过判别器的样本,就是argmax的解。所以在测试时,不需要再解argmax问题。
Part 2 二次元动漫人物头像生成
现在我们考虑给机器输入一个句子,比如说红发红眼的女孩,希望可以生成出这样一个图像,这是我在台大开的机器学习课的作业。
首先是数据获取,我让助教在动漫网站把图像爬下来,并用OpenCV把任务头像截成96*96尺寸,另外还爬下图像对应的标签,这些标签包括创作者给图像加上的信息,如紫色眼睛,紫色头发等。
其次是作业形式。学生把训练好的模型上交,输入一段指令,每个模型产生5张64*64图像。输入的指令事先明确只会输入头发的颜色和眼睛的颜色,不会有额外问题。
接下来是作业评价。我们的做法是把每个人产生出来的结果放到一个平台上面,全班同学对这些图像进行评价。评价的标准有两个方面,一是产生出来的图像有多符合文字的叙述,二是产生出来的图像有多真实。
条件GAN(conditional GAN)
要训练一个网络,输入一段文字,产生一张图像。我们先以生成火车图像为例,传统的监督学习方法是希望输出的图像与真正答案越接近越好,但是训练样本里火车图像可能出现过很多次,而且有各种不同形态。输入火车,机器产生哪一种图像,都会是好的。传统监督学习方法中,网络预测的会是各种模式火车图像的平均,而这样的结果通常是一个模糊的图像,不能满足我们对生成样本的要求。
因此需要使用条件GAN,在GAN的生成器里输入一段文字及噪声,输出不是一个图像,而是一个图像分布。在测试时,输入火车,可以输出图像分布,覆盖火车图像的多个模式,最后做采样时,会生成符合某种模式的样本,从而得到好的结果。
除了生成器,还要有一个判别器,从high level看看这个图像好不好。一种形式的判别器是输入真实样本或生成样本,输出是真实样本的可能性,但这种判别器只要求产生真实图像就好,可能会忽视生成器输入的文字。另一种形式的判别器更符合我们的要求,它不只看输入的图像,还要看生成器输入的文字,然后输出评价结果。它不只是判断生成样本是否真实,还要判断生成样本和输入文字是否匹配。还是以生成火车图像为例,训练时判别器的正样本是火车文本跟它对应的真实火车图像,负样本一种是火车文本和生成器生成的假图像,另一种是随机的文本和真实的火车图像。
实现细节
多数同学采用的架构如上图,输入一段句子,经过一个RNN,将句子编码成一个向量表示,再输入一个噪声。噪声和向量表示结合放到生成器,生成器有4层卷积神经网络(CNN),将输入变成一张图像。判别器同时输入图像和一段文字,这个判别器是精心设计的,图像先经过几个卷积后变成小的向量与句子经过RNN得到的向量表示组合,最后判别器判断是真匹配(real pair)还是假匹配(fake pair)。参数按照图中的设置就能够得到比较好的结果。
一些同学会用到进阶的技术,包括WGAN,Improved WGAN或StackGAN。StackGAN的做法是把图像生成过程分成2阶段,第一阶段先产生小像素图像,第二阶段再从小像素图像产生大像素图像。之后转成64*64,这样会比较清晰。
除了网络结构的改进,一些同学使用的技巧产生了更好的效果,以下是作业的前几名用到的技巧:
1.句子表示(sentence representation)。因为输入是一个句子,用RNN编码一个句子是很合理的想法,但是题目中说只会输入眼睛和头发的颜色,有的做法是不用RNN处理句子,而是直接把头发和眼睛的颜色找出来,用one-hot表示。先设定15种头发颜色和15种眼睛颜色,然后将输入的句子里头发和眼睛颜色分别用一个one-hot向量表示。为什么不用15×15的one-hot编码,而是把眼睛和头发颜色分开表示?因为不同的颜色组合构成的类别之间非常不平衡,有的类别样本很多,有的类别样本很少。如果把头发颜色和眼睛颜色分开,每个类别之间是比较平衡的。
2.数据增强(data augmentation)。因为提供的数据只有 3万张,而且不是所有的图像都有描述头发眼睛的颜色,只有1.5万张包含头发眼睛颜色的图像可以使用,这对训练一个生成器也许不太够。使用水平翻转+旋转,将每张图像都被复制十份,从而将图像扩充到15万张,这么做会生成更清晰的图像。
3.集成学习(ensemble)。采样的噪声对生成图像质量有影响。因为输入是一个高斯分布,在中心采样次数较多,生成的图像是比较真实的,而离均值较远的地方生成的图像可能不真实。当我们修改输入采样高斯分布的标准差,比较大的标准差和比较小的标准差有什么差别?大标准差的噪声产生的人脸变化是比较有多样性,但是没有办法排除会产生坏掉的图像。小标准差的噪声产生的图像都比较类似,比如全是正面,但是可以确保每张图都是好的。我们既希望生成图像质量很高,又希望图像之间变化较大,该怎么办?我们发现同样GAN的架构,每次训练得到的结果都会非常不一样,甚至在更新的过程中,即使认为网络已经收敛了,这一次更新与上一次更新生成的图像也会有差别。比如在某次更新时发现人脸看起来偏白色,而在下一更新后,虽然人脸没有变更清晰,但皮肤颜色都变黄了,再更新之后所有人脸又都变成咖啡色的。因此,可以做GAN的集成,产生5张图就训练5个生成器。给每一个生成器输入小的标准差,虽然每个生成器产生的很多图像会很类似,但评价时每个生成器都只生成一张,并且生成的都是好的,而且每张之间变化也足够大。
Part 3: 在自然语言及语音处理的应用
我主要研究自然语言和语音处理。现在语言和语音处理上用GAN的技术还没有那么多。我们先看一个例子,假设我们用GAN生成句子,会怎么做?
首先有一个生成器,输入一个噪声,产生一个句子,接下来判别器输入生成的句子和一些真实句子,并会判断输入的句子是不是真实句子。
如上图,生成器产生句子时,输入开始的token,机器输出分布,对分布做采样,假设采样得到B(可以采样概率最大的),将B作为下个时间点的输入,机器再输出分布,采样得到A,A做下一时间点输入,输出分布采样得到A,最后生成器的输出是BAA。将生成的BAA输入到判别器,判别器会输出一个数值(scalar)。我们希望可以调整生成器参数,让判别器的输出变大,也就是让判别器觉得生成器生成的是真的。这时问题出现了,在原来生成图像的问题里,生成器和判别器合起来可以做反向传播(backpropogation),但在生成文本的情况下没法做反向传播,因为它要求梯度,梯度可以看做是模型一个参数的小变动,对输出有多大影响。对于生成器RNN,把RNN的参数变动,对输出不会有影响。因为稍微变动生成器的参数,对生成器输出分布的采样结果没有影响,则判别器的输入是不变的,输出也不会变,因此就没有梯度,不能做反向传播。
这个问题解决方案是不做采样,在Improved WGAN里,没用RNN,直接把句子当做图像。真实的句子里的每个词汇用one-hot表示,排在一起组成一张图像。生成器的部分,在每个timestep生成分布,把这些分布的向量组合起来可以看做一张生成图像。而最大的问题是两个图像完全不一样。一个是one-hot向量,一个是分布。如果使用普通GAN,对于判别器,不管生成器产生什么都能判断是错的,生成器的训练没有方向,不能够学习生成真实句子的表示。对于这种真实数据空间与生成数据空间没有重叠的情况,需要用到WGAN,它能真正生成一些句子。
另一种使用GAN生成句子的方法叫SeqGAN,它将句子生成看成增强学习的问题,将判别器看做环境,将判别器的输出看做奖励(reward),更新生成器以从环境中获得最大的reward。
GAN应用在语音处理上,和之前介绍的方法类似,也是使用条件GAN,对于去除噪音问题,输入噪音频谱,输出真实频谱。
来源:自动化学报
责任编辑: