一、GAN 的概念

以生成图像为例说明:用一个被训练用于生成图像的神经网络,取代之前只能生成低质量图像的组件。我们称它为生成器(generator)。同时我们把分类器成为鉴别器(discriminator),这也是它在该架构中通用的命名。

image-20211211123234201

鉴别器的作用是把真实的图像和生成的图像区分开。如果生成器的表现不佳,区分工作就很容易。不过,如果训练生成器,它的表现应该越来越好,并生成越来越逼真的图像。鉴别器和生成器是竞争对手关系,双发都试图超越对方,并在这个过程中逐步提高。我们称这种架构为生成对抗网络。

GAN 的训练 —— 三步循环训练。

  1. 我们向鉴别器展示一副实际数据集中的图像,输出结果应该是1.0,并让它对图像进行分类。然后用损失来更新鉴别器。
  2. 向鉴别器展示生成器产生的图像,输出结果应该是0.0。然后用损失来更新鉴别器。
  3. 训练生成器。用它生成一个图像,并将生成的图像输入给鉴别器进行分类。鉴别器预期结果应该是1.0。然后根据损失来更新生成器。

二、生成1010 格式规律

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import torch
import torch.nn as nn
import pandas as pd
import matplotlib.pyplot as plt
import random
import numpy as np

## 真实数据源
def generateReal():
  realData = torch.FloatTensor(
      [random.uniform(0.8, 1.0),
       random.uniform(0.0, 0.2),
       random.uniform(0.8, 1.0),
       random.uniform(0.0, 0.2)]
  )
  return realData

generateReal()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## 构建鉴别器
class Discriminator(nn.Module):
  def __init__(self):
    super().__init__()
    self.model = nn.Sequential(
        nn.Linear(4, 3),
        nn.Sigmoid(),
        nn.Linear(3, 1),
        nn.Sigmoid()
    )
    self.loss_function = nn.MSELoss()
    self.optimiser = torch.optim.SGD(self.parameters(), lr=0.01)
    self.counter = 0
    self.progress = []
    pass

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

  def train(self, inputs, targets):
    outputs = self.forward(inputs)
    loss = self.loss_function(outputs, targets)
    self.counter += 1
    if (self.counter % 10 == 0):
      self.progress.append(loss.item())
      pass
    if (self.counter % 10000 == 0):
      print("counter = ", self.counter)
      pass
    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()
    pass
  
  def plotProgress(self):
    df = pd.DataFrame(self.progress, columns=['loss'])
    df.plot(ylim=(0, 1.0), figsize=(16, 8), alpha=0.1,
            marker='.', grid=True, yticks=(0, 0.25, 0.5))
    pass

def generateRandom(size):
  randomData = torch.rand(size)
  return randomData

D = Discriminator()

for i in range(10000):
  D.train(generateReal(), torch.FloatTensor([1.0]))
  D.train(generateRandom(4), torch.FloatTensor([0.0]))
  pass
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
## 构建生成器
class Generator(nn.Module):
  def __init__(self):
    super().__init__()
    self.model = nn.Sequential(
          nn.Linear(1, 3),
          nn.Sigmoid(),
          nn.Linear(3, 4),
          nn.Sigmoid()
      )
    self.optimiser = torch.optim.SGD(self.parameters(), lr=0.01)
    self.counter = 0
    self.progress = []
    pass

  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.counter += 1
    if (self.counter % 10 == 0):
      self.progress.append(loss.item())
      pass
    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()
    pass

G = Generator()
G.forward(torch.FloatTensor([0.5]))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
## 训练GAN网络
%%time
D = Discriminator()
G = Generator()
imageList = []
for i in range(10000):
  D.train(generateReal(), torch.FloatTensor([1.0]))
  D.train(G.forward(torch.FloatTensor([0.5])).detach(), torch.FloatTensor([0.0]))
  G.train(D, torch.FloatTensor([0.5]), torch.FloatTensor([1.0]))
  if (i % 1000 == 0):
    imageList.append(G.forward(torch.FloatTensor([0.5])).detach().numpy())
  pass