GAN思想是一种二人的零和博弈思想,GAN中有两个博弈者,一个生成器(G),一个判别器(D),这两个模型都有各自的输入和输出。具体功能如下:
生成器(G):输入一个随机噪声样本,通过生成器生成一个与真实样本无差的样本。
判别器(D):对输出模型进行打分,类似一个分类器,打分的对照样本是真实样本。




生成器的目标就是让判别器无法判断是生成图片还是真实图片,换种说法就是,生成器的目标都是生成真实图片,至少让判别器认为是真实的,生成器一开始生成图片过于模糊抽象,判别器可以轻易的将其识别,生成器为了提高自己生成图片的能力,就要不断的学习,具体而言,就是找到自己生成图片与真实图片的差距。然后弥补这个差距。这就是所谓的差距,其实就是损失,也就是在高维空间中生成图片的概率分布与真实图片的概率分布的不同之处,具体而言,就是两个概率图片的
J
S
散
度
JS散度
JS散度就是最小化生成图片的概率分布与真实图片的概率分布的
J
S
JS
JS散度。
import tensorflow as tf
from tensorflow import keras
from matplotlib import pyplot as plt
from tensorflow.keras import layers
# mnist = tf.keras.datasets.mnist
# (x_train, y_train), (x_test, y_test) = mnist.load_data()
# # 可视化训练集输入特征的第一个元素
# plt.imshow(x_train[0], cmap='gray') # 绘制灰度图
# plt.show()
(train_images, train_labels), (_, _) = keras.datasets.mnist.load_data()
'''mnist中的reshape
x_image = tf.reshape(x, [-1, 28, 28, 1])
这里是将一组图像矩阵x重建为新的矩阵,该新矩阵的维数为(a,28,28,1),其中-1表示a由实际情况来定'''
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images-127.5)/127.5 # -1~1
BATCH_SIZE = 256
BUFFER_SIZE = 60000
datasets = tf.data.Dataset.from_tensor_slices(train_images)
datasets = datasets.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
# 生成器
def generator_model(): # 用100个随机数(噪音)生成手写数据集
model = keras.Sequential()
model.add(layers.Dense(256, input_shape=(100,), use_bias=False))
model.add(layers.BatchNormalization()) # 规范化
model.add(layers.LeakyReLU())
model.add(layers.Dense(512, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(28 * 28 * 1, use_bias=False, activation='tanh'))
model.add(layers.BatchNormalization())
model.add(layers.Reshape((28, 28, 1)))
return model
# 判别器
def discriminator_model(): # 识别输入的图片
model = keras.Sequential()
model.add(layers.Flatten())
model.add(layers.Dense(512, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(256, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(1))
return model
cross_entropy = keras.losses.BinaryCrossentropy(from_logits=True)
# 判别器损失
def discriminator_loss(real_out, fake_out):
real_loss = cross_entropy(tf.ones_like(real_out), real_out)
fake_loss = cross_entropy(tf.zeros_like(fake_out), fake_out)
return real_loss + fake_loss
# 生成器损失
def generator_loss(fake_out):
return cross_entropy(tf.ones_like(fake_out), fake_out)
generator_opt = keras.optimizers.Adam(1e-4)
discriminator_opt = keras.optimizers.Adam(1e-4)
generator = generator_model()
discriminator = discriminator_model()
noise_dim = 100 # 即用100个随机数生成图片
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
real_out = discriminator(images, training=True)
gen_image = generator(noise, training=True)
fake_out = discriminator(gen_image, training=True)
gen_loss = generator_loss(fake_out)
disc_loss = discriminator_loss(real_out, fake_out)
gradient_gen = gen_tape.gradient(gen_loss, generator.trainable_variables)
gradient_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
generator_opt.apply_gradients(zip(gradient_gen, generator.trainable_variables))
discriminator_opt.apply_gradients(zip(gradient_disc, discriminator.trainable_variables))
def generate_plot_image(gen_model, test_noise):
pre_images = gen_model(test_noise, training=False)
plt.figure(figsize=(4, 4))
for i in range(pre_images.shape[0]):
plt.subplot(4, 4, i+1)
plt.imshow((pre_images[i, :, :, 0] + 1)/2, cmap='gray')
plt.axis('off')
plt.show()
EPOCHS = 100 # 训练100次
num_exp_to_generate = 16 # 生成16张图片
seed = tf.random.normal([num_exp_to_generate, noise_dim]) # 16组随机数组,每组含100个随机数,用来生成16张图片。
def train(dataset, epochs):
for epoch in range(epochs):
for image_batch in dataset:
train_step(image_batch)
print('.', end='')
if epoch % 10 == 0:
print('epoch: ', epoch)
generate_plot_image(generator, seed)
train(datasets, EPOCHS)