对 BEGAN 损失函数 的理解

具体的对BEGAN的原理和特点的讲解,就不展开了,具体可以参考这两篇文章

深度学习【43】BEGAN
BEGAN解读

但是其对BEGAN损失函数的解释,我觉得有点太理论化,不太好理解,以下是对这个对抗生成网络的损失函数的理解

BEGAN生成的图片质量和多样性有了很大的提升

GAN的损失函数

首先看一下CGAN的判别器和生成器的损失函数

CGAN中,生成器是通过一些条件,来生成需要的图像,而判别器是通过输入真假图片和条件,来输出判断的结果

gen_label = generator(image=train_picture, gf_dim=64, reuse=False, name='generator')  # 得到生成器的输出
dis_real = discriminator(image=train_picture, targets=train_label, df_dim=64, reuse=False, name="discriminator")  # 判别器返回的对真实标签的判别结果
dis_fake = discriminator(image=train_picture, targets=gen_label, df_dim=64, reuse=True, name="discriminator")  # 判别器返回的对生成(虚假的)标签判别结果

gen_loss = tf.reduce_mean(-tf.log(dis_fake))  # 计算生成器的loss
dis_loss = tf.reduce_mean(-(tf.log(dis_real) + tf.log(1 - dis_fake)))  # 计算判别器的loss

可以看到,判别器的目的是为了让真的图片的判别结果尽量靠近1,让生成的假的图像的判别结果尽量靠近0

而生成器的目的是为了让假的图像尽量像真的,也就是让假的图片的判别结果尽量靠近1

BEGAN的结构

BEGAN中,判别器并不是直观的输出判别的结果,而是一个自编码器,用图表示的话,如下图

自编码器也就是把一个图片压缩成一个小的向量,再把这个小的向量重新解压成一张图片。

那为什么要进行这个过程呢,因为在不断训练的这个过程中,这个自编码器就相当于变成了一个特征提取器。

形象的说,在这个过程中训练了一个压缩和解压的方法。这个自编码器(特征提取器)会根据图片的特征进行压缩和解压

  • 假如输入了一张人脸的图片,那在压缩时,会保存一些重要的特征,比如五官和发型。将这些特征抽象出来保存到一个小的向量中,再进行解压。解压的过程也是一样,把这些抽象的人脸特征再表达出来

  • 但是假如输入了一张乱七八糟的非人脸图。那么在压缩的时候,找不到人脸的有效特征,就会乱七八糟的压缩,得到的向量也没有什么价值,最后解压出来的结果也不会和原来输入的图像有什么关联

而生成器就相当于用了半个判别器,它只用到了解压的过程,也就是把一个带有特征的向量,生成一个人脸数据,自己画了一个简单的图

BEGAN的简单结构图

(其实我并不喜欢把这个结构看成是生成器-判别器的结构,而更喜欢看作是生成器-特征提取器的结构)

BEGAN的损失函数

一般生成对抗网络的两个结构(生成器、判别器)的损失函数都直接来源于判别器的输出结果,那现在这个判别器是一个特征提取器时,要怎么设计损失函数呢?

首先,一开始特征提取器的效果并不好,还学不到完全的人脸特征。所以我们需要让特征提取器尽量准确的提取特征,也就是让真图像经过特征提取器的压缩和解压之后,尽可能的形成和原图相似的图片(使用L1_loss)

于是有了第一个损失函数,下面的input_real是真实的图像,d_model_real是真实图像经过判别器(特征提取器)重构后的图像

d_real = tf.reduce_mean(tf.abs(input_real - d_model_real))  # 使用了L1_loss
d_loss = d_real

这个d_loss就是判别器(特征提取器)的损失函数原型。通过让重构后的图像和原图像尽量相似,来让特征提取器能够更加准确的提取人脸特征并进行重构。

因为这里是为了训练提取人脸特征的能力,所以我们主要是应用了真实人脸的重构数据,因为一开始假的人脸还非常假,所以其重构的结构不能作为判断条件

那生成器的Loss呢?

在论文中,生成器的Loss是下述代码中的g_loss,其中

d_fake = tf.reduce_mean(tf.abs(g_model_fake - d_model_fake))
g_loss = d_fake

很明显,它是通过让“人造人脸” 经过特征提取器后 重构的人脸 更加接近于 原来输入的“人造人脸”

因为这个特征提取器是一个“人脸特征提取器”,它可以很好的把人脸中的特征提取出来,压缩再解压,进行还原。假如现在有一张图像,通过这个特征提取器后,重构的图像和原图像很类似,那这个图像一定就是人脸图像!这也就是为什么可以用上述损失函数来作为生成器的损失函数,让生成器生成的人脸越来越逼真

但是论文中,还有另一个参数,叫k_t

刚才上面的判别器的损失函数,只是原型,其完整的损失函数如下

d_real = tf.reduce_mean(tf.abs(input_real - d_model_real))
d_fake = tf.reduce_mean(tf.abs(g_model_fake - d_model_fake))
d_loss = d_real - k_t * d_fake

也就是说,判别器不仅仅是用到了真实图像的重构结果,也用到了假的图像的重构结果

假的图像一开始生成的肯定不是人脸,为什么可以把它作为特征提取器的训练内容呢?

在这里,这个k_t的变量是不断变化的,其一开始是一个很小的小数,比如0.0001,所以在一开始生成器的结果还不是很好时,几乎就是真实图像在起作用。当训练了一段时间之后,k_t就会慢慢增加,差不多到2000次时,k_t增加到了0.04

也就是说,在训练了一段时间之后,随着生成的人脸图像越来越好。人造的人脸图像也会被加入到特征提取器的训练当中。

那为什么,是d_real - k_t * d_fake 而不是 d_real + k_t * d_fake

如果是用加号,那么我们是希望d_reald_fake都越小越好。也就是说我们希望真假图像在重构后,和原图一模一样

但是实际上这并不是我们想要的,而且这种训练方式会很难,在将一张图片进行压缩后,必定会损失某些信息,完全无损的还原,几乎是不可能的

所以在使用上述的——“让真图的重构结果和真图更相近的方法”训练判别器(特征提取器)时,在收敛到一定的层次之后就无法继续收敛

我们需要的是:当真实人脸经过 提取特征重构 之后,在眉头增加了一颗痣,那么这个重构误差就是这颗痣;当生成的人脸经过 提取特征重构 之后,也在眉头增加了一颗痣,那么重构误差也是一颗痣,他们的重构误差是接近的

所以当出现上述这种情况时,这个特征提取器就是一个非常好的特征提取器,也就是让真假图像的 重构误差的分布相似,以训练整个特征提取器提取的特征越来越好

判别器的损失函数总结

生成器在一开始生成图像的质量并不高时,k_t值很小,可以当做只是在让真实人脸重构后尽量像真实人脸,以达到快速收敛的效果。在收敛到一定程度之后,k_t的值已经是一个不可忽略的值了,而这时候仅适用真实图像重构的相似度也已经很难优化了,所以使用两个重构的误差来进行优化,达到进一步收敛的效果

所以,生成器和判别器的损失函数以及具体k_t值的变化过程如下

其中:

是真实图像的重构误差

是生成的图像的重构误差

另一种理解方式

另一种理解方式,假设真假图像经过判别器(特征提取器)重构后得到的和原图的误差分布分别为A'和B'

那么判别器D的目的就是让A'和B'的尽可能的相差大一点,也就是让特征提取器可以更好的分辨真假图像

然后生成器G的目的则是让假图像经过判别器 与原图的误差分布B'尽可能小,也就是让A'和B'尽可能相差的小一点

在论文中证明了A'和B'都是满足正态分布的,所以A'和B'的距离可以用
Wasserstein距离来得到


大概的概括一下原理就是:根据Wasserstein距离,来匹配自编码器的损失分布。并采用神经网络结构,在训练中添加额外的均衡过程,来平衡生成器和判别器(具体见论文和代码)

当然以上内容只是个人对该网络结构以及损失函数的理解而已,具体的推导过程可以见其他阐述原理的文章,或者是直接看 BEGAN论文

有一篇文章也不错 BEGAN论文阅读

你可能感兴趣的:(对 BEGAN 损失函数 的理解)