生成对抗网络中的一部分,用于从随机数据或其他分布的数据中生成一个与训练集类似的数据.。
也是生成对抗网络中的一部分,用于识别出哪些是有生成网络生成的“假”数据,哪些是真正的训练集数据。
生成对抗网络的目的就是生成不存在的数据,类似于让人工智能拥有想象力。
在一个图像生成对抗网络中,生成器负责生成假图像,这里认为训练集是真图像,而判别器负责判别图像真假。“对抗”的含义就是生成器通过不断的训练尽可能的生成以假乱真的图像,判别器通过不断的识别尽可能的区分图像的真假。
生成器的训练过程,简单来说就是,给定网络,给定标签,然后更新输入(这里是随机数据,可以符合一定的分布),使输出图像对应的标签逐渐靠近给定的标签;判别器的训练过程和一般神经网络的训练类似。
总结一下,模型通过 “ Generator生成器” 生成图像,并与真实图像一起输入 “Discriminator判别器” 进行判别。“Discriminator判别器” 通过 loss 以“真实图像为真,生成图像为假” 进行参数更新,而 “ Generator生成器” 通过 loss 以 “生成图像为真” 进行参数更新。
import tensorflow as tf
import matplotlib.pyplot as plt
(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape((-1, 28, 28, 1)).astype("float32")
# 由于tanh函数的值域为(-1, 1),故这里应该将像素值统一到(-1, 1)
train_images = (train_images - 127.5) / 127.5
# 将图像数组转换成张量
datasets = tf.data.Dataset.from_tensor_slices(train_images)
# 将这60000个张量打乱,每一批有256个张量
datasets = datasets.shuffle(60000).batch(256)
# 参数
n_dim = 100
batch_size = 256
epochs = 10
# 生成器
# 输入格式(batch_size, 100) => 输出格式(batch_size, 28, 28, 1)
generator = tf.keras.Sequential([
tf.keras.layers.Dense(3 * 3 * 512),
tf.keras.layers.Reshape([3, 3, 512]),
tf.keras.layers.Conv2DTranspose(256, 3, 2, activation="relu"),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2DTranspose(128, 2, 2, activation="relu"),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2DTranspose(64, 2, 2, activation="tanh"),
tf.keras.layers.Dense(1),
tf.keras.layers.Reshape([28, 28, 1])
])
# 辨别器
# 输入格式(batch_size, 28, 28, 1) => 输出格式(batch_size, 1)
discriminator = tf.keras.Sequential([
tf.keras.layers.Reshape([28, 28, 1]),
tf.keras.layers.Conv2D(64, 4, 2, activation="relu"),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(128, 4, 3, activation="relu"),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(256, 4, 3, activation="relu"),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1),
])
# 优化器
g_optimizer = tf.optimizers.Adam(learning_rate=1e-4)
d_optimizer = tf.optimizers.Adam(learning_rate=1e-4)
# 损失函数
# 判别器的输出用的是二分类的one-hot编码
loss = tf.losses.BinaryCrossentropy(from_logits=True)
# 训练模型
for i in range(epochs):
for real_images in datasets:
noise = tf.random.normal([batch_size, n_dim])
with tf.GradientTape() as g_tape, tf.GradientTape() as d_tape:
fake_images = generator(noise, training=True)
fake_out = discriminator(fake_images, training=True)
real_out = discriminator(real_images, training=True)
g_loss = loss(tf.ones_like(fake_out), fake_out)
d_loss = loss(tf.zeros_like(fake_out), fake_out) + loss(tf.ones_like(real_out), real_out)
g_gradient = g_tape.gradient(g_loss, generator.trainable_variables)
d_gradient = d_tape.gradient(d_loss, discriminator.trainable_variables)
g_optimizer.apply_gradients(zip(g_gradient, generator.trainable_variables))
d_optimizer.apply_gradients(zip(d_gradient, discriminator.trainable_variables))
# 预测结果
test_noise = tf.random.normal([16, n_dim])
pre_images = generator(test_noise, training=False)
fig = plt.figure(1)
for i in range(16):
plt.subplot(4, 4, i+1)
plt.imshow((pre_images[i, :, :, 0] + 1)/2)
plt.axis('off')
plt.show()
第一张图是训练集选取的部分图片,第二张图片是由生成器产生的图片,可以看出,通过多次训练,生成可以生成比较接近训练集图片的图片。这里只训练了10轮,通过增加训练轮数,生成器产生的图像会更加接近训练集的图像。