简述生成式对抗网络
来源:互联网 发布:大数据风控体系 编辑:程序博客网 时间:2024/05/22 05:28
【转载请注明出处】chenrudan.github.io
本文主要阐述了对生成式对抗网络的理解,首先谈到了什么是对抗样本,以及它与对抗网络的关系,然后解释了对抗网络的每个组成部分,再结合算法流程和代码实现来解释具体是如何实现并执行这个算法的,最后给出一个基于对抗网络改写的去噪网络运行的结果,效果虽然挺差的,但是有些地方还是挺有意思的。
- 1. 对抗样本
- 2. 生成式对抗网络GAN
- 3. 代码解释
- 4. 运行实例
- 5. 小结
- 6. 引用
1. 对抗样本(adversarial examples)
14年的时候Szegedy在研究神经网络的性质时,发现针对一个已经训练好的分类模型,将训练集中样本做一些细微的改变会导致模型给出一个错误的分类结果,这种虽然发生扰动但是人眼可能识别不出来,并且会导致误分类的样本被称为对抗样本,他们利用这样的样本发明了对抗训练(adversarial training),模型既训练正常的样本也训练这种自己造的对抗样本,从而改进模型的泛化能力[1]。如下图所示,在未加扰动之前,模型认为输入图片有57.7%的概率为熊猫,但是加了之后,人眼看着好像没有发生改变,但是模型却认为有99.3%的可能是长臂猿。
这个问题乍一看很像过拟合,在Goodfellow在15年[3]提到了其实模型欠拟合也能导致对抗样本,因为从现象上来说是输入发生了一定程度的改变就导致了输出的不正确,例如下图一,上下分别是过拟合和欠拟合导致的对抗样本,其中绿色的o和x代表训练集,红色的o和x即对抗样本,明显可以看到欠拟合的情况下输入发生改变也会导致分类不正确(其实这里我觉得有点奇怪,因为图中所描述的对抗样本不一定就是跟原始样本是同分布的,感觉是人为造的一个东西,而不是真实数据的反馈)。在[1]中作者觉得这种现象可能是因为神经网络的非线性和过拟合导致的,但Goodfellow却给出了更为准确的解释,即对抗样本误分类是因为模型的线性性质导致的,说白了就是因为
如果认为对抗样本是因为模型的线性性质导致的,那么是否能够构造出一个方法来生成对抗样本,即如何在输入上加扰动,Goodfellow给出了一种构造方法fast gradient sign method[2],其中
这个构造方法在[4]中有比较多的实例,这里截取了两个例子来说明,用imagenet图片缩放到64*64来训练一个一层的感知机,输入是64*64*3,输出是1000,权重是64*64*3*1000,训练好之后取权重矩阵对应某个输出类别的一行64*64*3,将这行还原成64*64图片显示为下图中第二列,再用公式1的方法从第一列的原始图片中算出第三列的对抗样本,可以看到第一行从预测为狐狸变成了预测为金鱼,第二行变成了预测为校车。
实际上不是只有纯线性模型才会出现这种情况,卷积网络的卷积其实就是线性操作,因此也有预测不稳定的情况,relu/maxout甚至sigmoid的中间部分其实也算是线性操作。因为可以自己构造对抗样本,那么就能应用这个性质来训练模型,让模型泛化能力更强。因而[2]给定了一种新的目标函数也就是下面的式子,相当于对输入加入一些干扰,并且也通过实验结果证实了训练出来的模型更加能够抵抗对抗样本的影响。
对抗样本跟生成式对抗网络没有直接的关系,对抗网络是想学样本的内在表达从而能够生成新的样本,但是有对抗样本的存在在一定程度上说明了模型并没有学习到数据的一些内部表达或者分布,而可能是学习到一些特定的模式足够完成分类或者回归的目标而已。公式1的构造方法只是在梯度方向上做了一点非常小的变化,但是模型就无法正确的分类。此外还观察到一个现象,用不同结构的多个分类器来学习相同数据,往往会将相同的对抗样本误分到相同的类中,这个现象看上去是所有的分类器都被相同的变化所干扰了。
2. 生成式对抗网络GAN
14年Goodfellow提出Generative adversarial nets即生成式对抗网络[5],它要解决的问题是如何从训练样本中学习出新样本,训练样本是图片就生成新图片,训练样本是文章就输出新文章等等。如果能够知道训练样本的分布
GAN的优化是一个极小极大博弈问题,最终的目的是generator的输出给discriminator时很难判断是真实or伪造的,即极大化
以上是关于最基本GAN的介绍,最开始我看了论文后产生了几个疑问,1.为什么不能直接学习
3. 代码解释
这部分主要结合tensorflow实现代码[7]、算法流程和下面的变化图[5]解释一下具体如何使用DCGAN来生成手写体图片。
下图中黑色虚线是真实数据的高斯分布,绿色的线是生成网络学习到的伪造分布,蓝色的线是判别网络判定为真实图片的概率,标x的横线代表服从高斯分布x的采样空间,标z的横线代表服从均匀分布z的采样空间。可以看出
a.起始情况
12345678
w = tf.get_variable('w', [4, 4, c_dim, num_filter],initializer=tf.truncated_normal_initializer(stddev=stddev))dconv = tf.nn.conv2d(ddata, w, strides=[1, 2, 2, 1], padding='SAME')biases = tf.get_variable('biases', [num_filter],initializer=tf.constant_initializer(0.0))bias = tf.nn.bias_add(dconv, biases)dconv1 = tf.maximum(bias, leak*bias)...
12345678910
w = tf.get_variable('w', [4, 4, num_filter, num_filter*2],initializer=tf.random_normal_initializer(stddev=stddev))deconv = tf.nn.conv2d_transpose(gconv2, w,output_shape=[batch_size, s2, s2, num_filter],strides=[1, 2, 2, 1])biases = tf.get_variable('biases', [num_filter],initializer=tf.constant_initializer(0.0))bias = tf.nn.bias_add(deconv, biases)deconv1 = tf.nn.relu(bias, name=scope.name)...
12
batch_z = np.random.uniform(-1, 1, [config.batch_size, self.z_dim]).astype(np.float32)
这个过程可以参考上图的a状态,判别曲线处于不够稳定的状态,两个网络都还没训练好。
b.训练判别网络
判别网络的损失函数由两部分组成,一部分是真实数据判别为1的损失,一部分是
123456789
self.G = self.generator(self.z)self.D, self.D_logits = self.discriminator(self.images)self.D_, self.D_logits_ = self.discriminator(self.G, reuse=True)self.d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(self.D_logits, tf.ones_like(self.D)))self.d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(self.D_logits_, tf.zeros_like(self.D_)))self.d_loss = self.d_loss_real + self.d_loss_fake
然后将一个batch的真实数据batch_images,和随机变量batch_z当做输入,执行session更新
123456
# update discriminator on reald_optim = tf.train.AdamOptimizer(FLAGS.learning_rate,beta1=FLAGS.beta1).minimize(d_loss, var_list=d_vars)...out1 = sess.run([d_optim], feed_dict={real_images: batch_images,noise_images: batch_z})
这一步可以对比图b,判别曲线渐渐趋于平稳。
c.训练生成网络
生成网络并没有一个独立的目标函数,它更新网络的梯度来源是判别网络对伪造图片求的梯度,并且是在设定伪造图片的label是1的情况下,保持判别网络不变,那么判别网络对伪造图片的梯度就是向着真实图片变化的方向。
12
self.g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(self.D_logits_, tf.ones_like(self.D_)))
然后用同样的随机变量batch_z当做输入更新
1234
g_optim = tf.train.AdamOptimizer(config.learning_rate, beta1=config.beta1).minimize(self.g_loss, var_list=self.g_vars)...out2 = sess.run([g_optim], feed_dict={noise_images:batch_z})
这一步可以对比图c,
因而针对我之前的问题,2已经有了答案,针对1,为什么不能直接学习
4. 运行实例
这里本来想用GAN来跑一个去噪的网络,基于[7]的代码改了一下输入,从一个100维的noise向量变成了一张输入图片,同时将generator网络的前面部分变成了卷积网络,再连上原来的逆卷积,就成了一个去噪网络,这里我没太多时间来细致的调节网络层数、参数等,就随便试了一下,效果也不是特别的好。代码在[9]中。首先我通过read_stl10.py对stl10数据集加上了均值为0方差为50的高斯噪声,前后对比如下。
然后执行对抗网络,会得到如下的去噪效果,从左到右分别是加了噪声的输入图片,对应的generator网络的输出图片,已经对应的干净图片,效果不是特别好,轮廓倒是能学到一点,但是这个颜色却没学到。
5. 小结
刚开始搜资料的时候发现了对抗样本,以为跟对抗网络有关系,就看了一下,后来看Goodfellow的论文时发现其实没什么关系,但是还是写了一些内容,因为这个东西的存在还是值得了解的,而对抗网络这个想法真的太赞了,它将一个无监督问题转化为有监督,更加像一种learn的方式来学习数据应该是如何产生,而不是find的方式来找某些特征,但是训练也是一个难题,从我的经验来看,特别容易过拟合,而且确实有一种对抗的感觉在里面,因为generator的输入时好时坏,总的来说是个很棒的算法,非常期待接下来的研究。
6. 引用
[1] Intriguing properties of neural networks
[2] EXPLAINING AND HARNESSING ADVERSARIAL EXAMPLES
[3] Adversarial Examples
[4] Breaking Linear Classifiers on ImageNet
[5] Generative Adversarial Nets
[6] Quick introduction to GANs
[7] carpedm20/DCGAN-tensorflow
[8] Generative Adversarial Nets in TensorFlow (Part I)
[9] chenrudan/deep-learning/denoise_dcgan/
- 简述生成式对抗网络
- 简述生成式对抗网络
- 简述生成式对抗网络 GAN
- 【GAN】简述生成对抗式网络
- 对抗样本与生成式对抗网络
- 对抗样本与生成式对抗网络
- 对抗样本与生成式对抗网络
- 对抗样本与生成式对抗网络
- GAN 生成式对抗网络
- 简单生成式对抗网络
- Generative Adversarial Nets 生成式对抗网络
- 生成式对抗网络GAN汇总
- 生成式对抗网络GAN汇总 研究进展
- GenerativeAdversarial Nets生成对抗式网络
- 生成式对抗网络GAN汇总
- 生成对抗式网络GAN 的 loss
- GAN生成式对抗网络总结
- 到底什么是生成式对抗网络GAN?
- HDU 5884 Sort (二分 贪心(k叉哈夫曼树))
- 给自己一个两年
- C# GDI+ 绘图
- 集合Collection
- Tensorflow 实战(-) 基础知识
- 简述生成式对抗网络
- 网络编程项目(聊天室项目)
- (function($) {…})(jQuery);
- 2.2logistic回归
- 线程安全、数据同步之synchronized与Lock
- Python笔记--默认参数最大的“坑”
- springboot 整合freemarker404问题
- webstorm配置sublime主题
- linux spi驱动开发学习-----spidev.c和spi test app