【GANs】Generative Adversarial Nets
1 GAN
1.1 GANs的简介
Generative Adversarial Nets原文链接
-
判别器模型(网络):一般熟知的带标签的分类、回归等监督学习都属于判别器模型。学习的是某种分布下的条件概率分布 p ( y ∣ x ) p(y|x) p(y∣x)。
-
生成器模型(网络):聚类、自动编码器等无监督学习模型。学习的是联合分布概率 p ( x , y ) p(x,y) p(x,y)。通过模型学习到最优的 p ( x ∣ y ) p(x|y) p(x∣y)
在现实中,判别模型在分类工作中的表现通常优于生成模型,但在一些创造性的工作中显然生成模型更有意义。
1.2 思想与目标函数
生成器和判别器不断对抗博弈,直到两个网络到达最终的动态均衡状态,即判别器无法识别生成器的图像真假。
我们想学习到的是像训练集那样的数据分布: p g ( z ) p_g(z) pg(z)➡真实数据分布, z z z是噪声。
但是 我们可知道的是,极大似然函数去找概率分布会有很复杂的计算问题,因此我们才看作者采用的方式,绕过极大似然函数来逼近真实数据分布。
逼近过程:
x ∼ P d a t a x \sim P_{data} x∼Pdata
z ∼ P z z \sim P_z z∼Pz
- 我们看训练 D D D(想让 D D D性能高):
if x is from Pdata : D(x) ↑ --→ log(D(x)) ↑
if z is from Pz : D(G(z)) ↓ --→ 1 - D(G(z)) ↑ <=> log(1 - D(G(z))) ↑
得到关于 D D D的目标函数
D m a x E x ∼ P d a t a [ l o g D ( x ) ] + E z ∼ P z ( 1 − D ( G ( z ) ) ) ^{max}_{\space\space\space D} E_{x \sim P_{data}}[logD(x)] + E_{z \sim P_z}(1-D(G(z))) DmaxEx∼Pdata[logD(x)]+Ez∼Pz(1−D(G(z)))
- 在来看训练 G G G(想让 G G G性能高):
z is from Pz : D(z) ↑ --→ 1-D(G(z)) ↓ <=> log(1-D(G(z))) ↓
得到关于 G G G的目标函数:
G m i n E z ∼ P z ( 1 − D ( G ( z ) ) ) ^{min}_{\space\space\space G} E_{z \sim P_z}(1-D(G(z))) GminEz∼Pz(1−D(G(z)))
由 G G G和 D D D的两个目标,得到总的目标函数:(GAN原始论文中的目标函数)
G m i n D m a x E x ∼ P d a t a [ l o g D ( x ) ] + E z ∼ P z ( 1 − D ( G ( z ) ) ) {^{min}_{\space\space\space G}} {^{max}_{\space\space\space D}} E_{x \sim P_{data}}[logD(x)] + E_{z \sim P_z}(1-D(G(z))) Gmin DmaxEx∼Pdata[logD(x)]+Ez∼Pz(1−D(G(z)))
以这个目标函数训练下去, G G G和 D D D将在博弈中达到最优。
全局最优存在且函数收敛,在介绍完代码后证明。
1.3 GAN代码
# GAN_2014.py
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras import Sequential,Model
from tensorflow.keras.layers import Dense,Reshape,Input,Flatten
from tensorflow.keras.layers import LeakyReLU,BatchNormalization
from tensorflow.keras.datasets import mnist
from tensorflow.keras.optimizers import Adam
class GAN():
def __init__(self):
self.latent_dim = 100
self.img_rows = 28
self.img_cols = 28
self.channel = 1
self.img_shape = (self.img_rows,self.img_cols,self.channel)
self.discrinator = self.build_discrinator() # 构建
optimizer = Adam(0.0002,0.5)
self.discrinator.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
self.generator = self.build_generator() # generator就可以完成从noise到img的生成
self.discrinator.trainable = False
z = Input(shape=(self.latent_dim,))
img = self.generator(z)
validity = self.discrinator(img)
self.combined = Model(z,validity)
self.combined .compile(loss='binary_crossentropy',optimizer=optimizer) # 完成了叠加模型的构建
# 构建生成器模型
def build_generator(self):
model = Sequential()
# 添加一层全连接层
model.add(Dense(256, input_dim=self.latent_dim )) # 输入噪声是一维含有100个元素的向量
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8)) # BN层
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8)) # BN层
model.add(Dense(1024))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8)) # BN层
model.add(Dense(np.prod(self.img_shape),activation='tanh')) # 神经元个数(输出)等于图像尺寸乘积
model.add(Reshape(self.img_shape)) # reshape成图像形状 28*28*1
model.summary() # 记录各层参数情况
noise = Input(shape=(self.latent_dim,))
img = model(noise)
return Model(noise,img) # 返回输入为噪声,输出为预测图的Model
# 构建判别器模型