前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一看就懂的Tensorflow实战(DCGAN)

一看就懂的Tensorflow实战(DCGAN)

作者头像
AI异构
发布2020-07-29 11:25:38
7240
发布2020-07-29 11:25:38
举报
文章被收录于专栏:AI异构AI异构

DCGAN简介

DCGAN在GAN的基础上优化了网络结构,加入了 convbatch_norm 等层,使得网络更容易训练,网络结构如下:

DCGAN网络结构图

注意:本图只是示例,与下面实际网络参数不对应。

Tensorflow实现DCGAN

代码语言:javascript
复制
from __future__ import division, print_function, absolute_import

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
导入数据集
代码语言:javascript
复制
# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./data/", one_hot=True)

代码语言:javascript
复制
Extracting ./data/train-images-idx3-ubyte.gz
Extracting ./data/train-labels-idx1-ubyte.gz
Extracting ./data/t10k-images-idx3-ubyte.gz
Extracting ./data/t10k-labels-idx1-ubyte.gz
设置参数
代码语言:javascript
复制
# 训练参数
num_steps = 10000 # 总迭代次数
batch_size = 128 # 批量大小
lr_generator = 0.002 # 生成器学习率
lr_discriminator = 0.002 # 判别器学习率

# 网络参数
image_dim = 784 # 28*28 pixels * 1 channel
noise_dim = 100 # Noise data points
构建DCGAN网络
代码语言:javascript
复制
# 构建网络
# 网络输入
noise_input = tf.placeholder(tf.float32, shape=[None, noise_dim])  # 生成器输入 噪声 batch*100,none后面被赋值batch
real_image_input = tf.placeholder(tf.float32, shape=[None, 28, 28, 1]) # 判别器输入 真实图像 batch*28*28*1
# A boolean to indicate batch normalization if it is training or inference time
# 判断是否在训练
is_training = tf.placeholder(tf.bool)

# 定义激活函数 LeakyReLU,在判别器网络中用
# LeakyReLU 是 ReLU 的变种 <a href="#footnote-1"><sup>[1]</sup></a>
def leakyrelu(x, alpha=0.2):
    return 0.5 * (1 + alpha) * x + 0.5 * (1 - alpha) * abs(x)

# 定义生成器网络
# 输入:噪声  输出:图像
# 训练时,才使用batch_normalization
def generator(x, reuse=False):
    with tf.variable_scope('Generator', reuse=reuse):
        # 第一层为全连接层,含神经元个数为7*7*128,输入是噪声batch*100
        x = tf.layers.dense(x, units=7 * 7 * 128)
        # tf.layers.batch_normalization() 的第二个参数axis表示在哪一个维度做normalize,通常数据排布顺序为(batch, height, width, channels),固默认为-1
        # 全连接层channel=1,所以是对所有数据做normalize
        x = tf.layers.batch_normalization(x, training=is_training)
        # 激活函数 rule
        x = tf.nn.relu(x)
        # Reshape为4维: (batch, height, width, channels),这里是 (batch, 7, 7, 128)
        x = tf.reshape(x, shape=[-1, 7, 7, 128])
        # 反卷积层1
        # 卷积核大小5*5*128,64个,步长2(tf.layers.conv2d_transpose函数前几个参数为input,filters(输出feature map通道数),kernel_size, strides,padding)
        # 输入x shape:(batch,7,7,128), 输出image shape: (batch, 14, 14, 64)
        x = tf.layers.conv2d_transpose(x, 64, 5, strides=2, padding='same')
        # batch normalization,在channel维度上做normalize
        x = tf.layers.batch_normalization(x, training=is_training)
        # 激活函数 relu
        x = tf.nn.relu(x)
        # 反卷积层2
        # 卷积核大小5*5*128,1个,步长2
        # 输入x shape:(batch,14,14,64), 输出image shape: (batch, 28, 28, 1)
        x = tf.layers.conv2d_transpose(x, 1, 5, strides=2, padding='same')
        # 激活函数 tanh
        # Apply tanh for better stability - clip values to [-1, 1].
        x = tf.nn.tanh(x)
        return x


# 定义判别器网络
# 输入:图像, 输出: 预测结果(Real/Fake Image)
# 同样训练时,才使用batch_normalization
def discriminator(x, reuse=False):
    with tf.variable_scope('Discriminator', reuse=reuse):
        # 卷积层1,输入x,卷积核大小5x5,64个,步长2
        x = tf.layers.conv2d(x, 64, 5, strides=2, padding='same')
        x = tf.layers.batch_normalization(x, training=is_training)
        # 激活函数 leakyrelu
        x = leakyrelu(x)
        # 卷积层2,输入第一个卷积层的输出,卷积核大小5x5,128个,步长2
        x = tf.layers.conv2d(x, 128, 5, strides=2, padding='same')
        x = tf.layers.batch_normalization(x, training=is_training)
        # 激活函数 leakyrelu
        x = leakyrelu(x)
        # 展平
        x = tf.reshape(x, shape=[-1, 7*7*128])
        # 全连接层,含1024个神经元
        x = tf.layers.dense(x, 1024)
        x = tf.layers.batch_normalization(x, training=is_training)
        # 激活函数 leakyrelu
        x = leakyrelu(x)
        # 输出2个类别: Real and Fake images
        x = tf.layers.dense(x, 2)
    return x

# 构建生成器
gen_sample = generator(noise_input)

# 构建两个判别器(一个是真实图像输入,一个是生成图像)
disc_real = discriminator(real_image_input)
disc_fake = discriminator(gen_sample, reuse=True)

# Build the stacked generator/discriminator
# 用于计算生成器的损失
stacked_gan = discriminator(gen_sample, reuse=True)

# 创建损失函数,交叉熵
# 真实图像,标签1
disc_loss_real = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
    logits=disc_real, labels=tf.ones([batch_size], dtype=tf.int32)))
# 生成图像,标签0
disc_loss_fake = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
    logits=disc_fake, labels=tf.zeros([batch_size], dtype=tf.int32)))
# 判别器损失函数是两者之和
disc_loss = disc_loss_real + disc_loss_fake
# 生成器损失函数 (生成器试图骗过判别器,因此这里标签是1)
gen_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
    logits=stacked_gan, labels=tf.ones([batch_size], dtype=tf.int32)))

# 创建优化器(采用Adam方法)
optimizer_gen = tf.train.AdamOptimizer(learning_rate=lr_generator, beta1=0.5, beta2=0.999)
optimizer_disc = tf.train.AdamOptimizer(learning_rate=lr_discriminator, beta1=0.5, beta2=0.999)

# Training Variables for each optimizer
# By default in TensorFlow, all variables are updated by each optimizer, so we
# need to precise for each one of them the specific variables to update.
# 生成网络的变量
gen_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Generator') # tf.get_collection:从一个结合中取出全部变量,是一个列表
# 判别器网络的变量
disc_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Discriminator')

# 创建训练操作
# TensorFlow UPDATE_OPS collection holds all batch norm operation to update the moving mean/stddev
gen_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='Generator')
# `control_dependencies` ensure that the `gen_update_ops` will be run before the `minimize` op (backprop)
with tf.control_dependencies(gen_update_ops):
    train_gen = optimizer_gen.minimize(gen_loss, var_list=gen_vars)
disc_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='Discriminator')
with tf.control_dependencies(disc_update_ops):
    train_disc = optimizer_disc.minimize(disc_loss, var_list=disc_vars)

# 变量全局初始化
init = tf.global_variables_initializer()
训练
代码语言:javascript
复制
# Start Training
# Start a new TF session
sess = tf.Session()

# Run the initializer
sess.run(init)

# Training
for i in range(1, num_steps+1):

    # Prepare Input Data
    # Get the next batch of MNIST data (only images are needed, not labels)
    batch_x, _ = mnist.train.next_batch(batch_size)
    batch_x = np.reshape(batch_x, newshape=[-1, 28, 28, 1])
    # Rescale to [-1, 1], the input range of the discriminator
    batch_x = batch_x * 2. - 1.

    # Discriminator Training
    # Generate noise to feed to the generator
    z = np.random.uniform(-1., 1., size=[batch_size, noise_dim])
    _, dl = sess.run([train_disc, disc_loss], feed_dict={real_image_input: batch_x, noise_input: z, is_training:True})

    # Generator Training
    # Generate noise to feed to the generator
    z = np.random.uniform(-1., 1., size=[batch_size, noise_dim])
    _, gl = sess.run([train_gen, gen_loss], feed_dict={noise_input: z, is_training:True})

    if i % 500 == 0 or i == 1:
        print('Step %i: Generator Loss: %f, Discriminator Loss: %f' % (i, gl, dl))

代码语言:javascript
复制
Step 1: Generator Loss: 4.064141, Discriminator Loss: 1.679586
Step 500: Generator Loss: 1.472707, Discriminator Loss: 0.974612
Step 1000: Generator Loss: 1.918907, Discriminator Loss: 0.964812
Step 1500: Generator Loss: 2.567637, Discriminator Loss: 0.717904
Step 2000: Generator Loss: 2.398796, Discriminator Loss: 0.512406
Step 2500: Generator Loss: 3.057401, Discriminator Loss: 1.235215
Step 3000: Generator Loss: 2.620444, Discriminator Loss: 0.539795
Step 3500: Generator Loss: 3.193395, Discriminator Loss: 0.265896
Step 4000: Generator Loss: 5.071162, Discriminator Loss: 0.409445
Step 4500: Generator Loss: 5.213869, Discriminator Loss: 0.203033
Step 5000: Generator Loss: 6.087250, Discriminator Loss: 0.350634
Step 5500: Generator Loss: 5.467363, Discriminator Loss: 0.424895
Step 6000: Generator Loss: 4.910432, Discriminator Loss: 0.196554
Step 6500: Generator Loss: 3.230242, Discriminator Loss: 0.268745
Step 7000: Generator Loss: 4.777361, Discriminator Loss: 0.676658
Step 7500: Generator Loss: 4.165446, Discriminator Loss: 0.150221
Step 8000: Generator Loss: 5.681596, Discriminator Loss: 0.108955
Step 8500: Generator Loss: 6.023059, Discriminator Loss: 0.114312
Step 9000: Generator Loss: 4.660669, Discriminator Loss: 0.182506
Step 9500: Generator Loss: 4.492438, Discriminator Loss: 0.411817
Step 10000: Generator Loss: 5.906080, Discriminator Loss: 0.088082
测试
代码语言:javascript
复制
# Testing
# Generate images from noise, using the generator network.
n = 6
canvas = np.empty((28 * n, 28 * n))
for i in range(n):
    # Noise input.
    z = np.random.uniform(-1., 1., size=[n, noise_dim])
    # Generate image from noise.
    g = sess.run(gen_sample, feed_dict={noise_input: z, is_training:False})
    # Rescale values to the original [0, 1] (from tanh -> [-1, 1])
    g = (g + 1.) / 2.
    # Reverse colours for better display
    g = -1 * (g - 1)
    for j in range(n):
        # Draw the generated digits
        canvas[i * 28:(i + 1) * 28, j * 28:(j + 1) * 28] = g[j].reshape([28, 28])

plt.figure(figsize=(n, n))
plt.imshow(canvas, origin="upper", cmap="gray")
plt.show()

参考

[1] [RELU 激活函数及其他相关的函数]https://blog.csdn.net/u013146742/article/details/51986575

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI异构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DCGAN简介
  • Tensorflow实现DCGAN
    • 导入数据集
      • 设置参数
        • 构建DCGAN网络
          • 训练
            • 测试
            • 参考
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档