GAN|生成手写数字|全连接网络

 老师给的建议:

1,阅读原论文看公式,理解怎么来的【待】

2,github找资源学习(如风格迁移)【待】

3,熟悉代码,化为己用【待】

4,转置卷积

GAN|生成手写数字|全连接网络

import torch
import torch.nn as nn
from torch.utils.data import Dataset
import pandas,numpy,random
import matplotlib.pyplot as plt

#数据集-------------------------------------------------------------------------
class MnistDataset(Dataset):

  def __init__(self, csv_file):
    self.data_df = pandas.read_csv(csv_file, header=None)

  def __len__(self):
    return len(self.data_df)

  def __getitem__(self, index):
    label = self.data_df.iloc[index,0]
    target = torch.zeros((10))
    target[label]=1.0
    image_values = torch.FloatTensor(self.data_df.iloc[index,1:].values)/255.0
    return label, image_values, target

  def plot_image(self, index):
    arr = self.data_df.iloc[index,1:].values.reshape(28,28)
    plt.title("label="+str(self.data_df.iloc[index,0]))
    plt.imshow(arr, interpolation='none',cmap='Blues')
mnist_dataset = MnistDataset('mount/My Drive/Colab Notebooks/mnist_data/mnist_train.csv')
mnist_test_dataset = MnistDataset('mount/My Drive/Colab Notebooks/mnist_data/mnist_test.csv')

#训练鉴别器的随机图
def generate_random_image(size):
  random_data = torch.rand(size)
  return random_data

#训练生成器的随机种子
def generate_random_seed(size):
  random_data = torch.randn(size)
  return random_data


#鉴别器-------------------------------------------------------------------------
class Discriminator(nn.Module):
  def __init__(self):
    super().__init__()
    self.model = nn.Sequential(
        nn.Linear(784,200),
        nn.LeakyReLU(0.02),
        nn.LayerNorm(200),
        nn.Linear(200,1),
        nn.Sigmoid()
    )
    self.loss_function = nn.BCELoss()
    self.optimiser = torch.optim.Adam(self.parameters(), lr=0.0001)
    self.counter = 0
    self.progress = []

  def forward(self, inputs):
    return self.model(inputs)

  def train(self, inputs, targets):
    outputs = self.forward(inputs)
    loss = self.loss_function(outputs, targets)

    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()

  def plot_progress(self):
    df = pandas.DataFrame(self.progress, columns=['loss'])
    df.plot(ylim=(0), figsize=(16,8), alpha=0.1, marker='.', grid=True, yticks=(0,0.25,1.0,0.5,5.0))
#训练鉴别器
D = Discriminator()
for label,image_data_tensor,target_tensor in mnist_dataset:
  D.train(image_data_tensor,torch.FloatTensor([1.0]))
  D.train(generate_random_image(784),torch.FloatTensor([0.0]))


#生成器-------------------------------------------------------------------------
class Generator(nn.Module):
  def __init__(self):
    super().__init__()
    self.model = nn.Sequential(
        nn.Linear(100,200),
        nn.LeakyReLU(0.02),
        nn.LayerNorm(200),
        nn.Linear(200,784),
        nn.Sigmoid()
    )
    self.optimiser = torch.optim.Adam(self.parameters(), lr=0.0001)
    self.counter=0
    self.progress=[]

  def forward(self, inputs):
    return self.model(inputs)

  def train(self, D, inputs, targets):
    g_output = self.forward(inputs)
    d_output = D.forward(g_output)
    loss = D.loss_function(d_output, targets)
   
    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()

  def plot_progress(self):
    df = pandas.DataFrame(self.progress, columns=['loss'])
    df.plot(ylim=(0), figsize=(16,8), alpha=0.1, marker='.', grid=True, yticks=(0,0.25,1.0,0.5,5.0))
#生成器未经过训练生成的图像
G = Generator()
output = G.forward(generate_random_seed(1))
img = output.detach().numpy().reshape(28,28)
plt.imshow(img,interpolation='none',cmap='Blues')

#训练GAN------------------------------------------------------------------------
D = Discriminator()
G = Generator()
epochs =4
for epoch in range(epochs):
  for label,image_data_tensor,target_tensor in mnist_dataset:
    D.train(image_data_tensor,torch.FloatTensor([1.0]))
    D.train(G.forward(generate_random_seed(100)).detach(),torch.FloatTensor([0.0]))
    G.train(D,generate_random_seed(100),torch.FloatTensor([1.0]))


#生成器经过训练生成的图像
f,axarr = plt.subplots(2,3,figsize=(16,8))
for i in range(2):
  for j in range(3):
    output = G.forward(generate_random_seed(100))
    img = output.detach().numpy().reshape(28,28)
    axarr[i,j].imshow(img,interpolation='none',cmap='Blues')


#遇到的问题,generate_random_seed(100),100是生成器输入的大小

nn.Sequential

一个序列容器,用于搭建神经网络的模块被按照被传入构造器的顺序添加到nn.Sequential()容器中。

一个包含神经网络模块的OrderedDict也可以被传入nn.Sequential()容器中。

利用nn.Sequential()搭建好模型架构,模型前向传播时调用forward()方法,模型接收的输入首先被传入nn.Sequential()包含的第一个网络模块中。然后,第一个网络模块的输出传入第二个网络模块作为输入,按照顺序依次计算并传播,直到nn.Sequential()里的最后一个模块输出结果。

item()

1,item()取出张量具体位置的元素元素值

2.并且返回的是该位置元素值的高精度值

3.保持原元素类型不变;必须指定位置

4.节省内存(不会计入计算图

鉴别器训练函数train()

  1. 获取loss:输入图像和标签,通过infer计算得到预测值,计算损失函数;

  2. optimizer.zero_grad() 清空过往梯度;

  3. loss.backward() 反向传播,计算当前梯度;

  4. optimizer.step() 根据梯度更新网络参数

D.train(generate_real(),torch.FloatTensor([1.0]))

D.train(generate_random()),torch.FloatTensor([0.0]))

符合格式规律的数据是真实的,目标输出为1.0

随机生成的数据是伪造的,目标输出为0.0

生成器训练函数train()

首先,self.forward(inputs)将输入值inputs传递给生成器自身的神经网络。

接着,通过D.forward(g_output)将生成器网络的输出g_ouput传递给鉴别器的神经网络,并输出分类结果 d_output。

鉴别器损失值由这个d_output和训练目标targets变量计算得出。

误差梯度的反向传播由这个损失值触发,在计算图中经过鉴别器回到生成器。

更新由self.optimiser而不是D.optimiser触发。这样一来,只有生成器的链接权重得到更新,这正是GAN训练循环第3步的目的

rand和randn

  • numpy.random.rand(d0, d1, …, dn)的随机样本位于[0, 1)中:本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。

  • numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样随机样本值。

 detach()将输出张量从计算图中分离出来,避免计算生成器中的梯度,减少计算量开销

学习要点|《pytorch生成式对抗网络编程》

在使用新的数据或者构建新的流程前,应尽量先通过预览了解数据。这样做可以确保数据被正常载入和变换。
PyTorch 可以替我们完成机器学习中的许多工作。为了
充分利用 PyTorch ,我们需要重复使用它的一些功能。比如,神经网络类需要从PyTorch的 nn.Module 父类继承。
通过可视化观察损失值 , 了解训练进程是很推荐的。
均方误差损失适用于输出是连续值的回归任务;二元交叉熵损失更适合输出是1 0 true false )的分类任务。
传统的 S 型激活函数在处理较大值时,具有梯度消失的缺点。这在网络训练时会造成反馈信号减弱。
ReLU 激活函数部分解决了这一问题,保持正值部分良好的梯度值。 LeakyReLU 进一步改良,在负值部分增加一个很小却不会消失的梯度值。
Adam 优化器使用动量来避免进入局部最小值,并保持每个可学习参数独立的学习率。在许多任务上,使用它的效果优于SGD 优化器。
标准化可以稳定神经网络的训练。一个网络的初始权重通常需要标准化。在信号通过一个神经网络时,使用LayerNorm标准化信号值可以提升网络性能。

GPU 包含许多计算内核,能以高度并行的方式运行一些计算。最初,它们被设计用来加速计算机图形计算,现在越来越多地被用于加速机器学习计算。CUDA NVIDIA 针对 GPU 加速计算而开发的编程框架。通过PyTorch 可以很方便地使用 CUDA ,无须过多地改变代码。
在简单的基准测试中,如矩阵乘法, GPU 的速度超过CPU150倍。
在单个计算上, GPU 可能比 CPU 慢。这是因为在 CPU之间和在GPU 之间的数据传送同样耗时。如果数据量不足 以分配给多个内核,GPU 的优势便无法得到发挥。

分类是对数据的简化。分类神经网络把较多的输入值缩减成很少的输出值,每个输出值对应一个类别。
生成是对数据的扩展。一个生成神经网络将少量的输入种子值扩展成大量的输出值,例如图像像素值。
生成对抗网络( GAN )由两个神经网络组成,一个是生成器,另一个是鉴别器,它们被设计为竞争对手。鉴别器经过训练后,可将训练集中的数据分类为真实数据,将生成器产生的数据分类为伪造数据;生成器在训练后,能创建可以以假乱真的数据来欺骗鉴别器。成功地设计和训练 GAN 并不容易。因为 GAN 的概念还很新,描述其工作原理以及为什么会训练失败的基本理论
尚未成熟。
标准的 GAN 训练循环有 3 个步骤。( 1 )用真实的训练数据集训练鉴别器;2)用生成的数据训练鉴别器; (3)训练生成器生成数据,并使鉴别器以为它是真实数
据。

构建和训练 GAN 的推荐步骤:( 1 )从真实数据集预 览数据;(2)测试鉴别器至少具备从随机噪声中区分真实数据的能力;(3)测试未经训练的生成器能否创建正确格式的数据;(4)可视化观察损失值,了解训练进展。
一个成功训练的 GAN 的鉴别器无法分辨真实的和生成的数据。因此,它的输出应该是介于0.0 1.0 ,也就是0.5。理想的均方误差损失是 0.25 。分别可视化并观察鉴别器和生成器的损失是非常有用的。生成器损失是鉴别器在判断生成数据时产生的损失。

处理单色图像不需要改变神经网络的设计。将二维像素数组简单地展开或重构成一维列表,即可输入鉴别器的输入层。如何做到这一点并不重要,不过要注意保持一致性。
模式崩溃是指一个生成器在有多个可能输出类别的情况下,一直生成单一类别的输出。模式崩溃是GAN 训练中最常见的挑战之一,其原因和解决方法尚未被完全理解,因此是一个相当活跃的研究课题。
着手设计 GAN 的一个很好开端是,镜像反映生成器和鉴别器的网络架构。这样做的目的是,尽量使它们之间达到平衡。在训练中,其中一方不会领先另一方太多。实验证据表明,成功训练GAN 的关键是质量,而不仅仅是数量。
生成器种子之间的平滑插值会生成平滑的插值图像。将种子相加似乎与图像特征的加法组合相对应。不过,种子相减所生成的图像并不遵循任何直观的规律。
理论上,一个经过完美训练的 GAN 的最优 MSE 损失(均方误差损失)为0.25 ,最优 BCE 损失(二元交叉熵损失)为ln 2 0.693

颜色可以用红、绿、蓝三种色光表示。因此,彩色图像常被表示为3 层像素值的数组,每层对应三原色之一, 且大小为(长,宽,3 )。
在处理由多个文件组成的数据集时,逐个读取和关闭每个文件的方法效率很低,特别是在虚拟环境中。一种推荐的做法是,将数据重新包装成一种为方便频繁、随机访问大量数据而设计的格式。成熟的 HDF 格式是科学计算中常见的格式。
一个 GAN 不会记忆训练数据中的样本,也不会复制和粘贴训练样本中的元素。它学习的是训练数据中特征的概率分布,并生成与训练数据看似来自同一分布的数据。
最先进的图像分类神经网络利用有意义的局部化特征。可识别的对象是由具有层次结构的特征构成的。低层次细节特征组成中层次特征,中层次特征本身又组成高层次对象。
卷积神经网络通过卷积核从一幅输入图像中生成特征图。指定的卷积核可以识别出图像中的特定图案。
神经网络中的卷积层可以针对具体任务学习合适的卷积核,也就是说,网络不需要我们直接设计特征,即可学到图像中最有用的特征。使用卷积层的神经网络在图像分
类任务上的表现,优于同等大小的全连接网络。 卷积模块缩减数据,同样配置的转置卷积模块可以抵消这种缩减。因此,转置卷积是生成网络的理想选择。
基于卷积网络的 GAN ,通过将低层次特征组成中层次特征,再由中层次特征组成高层次特征来构建图像。实验表明,由卷积GAN 生成的图像质量高于同等大小的全连接
GAN
与全连接 GAN 相比,卷积 GAN 占用的内存更少。在GPU内存受到限制时,这是处理较大大小的图像文件时需 要考虑的一个因素。我们看到卷积GAN 的内存使用只有全连接GAN 20% 左右。
卷积生成器的一个缺点是,它可能生成由相互不匹配的元素组成的图像。例如,包含不同眼睛的人脸。这是因
为卷积网络处理的信息是局部化的,而全局关系并没有被学习到。
不同于 GAN ,条件式 GAN 可以直接生成特定类型的输出。
训练条件式 GAN ,需要将类别标签分别与图像和种子一起输入鉴别器和生成器。由条件式 GAN 生成图像的质量,通常优于由不使用标签信息的同等GAN 生成的图像。
代码运行成功4.11

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值