李宏毅老师讲解的Generative Adversarial Network
Review: Auto-encoder -> VAE ->GAN
auto-encoder的学习结果中的decoder可以拿出来,喂一个code可以生成一个image
VAE更进一步引入了噪声,学习目标仍然是希望input 和output尽可能的接近,但不能单纯最小化两者之间的差异,因为这样学出来的结果肯定是噪声的权重为0,因此对优化目标reconstruction error做了一些改进
VAE存在的问题是:VAE并不是真的尝试去生成real图像;如左下和右下的图像和input图像其实都只差了一个像素点,但从人的角度看显然左下是realistic的图像而右下则是fake的图像,但在VAE的视角中两者与input图像间的差距是一样的
GAN概述
GAN中Generator与VAE中decoder的架构和做的事情是一样的,只是训练时的训练方法不一样
训练过程:
- How to learn Discriminator: 先随机初始化一个Generator,通过Generator生成一组假的images标为0,从data base选出一组real images标为1,把这两组都喂给Discriminator让它学习如何鉴别fake image和real image
- How to learn Generator: 更新Generatorv1的参数获得Generatorv2,要使Generatorv2生成的fake image 能骗过Discriminatorv1(即让Discriminatorv1的输出尽可能接近1);注意此时Discriminatorv1是fixed的
课程中提及的"GAN-二次元人物头像合成"的pratice的链接
Source of images: GAN学习指南:从原理入门到制作生成Demo
DCGAN: https://github.com/carpedm20/DCGAN-tensorflow
The basic idea of GAN
极大似然估计
- 数据集其实本身对应一个真实数据分布
P
d
a
t
a
(
x
)
P_{data}(x )
Pdata(x),但是我们没法形式化的写出来,不妨假设真实分布可表示为
P
G
(
x
;
θ
)
P_G(x;\theta)
PG(x;θ),
θ
\theta
θ是我们控制数据分布表示的变量;因此学习的目标是找到一个
θ
\theta
θ使两个两个分布尽可能的接近,但因为真实数据分布
P
d
a
t
a
(
x
)
P_{data}(x )
Pdata(x)未知,所以通过计算“从数据集中抽取一组sample {
x
1
,
x
2
,
.
.
.
x
m
x^1,x^2,...x^m
x1,x2,...xm}(可以看作是从真实数据分布
P
d
a
t
a
(
x
)
P_{data}(x )
Pdata(x)中采样获得的样本),似然就是从
P
G
(
x
;
θ
)
P_G(x;\theta)
PG(x;θ)中采样获得这些样本的概率”
如果单纯假设 P G ( x ; θ ) P_G(x;\theta) PG(x;θ)是高斯分布,不具有一般性,因此假设 P G ( x ; θ ) P_G(x;\theta) PG(x;θ)是一个NN,因为仅仅是只有一个隐藏层的NN,也可以表示复杂的分布
Basic idea of GAN
横线部分:给定G,对应的红点即为maxmize处D的值
V具体是什么?
对于给定的G,max处
D
∗
D^*
D∗的值
最高点处就是两个分布间的差异值
Algorithm
- Generator的优化:将
m
a
x
D
V
max_DV
maxDV部分看作损失函数
L
(
G
)
L(G)
L(G),尽管
L
(
G
)
L(G)
L(G)有max部分但仍然有办法对G求偏导,最简单的办法就是分段考虑,给一个
x
x
x,看哪个
D
(
x
)
D(x)
D(x)的值最大就用哪个对G求偏导
更新流程:给定 G 0 G_0 G0,找到最大化 V ( G 0 , D ) V(G_0,D) V(G0,D)的 D 0 ∗ D_0^* D0∗,再用 D 0 ∗ D_0^* D0∗对 G 0 G_0 G0进行更新获得 G 1 G_1 G1;依此循环
这里存在的一个问题是:根据 D 0 ∗ D_0^* D0∗将 G 0 G_0 G0更新为 G 1 G_1 G1后,虽然保证了 V ( G 1 , D 0 ∗ ) < V ( G 0 , D 0 ∗ ) V(G_1,D_0^*)<V(G_0,D_0^*) V(G1,D0∗)<V(G0,D0∗),但是对于 G 1 G_1 G1可能存在某个 D ∗ D^* D∗使得 V ( G 1 , D 0 ∗ ) < V ( G 1 , D 1 ∗ ) V(G_1,D_0^*)<V(G_1,D_1^*) V(G1,D0∗)<V(G1,D1∗)(即 D 0 ∗ D_0^* D0∗不再是给定 G 1 G_1 G1情况下V最大时D的取值);为了避免这个问题,解决办法是使用小的学习率
这里minimize处漏了两个负号
Training iteration
train Discriminator
train Generator
在一次iteration中需重复多次(也可一次)蓝框内步骤后做一次红框内步骤。
原始目标函数在优化最开始的时候,sample出来的x会集中在D(x)很小的那块区域,而这块区域的梯度很小,优化的时候就会很慢;所以对其做了一个优化,如图,替换后当D(x)很小时梯度较大,D(x)较大时梯度较小即“离目标远的时候update快一点,离目标近的时候update慢一点”,目标就是让D(x)尽可能的趋近于1
有一个矛盾点:理论上希望discriminator powerful一点,但是实做上发现discriminator powerful以后JS divergence一直为lg2
实做上的理由:
理论上的理由:
evaluation,for example
因为两个分布没有交叠,所以JS divergence一直是log2
解决办法:
- add noise:实做中随着时间noise越来越小
另一个问题 mode collapse-其实生成分布集中在某一部分,如右图其实有很多重复的图像,但一般不容易发现,因为我们通常只关注到模型生成了什么,而了解不到模型没有生成什么
产生原因:若
P
d
a
t
a
P_{data}
Pdata有值而
P
G
P_G
PG趋向于0的话,KL会很大,因此一般要求
P
d
a
t
a
P_{data}
Pdata有值的地方而
P
G
P_G
PG也有值;在此要求下,若模型最小化目标如左下,则
P
G
P_G
PG会尽可能覆盖住
P
d
a
t
a
P_{data}
Pdata有值的地方;若调换一下
P
G
P_G
PG和
P
d
a
t
a
P_{data}
Pdata,如右下,则会在某些地方产生无穷大的KL,这会导致
P
G
P_G
PG在分布时会很保守,宁愿产生固定的某些image而不会冒险产生新的image。
Conditional GAN