如何训练生成器:
随着训练的进展,鉴别器的表现越来越好,生成器也必须不断进步,才能骗过更好的鉴别器。最终,生成器也变得非常出色,可以生成足以以假乱真的图像。
这种架构叫做生成对抗网络(Generative Adversarial Network, GAN)。它利用竞争来驱动进步,并且,我们不需要定义具体的规则来描述要编码到损失函数中的真实图像,相反,我们让GAN自己来学习什么是真正的图像。
def generate_real():
real_data = 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 real_data
generate_real()
class Discriminator(nn.Module):
def __init__(self):
# 初始化PyTorch父类
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)
# 每训练10次增加计数器
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 generate_random(size):
random_data = torch.rand(size)
return random_data
D = Discriminator()
for i in range(10000):
# 真实数据
D.train(generate_real(), torch.FloatTensor([1.0]))
# 随机数据
D.train(generate_random(4), torch.FloatTensor([0.0]))
pass
class Generator(nn.Module):
def __init__(self):
# 初始化PyTorch父类
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)
# 每训练10次增加计数器
self.counter += 1
if (self.counter % 10 == 0):
self.progress.append(loss.item())
pass
# 梯度归零,反向传播,并更新权重
self.optimiser.zero_grad()
loss.backward()
self.optimiser.step()
pass
# 创建鉴别器和生成器
D = Discriminator()
G = Generator()
# 训练鉴别器和生成器
for i in range(10000):
# 用真实样本训练鉴别器
D.train(generate_real(), torch.FloatTensor([1.0]))
# 用生成样本训练鉴别器
# 使用detach()以避免计算生成器G中的梯度
D.train(G.forward(torch.FloatTensor([0.5])).detach(), torch.FloatTensor([0.0]))
# 训练生成器
G.train(D, torch.FloatTensor([0.5]), torch.FloatTensor([1.0]))
pass
# 每训练1000次记录图像
if (i%1000 == 0):
image_list.append(G.forward(torch.FloatTensor([0.5])).detach().numpy())