首页 > 数据库 > 数据库开发技术 > GAN对抗网络入门教程
A Beginner's Guide to Generative Adversarial Networks (GANs) https://skymind.ai/wiki/generative-adversarial-network-gan
生成对抗网络常用于生成以假乱真的图片。此外,该方法还被用于生成影片、三维物体模型等。
虽然生成对抗网络原先是为了无监督学习提出的,它也被证明对半监督学习、完全监督学习 、强化学习是有用的。
下面两句话将判别与生成区分开来:
判别模型学习了类之间的界限
生成模型模拟各个类的分布
G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片,记做G(z)。D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。这样,G和D构成了一个动态的“博弈过程”。
最后博弈的结果是什么?在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。
reference:https://zhuanlan.zhihu.com/p/24767059
以下是GAN大致步骤:
生成器接收随机数并返回图像。
将生成的图像与从真实数据集中获取的图像流一起馈送到判别器中。
判别器接收真实和假图像并返回概率,0到1之间的数字,1表示真实性的预测,0表示假。
下面对生成性对抗网络与其他神经网络(例如自动编码器和变分自动编码器)进行比较。
自动编码器将输入数据编码为矢量。它们创建原始数据的隐藏或压缩表示,在减少维数方面很有用; 也就是说,用作隐藏表示的向量将原始数据压缩为较少数量的突出维度。自动编码器可以与所谓的解码器配对,允许您根据其隐藏的表示重建输入数据,就像使用受限制的Boltzmann机器一样。



变分自动编码器是生成算法,其为编码输入数据添加额外约束,即隐藏表示被标准化。变分自动编码器能够像自动编码器一样压缩数据并像GAN一样合成数据。然而GAN可以更精细、细粒度的生成数据,VAE生成的图像往往更加模糊。Deeplearning4j的例子包括自动编码器和变分自动编码器。
https://github.com/eriklindernoren/Keras-GAN
from __future__ import print_function, division
from keras.datasets import mnist
from keras.layers import Input, Dense, Reshape, Flatten, Dropout
from keras.layers import BatchNormalization, Activation, ZeroPadding2D
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.convolutional import UpSampling2D, Conv2D
from keras.models import Sequential, Model
from keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import numpy as np
Using TensorFlow backend.
class GAN():
def __init__(self):
self.img_rows = 28
self.img_cols = 28
self.channels = 1
self.img_shape = (self.img_rows, self.img_cols, self.channels)
optimizer = Adam(0.0002, 0.5)
# Build and compile the discriminator
self.discriminator = self.build_discriminator()
self.discriminator.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
# Build and compile the generator
self.generator = self.build_generator()
self.generator.compile(loss='binary_crossentropy', optimizer=optimizer)
# The generator takes noise as input and generated imgs
z = Input(shape=(100,))
img = self.generator(z)
# For the combined model we will only train the generator
self.discriminator.trainable = False
# The valid takes generated images as input and determines validity
valid = self.discriminator(img)
# The combined model (stacked generator and discriminator) takes
# noise as input => generates images => determines validity
self.combined = Model(z, valid)
self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)
def build_generator(self):
noise_shape = (100,)
model = Sequential()
model.add(Dense(256, input_shape=noise_shape))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(1024))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(np.prod(self.img_shape), activation='tanh'))
model.add(Reshape(self.img_shape))
model.summary()
noise = Input(shape=noise_shape)
img = model(noise)
return Model(noise, img)
def build_discriminator(self):
img_shape = (self.img_rows, self.img_cols, self.channels)
model = Sequential()
model.add(Flatten(input_shape=img_shape))
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(256))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(1, activation='sigmoid'))
model.summary()
img = Input(shape=img_shape)
validity = model(img)
return Model(img, validity)
def train(self, epochs, batch_size=128, save_interval=50):
# Load the dataset
(X_train, _), (_, _) = mnist.load_data()
# Rescale -1 to 1
X_train = (X_train.astype(np.float32) - 127.5) / 127.5
X_train = np.expand_dims(X_train, axis=3)
half_batch = int(batch_size / 2)
for epoch in range(epochs):
# ---------------------
# Train Discriminator
# ---------------------
# Select a random half batch of images
idx = np.random.randint(0, X_train.shape[0], half_batch)
imgs = X_train[idx]
noise = np.random.normal(0, 1, (half_batch, 100))
# Generate a half batch of new images
gen_imgs = self.generator.predict(noise)
# Train the discriminator
d_loss_real = self.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))
d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))
d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)
# ---------------------
# Train Generator
# ---------------------
noise = np.random.normal(0, 1, (batch_size, 100))
# The generator wants the discriminator to label the generated samples
# as valid (ones)
valid_y = np.array([1] * batch_size)
# Train the generator
g_loss = self.combined.train_on_batch(noise, valid_y)
# Plot the progress
if epoch%1000==0:
print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))
# If at save interval => save generated image samples
if epoch % save_interval == 0:
self.save_imgs(epoch)
def save_imgs(self, epoch):
r, c = 5, 5
noise = np.random.normal(0, 1, (r * c, 100))
gen_imgs = self.generator.predict(noise)
# Rescale images 0 - 1
gen_imgs = 0.5 * gen_imgs + 0.5
fig, axs = plt.subplots(r, c)
cnt = 0
for i in range(r):
for j in range(c):
axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
axs[i,j].axis('off')
cnt += 1
fig.savefig("data/gan/images/mnist_%d.png" % epoch)
plt.close()
if __name__ == '__main__':
gan = GAN()
gan.train(epochs=30000, batch_size=32, save_interval=200)
输出:
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:66: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:541: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:4432: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten_1 (Flatten) (None, 784) 0
_________________________________________________________________
dense_1 (Dense) (None, 512) 401920
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU) (None, 512) 0
_________________________________________________________________
dense_2 (Dense) (None, 256) 131328
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU) (None, 256) 0
_________________________________________________________________
dense_3 (Dense) (None, 1) 257
=================================================================
Total params: 533,505
Trainable params: 533,505
Non-trainable params: 0
_________________________________________________________________
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\optimizers.py:793: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3657: The name tf.log is deprecated. Please use tf.math.log instead.
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\ops\nn_impl.py:180: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
WARNING:tensorflow:From D:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:148: The name tf.placeholder_with_default is deprecated. Please use tf.compat.v1.placeholder_with_default instead.
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_4 (Dense) (None, 256) 25856
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU) (None, 256) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 256) 1024
_________________________________________________________________
dense_5 (Dense) (None, 512) 131584
_________________________________________________________________
leaky_re_lu_4 (LeakyReLU) (None, 512) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 512) 2048
_________________________________________________________________
dense_6 (Dense) (None, 1024) 525312
_________________________________________________________________
leaky_re_lu_5 (LeakyReLU) (None, 1024) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 1024) 4096
_________________________________________________________________
dense_7 (Dense) (None, 784) 803600
_________________________________________________________________
reshape_1 (Reshape) (None, 28, 28, 1) 0
=================================================================
Total params: 1,493,520
Trainable params: 1,489,936
Non-trainable params: 3,584
_________________________________________________________________
D:\ProgramData\Anaconda3\lib\site-packages\keras\engine\training.py:493: UserWarning: Discrepancy between trainable weights and collected trainable weights, did you set `model.trainable` without calling `model.compile` after ?
'Discrepancy between trainable weights and collected trainable'
0 [D loss: 0.735185, acc.: 46.88%] [G loss: 0.829077]
D:\ProgramData\Anaconda3\lib\site-packages\keras\engine\training.py:493: UserWarning: Discrepancy between trainable weights and collected trainable weights, did you set `model.trainable` without calling `model.compile` after ?
'Discrepancy between trainable weights and collected trainable'
1000 [D loss: 0.590758, acc.: 71.88%] [G loss: 0.793450]
2000 [D loss: 0.587990, acc.: 62.50%] [G loss: 0.956186]
3000 [D loss: 0.644352, acc.: 59.38%] [G loss: 0.914777]
4000 [D loss: 0.673936, acc.: 62.50%] [G loss: 0.971460]
5000 [D loss: 0.759974, acc.: 53.12%] [G loss: 0.904706]
6000 [D loss: 0.555306, acc.: 81.25%] [G loss: 0.835633]
7000 [D loss: 0.674409, acc.: 62.50%] [G loss: 0.823623]
8000 [D loss: 0.672854, acc.: 53.12%] [G loss: 0.863680]
9000 [D loss: 0.743683, acc.: 46.88%] [G loss: 0.868321]
10000 [D loss: 0.635190, acc.: 59.38%] [G loss: 0.854181]
11000 [D loss: 0.700397, acc.: 56.25%] [G loss: 0.778778]
12000 [D loss: 0.741978, acc.: 46.88%] [G loss: 0.813542]
13000 [D loss: 0.760614, acc.: 46.88%] [G loss: 0.833507]
14000 [D loss: 0.671199, acc.: 68.75%] [G loss: 0.853395]
15000 [D loss: 0.676217, acc.: 62.50%] [G loss: 0.920993]
16000 [D loss: 0.593898, acc.: 68.75%] [G loss: 0.889001]
17000 [D loss: 0.724363, acc.: 50.00%] [G loss: 0.893431]
18000 [D loss: 0.779740, acc.: 43.75%] [G loss: 0.853765]
19000 [D loss: 0.642237, acc.: 59.38%] [G loss: 0.830348]
20000 [D loss: 0.587237, acc.: 62.50%] [G loss: 0.876839]
21000 [D loss: 0.645381, acc.: 62.50%] [G loss: 0.827465]
22000 [D loss: 0.723597, acc.: 46.88%] [G loss: 0.862281]
23000 [D loss: 0.671319, acc.: 65.62%] [G loss: 0.903444]
24000 [D loss: 0.684801, acc.: 62.50%] [G loss: 0.807403]
25000 [D loss: 0.737355, acc.: 43.75%] [G loss: 0.813877]
26000 [D loss: 0.606201, acc.: 68.75%] [G loss: 0.802509]
27000 [D loss: 0.711020, acc.: 56.25%] [G loss: 0.894887]
28000 [D loss: 0.641023, acc.: 56.25%] [G loss: 0.856079]
29000 [D loss: 0.696889, acc.: 46.88%] [G loss: 0.728626]
GAN学习指南:从原理入门到制作生成Demo https://zhuanlan.zhihu.com/p/24767059
A Beginner's Guide to Generative Adversarial Networks (GANs) https://skymind.ai/wiki/generative-adversarial-network-gan



学习交流群,可扫码:



原文作者:ChallengeHub;如有侵权,请联系管理员删除。