GAN 学习 (1)

GAN 学习 第一天

这篇博客主要是学习这个网址上的内容。
https://wiseodd.github.io/techblog/2016/09/17/gan-tensorflow/
关于GAN,就是警察抓罪犯,罪犯设法躲避警察的故事。
今天是第一天学习GAN,看了Goodfellow的 Generative Adversarial Nets ,为了加深印象,看了一些网上写的代码,虽然没有具体去操作运行,但是观看代码可以进一步的理解文章中GAN的具体操作。
这些代码实在tensorflow上编写的,原文的实现代码不是在tf上做的,是一个很老的机器学习框架。没具体接触过tf,也没学过python语句,所以这里做一些代码的注释,就相当于一个学习的过程。一能理解GAN,而能学习python以及tf的使用。

  • 一、代码解读
    首先 GAN 需要两个网络,一个G网络(Discriminator Net),一个D网络(Generator Net),
import numpy as np   # NumPy is the fundamental package for scientific computing with Python
import tensorflow as tf
# xavier_init,概括来讲,就是根据每层的输入个数和输出个数来决定参数随机初始化的分布范围。对model内部参数进行初始化
def xavier_init(fan_in, fan_out, constant = 1):
    low = -constant * np.sqrt(6.0 / (fan_in + fan_out))
    high = constant * np.sqrt(6.0 / (fan_in + fan_out))
    # tf.random_uniform是用于生成随机数tensor的。尺寸是shape。tf.random_uniform(shape,minval=0,maxval=None,dtype=tf.float32,seed=None,name=None)。random_uniform:均匀分布随机数,范围为[minval,maxval] 
    return tf.random_uniform((fan_in, fan_out),
                         minval = low, maxval = high,
                         dtype = tf.float32)
# Discriminator Net
X = tf.placeholder(tf.float32, shape=[None, 784], name='X')#Tensor("X:0", shape=(?, 784), dtype=float32)
#tf.placeholder(dtype, shape=None, name=None)此函数可以理解为形参,用于定义过程,在执行的时候再赋具体的值。
#参数:
    #dtype:数据类型。常用的是tf.float32,tf.float64等数值类型
    #shape:数据形状。默认是None,就是一维值,也可以是多维,比如[2,3], [None, 3]表示列是3,行不定
    #name:名称。
D_W1 = tf.Variable(xavier_init(784, 128), name='D_W1')  #Tensor("random_uniform:0", shape=(784, 128), dtype=float32)
#tf.Variable一个变量通过调用run() 方法维持图的状态。你通过构造variable 类的实例来添加一个变量到图中。Variable() 构造器需要一个初始值,可以是任意类型和shape 的Tensor。初始值定义了变量的type和shape。构造完成之后,变量的type和shape 是固定的。可以使用assign 方法来修改变量的值。
D_b1 = tf.Variable(tf.zeros(shape=[128]), name='D_b1')

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

theta_D = [D_W1, D_W2, D_b1, D_b2]

# Generator Net
Z = tf.placeholder(tf.float32, shape=[None, 100], name='Z')

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

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

theta_G = [G_W1, G_W2, G_b1, G_b2]


def generator(z):
    G_h1 = tf.nn.relu(tf.matmul(z, G_W1) + G_b1)
    #tf.matmul(z, G_W1) + G_b1,输入乘以权值,再加上一个输入
    #tf.nn.relu作用:计算修正线性单元(非常常用):max(features, 0).并且返回和feature一样的形状的tensor。tf.nn.relu tf.nn.relu6 tf.nn.crelu tf.nn.elu  tf.nn.softplus tf.nn.softsign tf.nn.dropout tf.nn.bias_add tf.sigmoid tf.tanh

    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

**注:tf.matmul两个矩阵相乘,不是点乘,print打印不了数值,具体打印方法**
1import numpy as np
import tensorflow as tf
a = tf.constant([1,2,3,4,5,6],shape=[2,3])
print(a)
b = tf.constant([7,8,9,10,11,12],shape=[3,2])
print(b)
c = tf.matmul(a, b)
print(c)
# Launch the graph in a session.  
sess = tf.Session()  
# Evaluate the tensor `c`.  
print(sess.run(c)) 
2import numpy as np
import tensorflow as tf
a = tf.constant([1,2,3,4,5,6],shape=[2,3])
print(a)
b = tf.constant([7,8,9,10,11,12],shape=[3,2])
print(b)
c = tf.matmul(a, b)
print(c)
with tf.Session():  
  # We can also use 'c.eval()' here.  
  print(c.eval())  

从上面代码可以看到, generator(z)的输入是n×100的数据,而输出是n×786的数据,MNIST图像的大小为28*18.z是对于G(z)来说,初始时是一个随机噪声。在某种程度上,G(z)是在学习一个映射,而这个映射可以使的z映射到数据集P_data中。(附上论文中的一张示意图)

这里写图片描述

discriminator(x) 的输入是 MNIST images,然后会返回一个表示图像为真实MNIST图像的概率值。
下面的截图为论文中的算法:
这里写图片描述

下面为算法实现的具体代码

G_sample = generator(Z) #G网络生成的图像数据
D_real, D_logit_real = discriminator(X) #对真实数据进行识别,输出概率值
D_fake, D_logit_fake = discriminator(G_sample)#对虚拟图像G数据进行识别,输出概率值

D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake))
G_loss = -tf.reduce_mean(tf.log(D_fake))

# tf.reduce_mean
     假设x = [[1,2]
               [3,4]]
     tf.reduce_mean(x) ==> 2.5 #如果不指定第二个参数,那么就在所有的元素中取平均值
     tf.reduce_mean(x, 0) ==> [2.,  3.] #指定第二个参数为0,则第一维的元素取平均值,即每一列求平均值
     tf.reduce_mean(x, 1) ==> [1.5,  3.5] #指定第二个参数为1,则第二维的元素取平均值,即每一行求平均值

使用负号是因为loss要进行最大化,而且tf只能做最小化运算。
接着,使用这些对抗网络一步一步的进行训练。

# 只对D(X)进行参数更新, 所以theta_G用不到。tf.train.AdamOptimizer().minimize参数优化器
D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
#只对G(X)进行参数更新, 所以theta_D用不到
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)
#定义一个随机的噪声作为G的输入
def sample_Z(m, n):
    '''Uniform prior for G(Z)'''
    return np.random.uniform(-1., 1., size=[m, n])
#不过TensorFlow封装的比较好,所以只需要3句话就可以训练1000000次,mb_size是每次随机选择mb_size个样本进行训练:
for it in range(1000000):
    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)})

到此,整个对抗网络基本已经完成。我们可以通过对 G(Z)进行采样,得到产生的数据图像,以此来观察其训练过程。

总结:
GAN的G网络开始于一组随机噪声,G(z)通过训练使生成的数据越来越接近于真实数据的分布。
discriminator(X)想要所有的输出结果都等于1,即想要得到真实数据的的得分概率值最大。discriminator(G_sample)想要所有的输出结果都为0,即想要得到伪造数据的得分值最小。而
generator(Z)却想使discriminator(G_sample)最大。
所以,应该可以通过改进这一块的计算方法来提升性能。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值