GAN with Tensorflow:生成对抗网络的基础知识

机器学习一般分为三类:监督学习,无监督学习和强化学习。

GAN with Tensorflow:生成对抗网络的基础知识

机器学习的类别

理解对象是监督/无监督学习的最终目标。我们可以使用训练过的基于数据的判别模型(Discriminative Model)对图像进行分类。我们还可以使用训练过的生成模型(Generative Model)创建样本图像。

Ian Goodfellow引入了GAN(生成对抗性网络)作为一种理解数据的新方法。

什么是GAN?

GAN由一个generator和一个discriminator组成,两者互为竞争对手,性能逐渐提高。

伊恩·古德费罗(Ian Goodfellow)将上述过程比作伪钞制造者generator)和警察(discriminator)。假钞制造者试图欺骗警察,另一方面,警察试图将这些假钞分为真钞和假钞。在这场比赛中,双方都培养了能力。最终,警察无法区分真钞和假钞。

GAN with Tensorflow:生成对抗网络的基础知识

GAN的概念

MNIST

GAN with Tensorflow:生成对抗网络的基础知识

样本mnist(数字1)矩阵

MNIST机器学习数据集由手写数字图像(矩阵)组成。在本教程中,我们将生成手写数字的示例图像。如前所述,我们需要知道组成数字图像的像素值的分布,以便生成数字图像。

GAN with Tensorflow:生成对抗网络的基础知识

G的分布(绿色)和 D的决定边界(蓝色)的演变

上图显示了G如何知道真实的分布(黑点)。当重复学习时,G的分布与真实的分布相吻合。最终完全匹配时,D不能区分两个数字图像(P = 0.5)。

对于学习,它需要训练网络(generators和discriminators)和DB。

Generators

GAN with Tensorflow:生成对抗网络的基础知识

2层神经网络

我们的generators很简单。它由两个全连接层组成。输入层节点个数与“n_noise”相同。输出层节点个数与mnist图像的分辨率“n_input”相同。2个全连接层网络有4个可训练变量:两个权值变量G_W1,G_W2和两个偏差变量G_b1, G_b2。隐藏层使用“relu”函数作为激活函数。mnist图像的像素范围为[0,1]。因此我们使用sigmoid激活函数作为输出层,将结果归一化为[0,1]。实现的Python代码如下(generators.py):

import tensorflow as tf
class Generator:
 def __init__(self, n_input, n_noise):
 self.n_hidden = 256
 self.n_input = n_input
 self.n_noise = n_noise 
 def net(self, noise_z):
 with tf.variable_scope("generator"):
 G_W1 = tf.get_variable('G_W1', [self.n_noise, self.n_hidden], initializer = tf.random_normal_initializer(stddev=0.01))
 G_b1 = tf.get_variable('G_b1', [self.n_hidden], initializer = tf.constant_initializer(0))
 G_W2 = tf.get_variable('G_W2', [self.n_hidden, self.n_input], initializer = tf.random_normal_initializer(stddev=0.01))
 G_b2 = tf.get_variable('G_b2', [self.n_input], initializer = tf.constant_initializer(0)) 
 hidden = tf.nn.relu(
 tf.matmul(noise_z, G_W1) + G_b1)
 output = tf.nn.sigmoid(
 tf.matmul(hidden, G_W2) + G_b2)
 return output

GAN with Tensorflow:生成对抗网络的基础知识

Discriminator

我们的Discriminator也由两个全连接层组成。当然,输入节点的数量等于n_input。Discriminator输出为true/false。输入节点的个数是1。输出层使用sigmoid激活函数将结果归一化为[0,1]。如果确定输入为false,则输出接近于零,反之亦然。实现的Python代码如下(discriminators.py):

import tensorflow as tf
class Discriminator:
 def __init__(self, n_input, n_noise):
 self.n_hidden = 256
 self.n_input = n_input
 self.n_noise = n_noise
 def net(self, inputs, reuse = False):
 with tf.variable_scope("discriminator") as scope:
 if reuse:
 scope.reuse_variables()
 D_W1 = tf.get_variable('D_W1', [self.n_input, self.n_hidden], initializer = tf.random_normal_initializer(stddev=0.01))
 D_b1 = tf.get_variable('D_b1', [self.n_hidden], initializer = tf.constant_initializer(0))
 D_W2 = tf.get_variable('D_W2', [self.n_hidden, 1], initializer = tf.random_normal_initializer(stddev=0.01))
 D_b2 = tf.get_variable('D_b2', [1], initializer = tf.constant_initializer(0))
 
 hidden = tf.nn.relu(
 tf.matmul(inputs, D_W1) + D_b1)
 output = tf.nn.sigmoid(
 tf.matmul(hidden, D_W2) + D_b2)
 return output

GAN with Tensorflow:生成对抗网络的基础知识

训练模型

我们做了generator和discriminator。现在,我们需要训练DB(mnist数据集)。幸运的是,tensorflow提供了它。

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import os
from generators import Generator
from discriminators import Discriminator
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
total_epoch = 100
batch_size = 100
learning_rate = 0.0002
n_input = 28 * 28
n_noise = 128 
def get_noise(batch_size, n_noise):
 return np.random.normal(size=(batch_size, n_noise))

GAN with Tensorflow:生成对抗网络的基础知识

首先导入Python库:tensorflow,numpy,os,plt(用于保存结果图像)。并导入generator和discriminator类。

您只需通过代码行下载和存储mnist数据集即可。

mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)

定义一些参数:total_epoch,batch_size,learning_rate

n_input是28 * 28,等于mnist图像的大小。

n_noise是潜在向量的长度,它定义为128

我们还定义了“get_noise”函数,它生成一个随机向量数组。

X = tf.placeholder(tf.float32, [None, n_input])
Z = tf.placeholder(tf.float32, [None, n_noise])
G = Generator(n_input, n_noise)
G_out = G.net(Z)
D = Discriminator(n_input, n_noise)
D_gene = D.net(G_out, reuse = False)
D_real = D.net(X, reuse = True)

GAN with Tensorflow:生成对抗网络的基础知识

之后我们定义了一个generator和discriminator。G.net(Z)从随机向量Z返回生成的样本(假样本).D.net()测量样本的真实程度。 D_gene表示假样本的实际得分,D_real表示mnist数据集中实际样本的实际得分。

loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1 - D_gene))
loss_G = tf.reduce_mean(tf.log(D_gene))
D_var_list = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='discriminator')
G_var_list = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator')
train_D = tf.train.AdamOptimizer(learning_rate).minimize(-loss_D,
 var_list=D_var_list)
train_G = tf.train.AdamOptimizer(learning_rate).minimize(-loss_G,
 var_list=G_var_list)

GAN with Tensorflow:生成对抗网络的基础知识

我们希望D在真实图像时返回高分,并在假图像时返回低分。另一方面,G应该创造一个虚假的形象,欺骗D获得高分。这两个网络发生冲突。Ian Goodfellow介绍下面的函数V(G,D)来表示D和G之间的博弈。

GAN with Tensorflow:生成对抗网络的基础知识

下面的Python代码代表了上面的等式:

loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1 — D_gene))

我们训练D使其最大化。我们使用AdamOptimizer最小化函数,我们训练D最大化“-loss_D”

在上面的等式中,我们应该训练G以最小化log(1-D(G(z))。在学习的早期,log的梯度(1-D(G(z))很小并且它被非常缓慢地优化。 ,我们训练G以最大化log D(G(z))。参见下图。

在上面的方程中,我们应该训练G减少log(1 − D(G(z))。在学习初期,梯度的log(1−D(G(z))很小,优化的非常缓慢。我们训练G使log D(G(z))最大化。参考下图

GAN with Tensorflow:生成对抗网络的基础知识

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
sess.run(tf.global_variables_initializer())
total_batch = int(mnist.train.num_examples/batch_size)
loss_val_D, loss_val_G = 0, 0
for epoch in range(total_epoch):
 for i in range(total_batch):
 batch_xs, batch_ys = mnist.train.next_batch(batch_size)
 noise = get_noise(batch_size, n_noise)
 _, loss_val_D = sess.run([train_D, loss_D],
 feed_dict={X: batch_xs, Z: noise})
 _, loss_val_G = sess.run([train_G, loss_G],
 feed_dict={Z: noise})
 print('Epoch:', '%04d' % epoch,
 'D loss: {:.4}'.format(loss_val_D),
 'G loss: {:.4}'.format(loss_val_G))
 if epoch == 0 or (epoch + 1) % 10 == 0:
 sample_size = 10
 noise = get_noise(sample_size, n_noise)
 samples = sess.run(G_out, feed_dict={Z: noise})
 fig, ax = plt.subplots(1, sample_size, figsize=(sample_size, 1))
 for i in range(sample_size):
 ax[i].set_axis_off()
 ax[i].imshow(np.reshape(samples[i], (28, 28)))
 plt.savefig('samples/{}.png'.format(str(epoch).zfill(3)), bbox_inches='tight')
 plt.close(fig)
print('Complite')

GAN with Tensorflow:生成对抗网络的基础知识

使用sess.run(tf.global_variables_initializer())初始化所有变量。

我们可以通过sess.run([train_D])优化D,以便为输入提供数据。 train_D需要loss_D,它也需要D_gene,D_real。 D_gene取G_out, G_out取Z。D_real也取X。所以我们输入X和Z来执行sess.run([train_D,loss_D])。 X是从mnist数据集接收的batch_xs中分配的。 Z由get_noise函数生成的噪声分配。

与D中一样,G在上述Python代码中也得到了优化:ses .run([train_G, loss_G], feed_dict={Z: noise})。

我们也打印每个epoch的损失值。

此外,我们每10个epochs保存生成的图像。

GAN with Tensorflow:生成对抗网络的基础知识

生成的图像

生成的图像(假样本)看起来像真正的手写数字。

GAN with Tensorflow:生成对抗网络的基础知识

关于收敛过程的动画

上图显示,随着学习的重复,generator逐渐收敛。我们可以使用GAN创建数字图像,但它仍然有一些问题:在某些图像中,7和9没有明确区分。

使用DCGAN,您可以获得更好的图像。

相关推荐