《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座,并分享给大家,希望您喜欢。由于作者的英文水平和学术能力不高,需要不断提升,所以还请大家批评指正,非常欢迎大家给我留言评论,学术路上期待与您前行,加油~
文章目录:
一.GAN简介
1.GAN背景知识
2.GAN原理解析
3.GAN经典案例
二.GAN预备知识
1.什么是神经网络
2.全连接层
3.激活函数
4.反向传播
5.优化器选择
6.卷积层
7.池化层
8.图像问题基本思路
三.GAN网络实战分析
1.GAN模型解析
2.生成手写数字demo分析
3.其他常见GAN网络
CGAN DCGAN ACGAN infoGAN LAPGAN EBGAN
4.GAN改进策略
四.总结
前文推荐:
GAN原文:https://arxiv.org/abs/1406.2661
https://arxiv.org/pdf/1701.00160.pdf
https://github.com/hindupuravinash/
the-gan-zoo
Generative:生成式模型
Adversarial:采取对抗的策略
Networks:网络(不一定是深度学习)
bicubic:第二张图是bicubic方法恢复的图像。经过压缩再拉伸还原图像,通过插值运算实现,但其图像会变得模糊。
SRResNet:第三张图像是通过SRResNet实现的恢复,比如先压缩图像再用MSE和神经网络学习和真实值的差别,再进行恢复。(SRResNet is a neural network trained with mean squared error)
SRGAN:第四张图是通过SRGAN实现的,其恢复效果更优。SRGAN是在GAN基础上的改进,它能够理解有多个正确的答案,而不是在许多答案中给出一个最佳输出。
https://link.springer.com/chapter/
10.1007/978-3-319-10593-2_13
http://cn.arxiv.org/pdf/1711.09020.pdf
神经网络常见层
全连接层、激活层、BN层、Dropout层、卷积层、池化层、循环层、Embedding层、Merege层等
网络配置
损失函数、优化器、激活函数、性能评估、初始化方法、正则项等
网络训练流程
预训练模型、训练流程、数据预处理(归一化、Embedding)、数据增强(图片翻转旋转曝光生成海量样本)等
对于隐藏层,我们可以使用relu、tanh、softplus等非线性关系;
对于分类问题,我们可以使用sigmoid(值越小越接近于0,值越大越接近于1)、softmax函数,对每个类求概率,最后以最大的概率作为结果;
对于回归问题,可以使用线性函数(linear function)来实验。
一种优化器是跟着梯度走,每次只观察自己的梯度,它不带重量
一种优化器是带重量的
class tf.train.GradientDescentOptimizer
class tf.train.AdagradOptimizer
class tf.train.AdadeltaOptimizer
class tf.train.MomentumOptimizer
class tf.train.AdamOptimizer
class tf.train.FtrlOptimizer
class tf.train.RMSPropOptimizer
图片参数太多,比如1000*1000的图片,加一个隐藏层,隐藏层节点同输入维数,全连接的参数是10^12,根本训练不过来这么多参数。
卷积核数目
卷积核大小:如上面3x3卷积核
卷积核数目
卷积核步长:上面的步长是1,同样可以调格
激活函数
Padding:比如上图需要输出5x5的结果图,我们需要对其外圆补零
是否使用偏置
学习率
初始化
使特征图变小,简化网络;特征压缩,提取主要特征
最大池化:比如从左上角红色区域中选择最大的6,接着是8、3、4
平均池化:选择平均值
输入层
如NLP句子、句对,图像的像素矩阵,语音的音频信息
表示成
DNN:全连接+非线性(特征非线性融合)
CNN:Conv1d、Conv2d、Pooling
RNN:LSTM、GRU(选择记忆性)
应用层
分类、回归、序列预测、匹配
Generative:生成式模型
Adversarial:采取对抗的策略
Networks:网络
最开始在图(a)中我们生成绿线,即生成样本的概率分布,黑色的散点是真实样本的概率分布,这条蓝线是一个判决器,判断什么时候应该是真的或假的。
我们第一件要做的事是把判决器判断准,如图(b)中蓝线,假设在0.5的位置下降,之前的认为是真实样本,之后的认为是假的样本。
当它固定完成后,在图(c)中,生成器想办法去和真实数据作拟合,想办法去误导判决器。
最终输出图(d),如果你真实的样本和生成的样本完全一致,分布完全一致,判决器就傻了,无法继续判断。
生成器:学习真实样本以假乱真
判别器:小孩通过学习成验钞机的水平
目标函数如何设定?
如何生成图片?
G生成器和D判决器应该如何设置?
如何进行训练?
max()式子是第一步,表示把生成器G固定,让判别器尽量区分真实样本和假样本,即希望生成器不动的情况下,判别器能将真实的样本和生成的样本区分开。
min()式子是第二步,即整个式子。判别器D固定,通过调整生成器,希望判别器出现失误,尽可能不要让它区分开。
式子由两项构成,x表示真实图片,z表示输入G网络的噪声,而G(z)表示G网络生成的图片。
D(x)表示D网络判断真实图片是否真实的概率(因为x就是真实的,所以对于D来说,这个值越接近1越好)。
D(G(z))是D网络判断G生成的图片是否真实的概率。
G的目的:G应该希望自己生成的的图片越接近真实越好。
D的目的:D的能力越强,D(x)应该越大,D(G(x))应该越小,这时V(D,G)会变大,因此式子对于D来说是求最大(max_D)。
trick:为了前期加快训练,生成器的训练可以把log(1-D(G(z)))换成-log(D(G(z)))损失函数。
最外层是一个for循环,接着是k次for循环,中间迭代的是判决器。
k次for循环结束之后,再迭代生成器。
最后结束循环。
步骤1是在生成器固定的时候,我让它产生一批样本,然后让判决器正确区分真实样本和生成样本。(生成器标签0、真实样本标签1)
步骤2是固定判决器,通过调整生成器去尽可能的瞒混判决器,所以实际上此时训练的是生成器。(生成器的标签需要让判决器识别为1,即真实样本)
for 迭代 in range(迭代总数):
for batch in range(batch_size):
新batch = input1的batch + input2的batch (batch加倍)
for 轮数 in range(判别器中轮数):
步骤一 训练D
步骤二 训练G
https://github.com/jacobgil/
keras-dcgan/blob/master/dcgan.py
全连接层:输入100维,输出1024维
全连接层:128x7x7表示图片128通道,大小7x7
BatchNormalization:如果不加它DCGAN程序会奔溃
UpSampling2D:对卷积结果进行上采样从而将特征图放大 14x14
Conv2D:卷积操作像素尺度不变(same)
UpSampling2D:生成28x28
Conv2D:卷积操作
Activation:激活函数tanh
Conv2D:卷积层
MaxPooling2D:池化层
Conv2D:卷积层
MaxPooling2D:池化层
Flatten:拉直一维
Dense:全连接层
Activation:sigmoid二分类
model.add(g):加载生成器G
d.trainable=False:判决器D固定
load_data:载入图片
d = discriminator_model:定义判别器D
g = generator_model:定义生成器G
generator_containing_discriminator:固定D调整G
SGD、compile:定义参数、学习率
for epoch in range、for index in rangeBATCH
X = np.concatenate:图像数据和生成数据混合
y = [1] x BATCH_SIZE + [0] x BTCH_SIZE:输出label
d_loss = d.train_on_batch(X,y):训练D判别器(步骤一)
d.trainable = False:固定D
g_loss = d_on_g.train_on_batch(noise, [1]xBATCH_SIZE):训练G生成器(步骤二),混淆
d.trainable = True:打开D重复操作
保存参数和模型
g = generator_model:定义生成器模型
g.load_weights:载入训练好的生成器(generator)
noise:随机产生噪声
然后用G生成一幅图像,该图像就能欺骗判别器D
# -*- coding: utf-8 -*-
"""
Created on 2021-03-19
@author: xiuzhang Eastmount CSDN
参考:https://github.com/jacobgil/keras-dcgan
"""
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Reshape
from keras.layers.core import Activation
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import UpSampling2D
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers.core import Flatten
from keras.optimizers import SGD
from keras.datasets import mnist
import tensorflow as tf
import numpy as np
from PIL import Image
import argparse
import math
import os
## GPU处理 读者如果是CPU注释该部分代码即可
## 指定每个GPU进程中使用显存的上限 0.9表示可以使用GPU 90%的资源进行训练
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
#----------------------------------------------------------------
#生成器
def generator_model():
model = Sequential()
model.add(Dense(input_dim=100, output_dim=1024))
model.add(Activation('tanh'))
model.add(Dense(128*7*7)) #7x7 128通道
model.add(BatchNormalization())
model.add(Activation('tanh'))
model.add(Reshape((7, 7, 128), input_shape=(128*7*7,)))
model.add(UpSampling2D(size=(2, 2)))
model.add(Conv2D(64, (5, 5), padding='same'))
model.add(Activation('tanh'))
model.add(UpSampling2D(size=(2, 2)))
model.add(Conv2D(1, (5, 5), padding='same'))
model.add(Activation('tanh'))
return model
#----------------------------------------------------------------
#判别器
def discriminator_model():
model = Sequential()
model.add(
Conv2D(64, (5, 5),
padding='same',
input_shape=(28, 28, 1))
)
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (5, 5)))
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('tanh'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
return model
#----------------------------------------------------------------
#辅助函数 固定D调整G
def generator_containing_discriminator(g, d):
model = Sequential()
model.add(g)
d.trainable = False
model.add(d)
return model
#辅助函数 合并图像
def combine_images(generated_images):
num = generated_images.shape[0]
width = int(math.sqrt(num))
height = int(math.ceil(float(num)/width))
shape = generated_images.shape[1:3]
image = np.zeros((height*shape[0], width*shape[1]),
dtype=generated_images.dtype)
for index, img in enumerate(generated_images):
i = int(index/width)
j = index % width
image[i*shape[0]:(i+1)*shape[0], j*shape[1]:(j+1)*shape[1]] = \
img[:, :, 0]
return image
#----------------------------------------------------------------
#训练
def train(BATCH_SIZE):
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = (X_train.astype(np.float32) - 127.5)/127.5
X_train = X_train[:, :, :, None]
X_test = X_test[:, :, :, None]
#X_train = X_train.reshape((X_train.shape, 1) + X_train.shape[1:])
d = discriminator_model()
g = generator_model()
d_on_g = generator_containing_discriminator(g, d)
d_optim = SGD(lr=0.0005, momentum=0.9, nesterov=True)
g_optim = SGD(lr=0.0005, momentum=0.9, nesterov=True)
g.compile(loss='binary_crossentropy', optimizer="SGD")
d_on_g.compile(loss='binary_crossentropy', optimizer=g_optim)
d.trainable = True
d.compile(loss='binary_crossentropy', optimizer=d_optim)
for epoch in range(100):
print("Epoch is", epoch)
print("Number of batches", int(X_train.shape[0]/BATCH_SIZE))
for index in range(int(X_train.shape[0]/BATCH_SIZE)):
noise = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]
generated_images = g.predict(noise, verbose=0)
if index % 20 == 0:
image = combine_images(generated_images)
image = image*127.5+127.5
Image.fromarray(image.astype(np.uint8)).save(
str(epoch)+"_"+str(index)+".png")
X = np.concatenate((image_batch, generated_images))
y = [1] * BATCH_SIZE + [0] * BATCH_SIZE
d_loss = d.train_on_batch(X, y)
print("batch %d d_loss : %f" % (index, d_loss))
noise = np.random.uniform(-1, 1, (BATCH_SIZE, 100))
d.trainable = False
g_loss = d_on_g.train_on_batch(noise, [1] * BATCH_SIZE)
d.trainable = True
print("batch %d g_loss : %f" % (index, g_loss))
if index % 10 == 9:
g.save_weights('generator', True)
d.save_weights('discriminator', True)
#----------------------------------------------------------------
#GAN图片生成
def generate(BATCH_SIZE, nice=False):
g = generator_model()
g.compile(loss='binary_crossentropy', optimizer="SGD")
g.load_weights('generator')
if nice:
d = discriminator_model()
d.compile(loss='binary_crossentropy', optimizer="SGD")
d.load_weights('discriminator')
noise = np.random.uniform(-1, 1, (BATCH_SIZE*20, 100))
generated_images = g.predict(noise, verbose=1)
d_pret = d.predict(generated_images, verbose=1)
index = np.arange(0, BATCH_SIZE*20)
index.resize((BATCH_SIZE*20, 1))
pre_with_index = list(np.append(d_pret, index, axis=1))
pre_with_index.sort(key=lambda x: x[0], reverse=True)
nice_images = np.zeros((BATCH_SIZE,) + generated_images.shape[1:3], dtype=np.float32)
nice_images = nice_images[:, :, :, None]
for i in range(BATCH_SIZE):
idx = int(pre_with_index[i][1])
nice_images[i, :, :, 0] = generated_images[idx, :, :, 0]
image = combine_images(nice_images)
else:
noise = np.random.uniform(-1, 1, (BATCH_SIZE, 100))
generated_images = g.predict(noise, verbose=1)
image = combine_images(generated_images)
image = image*127.5+127.5
Image.fromarray(image.astype(np.uint8)).save(
"generated_image.png")
#参数设置
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--mode", type=str)
parser.add_argument("--batch_size", type=int, default=128)
parser.add_argument("--nice", dest="nice", action="store_true")
parser.set_defaults(nice=False)
args = parser.parse_args()
return args
if __name__ == "__main__":
"""
args = get_args()
if args.mode == "train":
train(BATCH_SIZE=args.batch_size)
elif args.mode == "generate":
generate(BATCH_SIZE=args.batch_size, nice=args.nice)
"""
mode = "train"
if mode == "train":
train(BATCH_SIZE=128)
elif mode == "generate":
generate(BATCH_SIZE=128)
Training:
python dcgan.py --mode train --batch_size <batch_size>
python dcgan.py --mode train --path ~/images --batch_size 128
Image generation:
python dcgan.py --mode generate --batch_size <batch_size>
python dcgan.py --mode generate --batch_size <batch_size> --nice : top 5%
python dcgan.py --mode generate --batch_size 128
Epoch is 0
Number of batches 468
batch 0 d_loss : 0.648902
batch 0 g_loss : 0.672132
batch 1 d_loss : 0.649307
....
batch 466 g_loss : 1.305099
batch 467 d_loss : 0.375284
batch 467 g_loss : 1.298173
Epoch is 1
Number of batches 468
batch 0 d_loss : 0.461435
batch 0 g_loss : 1.231795
batch 1 d_loss : 0.412679
....
https://arxiv.org/pdf/1511.06434.pdf
所有pooling都用strided convolutions代替,pooling的下采样是损失信息的,strided convolutions可以让模型自己学习损失的信息
生成器G和判别器D都要用BN层(解决过拟合)
把全连接层去掉,用全卷积层代替
生成器除了输出层,激活函数统一使用ReLU,输出层用Tanh
判别器所有层的激活函数统一都是LeakyReLU
https://arxiv.org/pdf/1610.09585.pdf
D网络的输入只有x,不加c
Q网络和D网络共享同一个网络,只是到最后一层独立输出
G(z)的输出和条件c区别大
首先用噪声去生成一个小的图片,分辨率极低,我们对其拉伸。
拉伸之后,想办法通过之前训练好的GAN网络生成一个它的残差。
残差和拉伸图相加就生成一张更大的图片,以此类推,拉普拉斯生成一张大图。
《Energy-based Generative Adversarial Network》Junbo Zhao, arXiv:1609.03126v2
G、D迭代的方式能达到全局最优解吗?大部分情况是局部最优解。
不一定收敛,学习率不能高,G、D要共同成长,不能其中一个成长的过快。
– 判别器训练得太好,生成器梯度消失,生成器loss降不下去
– 判别器训练得不好,生成器梯度不准,四处乱跑
奔溃的问题,通俗说G找到D的漏洞,每次都生成一样的骗D
无需预先建模,模型过于自由,不可控
“生成器没能生成真实的样本” 惩罚小
“生成器生成不真实的样本” 惩罚大
判别器最后一层去掉sigmoid
生成器和判别器的loss不取log
每次更新判别器的参数之后把它们的绝对值截断到不超过一个固定的常数c
不要用基于动量的优化算法(包括Momentum和Adam),推荐使用RMSProp、SGD
用Wasserstein距离代替KL散度,训练网络稳定性大大增强,不用拘泥DCGAN的那些策略(tricks)
https://arxiv.org/pdf/1705.07215.pdf
https://arxiv.org/pdf/1711.10337.pdf
https://arxiv.org/pdf/1706.08500.pdf
一.GAN简介
1.GAN背景知识
2.GAN原理解析
3.GAN经典案例
二.GAN预备知识
1.什么是神经网络
2.全连接层
3.激活函数
4.反向传播
5.优化器选择
6.卷积层
7.池化层
8.图像问题基本思路
三.GAN网络实战分析
1.GAN模型解析
2.生成手写数字demo分析
3.CGAN、DCGAN、ACGAN、infoGAN、LAPGAN、EBGAN
4.GAN改进策略
“娜璋AI安全之家”主要围绕Python大数据分析、网络空间安全、人工智能、Web渗透及攻防技术进行讲解,同时分享CCF、SCI、南核北核论文的算法实现。娜璋之家会更加系统,并重构作者的所有文章,从零讲解Python和安全,写了近十年文章,真心想把自己所学所感所做分享出来,还请各位多多指教,真诚邀请您的关注!谢谢。
https://www.bilibili.com/video/BV1ht411c79k
https://arxiv.org/abs/1406.2661
https://www.cntofu.com/book/85/dl/gan/gan.md
https://github.com/hindupuravinash/the-gan-zoo
https://arxiv.org/pdf/1701.00160.pdf
https://link.springer.com/chapter/10.1007/978-3-319-10593-2_13
https://zhuanlan.zhihu.com/p/76520991
http://cn.arxiv.org/pdf/1711.09020.pdf
https://www.sohu.com/a/121189842_465975
https://www.jianshu.com/p/88bb976ccbd9
https://zhuanlan.zhihu.com/p/23270674
ttps://blog.csdn.net/weixin_40170902/article/details/80092628
https://www.jiqizhixin.com/articles/2016-11-21-4
https://github.com/jacobgil/keras-dcgan/blob/master/dcgan.py
https://arxiv.org/abs/1511.06434
https://arxiv.org/pdf/1511.06434.pdf
https://blog.csdn.net/weixin_41697507/article/details/87900133
https://zhuanlan.zhihu.com/p/91592775
https://liuxiaofei.com.cn/blog/acgan与cgan的区别/
https://arxiv.org/abs/1606.03657
https://blog.csdn.net/sdnuwjw/article/details/83614977
《Energy-based Generative Adversarial Network》Junbo Zhao, arXiv:1609.03126v2
https://www.jiqizhixin.com/articles/2017-03-27-4
https://zhuanlan.zhihu.com/p/25071913
https://arxiv.org/pdf/1705.07215.pdf
https://arxiv.org/pdf/1706.08500.pdf
https://arxiv.org/pdf/1711.10337.pdf
https://www.zhihu.com/question/263383926