GAN的开始

https://blog.csdn.net/leviopku/article/details/81292192

1.概况

  Gan主要包含两个部分,一部分是生成器generator一部分是判别器discriminator。生成器主要用来学习真实图像分布从而让自身生成的图像更加真实,以骗过判别器。判别器则是对接收的图片进行真假判别。整个的过程就是生成器生成的图片越来越真实,判别器判别真实图片的性能更加准确,随着时间的推移,两个模型达到一种平衡。生成器生成的图片接近于真实图片,判别器识别不出来真假图片,对给定的图像的预测为真的概率接近0.5.

我们可以将上面的内容进行一个总结。给定真 = 1,假 = 0,那么有:

对于给定的真实图片(real image),判别器要为其打上标签 1;

对于给定的生成图片(fake image),判别器要为其打上标签 0;

对于生成器传给辨别器的生成图片,生成器希望辨别器打上标签 1。

2. GAN的特点:

●  相比较传统的模型,他存在两个不同的网络,而不是单一的网络,并且训练方式采用的是对抗训练方式

●  GAN中G的梯度更新信息来自判别器D,而不是来自数据样本

3.GAN优点

●  GAN是一种生成式模型,相比较其他生成模型(玻尔兹曼机和GSNs)只用到了反向传播,而不需要复杂的马尔科夫链

●  相比其他所有模型, GAN可以产生更加清晰,真实的样本

●  GAN采用的是一种无监督的学习方式训练,可以被广泛用在无监督学习和半监督学习领域

●  相比于变分自编码器, GANs没有引入任何决定性偏置( deterministic bias),变分方法引入决定性偏置,因为他们优化对数似然的下界,而不是似然度本身,这看起来导致了VAEs生成的实例比GANs更模糊

●  相比VAE, GANs没有变分下界,如果鉴别器训练良好,那么生成器可以完美的学习到训练样本的分布.换句话说,GANs是渐进一致的,但是VAE是有偏差的

●  GAN应用到一些场景上,比如图片风格迁移,超分辨率,图像补全,去噪,避免了损失函数设计的困难,不管三七二十一,只要有一个的基准,直接上判别器,剩下的就交给对抗训练了。

4.GAN缺点

●  训练GAN需要达到纳什均衡,有时候可以用梯度下降法做到,有时候做不到.我们还没有找到很好的达到纳什均衡的方法,所以训练GAN相比VAE或者PixelRNN是不稳定的,但我认为在实践中它还是比训练玻尔兹曼机稳定的多

●  GAN不适合处理离散形式的数据,比如文本

●  GAN存在训练不稳定、梯度消失、模式崩溃的问题

5.原理

gan网络流程图

损失函实际上是一个交叉熵,判别器的目的是尽可能的令D(x)接近1,令D(G(z))接近0,所以D主要是最大化上面的损失函数,G恰恰相反,他主要是最小化上述损失函数。

训练过程:

求平衡点之前,我们先做一个数学假设,即G固定情况下D的最优形式,然后根据D的最优形式再去观察G最小化损失函数的问题。

假设在G固定的条件下,并将损失函数化为如下简单形式:

D的目标就是最大化L,我们可以通过对L求导,并令导数为0,计算出L取最大值时y的取值如下:

所以,换为原来的式子D的最优解形式为:

到这里我们得出了结论,当G固定时,D的最优形式是上面形式。

接下来我们求一下D最优时,G最小化损失函数到什么形式才能达到二者相互博弈的平衡点。

带入到损失函数里面后,损失函数可以写为如下形式:

这时观察到,上面式子仍然是一个交叉熵也称KL散度的形式,KL散度通常用来衡量分布之间的距离,它是非对称的。同样还有另一个衡量数据分布距离的散度--JS散度,他们之间有如下关系。

不过JS散度有一个很重要的性质就是总是大于等于0的,当且仅当 P1=P2上面的式子取得最小值0,

所以我们可以将C(G)写成JS散度的形式:

也即是当且仅当Pg=Pdata时,C(G)取得最小值-log(4),也即是D最优时,G能将损失函数最小化到-log(4),最小点处Pg=Pdata。即真实数据的分布和生成数据的分布相等。

分析到这里,直观上也很好理解了,Pg=Pdata意味着此时D恰好等于0.5,就是D有一半的概率认为D(G(z))是真的数据,有一半概率认为是假的数据,这不就和猜硬币正反面一样嘛。也说明了此时G生成的数据足以以假乱真。

代码

-- coding: utf-8 --

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os

读入数据

mnist = input_data.read_data_sets(’./mnist’, one_hot=True) # 代码和数据集文件夹放在同一目录下

从正态分布输出随机值

def xavier_init(size):
in_dim = size[0]
xavier_stddev = 1. / tf.sqrt(in_dim / 2.)
return tf.random_normal(shape=size, stddev=xavier_stddev)

判别模型的输入和参数初始化

X = tf.placeholder(tf.float32, shape=[None, 784])

D_W1 = tf.Variable(xavier_init([784, 128]))
D_b1 = tf.Variable(tf.zeros(shape=[128]))

D_W2 = tf.Variable(xavier_init([128, 1]))
D_b2 = tf.Variable(tf.zeros(shape=[1]))

theta_D = [D_W1, D_W2, D_b1, D_b2]

生成模型的输入和参数初始化

Z = tf.placeholder(tf.float32, shape=[None, 100])

G_W1 = tf.Variable(xavier_init([100, 128]))
G_b1 = tf.Variable(tf.zeros(shape=[128]))

G_W2 = tf.Variable(xavier_init([128, 784]))
G_b2 = tf.Variable(tf.zeros(shape=[784]))

theta_G = [G_W1, G_W2, G_b1, G_b2]

随机噪声采样函数

def sample_Z(m, n):
return np.random.uniform(-1., 1., size=[m, n])

生成模型

def generator(z):
G_h1 = tf.nn.relu(tf.matmul(z, G_W1) + G_b1)
G_log_prob = tf.matmul(G_h1, G_W2) + G_b2
G_prob = tf.nn.sigmoid(G_log_prob)

return G_prob

判别模型

def discriminator(x):
D_h1 = tf.nn.relu(tf.matmul(x, D_W1) + D_b1)
D_logit = tf.matmul(D_h1, D_W2) + D_b2
D_prob = tf.nn.sigmoid(D_logit)

return D_prob, D_logit

画图函数

def plot(samples):
fig = plt.figure(figsize=(4, 4))
gs = gridspec.GridSpec(4, 4)
gs.update(wspace=0.05, hspace=0.05)

for i, sample in enumerate(samples):
    print('sample.shape',sample.shape)
    ax = plt.subplot(gs[i])
    plt.axis('off')
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    ax.set_aspect('equal')
    plt.imshow(sample.reshape(28, 28), cmap='Greys_r')

return fig

喂入数据

G_sample = generator(Z)
D_real, D_logit_real = discriminator(X)
D_fake, D_logit_fake = discriminator(G_sample)

计算losses:

D_loss_real = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_real, labels=tf.ones_like(D_logit_real)))
D_loss_fake = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_fake, labels=tf.zeros_like(D_logit_fake)))
D_loss = D_loss_real + D_loss_fake

G_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_fake, labels=tf.ones_like(D_logit_fake)))

D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)

mb_size = 128
Z_dim = 100

sess = tf.Session()
sess.run(tf.global_variables_initializer())

if not os.path.exists(‘out/’):
os.makedirs(‘out/’)

i = 0

开始训练

for it in range(1000000):
if it % 1000 == 0:
samples = sess.run(G_sample, feed_dict={Z: sample_Z(16, Z_dim)})
print(‘samples.shape’,samples.shape)

    fig = plot(samples)
    plt.savefig('out/{}.png'.format(str(i).zfill(3)), bbox_inches='tight')
    i += 1
    plt.close(fig)

X_mb, _ = mnist.train.next_batch(mb_size)

_, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: sample_Z(mb_size, Z_dim)})
_, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: sample_Z(mb_size, Z_dim)})

if it % 1000 == 0:
    print('Iter: {}'.format(it))
    print('D loss: {:.4}'.format(D_loss_curr))
    print('G_loss: {:.4}'.format(G_loss_curr))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值