炼丹师初体验

上一篇文章,第一次尝试 GAN 后,有了一些奇思妙想。

数据集

翻找了不少本地版图鉴、爱好者论坛,最后使用的数据主要来自官方的网页版图鉴 The official Pokémon Website in China,直接用爬虫爬了从关都到阿罗拉地区的 807 图鉴所有形态图片。抽样显示如下:


预处理主要涉及分辨率处理(64×64)、数据增广(左右反转、顺逆时针旋转 5°)。 在 TensorFlow 中设置数据集主要参考了这篇博客的代码:TensorFlow2.0(10):加载自定义图片数据集到 Dataset https://www.cnblogs.com/chenhuabin/p/11863889.html

神经网络

使用和 上一篇文章 相似的网络结构进行训练,参数基本不变,仅修改了输入输出的通道数,训练时网络的 Loss 曲线如下所示。

Discriminator Loss for Fake Imgaes

Discriminator Loss for Real Imgaes

Generator Loss

迭代起来的输出是这样的,比较恐怖,轮廓有一些创新,但细节全损。


放在 MistGPU 服务器(广告费结一下)上训练,吃了个饭回来 100k 轮了,输出一些成果如下。


👎完蛋。

接着开始玄学调参,但很可惜的是基本没有什么大的改观。

分析了一下,这次失败有以下几个原因:首先,和人脸、手写数字的二维特征相比,Pokémon 相当于是三维特征的投影,且特征更多更复杂,简单的网络结构可能很难学会;其次,网络分辨率太小太小,应对单个数字可能还行,Pokémon 可能就直接糊了;此外,这次的数据集明显偏小,可能会存在过拟合现象;另一种想法是为了抑制噪声,可能需要增加多尺度下的判别器,或许可以学会对颜色平滑度做出限制。

DCGAN

微调了一下网络结构,效果也一般,于是借用了一下 开源的 DCGAN 跑跑。

最开始使用默认参数进行训练,很恐怖,在 400 轮左右就开始全屏马赛克,调出 Loss 曲线看了一下。

Discriminator Loss for Fake Imgaes

Discriminator Loss for Real Imgaes

Generator Loss

查阅资料后,了解到这是一种梯度消失的情况。当判别器非常准确时,其损失很快收敛到 0,从而无法提供可靠的路径使生成器的梯度继续更新,造成生成器梯度消失。GAN 的训练因为一开始随机噪声分布,与真实数据分布相差距离太远,两个分布之间几乎没有任何重叠的部分,这时候判别器能够很快的学习把真实数据和生成的假数据区分开,达到判别器的最优,造成生成器的梯度无法继续更新甚至梯度消失。

相似的,还有一种异常叫做模式崩溃:对于不同的输入生成相似的样本,最坏的情况仅生成一种样本,判别器的学习会拒绝这些相似甚至相同的单一样本。在实际应用中,完全的模式崩溃很少,局部的模式崩溃很常见。局部模式崩溃是指生成器使不同的图片包含相同的颜色或者纹理主题,或者不同的图片包含同一只狗的不同部分。

于是进行针对性调参,尽量让判别器学得慢一点,而生成器多迭代几次,最后超参数设置如下:

Hyperparametervalue
image siza64×64
batch size64
Adam learning rate0.0002
Adam momentum0.5

最后效果就差不多了😎,给一组随机输入,生成器的输出如下所示。


效果提升非常明显,噪点减少,轮廓清晰。当然这个结果也还存在一定缺陷,仔细观察可以发现,结果局限于几种特定的模式,甚至有出现和原数据完全一样的图片(尾立🎯),这可能是数据量不足造成的过拟合吧。