• GAN


    生成式对抗网络

    • 借助于 sklearn.datasets.make_moons 库,生成双半月形的数据,同时把数据点画出来。

      import numpy as np
      import matplotlib.pyplot as plt
      from sklearn.datasets import make_moons
      
      import torch
      # 使用GPU训练,可以在菜单 "代码执行工具" -> "更改运行时类型" 里进行设置
      device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
      
      # 这是一个展示数据的函数
      def plot_data(ax, X, Y, color = 'bone'):
          plt.axis('off')
          ax.scatter(X[:, 0], X[:, 1], s=1, c=Y, cmap=color)
          
      X, y = make_moons(n_samples=2000, noise=0.05)
      
      n_samples = X.shape[0]
      Y = np.ones(n_samples)
      fig, ax = plt.subplots(1, 1, facecolor='#4B6EA9')
      plot_data(ax, X, Y)
      plt.show()
      

    • 一个简单的GAN

      import torch.nn as nn
      
      z_dim = 32
      hidden_dim = 128
      
      # 定义生成器
      net_G = nn.Sequential(
                  nn.Linear(z_dim,hidden_dim),
                  nn.ReLU(), 
                  nn.Linear(hidden_dim, 2))
      
      # 定义判别器
      net_D = nn.Sequential(
                  nn.Linear(2,hidden_dim),
                  nn.ReLU(),
                  nn.Linear(hidden_dim,1),
                  nn.Sigmoid())
      
      # 网络放到 GPU 上
      net_G = net_G.to(device)
      net_D = net_D.to(device)
      
      # 定义网络的优化器
      optimizer_G = torch.optim.Adam(net_G.parameters(),lr=0.0001)
      optimizer_D = torch.optim.Adam(net_D.parameters(),lr=0.0001)
      
    • 对抗训练过程

      batch_size = 50
      nb_epochs = 1000
      
      loss_D_epoch = []
      loss_G_epoch = []
      
      for e in range(nb_epochs):
          np.random.shuffle(X)
          real_samples = torch.from_numpy(X).type(torch.FloatTensor)
          loss_G = 0
          loss_D = 0
          for t, real_batch in enumerate(real_samples.split(batch_size)):
              z = torch.empty(batch_size,z_dim).normal_().to(device)
              fake_batch = net_G(z)
              # 将真、假样本分别输入判别器,得到结果
              D_scores_on_real = net_D(real_batch.to(device))
              D_scores_on_fake = net_D(fake_batch)
              # 优化过程中,假样本的score会越来越小,真样本的score会越来越大,下面 loss 的定义刚好符合这一规律,
              # 要保证loss越来越小,真样本的score前面要加负号
              # 要保证loss越来越小,假样本的score前面是正号(负负得正)
              loss = -torch.mean(torch.log(1-D_scores_on_fake) + torch.log(D_scores_on_real))
      
              optimizer_D.zero_grad()
              loss.backward()
              optimizer_D.step()
              loss_D += loss
                          
              # 固定判别器,改进生成器
              # 生成一组随机噪声,输入生成器得到一组假样本
              z = torch.empty(batch_size,z_dim).normal_().to(device)
              fake_batch = net_G(z)
              # 假样本输入判别器得到 score
              D_scores_on_fake = net_D(fake_batch)
              # 我们希望假样本能够骗过生成器,得到较高的分数,下面的 loss 定义也符合这一规律
              # 要保证 loss 越来越小,假样本的前面要加负号
              loss = -torch.mean(torch.log(D_scores_on_fake))
              optimizer_G.zero_grad()
              loss.backward()
              optimizer_G.step()
              loss_G += loss
          
          if e % 50 ==0:
              print(f'
       Epoch {e} , D loss: {loss_D}, G loss: {loss_G}') 
      
          loss_D_epoch.append(loss_D)
          loss_G_epoch.append(loss_G)
      
    • 显示loss的变化情况

      plt.plot(loss_D_epoch)
      plt.plot(loss_G_epoch)
      

    • 利用生成器生成一组假样本,观察是否符合两个半月形状的数据分布:

      z = torch.empty(n_samples,z_dim).normal_().to(device)
      fake_samples = net_G(z)
      fake_data = fake_samples.cpu().data.numpy()
      
      fig, ax = plt.subplots(1, 1, facecolor='#4B6EA9')
      all_data = np.concatenate((X,fake_data),axis=0)
      Y2 = np.concatenate((np.ones(n_samples),np.zeros(n_samples)))
      plot_data(ax, all_data, Y2)
      plt.show()
      

      其中,白色的是原来的真实样本,黑色的点是生成器生成的样本。

    • 看起来,效果不好。现在把学习率修改为 0.001,batch_size改大到250,再试一次:

      optimizer_G = torch.optim.Adam(net_G.parameters(),lr=0.001)
      optimizer_D = torch.optim.Adam(net_D.parameters(),lr=0.001)
      
      batch_size = 250
      

      loss明显减小。

    • 再次利用噪声生成一组数据观察一下:

      效果明显改善。

  • 相关阅读:
    令我印象最深刻的三个老师
    硬盘大于2T安装CentOS7.X时要注意分区
    Linux网卡配置
    Python13:文件操作
    Python12:集合
    Python11:字典
    Python10:String字符串
    Python09:元组
    Python08:列表
    Python07:模块初识
  • 原文地址:https://www.cnblogs.com/lixinhh/p/13657418.html
Copyright © 2020-2023  润新知