InfoGAN 非监督条件生成
学习资料:
- 我制作的GAN简介短片
- 我制作的让GAN生成你想要的
- 论文 InfoGAN: Interpretable Representation Learning by Information Maximizing Generative Adversarial Nets
- 本节代码
- 代码有我自己定义的依赖utils.py, visual.py, mnist_ds.py
怎么了¶
上文我们介绍过 ACGAN 在训练Generator的时候可以自定义标签, 按照标签来输出生成的图片。这次介绍的 InfoGAN 也是做这回事,不过它又有稍稍不同。一句话来介绍 InfoGAN: 模型自己给生成器创造出适用的标签或调控开关,来控制生成的结果。 我再详细阐述一下这句话,也就是说,如果 ACGAN 是人为给定一些数据标签, 让模型学着使用这些标签来生成对应的图片,那么 InfoGAN 是完全的非监督学习,预设你想要分多少个类, 用多少个调控器
,InfoGAN 自动给你将这些类别,调控器配置好。所以在一开始的时候,这些类别和调控器都是一种空瓶
,模型训练好以后, 自己给空瓶填上了富有意义的液体,这些类别和调控器才能被有意义地使用。
在最后应用的时候,同样是按条件生成,它又和 ACGAN 有什么不同呢?
上面第一张是 ACGAN 的训练模式,第二张是 InfoGAN 的模式, InfoGAN 采取的是非监督模式,自己赋予条件以意义。
他们的不同点具体如下:
类比 | ACGAN | InfoGAN |
---|---|---|
标签 | 真实 | 虚拟 |
学习模式 | 监督学习 | 非监督 |
条件输入在训练前 | 有意义 | 无意义 |
条件输入在训练后 | 有意义 | 有意义 |
仔细观察训练的步骤就不难发现,每一行都有比较固定的非监督-自学习
标签。而且从左到右比较明显,也学习出了一种斜度的特征。
怎么训练¶
再看到这张网络结构,我们发现它将 Discriminator 的原始功能(判断真假)交还给了 Discriminator,而且 Discriminator 就只负责判断真假。 另外我们额外加一个 Recognition(R)网络,这个网络的作用就是让 InfoGAN 可以做非监督学习,自学出来一些可作为条件的特征。
乍一看的确可以这么做,但是这种设计是存在资源浪费的,D 网络和 R 网络对于图片的理解能否通用呢?或者说CNN的图片理解,是否可以被 D R 两个网络共用? 这样我们就能节省计算开销了。的确没错,像下面这样稍作修改,让 D 和 R 共用一部分网络参数,共用一个对图片特征的高层抽象理解,然后再做不同的任务。
与 ACGAN 不同的是,我们不需要提供额外的标签信息,条件信息在 InfoGAN 中也是随机采样的, 只需要在 R 网络那边将刚刚随机采样的 X 当成 Y,做一个非监督,就能让 G 网络掌握这个随机条件分布可以发挥的作用了。
秀代码¶
如果想直接看全部代码, 请点击这里去往我的Github. 我在这里说一下代码当中的重点部分。
Training 的步骤和之前其他的GAN并没有太大差别。重点是在 InfoGAN 的结构上。我们先看 Generator,我分别给了三个 Input
。
noise
通常 GAN 中的随机噪点style
封闭空间的连续值随机数label
随机类别
通过这三种不同的随机方式来控制生成器的结果。style
就像一个数值调控器,调节大小,label
是类别调控器,调节种类。 我使用了自己封装的 mnist_uni_gen_cnn
来标准化这个教程中的一些其他 GAN 网络设定,这样可以做横向对比。
接下来看看稍稍复杂一点的 Discriminator,里面包含了一个共用网络 s
, 这个 s
是用来抽取图片高层特征的,这个高层特征将同时被 D 和 R 网络使用。 D 网络好说,直接输出真假判断。但是 R 网络可能同时包含了连续值特征和类别特征,而且连续值特征还可以是一个正态分布。所以这里我们分情况处理了一下。
接下来,我们在看看loss的结算模式吧,除了正常的 真假 loss,论文中还引入了一个叫 info loss 的 loss,这个 loss 就是用来表示通过随机条件生成的图片, 还能不能从生成图片中重新提取出来这些随机条件?如果G网络生成了带有条件信息的图片,而R网络也能从照片里提取出这样的条件, 那么就从侧面说明了这个条件被合理的使用到了生成的图片上,也就是说,G真的按条件生成了图片。 举个例子,如果G按照大眼睛,高鼻子生成了大眼睛高鼻子的图片,但R也从图片里没有发现了大眼高鼻特征,这就说明G不理解条件,生成得不好。
在计算这个 info loss 时,可以分:
- 类别误差:crossentropy loss
- 连续值概率误差:这也可以通过正态分布的信息误差来计算
其他的代码我就不细说了, 如果理解了上面的重点部分,其他代码其实也还比较好理解。我们看看最后一个 epoch 生成的图片吧,我加了两个style
连续随机,一个label
类别误差。 这里的 style
模型学出来的结果看起来是去控制字体的斜度和横向的宽窄了,而 label
学出来尝试去区分 1234 这样的数字,但是还没有学好分类。 你可以看到在3这个类别里,还冒出了一个5,说明网络觉得 3 和 5 还是有些接近的。
问题¶
所以 InfoGAN 的标签是在训练后才变得有意义的,而且也有一个非监督学习的通病,和 Kmeans 算法一样,我要在训练之后,手动归类一下模型学出来的类别。 比如我要模型生成 1234 类别,但是我并不知道它依据的是什么在分类,只有当模型训练好,我在把它的 1234 类别挑出来溜溜, 我才知道它认为的 1234 是我认知中的哪些类别。
从这张图就可以看出,虽然我的生成的标签排序是按照 0~9 从上到下排列的,但是模型并不会按照我给的 0~9 标签生成数字 0~9,而是按照他自己随机学习到的标签映射。 从左到右我也没有告诉它先 / 后 \ 。这都是他自己的安排。如果要使用这些非监督学出来的条件规则,那这就是非监督的一种不太好用的地方。
总结¶
InfoGAN 是一种非监督学习,他可以自己设计条件属性,我们可以在生成的时候,调控这些自己生成的条件属性。通过它的自发性学习,得到这些调控器
, 我自己玩调控器
的时候,感觉还是挺有意思的。