torch_09_GAN
1.生成对抗网络
让两个网络相互竞争,通过生成网络来生成假的数据,对抗网络通过判别器判别真伪,最后希望生成网络生成的数据能够以假乱真骗过判别器
2.生成模型
就是‘生成’样本和‘真实’的样本尽可能的相似。生成模型的两个主要功能是学习一个概率分布Pmodel(X)和生成数据。
在生成对抗网络中,不再是将图片输入编码器得到隐含向量然后生成图片,而是随机初始化一个隐含向量,根据变分自动编码器的特点,初始化一个正态分布的隐含向量,通过类似解码的过程,将它映射到一个更高的维度,最后生成一个与输入数据相似的数据,这就是假的数据。生成对抗网络过程通过计算对抗过程来计算损失函数。
2.1 自动编码器(AutoEncoder)
编码器的结构:
第一部分是编码器(Encoder),第二部分是解码器(Decoder),编码器和解码器都可以是任意的模型,通常使用神经网络模型作为编码器和解码器。输入的数据经过神经网络降维到一个编码(code),接着又通过另外一个神经网络去解码得到一个与输入数据一模一样的生成数据,然后通过比较这两个数据,最小化™之间的差异来训练这个网络中编码器和解码器的参数。当这个过程训练完之后,拿出这个解码器,随机传入一个编码,通过解码器能够生成一个和原数据差不多的数据。如下图:
2.2 变分自动编码器(Variational AutoEncoder-- VAE)
结构与自动编码器是相似的,也是由编码器和解码器构成的。
在自动编码器中只能输入一张图片,才能产生隐含向量,不能输入一个随机向量,虽然自动编码器能输出与原图很接近的图片,但是缺乏多样性。在变分自动编码器中,只需要在编码过程给它增加一些限制,迫使它生成的隐含向量能够粗略的遵循一个标准正态分布,这就是它与一般的自动编码器最大的不同。
在变分自动编码器中,只需要给它一个标准正态分布的随机向量,利用解码器就可以生成一张图片。不需要先给它一张原始图片。
模型的准确率:解码器生成的图片与原图片的相似程度。
loss的计算:解码器生成图片与原始图片的均方误差 + 隐含向量与标准正态分布之间的差异 (使用的是KL divergence)
在变分编码器中,使用了一个技巧-重新参数化,来解决KL divergence的计算问题
不再每次生成一个隐含向量,而是生成两个向量:一个表示均值,一个表示标准差,然后通过这两个统计量合成隐含向量,用一个标准正态分布先乘上标准差再加上均值。这里默认编码之后的隐含向量是服从一个正态分布的,这个时候要让均值尽可能接近0,
3.对抗过程
对抗过程是一个判断真假的判别器,相当于一个二分类问题。输入一张图片,如果是真的图片希望判别器输出为1,假的图片输出为0,这与图片的标签没有关系。
4.训练过程
先优化判别器,将真的图片和假的图片都输入给判别模型,让判别器计算损失,不断优化,让判别器能够区分出真的图片和假的图片,真的图片为1,假的为0.
然后优化生成器。固定判别器的参数,不断优化生成器,使生成器的生成的结果传递给判别器之后,尽可能的接近1,调整损失函数。
5.判别模型训练
开始需要自己创建label,真实的数据时1,生成的假的数据时0,然后将真实的数据输入给判别器,计算loss值,将假的数据输入判别器得到loss,将这两个loss加起来得到总的loss,然后反向传播更新参数能够得到一个优化好的判别器。
6.生成器训练
一个随机隐含向量通过生成网络得到了一个假的数据,然后希望假的数据经过判别模型尽可能和真实label接近,通过g_loss = criterion(output,real_label)实现,然后反向传播去优化生成器的参数,在这个过程中,判别器的参数不再发生变化,否则生成器永远无法骗过优化的判别器。
DCGAN,使用celeba数据集
训练过程:
第一批次(batch-size):
1.将随机生成的128*100*1*1给G网络,生成128*3*64*64的图片
2.将这些假图片给D网络,计算损失,并且把一批真图片(128*3*64*64,每次从Dataloder迭代器中拿出来一批作为真图片 )计算损失,两者损失相加,进行梯度优化
3.计算生成器损失,计算D(G(X)),把128张假图片,放入判别器,更新G的梯度,假图片标签为1
4.这就完成了一次一批(128张)的生成和判别
第二批次(batch-size):
1.又取出来一批真数据,假数据(重新生成一批假数据放入G网络中,生成128张假数据),放入D网络,真数据标签为1,假数据标签为0,放在一起计算损失,进行优化
2.然后把这些假数据放入D网络中,计算损失更新G网络的参数权重,注意的一点是,此时假数据的标签为1
3.规定训练到一定次数时,随机生成64*100*1*1的向量生成64张图片来查看生成假图片的效果
......
训练5个epochs
torch_09_GAN的更多相关文章
随机推荐
- WPF-控件模板
说起控件模板,还是因为在一次需求实现中,我碰到了一个圆形按钮.一开始我认知的按钮是方形灰不拉几的一个块儿.这如何实现一个圆形按钮? 我最先想到的是使用样式,可是发现根本就没有改变Button形状的属性 ...
- 如何使用Charles让手机访问PC自定义域名?
需求:移动端访问PC上的自定义域名,如在Nginx上配置的域名 如vv.zzcloud.com这个域名在pc上是通过host映射的方式访问,现在需要在手机上访问到这个域名. 工具:Charles代 ...
- rabbitmq 实现多个消费队列
1.将消费程序复制重新生成一个. 2.channel.BasicQos(0, 1, false); 空闲的先消费
- Java网络编程 -- Netty中的ByteBuf
由于JDK中提供的ByteBuffer无法动态扩容,并且API使用复杂等原因,Netty中提供了ByteBuf.Bytebuf的API操作更加便捷,可以动态扩容,提供了多种ByteBuf的实现,以及高 ...
- LeetCode——Department Highest Salary(花式使用IN以及GROUP BY)
The Employee table holds all employees. Every employee has an Id, a salary, and there is also a colu ...
- Spring Cloud Eureka的自我保护模式与实例下线剔除
之前我说明了Eureka注册中心的保护模式,由于在该模式下不能剔除失效节点,故按原有配置在实际中不剔除总感觉不是太好,所以深入研究了一下.当然,这里重申一下,不管实例是否有效剔除,消费端实现Ribbo ...
- C++编译错误 --- 成员函数定义在 .h 文件中出现重定义错误(Error LNK 2005)
今天写了一个简单的类,定义在 .h 文件中, 类很简单就将其成员函数定义在了一起(class类后面).运行的时候出现了如下图所示的编译错误(error LNK2005) 查资料,大部分都是说需要加上 ...
- Rust中的函数调用
注意区别语句和表达式哟. Rust是一门基于表示式的语言,牢记!!! fn main() { println!("Hello world!"); another_function( ...
- React 受控组件和非受控组件
需求用户名自动获取 onChange用户状态发生改变 就获取值 就是时时获取值 使用onChange 点击按钮 获取密码 只要绑定了点击事件 就可以获取值 通过 let usercont=event. ...
- Anslble 部署安装
安装文档:https://ansible-tran.readthedocs.io/en/latest/docs/intro_configuration.html https://docs.ansibl ...