GAN生成图像质量的两个评价指标——IS与FID

13 篇文章 2 订阅
4 篇文章 0 订阅

GAN生成性能的两个评价指标——IS与FID


 
 
    很久没有写原创博客了,最近在研究图像生成,看到关于生成器的评价指标有这么几个——IS(Inception Score)、FID(Fréchet Inception Distance)以及一些其它距离指标,下面主要参考三个博客,写写我的理解与感受吧。

    首先感谢三位博主的分享,这里是三个博客的链接:

1、全面解析Inception Score原理及其局限性
2、如何评价GAN网络的好坏?IS(inception score)和FID(Fréchet Inception Distance)
3、GAN的几种评价指标

 

一、IS(Inception Score)

 
    假设 x x x 为数据特征, y y y 为标签,则将一幅图像输入神经网络(Inception V3)中,输出层输出其属于各个类别的概率,即给定数据特征判断是哪个标签的概率 p ( y ∣ x ) p(y|x) p(yx) ,而各个标签(类别)的分布则为 p ( y ) p(y) p(y)

    为什么要单单提起这两个分布呢?我觉得这是论文 A Note on the Inception Score 中一个很巧妙的idea——对于生成式对抗网络GAN,生成器目标是生成能欺骗过判别器的以假乱真的图像,判别器的目标是判别一个图像是生成图像还是判别图像,因此生成的图像可以保证“以假乱真”,即近似于真实图像,但生成图像的清晰度和多样性并不能保证。这里定义的“清晰的图像”并不是指分辨率高或图像边缘清晰,而是指图像中物体的归类是清晰的,即 p ( y i ∣ x ) p(y_i|x) p(yix) p ( y j ∣ x ) , j ≠ i p(y_j|x),j \neq{i} p(yjx),j=i 显著大。其可以描述为 p ( y ∣ x ) p(y|x) p(yx) 的熵(混乱度)越低,生成图像的“清晰度”越高(但若是同时多个输出层单元输出值都比别的值显著大呢?);生成图像的多样性也很重要,传统的GAN很容易发生模式坍塌,即生成器在与判别器的对抗过程中找到了一种能较为容易地骗过判别器的模式,从而生成这种模式图像的概率会越来越大,导致生成图像趋于一致而多样性降低。多样性即指生成图像属于每个类别的概率是相同的,同样可以用熵(混乱度)描述为 p ( y ) p(y) p(y) 越大(趋于均匀分布),生成图像越多样化。(为什么均匀分布熵最大呢?百度上可以搜到很多数学证明,我有一个很容易理解的比喻:比如小朋友在一个限定区域内堆叠积木块,若某个积木块堆比其他积木块堆明显高很多,则这堆很容易坍倒;而当所有积木堆几乎一样高时,才是最稳定的状态。世界上一切事物或系统均有熵增的倾向,系统的熵越大,系统越稳定,因此可以把均匀分布(积木堆一样高)看做熵最大的分布。不知道我这个比喻是否恰当,但很容易理解并记住。[这么有趣的比喻很难得啦,接下来就要上数学公式啦])

    IS评价指标的计算公式如下所示:
IS ( G ) = e x p ( E x ∼ p g D K L ( p ( y ∣ x ) ∣ ∣ p ( y ) ) ) {\rm\textbf {IS}}(G) = exp(\mathbb{E_{x \sim{p_g}}}D_{KL}(p(y|x)||p(y))) IS(G)=exp(ExpgDKL(p(yx)p(y)))
    IS评价指标越大,说明 p ( y ∣ x ) p(y|x) p(yx) p ( y ) p(y) p(y) 的分布的差异越大。的确,我们之前分析出IS的目标是 p ( y ∣ x ) p(y|x) p(yx) 近似为尖峰分布, p ( y ) p(y) p(y) 近似为均匀分布,二者分布差异很大,且一个熵小,一个熵大。但这似乎不足以说明公式的必要性,我自己在对公式中的KL散度做公式推导时的结果也与两个分布的熵的减结果有点出入,后来知乎上的一篇推导提醒了我(链接为哪位大神解释下inception score?)原来是忽视了公式中的期望符号。正确的推导如下图所示:

Alt
    对于IS评价指标,根据上述关于类别、标签的描述,可以发现Inception V3这个判别模型要与GAN在同样的数据集上进行训练(ImageNet),否则GAN很难生成可以归类于Inception V3训练集类别的图像。论文中作者还通过实验发现IS指标对神经网络内部权重很敏感,就算是相同的准确率但不同的权重会导致IS差异较大;并且涉及到概率分布的地方,都存在数据量越大概率分布拟合越准确的问题,当样本较少时,概率分布是很难准确估计的;此外,原博主发现,若神经网络记住了所有训练数据,IS值会很高,但这并不是我们想要的结果,也就是说,除了IS反映的GAN生成图像的清晰度和多样性之外,还有很多方面是值得考虑的。
 
 

二、FID(Fréchet Inception Distance)

 
    一般情况下IS评价指标的使用很少,因为它只考虑了GAN生成样本的质量,并没有考虑真实数据的影响。IS用Inception V3直接输出类别,而FID则用其输出特征。借用原博主的博文—— IS 无法反映真实数据和样本之间的距离,IS 判断数据真实性的依据,源于 Inception V3 的训练集—— ImageNet,在 Inception V3 的“世界观”下,凡是不像 ImageNet 的数据,都是不真实的,都不能保证输出一个 sharp 的 predition distribution。而FID距离计算真实样本,生成样本在特征空间之间的距离。首先利用Inception网络来提取特征,然后使用高斯模型对特征空间进行建模,再去求解两个特征之间的距离,较低的FID意味着较高图片的质量和多样性。

    相比于IS,FID对噪声更加鲁棒,但仍未解决大规模数据集上过拟合的问题,并且基于特征提取的方法只能根据特征的有无进行评价,而不能评价特征的相对空间位置。“GAN的论文中经常使用FID作为IS的补充,特别是在多样性和mode collapse问题上,FID有更好地评价表现,但也有和IS同样的缺陷,比如不适合在内部差异较大的数据集上使用,无法区分过拟合等。”(原谅我多次引用原博主的博文,因为数学公式和推导实在太少,并且原博主已经总结得很不错啦,为何不站在巨人的肩膀上眺望远方呢~嘿嘿。)
 
 

三、其它一些评价指标

 
    (嗯,没错,我这里汇总得这么全面是为了日后研究中方便查找学习[标题外的拓展被发现了~])

    由于评价指标有点多,并且日后可以继续查找相关资料,这里就简写为Mode Score、Kernel MMD (Maximum Mean Discrepancy)、Wasserstein distance(这个我在以前读wGAN两篇论文时接触过一些)、1-Nearest Neighbor classifier……

    以下是引用:

    虽然目前GAN论文中用到的指标仍然是IS和FID偏多,但是MMD和1-Nearest Neighbor classifier是最为合适的评价指标,这两个指标可以较好的区分:真实样本和生成的样本,mode dropping, mode collapsing,且计算高效。1-NN 分类器几乎是评估 GAN 的完美指标,它不仅具备其他指标的所有优势,其输出分数还在 [0, 1] 区间中,类似于分类问题中的准确率。

    下面是原博主们的一些参考引用:
GAN的评价:An empirical study on evaluation metrics of generative adversarial networks
六种GAN评估指标的综合评估实验,迈向定量评估GAN的重要一步
Inception Score 的原理和局限性

Fréchet Inception Distance
Fréchet Inception Distance (FID)
 
 

小结

 
    距离上次写原创已经差不多一个月了,虽然这篇博文借鉴了很多其他博主的博文,但我还是学到了很多东西。还是那句老话,笔者还是小白一枚,若有不恰当、不正确的地方还请及时指出;如果你有更好的建议与方法,欢迎赐教~
 
 

纵心似水
2019.10.15
——与世界共情,与你同感

  • 27
    点赞
  • 139
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
以下是使用Inception Score评价GAN网络生成图片质量的Python代码: ```python import tensorflow as tf import numpy as np import os import functools from tensorflow.python.ops import array_ops from tensorflow.python.ops import functional_ops slim = tf.contrib.slim def inception_score(images, num_classes=1000, batch_size=32, splits=10): """ 计算Inception Score :param images: 生成图片的张量,shape为[batch_size, height, width, channels],像素值范围为[0, 255] :param num_classes: Inception网络的类别数,默认为1000 :param batch_size: 计算Inception Score时的batch大小,默认为32 :param splits: 分割数量,默认为10 :return: Inception Score """ assert (images.shape[1] == images.shape[2]) # 保证图片为正方形 inception_images = tf.image.resize_bilinear(images, [299, 299]) inception_images = tf.divide(inception_images, 255.0) logits = [] for i in range(0, images.shape[0], batch_size): batch = inception_images[i:i + batch_size, :, :, :] logit = functional_ops.softmax( functional_ops.in_top_k( predictions=tf.cast(batch, tf.float32), targets=tf.constant(np.arange(num_classes)), k=1) ) logits.append(logit) logits = array_ops.concat(logits, 0) scores = [] for i in range(splits): part = logits[ (i * logits.shape[0] // splits): ((i + 1) * logits.shape[0] // splits), :] kl = part * (tf.log(part) - tf.log(tf.reduce_mean(part, 0, keepdims=True))) kl = tf.reduce_mean(tf.reduce_sum(kl, 1)) scores.append(tf.exp(kl)) return tf.reduce_mean(scores) def get_inception_score(sess, images_ph, fake_images): """ 计算Inception Score :param sess: TensorFlow会话 :param images_ph: 真实图片的占位符 :param fake_images: 生成图片的张量 :return: Inception Score """ assert (fake_images.shape[1] == fake_images.shape[2]) # 保证图片为正方形 fake_images = (fake_images + 1.0) / 2.0 # 将像素值从[-1, 1]转换为[0, 1] num_images = fake_images.shape[0] num_batches = int(np.ceil(num_images / 32)) scores = [] for i in range(num_batches): batch_fake_images = fake_images[i * 32:(i + 1) * 32] score = sess.run(inception_score(images_ph, fake_images=batch_fake_images)) scores.append(score) return np.mean(scores) if __name__ == '__main__': # 在此处定义生成生成的图片张量fake_images # ... # 加载Inception模型 inception_path = os.path.join('inception', 'inception_v3.ckpt') sess = tf.Session() images_ph = tf.placeholder(tf.float32, shape=[None, None, None, 3]) with slim.arg_scope(inception_v3_arg_scope()): _, end_points = inception_v3(images_ph, num_classes=1000, is_training=False) inception_variables = slim.get_variables(scope='InceptionV3') saver = tf.train.Saver(var_list=inception_variables) saver.restore(sess, inception_path) # 计算Inception Score inception_score = get_inception_score(sess, images_ph, fake_images) print('Inception Score:', inception_score) sess.close() ``` 需要注意的是,这里假设生成生成的图片像素值范围为[-1, 1],因此需要先将像素值从[-1, 1]转换为[0, 1]。同时,需要将Inception模型文件(`inception_v3.ckpt`)和代码文件放在同一个目录下。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值