23.GAN--study

'''
Description: GAN--study
Autor: 365JHWZGo
Date: 2021-11-12 22:06:12
LastEditors: 365JHWZGo
LastEditTime: 2021-11-13 18:24:05
'''

# 导包
import torch
import matplotlib.pyplot as plt
from torch.autograd import Variable
import numpy as np

# 超参数设置
BATCH_SIZE = 64  # 每一批所处理的数据集
LR_G = 0.0001  # generator的学习效率
LR_D = 0.0001  # discriminator的学习效率
N_IDEAS = 5  # generator的学习灵感
ART_COMPONENTS = 15  # generator创作的点数
# 一次处理中所产生的点数,二维矩阵
PAINT_POINTS = np.vstack([np.linspace(-1, 1, ART_COMPONENTS)
                         for _ in range(BATCH_SIZE)])  # shape(64,15)


# 著名画家的画
def artist_works():
    #从[1,2)的正态分布中随机选取64个数字,并在第二维度新加一个维度
    a = np.random.uniform(1, 2, size=BATCH_SIZE)[:, np.newaxis]
    #生成这些点的纵坐标
    paintings = a*np.power(PAINT_POINTS, 2)+(a-1)  # shape(64,15)
    # 将其转变为tensor数据
    paintings = torch.from_numpy(paintings).float()
    return paintings


# Generator network
# generator将自己的灵感变成15个点
G = torch.nn.Sequential(
    torch.nn.Linear(N_IDEAS, 128),
    torch.nn.ReLU(),
    torch.nn.Linear(128, ART_COMPONENTS)
)

# Discriminator network
# 对画作进行鉴别,输出一个它判断该画作是否为著名画家画作的概率值,sigmoid()用于生成一个概率值
D = torch.nn.Sequential(
    torch.nn.Linear(ART_COMPONENTS, 128),
    torch.nn.ReLU(),
    torch.nn.Linear(128, 1),
    torch.nn.Sigmoid()
)

#当在class中才需要新建实例
opt_D = torch.optim.Adam(D.parameters(), lr=LR_D)
opt_G = torch.optim.Adam(G.parameters(), lr=LR_G)

plt.ion()

# training
if __name__ == '__main__':
    for step in range(10000):
        #著名画家的画作
        artist_paintings = artist_works()

        # 用于随机生成generator的灵感
        G_ideas = torch.randn(BATCH_SIZE, N_IDEAS,requires_grad=True)  # shape(64,5)

        #根据生成的灵感来作画
        G_paintings = G(G_ideas)

        # discriminator判断这些画作【G自己的灵感画作】来自著名画家的概率为多少
        prob_G = D(G_paintings)

        #这种概率要越低越好,因为它是永远是在模仿
        G_loss = torch.mean(torch.log(1.-prob_G))
       
        #优化
        opt_G.zero_grad()   #将模型中的梯度清零
        G_loss.backward()   #求目标函数的梯度
        opt_G.step()        #梯度下降,更新G的参数


        # discriminator判断这些画作【著名画家画作】来自著名画家的概率为多少,希望越高越好
        prob_a = D(artist_paintings)

        #G_paintings的梯度不会更新
        prob_G = D(G_paintings.detach())    #锁住G的参数不求导

        #我们是希望它越大越好,但是torch中只有减小误差才会提升
        D_loss = -torch.mean(torch.log(prob_a)+torch.log(1.-prob_G))
        opt_D.zero_grad()
        #retain_graph是为了再次使用计算图纸
        D_loss.backward(retain_graph=True)
        opt_D.step()

        if step % 150 == 0:
            print(step)
            plt.cla()
            plt.plot(PAINT_POINTS[0], G_paintings.data.numpy(
            )[0], c='r', lw=3, label='Generated painting')
            plt.plot(PAINT_POINTS[0], 2 * np.power(PAINT_POINTS[0],
                     2) + 1, c='#74BCFF', lw=3, label='upper bound')
            plt.plot(PAINT_POINTS[0], 1 * np.power(PAINT_POINTS[0],
                     2) + 0, c='#FF9359', lw=3, label='lower bound')
            plt.text(-.5, 2.3, 'D accuracy = %.2f(0.5 for D to converage)' %
                     prob_a.data.numpy().mean(), fontdict={'size': 15, 'color': 'blue'})
            plt.text(-.5, 2, 'D score = %.2f(-1.38 for G to converage)' % -
                     D_loss.data.numpy(), fontdict={'size': 15, 'color': 'blue'})
            plt.ylim((0, 3))
            plt.legend(loc='upper right', fontsize=10)
            plt.draw()
            plt.pause(0.01)
    plt.ioff()
    plt.savefig()
    plt.show()

GAN

generator:生成器G的优化目标是生成尽可能真实的数据来“骗过”判别器,使判别器给生成的数据高分。

discriminator:判别器D的优化目标是使判别器对数据集中采集的真实数据判为高分,而对合成数据判为低分。

在这个GAN例子中,需要注意的点有:

  • PAINT_POINTS = np.vstack([np.linspace(-1, 1, ART_COMPONENTS) for _ in range(BATCH_SIZE)])
    写到这儿,我原来也好奇为什么不直接写 PAINT_POINTS = [np.linspace(-1, 1, ART_COMPONENTS) for _ in range(BATCH_SIZE)],而是非要再加上一个**np.vsatck()**来进行过垂直合并?它俩看上去作用是一样的呀。
    后来我又进行测试
print([np.linspace(-1, 1, 4)for _ in range(3)])
print(np.vstack([np.linspace(-1, 1, 4)for _ in range(3)]))

在这里插入图片描述
到这里,应该可以看出差别了,如果直接用[]list生成的话,它俩是不兼容的,因为用np.linspace()生成的是numpy数据,而使用np.vstack()之后,它俩就都变成numpy可以进行运算了。

  • 另一个比较迷惑的点是:下面两个loss究竟代表什么
D_loss = -torch.mean(torch.log(prob_a)+torch.log(1.-prob_G))

在gan中我们希望torch.mean(torch.log(prob_a)+torch.log(1.-prob_G))是越大越好,而神经网络中差值越小才有利于神经网络的提升,所以要加一个负号。

G_loss = torch.mean(torch.log(1.-prob_G))

在gan中要G_loss越小越好,所以用1.-prob_G
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

365JHWZGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值