老照片、老电影总能让人们的思绪飘回那些久远的年代,沉淀于其中,可与此同时,模糊的画面又不免给记忆蒙上了一层薄雾。如今,随着人工智能技术的发展,SRGAN(超分辨率生成对抗网络)使得拨散云雾始见真,成倍还原了画面质量。
2019年底,WAIC开发者·上海临港人工智能开发者大会的开幕式上,上海市经济和信息化委员会副主任张英为上海市人工智能创新中心授牌,深兰科技等7家企业首批入选,同时深兰科技两项应用场景方案入围“上海市第二批人工智能试点应用场景”。
其中,在AI+文化旅游场景中,深兰科技入围成为上海文化广告影视集团有限公司的解决方案供应商,将为其提供视频图像质量增强技术,通过智能算法提高视频画面质量,使2K高清素材达到4K超高清要求,优化提升老旧节目的图像清晰度。
今天,就来个承上启下,回顾前一年成绩的同时,也用创新和进步为新的一年注入能量。获奖方案的团队负责人、深兰科学院深度学习科学家方林博士,给出了实现超分辨率的SRGAN模型的网络结构、训练步骤和损失函数,将帮助GAN的初学者理解对抗网络的实质,为今后设计更加复杂的超分模型打下基础。
超分辨率
超分辨率的目的是把低分辨率的图像或者视频转为高分辨率,比如:
我们利用超分辨率生成式对抗网络(SRGAN, Super Resolution Generative Adversarial Network)实现超分辨率。
下面我们通过一个简单的SRGAN模型来说明超分模型的基本结构和训练步骤。
图片准备
超分模型由两张图片组成,第一张是模糊图片,形状为[128, 128, 3];第二张是对应的清晰图片,形状为[512, 512, 3]。清晰图片的长宽分别是模糊图片的长宽的4倍。我们的目标是把模糊图片的分辨率提高16倍。
图片必须是一一对应的,即一张模糊图片必须有对应的一张清晰图片。为了准备图片,我们先收集足够数量(最好2万张以上)的清晰图片,图片的长度和宽度应该都大于等于512。然后选取任意一个512*512的部分进行剪裁。
注意:
不要把一个大的图片resize成512*512大小,因为这会导致图片变形;
由于我们可以在大图片的任意位置剪裁出512*512的图片,所以长度或者宽度大于512的图片可以生成多个清晰图片。比如520*520的图片可以生成64个清晰图片。
当我们获得了所有清晰图片之后,再把每张清晰图片resize到128*128大小,这样我们就获得了模糊图片。OpenCV的resize()方法可以帮助我们改变图片大小。
SRGAN模型
1、主要结构
SRGAN模型结构如下图所示:
图中“模糊”是指模糊图片,“清晰”是指清晰图片,“生成”是指生成器生成的图片。生成图片的分辨率与清晰图片相同,为512*512。模糊图片的分辨率是128*128,为清晰图片的1/16。
上图中的模型主要由生成器和辨别器两部分组成。生成器的目的是输入模糊图片(图中的“模糊”),输出生成图片(图中的“生成”)。辨别器的输入由a、b两个参数组成。其中b是模糊图片,a是生成图片或者清晰图片。辨别器的目的是判断图片a是否是真实的清晰图片。b是用来协助辨别器进行判断的。辨别器的输出p是一个概率,1表示a是100%的真实清晰图片,0%表示a是100%的生成图片。
训练上述模型时,生成器总是尽可能生成像真实图片的图片,而辨别器则尽可能分辨出a是真实图片还是生成图片。所以辨别器和生成器之间存在着一种对抗:生成器越优化,辨别器越不能分辨生成图片的真假;辨别器越优化,生成器生成的图片就越不能通过辨别器的检查。对抗的结果是双方的能力都得到了提高,最后达到纳什均衡:即生成器生成了很像真实图片的图片,连辨别器也无法分辨其中的真假。这就是SRGAN的基本原理。
2、生成器结构
生成器的输入是128*128的3通道图片,输出是512*512的3通道图片。SRGAN使用U型网络实现这种图片到图片的转化,结构如下:
请注意:
第一,整个U型网络的左半部分全部由卷积操作组成,用来抽取输入图像的特征。右半部分全部由反卷积操作组成,用来根据特征构建清晰图片。由于输出图片比输入图片大4倍,所以右边比左边高出一截。
第二,左右两边相同大小的图片之间的连线称为捷径,表示左边的图片与右边的图片进行加法操作,结果保留在右边。这是借用了残差神经网络(ResNet)的做法。不过ResNet中的捷径跨越相同数量的操作,而这里的捷径跨越不同数量的操作,并且越上方的捷径离输入和输出越近,快速传播梯度的效果越好。
第三,左边最后的卷积和最后的反卷积操作都不含激活函数,并且整个网络中不使用Dropout,这样做的原因超出了本文的讨论范畴,这里不叙述。
3、辨别器结构
辨别器有两个输入,a表示要判断真假的图片,b是辅助辨别器判断的模糊图片。两者的分辨率分别是512*512和128*128。对于参数a,我们采用卷积操作不断提纯其特征,最后全连接到一个神经元,最后经过sigmoid激活后得到一个概率。这条路径我们称为主路径。参数b,我们通过resize改变其大小,然后从侧面切入到主路径中去,从而影响特征的提取。下图显示了辨别器结构:
请注意,全连接之后使用sigmoid激活函数,这样可以获得概率值。
SRGAN训练
SRGAN的训练分三步完成。第一步,训练辨别器识别真样本。这一步图示如下:
这一步的目的是用每一对模糊和清晰图片训练辨别器,使得辨别器的输出尽可能趋近于1。注意:清晰图片对应于参数a,模糊图片对应于参数b,辨别器的期望输出是1。
假设我们用函数 disc(a,b) 表示辨别器的输出(表示a为真实样本的概率),则这一步的损失可以用交叉熵表示为:
其中a和b分别表示真实的清晰图片和对应的模糊图片。
第二步,训练辨别器识别假样本。这一步图示如下:
请注意:生成器在这一步中是固定不变的,只有辨别器才被优化。这是因为这一步只是为了训练辨别器识别假样本,也就是说辨别器的期望输出是0,所以就不能改动生成器。否则就会导致生成器试图生成让辨别器输出为0的图片,这不是生成器所期望的。生成器应该期望生成能让辨别器以为是真(即辨别器输出为1)的图片。
很多算法工程师不清楚在这一步训练中如何达到仅训练一个模块(比如说辨别器),而固定其他模块(比如说生成器)的目的。
在Tensorflow中,一般地,我们可以调用函数:
来实现梯度的反向传播和对模型参数的优化。此时我们只需指定第二个参数varlist等于辨别器中所有可训练参数的列表(list)即可。其他未被指定的参数(比如生成器中的参数)就不会被优化,也就是说,被固定了。
假设我们用函数gen()表示生成的输出,则这一步辨别器的输出是:
由于这一步辨别器的期望输出是0,所以这一步的损失可以用交叉熵表示为:
第三步,训练辨别器识别假样本。这一步图示如下:
请注意,在这一步训练中辨别器被固定住了,保持不变,被训练优化的是生成器。因为这一步的目的是要让生成器生成辨别器以为是真实图片的图片,所以辨别器的期望输出是1。此时我们必须固定住辨别器,否则辨别器会变成这个样子:不管生成器输出什么样的图片,辨别器都尽可能输出1。显然,这不是我们所期望的。
这一步训练的结构跟第二步相同,不同的是固定的是什么,训练的是什么,以及辨别器的期望输出不同。
由于这一步辨别器的期望输出是1,所以这一步的损失可以用交叉熵表示为:
我们可以发现,第二步和第三步训练的输入数据都是b,网络的输出都是disc(gen(b),b), 但是期望输出一个是0,另一个是1。对抗由此产生,最终的结果将达到纳什均衡。理想情况下,disc(gen(b),b) 的结果既不是0也不是1,而是接近0.5。
结束语
我们有了三个训练步骤,有了三个损失函数,并且知道每一步训练什么、固定什么,则依次循环执行这三步训练就能达到实现超分模型的目的。
本文是对GAN和SRGAN的一个简单说明,是给初学者理解SRGAN模型看的,没有涉及到GAN更高深的知识(比如WGAN和推土机距离等)。如有错漏之处希望给以批评指正。