1、前言
本文将讲近些年来挺火的一个生成模型
g
a
n
生成对抗网络
\boxed{\mathbf{gan生成对抗网络}}
gan生成对抗网络,其特殊的思路解法实在让人啧啧称奇。
数学基础:【概率论与数理统计知识复习-哔哩哔哩】
视频:【生成对抗网络gan原理解析-哔哩哔哩】
2、原理
2.1、gan的运行机理
在传统的生成模型中,我们总是对我们的训练数据(或观测变量和隐变量)进行建模,得到概率分布,然后进行数据的生成。可gan却不是这样,其利用神经网络这个函数逼近器,求解出了模型中概率分布的参数 在不知道概率分布是什么的情况下 \boxed{在不知道概率分布是什么的情况下} 在不知道概率分布是什么的情况下。
其主要思想是,从一个简单的概率分布中采样,得到样本经过神经网络变换,得到一个新的样本,我们就假设这个样本就来自我们需要求解的概率分布中。然后用神经网络去辨别其是来自真实分布,还是我们要求解的概率分布。
先来看模型图
我们的训练数据 x x x是来自真实分布 对应图中 p ( d a t a ) \boxed{\mathbf{对应图中p(data)}} 对应图中p(data),我们记作 p d a t a p_{data} pdata,训练数据都是从 p d a t a p_{data} pdata中采样得来(图中上半部分的x)。
而我们从简单的概率分布中抽样 p ( z ) p(z) p(z) 如正态分布 \boxed{\mathbf{如正态分布}} 如正态分布,让所得的样本经过一个神经网络 g ( z ) g(z) g(z),得到一个新的样本 x x x,这个样本就来自我们的需要求解的概率分布,我们记作 p g p_{g} pg。
然后将两个x给神经网络 d ( x ) d(x) d(x)判断真伪,让它区分这个x是来自 p d a t a p_{data} pdata还是 p g p_g pg,其输出样本来自 p d a t a p_{data} pdata的概率。依据所得信息使用梯度下降更新神经网络参数, g ( z ) g(z) g(z)也是如此。
而 g ( z ) g(z) g(z)被称为生成器 ( 用于生成样本 ) \boxed{\mathbf{(用于生成样本)}} (用于生成样本), d ( x ) d(x) d(x)被称为判别器 用于判别样本真伪 \boxed{\mathbf{用于判别样本真伪}} 用于判别样本真伪。
2.2、目标函数
损失函数来自判别器和生成器 \boxed{\mathbf{损失函数来自判别器和生成器}} 损失函数来自判别器和生成器
对于判别器 \boxed{对于判别器} 对于判别器
当样本来自
p
d
a
t
a
p_{data}
pdata,我们要让所得的概率越大越好;当样本来自
p
g
p_g
pg,我们要让其概率越小越好,即
①
max
d
d
(
x
i
)
②
min
d
d
(
g
(
z
i
)
)
①\max\limits_{d}d(x_i)\\ ②\min\limits_{d}d(g(z_i))
①dmaxd(xi)②dmind(g(zi))
将最小化换成最大化
max
d
[
1
−
d
(
g
(
z
i
)
)
]
\max\limits_{d}[1-d(g(z_i))]
dmax[1−d(g(zi))]
所以单个样本判别器的损失函数可以写成
max
d
{
d
(
x
i
)
+
[
1
−
d
(
g
(
z
i
)
)
]
}
\max\limits_{d}\left\{d(x_i)+[1-d(g(z_i))]\right\}
dmax{d(xi)+[1−d(g(zi))]}
对于所有样本n,我们希望均值最大
max
d
{
1
n
∑
i
=
1
n
d
(
x
i
)
+
1
n
∑
i
=
1
n
[
1
−
d
(
g
(
z
i
)
)
]
}
\max_d\left\{\frac{1}{n}\sum\limits_{i=1}^nd(x_i)+\frac{1}{n}\sum\limits_{i=1}^n[1-d(g(z_i))]\right\}
dmax{n1i=1∑nd(xi)+n1i=1∑n[1−d(g(zi))]}
写成期望形式(并取log最大
不改变最大值
\boxed{不改变最大值}
不改变最大值),得到判别器的损失函数(
x
∼
p
d
a
t
a
x\sim p_{data}
x∼pdata表示样本来自真实分布,
p
z
p_z
pz表示正态分布)
max
d
{
e
x
∼
p
d
a
t
a
[
log
d
(
x
)
]
+
e
z
∼
p
z
[
log
(
1
−
d
(
g
(
z
)
)
)
]
}
\boxed{\max\limits_{d}\left\{\mathbb{e}_{x\sim p_{data}}\left[\log d(x)\right]+\mathbb{e}_{z\sim p_z}\left[\log(1-d(g(z)))\right]\right\}}
dmax{ex∼pdata[logd(x)]+ez∼pz[log(1−d(g(z)))]}
接着,我们在上面讲到过,g(z)表示的是,采用一个z,经过一个神经网络,得到一个伪造出来的x。这个伪造的x服从分布
p
g
p_g
pg。那么我们就可以把第二个期望改写成x的表达式,于是便可得到
max
d
{
e
x
∼
p
d
a
t
a
[
log
d
(
x
)
]
+
e
x
∼
p
g
[
log
(
1
−
d
(
x
)
)
]
}
\boxed{\max\limits_{d}\left\{\mathbb{e}_{x\sim p_{data}}\left[\log d(x)\right]+\mathbb{e}_{x\sim p_g}\left[\log(1-d(x))\right]\right\}}
dmax{ex∼pdata[logd(x)]+ex∼pg[log(1−d(x))]}
对于生成器
\boxed{对于生成器}
对于生成器
它希望生成的样本让判别器判别为真的概率越大越好,所以直接设计成(将最大写成最小)
min
g
e
x
∼
p
g
[
log
(
1
−
d
(
x
)
)
]
\boxed{\min\limits_{g}\mathbb{e}_{x\sim p_g}\left[\log(1-d(x))\right]}
gminex∼pg[log(1−d(x))]
所以最终的目标函数可以写成
min
g
max
d
{
e
x
∼
p
d
a
t
a
[
log
d
(
x
)
]
+
e
x
∼
p
g
[
log
(
1
−
d
(
x
)
)
]
}
\min\limits_{g}\max\limits_{d}\left\{\mathbb{e}_{x\sim p_{data}}\left[\log d(x)\right]+\mathbb{e}_{x\sim p_g}\left[\log(1-d(x))\right]\right\}
gmindmax{ex∼pdata[logd(x)]+ex∼pg[log(1−d(x))]}
3、最优解求解
得到了目标函数,我们很显然还需要证明其存在最优解。并且最优解的 p g p_g pg是否和 p d a t a p_{data} pdata无限接近
先求里层(关于
d
求最大)
\boxed{先求里层(关于d求最大)}
先求里层(关于d求最大)
e
x
∼
p
d
a
t
a
[
log
d
(
x
)
]
+
e
x
∼
p
g
[
log
(
1
−
d
(
x
)
)
]
=
∫
x
log
d
(
x
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
1
−
d
(
x
)
)
p
g
(
x
)
d
x
=
∫
x
[
log
d
(
x
)
p
d
a
t
a
(
x
)
+
log
(
1
−
d
(
x
)
)
p
g
(
x
)
]
d
x
\begin{aligned} &\mathbb{e}_{x\sim p_{data}}\left[\log d(x)\right]+\mathbb{e}_{x\sim p_g}\left[\log(1-d(x))\right] \\=&\int_x\log d(x)p_{data}(x)dx+\int_x\log(1-d(x))p_g(x)dx \\=&\int_x\left[\log d(x)p_{data}(x)+\log(1-d(x))p_g(x)\right]dx \end{aligned}
==ex∼pdata[logd(x)]+ex∼pg[log(1−d(x))]∫xlogd(x)pdata(x)dx+∫xlog(1−d(x))pg(x)dx∫x[logd(x)pdata(x)+log(1−d(x))pg(x)]dx
要求积分最大,就是要求里面的每一个最大
max
d
[
log
d
(
x
)
p
d
a
t
a
(
x
)
+
log
(
1
−
d
(
x
)
)
p
g
(
x
)
]
\max_d \left[{\log d(x)p_{data}(x)+\log(1-d(x))p_g(x)}\right]
dmax[logd(x)pdata(x)+log(1−d(x))pg(x)]
求导
∂
∂
d
l
o
g
d
(
x
)
p
d
a
t
a
(
x
)
+
log
(
1
−
d
(
x
)
)
p
g
(
x
)
=
1
d
(
x
)
p
d
a
t
a
(
x
)
−
1
1
−
d
(
x
)
p
g
(
x
)
\begin{aligned} &\frac{\partial }{\partial d}{log d(x)p_{data}(x)+\log(1-d(x))p_g(x)} \\=&\frac{1}{d(x)}p_{data}(x)-\frac{1}{1-d(x)}p_g(x) \end{aligned}
=∂d∂logd(x)pdata(x)+log(1−d(x))pg(x)d(x)1pdata(x)−1−d(x)1pg(x)
整理得
d
(
x
)
=
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
\boxed{d(x)=\frac{p_{data}(x)}{p_{g}(x)+p_{data}(x)}}
d(x)=pg(x)+pdata(x)pdata(x)
将其代入目标函数,并且关于外层
g
求最小
\boxed{将其代入目标函数,并且关于外层g求最小}
将其代入目标函数,并且关于外层g求最小
min
g
∫
x
[
log
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
p
d
a
t
a
(
x
)
+
log
(
1
−
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
)
p
g
(
x
)
]
d
x
=
min
g
[
∫
x
log
(
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
∗
1
2
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
p
g
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
∗
1
2
)
p
g
(
x
)
d
x
]
=
min
g
[
∫
x
log
(
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
p
g
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
g
(
x
)
d
x
+
∫
log
1
2
p
d
a
t
a
(
x
)
d
x
+
∫
log
1
2
p
g
(
x
)
d
x
]
=
min
g
[
∫
x
log
(
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
p
g
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
g
(
x
)
d
x
+
log
1
2
∫
p
d
a
t
a
(
x
)
d
x
+
log
1
2
∫
p
g
(
x
)
d
x
]
=
min
g
[
∫
x
log
(
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
p
g
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
g
(
x
)
d
x
+
log
1
2
+
log
1
2
]
=
min
g
[
∫
x
log
(
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
d
a
t
a
(
x
)
d
x
+
∫
x
log
(
p
g
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
2
)
p
g
(
x
)
d
x
+
log
1
4
]
=
min
g
k
l
(
p
d
a
t
a
(
x
)
∣
∣
p
d
a
t
a
(
x
)
+
p
g
(
x
)
2
)
+
k
l
(
p
g
(
x
)
∣
∣
p
d
a
t
a
(
x
)
+
p
g
(
x
)
2
)
−
log
4
\begin{aligned} &\min_g \int_x\left[{\log \frac{p_{data}(x)}{p_{g}(x)+p_{data}(x)}p_{data}(x)+\log(1-\frac{p_{data}(x)}{p_{g}(x)+p_{data}(x)})p_g(x)}\right]dx \\=&\min\limits_{g}\left[\int_x\log\left(\frac{p_{data}(x)}{\frac{p_{g}(x)+p_{data}(x)}{2}}*\frac{1}{2}\right)p_{data}(x)dx+\int_x\log\left(\frac{p_g(x)}{\frac{p_g(x)+p_{data}(x)}{2}}*\frac{1}{2}\right)p_g(x)dx\right] \\=&\min\limits_{g}\left[\int_x\log\left(\frac{p_{data}(x)}{\frac{p_{g}(x)+p_{data}(x)}{2}}\right)p_{data}(x)dx+\int_x\log\left(\frac{p_g(x)}{\frac{p_g(x)+p_{data}(x)}{2}}\right)p_g(x)dx+\int \log\frac{1}{2}p_{data}(x)dx+\int\log\frac{1}{2}p_{g}(x)dx\right]\\=&\min\limits_{g}\left[\int_x\log\left(\frac{p_{data}(x)}{\frac{p_{g}(x)+p_{data}(x)}{2}}\right)p_{data}(x)dx+\int_x\log\left(\frac{p_g(x)}{\frac{p_g(x)+p_{data}(x)}{2}}\right)p_g(x)dx+\log\frac{1}{2}\int p_{data}(x)dx+\log\frac{1}{2}\int p_{g}(x)dx\right]\\=&\min\limits_{g}\left[\int_x\log\left(\frac{p_{data}(x)}{\frac{p_{g}(x)+p_{data}(x)}{2}}\right)p_{data}(x)dx+\int_x\log\left(\frac{p_g(x)}{\frac{p_g(x)+p_{data}(x)}{2}}\right)p_g(x)dx+\log\frac{1}{2}+\log\frac{1}{2}\right]\\=&\min\limits_{g}\left[\int_x\log\left(\frac{p_{data}(x)}{\frac{p_{g}(x)+p_{data}(x)}{2}}\right)p_{data}(x)dx+\int_x\log\left(\frac{p_g(x)}{\frac{p_g(x)+p_{data}(x)}{2}}\right)p_g(x)dx+\log\frac{1}{4}\right] \\=&\min\limits_{g}kl\left(p_{data}(x)||\frac{p_{data}(x)+p_{g}(x)}{2}\right)+kl\left(p_{g}(x)||\frac{p_{data}(x)+p_{g}(x)}{2}\right)-\log4 \end{aligned}
======gmin∫x[logpg(x)+pdata(x)pdata(x)pdata(x)+log(1−pg(x)+pdata(x)pdata(x))pg(x)]dxgmin[∫xlog(2pg(x)+pdata(x)pdata(x)∗21)pdata(x)dx+∫xlog(2pg(x)+pdata(x)pg(x)∗21)pg(x)dx]gmin[∫xlog(2pg(x)+pdata(x)pdata(x))pdata(x)dx+∫xlog(2pg(x)+pdata(x)pg(x))pg(x)dx+∫log21pdata(x)dx+∫log21pg(x)dx]gmin[∫xlog(2pg(x)+pdata(x)pdata(x))pdata(x)dx+∫xlog(2pg(x)+pdata(x)pg(x))pg(x)dx+log21∫pdata(x)dx+log21∫pg(x)dx]gmin[∫xlog(2pg(x)+pdata(x)pdata(x))pdata(x)dx+∫xlog(2pg(x)+pdata(x)pg(x))pg(x)dx+log21+log21]gmin[∫xlog(2pg(x)+pdata(x)pdata(x))pdata(x)dx+∫xlog(2pg(x)+pdata(x)pg(x))pg(x)dx+log41]gminkl(pdata(x)∣∣2pdata(x)+pg(x))+kl(pg(x)∣∣2pdata(x)+pg(x))−log4
k l ( p ∣ ∣ q ) = ∫ x p log p q d x kl(p||q)=\int_xp\log\frac{p}{q}dx kl(p∣∣q)=∫xplogqpdx,kl散度是衡量概率分布 p p p和 q q q的相似程度,其大于等于0,当其相似程度一样时,则散度为0,也就是我们要求的最小值。
小补充
\boxed{小补充}
小补充
2
j
s
(
p
d
a
t
a
(
x
)
∣
∣
p
g
(
x
)
)
=
k
l
(
p
d
a
t
a
(
x
)
∣
∣
p
d
a
t
a
(
x
)
+
p
g
(
x
)
2
)
+
k
l
(
p
g
(
x
)
∣
∣
p
d
a
t
a
(
x
)
+
p
g
(
x
)
2
)
\boxed{\mathbf{2js\left(p_{data}(x)||p_g(x)\right)=kl\left(p_{data}(x)||\frac{p_{data}(x)+p_{g}(x)}{2}\right)+kl\left(p_{g}(x)||\frac{p_{data}(x)+p_{g}(x)}{2}\right)}}
2js(pdata(x)∣∣pg(x))=kl(pdata(x)∣∣2pdata(x)+pg(x))+kl(pg(x)∣∣2pdata(x)+pg(x))
j
s
(
p
∣
∣
q
)
js(p||q)
js(p∣∣q)被称为js散度,其仍然是大于等于0的。所以是一样的。
所以
p
d
a
t
a
(
x
)
=
p
g
(
x
)
+
p
d
a
t
a
2
→
p
d
a
t
a
=
p
g
(
x
)
p_{data}(x)=\frac{p_g(x)+p_{data}}{2} \rightarrow p_{data}=p_g(x)
pdata(x)=2pg(x)+pdata→pdata=pg(x)
由此可见,目标函数最优值能够让
p
g
逼近
p
d
a
t
a
\boxed{\mathbb{由此可见,目标函数最优值能够让p_g 逼近p_{data}}}
由此可见,目标函数最优值能够让pg逼近pdata,并且当其相等时,有
d
(
x
)
=
p
d
a
t
a
(
x
)
p
g
(
x
)
+
p
d
a
t
a
(
x
)
=
1
2
\boxed{d(x)=\frac{p_{data}(x)}{p_{g}(x)+p_{data}(x)}}=\frac{1}{2}
d(x)=pg(x)+pdata(x)pdata(x)=21
也就是判别器再也无法判断出样本是来自
p
d
a
t
a
p_{data}
pdata还是
p
g
p_g
pg
4、代码实现
结果如下
效果一般,在其他变种优化有很多比这个好的,感兴趣的读者自行查阅。
import torch
from torchvision.datasets import mnist
from torchvision import transforms
from torch.utils.data import dataloader
from tqdm import tqdm
import matplotlib.pyplot as plt
class generate_model(torch.nn.module):
'''
生成器
'''
def __init__(self):
super().__init__()
self.fc=torch.nn.sequential(
torch.nn.linear(in_features=128,out_features=256),
torch.nn.tanh(),
torch.nn.linear(in_features=256,out_features=512),
torch.nn.relu(),
torch.nn.linear(in_features=512,out_features=784),
torch.nn.tanh()
)
def forward(self,x):
x=self.fc(x)
return x
class distinguish_model(torch.nn.module):
'''
判别器
'''
def __init__(self):
super().__init__()
self.fc=torch.nn.sequential(
torch.nn.linear(in_features=784,out_features=512),
torch.nn.tanh(),
torch.nn.linear(in_features=512,out_features=256),
torch.nn.tanh(),
torch.nn.linear(in_features=256,out_features=128),
torch.nn.tanh(),
torch.nn.linear(in_features=128,out_features=1),
torch.nn.sigmoid()
)
def forward(self,x):
x=self.fc(x)
return x
def train():
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu") #判断是否存在可用gpu
transformer = transforms.compose([
transforms.totensor(),
transforms.normalize(mean=0.5, std=0.5)
]) #图片标准化
train_data = mnist("./data", transform=transformer,download=true) #载入图片
dataloader = dataloader(train_data, batch_size=64,num_workers=4, shuffle=true) #将图片放入数据加载器
d = distinguish_model().to(device) #实例化判别器
g = generate_model().to(device) #实例化生成器
d_optim = torch.optim.adam(d.parameters(), lr=1e-4) #为判别器设置优化器
g_optim = torch.optim.adam(g.parameters(), lr=1e-4) #为生成器设置优化器
loss_fn = torch.nn.bceloss() #损失函数
epochs = 100 #迭代100次
for epoch in range(epochs):
dis_loss_all=0 #记录判别器损失损失
gen_loss_all=0 #记录生成器损失
loader_len=len(dataloader) #数据加载器长度
for step,data in tqdm(enumerate(dataloader), desc="第{}轮".format(epoch),total=loader_len):
# 先计算判别器损失
sample,label=data #获取样本,舍弃标签
sample = sample.reshape(-1, 784).to(device) #重塑图片
sample_shape = sample.shape[0] #获取批次数量
#从正态分布中抽样
sample_z = torch.normal(0, 1, size=(sample_shape, 128),device=device)
dis_true = d(sample) #判别器判别真样本
true_loss = loss_fn(dis_true, torch.ones_like(dis_true)) #计算损失
fake_sample = g(sample_z) #生成器通过正态分布抽样生成数据
dis_fake = d(fake_sample.detach()) #判别器判别伪样本
fake_loss = loss_fn(dis_fake, torch.zeros_like(dis_fake)) #计算损失
dis_loss = true_loss + fake_loss #真假加起来
d_optim.zero_grad()
dis_loss.backward() #反向传播
d_optim.step()
# 生成器损失
dis_g = d(fake_sample) #判别器判别
g_loss = loss_fn(dis_g, torch.ones_like(dis_g)) #计算损失
g_optim.zero_grad()
g_loss.backward() #反向传播
g_optim.step()
with torch.no_grad():
dis_loss_all+=dis_loss #判别器累加损失
gen_loss_all+=g_loss #生成器累加损失
with torch.no_grad():
dis_loss_all=dis_loss_all/loader_len
gen_loss_all=gen_loss_all/loader_len
print("判别器损失为:{}".format(dis_loss_all))
print("生成器损失为:{}".format(gen_loss_all))
torch.save(g, "./model/g.pth") #保存模型
torch.save(d, "./model/d.pth") #保存模型
if __name__ == '__main__':
# train() #训练模型
model_g=torch.load("./model/g.pth",map_location=torch.device("cpu")) #载入模型
fake_z=torch.normal(0,1,size=(10,128)) #抽样数据
result=model_g(fake_z).reshape(-1,28,28) #生成数据
result=result.detach().numpy()
#绘制
for i in range(10):
plt.subplot(2,5,i+1)
plt.imshow(result[i])
plt.gray()
plt.show()
5、结束
以上,就是gan生成对抗网络的全部内容了,如有问题,还望指出。阿里嘎多
发表评论