gan实战(基础GAN、DCGAN)

一、基础Gan

1.1 参数

(1)输入:会被放缩到64*64
(2)输出:64*64
(3)数据集:https://pan.baidu.com/s/1RY1e9suUlk5FLYF5z7DfAw 提取码:8n89

1.2 实现

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import torchvision
from torchvision import transforms
import time
from torch.utils import data
from PIL import Image
import glob

# 生成器生成的数据在 [-1, 1]
transform = transforms.Compose([
#     transforms.Grayscale(num_output_channels=1),
    transforms.Resize(64),
    transforms.ToTensor(),  # 会做0-1归一化,也会channels, height, width
    transforms.Normalize((0.5,), (0.5,))
])

class FaceDataset(data.Dataset):
    def __init__(self, images_path):
        self.images_path = images_path

    def __getitem__(self, index):
        image_path = self.images_path[index]
        pil_img = Image.open(image_path)
        pil_img = transform(pil_img)
        return pil_img

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

images_path = glob.glob('./data/yellow/*.png')
BATCH_SIZE = 16
dataset = FaceDataset(images_path)
dataLoader = data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)

# 生成器网络定义
# 输入是长度为100的噪声(正态分布随机数)
# 输出为(1, 28, 28)的图片
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(100, 256),
            nn.ReLU(),
            nn.Linear(256, 512),
            nn.ReLU(),
            nn.Linear(512, 64*64*3),
            nn.Tanh()
        )

    def forward(self, x):
        img = self.main(x)
        img = img.view(-1, 3, 64, 64)
        return img

# 判别器网络定义
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(64*64*3, 512),
            nn.LeakyReLU(),
            nn.Linear(512, 256),
            nn.LeakyReLU(),
            nn.Linear(256, 1),
            nn.Sigmoid()
        )

    def forward(self, x):
        x = x.view(-1, 64*64*3)
        x = self.main(x)
        return x


device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
print(device)
gen = Generator().to(device)
dis = Discriminator().to(device)
d_optimizer = torch.optim.Adam(dis.parameters(), lr=0.00001)
g_optimizer = torch.optim.Adam(gen.parameters(), lr=0.0001)

# 损失函数
loss_fn = torch.nn.BCELoss()

# 绘图函数
def gen_img_plot(model, test_input):
    prediction = np.squeeze(model(test_input).permute(0, 2, 3, 1).detach().cpu().numpy())
    fig = plt.figure(figsize=(20, 160))
    for i in range(8):
        plt.subplot(1, 8, i+1)
        plt.imshow((prediction[i] + 1)/2)
        plt.axis('off')
    plt.show()

# step绘图函数
def gen_img_plot_step(img_data, step):
    predictions = img_data.permute(0, 2, 3, 1).detach().cpu().numpy()
    print("step:", step)
    fig = plt.figure(figsize=(3, 3))
    for i in range(1):
        plt.imshow((predictions[i]+1)/2)
    plt.show()


test_input = torch.randn(8, 100, device=device)


# GAN训练
D_loss = []
G_loss = []


# 训练循环
for epoch in range(500):
    time_start = time.time()
    d_epoch_loss = 0
    g_epoch_loss = 0
    count = len(dataLoader)  # 返回批次数
    for step, img in enumerate(dataLoader):
        img = img.to(device)
        size = img.size(0)
        random_noise = torch.randn(size, 100, device=device)

        # 固定生成器,训练判别器
        d_optimizer.zero_grad()
        real_output = dis(img)  # 对判别器输入真实图片, real_output是对真实图片的判断结果
        d_real_loss = loss_fn(real_output, torch.ones_like(real_output))  # 判别器在真实图像上的损失
        d_real_loss.backward()

        gen_img = gen(random_noise)
#         gen_img_plot_step(gen_img, step)
        
        fake_output = dis(gen_img.detach())  # 判别器输入生成的图片,fake_output对生成图片的预测
        d_fake_loss = loss_fn(fake_output, torch.zeros_like(fake_output))  # 判别器在生成图像上的损失
        d_fake_loss.backward()
        d_loss = d_real_loss + d_fake_loss
        d_optimizer.step()

        # 生成器的损失与优化
        g_optimizer.zero_grad()
        fake_output = dis(gen_img)
        g_loss = loss_fn(fake_output, torch.ones_like(fake_output))  # 生成器的损失
        g_loss.backward()
        g_optimizer.step()

        with torch.no_grad():
            d_epoch_loss += d_loss
            g_epoch_loss += g_loss
    

    with torch.no_grad():
        d_epoch_loss /= count
        g_epoch_loss /= count
        D_loss.append(d_epoch_loss)
        G_loss.append(g_epoch_loss)
        print("Epoch:", epoch)
        gen_img_plot(gen, test_input)
    time_end = time.time()
    print("epoch{}花费时间为:{}, d_loss:{}, g_loss:{}".format(epoch, time_end - time_start, d_loss, g_loss))

1.3 实验效果

Epoch: 0
在这里插入图片描述
Epoch: 20
在这里插入图片描述

Epoch: 40
在这里插入图片描述

Epoch: 60
在这里插入图片描述

Epoch: 80
在这里插入图片描述

Epoch: 100
在这里插入图片描述

Epoch: 120
在这里插入图片描述

Epoch: 140
在这里插入图片描述

Epoch: 150
在这里插入图片描述

二、DCGAN

2.1 参数

(1)输入:会被放缩到64*64
(2)输出:64*64
(3)数据集:数据集:https://pan.baidu.com/s/1RY1e9suUlk5FLYF5z7DfAw 提取码:8n89

2.2 实现

import glob
import torch
from PIL import Image
from torch import nn
from torch.utils import data
from torchvision import transforms
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np
from torch.utils.tensorboard import SummaryWriter
import os

log_dir = "./model/dcgan.pth"
images_path = glob.glob('./data/xinggan_face/*.jpg')

BATCH_SIZE = 32
dataset = FaceDataset(images_path)
data_loader = data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)
image_batch = next(iter(data_loader))

transform = transforms.Compose([
    transforms.Resize(64),
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])


class FaceDataset(data.Dataset):
    def __init__(self, images_path):
        self.images_path = images_path

    def __getitem__(self, index):
        image_path = self.images_path[index]
        pil_img = Image.open(image_path)
        pil_img = transform(pil_img)
        return pil_img

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


# 定义生成器
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.linear1 = nn.Linear(100, 256*16*16)
        self.bn1 = nn.BatchNorm1d(256*16*16)
        self.deconv1 = nn.ConvTranspose2d(256, 128, kernel_size=3, padding=1)  # 输出:128*16*16
        self.bn2 = nn.BatchNorm2d(128)
        self.deconv2 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1)  # 输出:64*32*32
        self.bn3 = nn.BatchNorm2d(64)
        self.deconv3 = nn.ConvTranspose2d(64, 3, kernel_size=4, stride=2, padding=1)  # 输出:3*64*64

    def forward(self, x):
        x = F.relu(self.linear1(x))
        x = self.bn1(x)
        x = x.view(-1, 256, 16, 16)
        x = F.relu(self.deconv1(x))
        x = self.bn2(x)
        x = F.relu(self.deconv2(x))
        x = self.bn3(x)
        x = F.tanh(self.deconv3(x))
        return x


# 定义判别器
class Discrimination(nn.Module):
    def __init__(self):
        super(Discrimination, self).__init__()

        self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=2)  # 64*31*31
        self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=2)  # 128*15*15
        self.bn1 = nn.BatchNorm2d(128)
        self.fc = nn.Linear(128*15*15, 1)

    def forward(self, x):
        x = F.dropout(F.leaky_relu(self.conv1(x)), p=0.3)
        x = F.dropout(F.leaky_relu(self.conv2(x)), p=0.3)
        x = self.bn1(x)
        x = x.view(-1, 128*15*15)
        x = torch.sigmoid(self.fc(x))
        return x


# 定义可视化函数
def generate_and_save_images(model, epoch, test_noise_):
    predictions = model(test_noise_).permute(0, 2, 3, 1).cpu().numpy()
    fig = plt.figure(figsize=(20, 160))
    for i in range(predictions.shape[0]):
        plt.subplot(1, 8, i+1)
        plt.imshow((predictions[i]+1)/2)
        # plt.axis('off')
    plt.show()


# 训练函数
def train(gen, dis, loss_fn, gen_opti, dis_opti, start_epoch):
    print("开始训练")
    test_noise = torch.randn(8, 100, device=device)
    writer = SummaryWriter(r'D:\Project\PythonProject\Ttest\run')
    writer.add_graph(gen, test_noise)

    #############################
    D_loss = []
    G_loss = []

    # 开始训练
    for epoch in range(start_epoch, 500):
        D_epoch_loss = 0
        G_epoch_loss = 0
        batch_count = len(data_loader)   # 返回批次数
        for step, img, in enumerate(data_loader):
            img = img.to(device)
            size = img.shape[0]
            random_noise = torch.randn(size, 100, device=device)  # 生成随机输入

            # 固定生成器,训练判别器
            dis_opti.zero_grad()
            real_output = dis(img)
            d_real_loss = loss_fn(real_output, torch.ones_like(real_output, device=device))
            d_real_loss.backward()
            generated_img = gen(random_noise)
            # print(generated_img)
            fake_output = dis(generated_img.detach())
            d_fake_loss = loss_fn(fake_output, torch.zeros_like(fake_output, device=device))
            d_fake_loss.backward()

            dis_loss = d_real_loss + d_fake_loss
            dis_opti.step()

            # 固定判别器,训练生成器
            gen_opti.zero_grad()
            fake_output = dis(generated_img)
            gen_loss = loss_fn(fake_output, torch.ones_like(fake_output, device=device))
            gen_loss.backward()
            gen_opti.step()

            with torch.no_grad():
                D_epoch_loss += dis_loss.item()
                G_epoch_loss += gen_loss.item()

        writer.add_scalar("loss/dis_loss", D_epoch_loss / (epoch+1), epoch+1)
        writer.add_scalar("loss/gen_loss", G_epoch_loss / (epoch+1), epoch+1)


        with torch.no_grad():
            D_epoch_loss /= batch_count
            G_epoch_loss /= batch_count
            D_loss.append(D_epoch_loss)
            G_loss.append(G_epoch_loss)

            print("Epoch:{}, 判别器损失:{}, 生成器损失:{}.".format(epoch, dis_loss, gen_loss))
            generate_and_save_images(gen, epoch, test_noise)
        
        state = {
            "gen": gen.state_dict(),
            "dis": dis.state_dict(),
            "gen_opti": gen_opti.state_dict(),
            "dis_opti": dis_opti.state_dict(),
            "epoch": epoch
        }
        torch.save(state, log_dir)

    plt.plot(range(1, len(D_loss)+1), D_loss, label="D_loss")
    plt.plot(range(1, len(D_loss)+1), G_loss, label="G_loss")
    plt.xlabel('epoch')
    plt.legend()
    plt.show()
    

if __name__ == '__main__':
    device = "cuda:0" if torch.cuda.is_available() else "cpu"
    gen = Generator().to(device)
    dis = Discrimination().to(device)
    loss_fn = torch.nn.BCELoss()
    gen_opti = torch.optim.Adam(gen.parameters(), lr=0.0001)
    dis_opti = torch.optim.Adam(dis.parameters(), lr=0.00001)
    start_epoch = 0
    if os.path.exists(log_dir):
        checkpoint = torch.load(log_dir)
        gen.load_state_dict(checkpoint["gen"])
        dis.load_state_dict(checkpoint["dis"])
        gen_opti.load_state_dict(checkpoint["gen_opti"])
        dis_opti.load_state_dict(checkpoint["dis_opti"])
        start_epoch = checkpoint["epoch"]
        print("模型加载成功,epoch从{}开始训练".format(start_epoch))
    train(gen, dis, loss_fn, gen_opti, dis_opti, start_epoch)

2.3 实验效果

开始训练
Epoch:0, 判别器损失:1.6549043655395508, 生成器损失:0.7864767909049988.
在这里插入图片描述
Epoch:20, 判别器损失:1.3690211772918701, 生成器损失:0.6662370562553406.
在这里插入图片描述
Epoch:40, 判别器损失:1.413375735282898, 生成器损失:0.7497923970222473.
在这里插入图片描述
Epoch:60, 判别器损失:1.2889504432678223, 生成器损失:0.8668195009231567.
在这里插入图片描述
Epoch:80, 判别器损失:1.2824485301971436, 生成器损失:0.805076003074646.
在这里插入图片描述
Epoch:100, 判别器损失:1.3278448581695557, 生成器损失:0.7859240770339966.
在这里插入图片描述
Epoch:120, 判别器损失:1.39650297164917, 生成器损失:0.7616179585456848.
在这里插入图片描述
Epoch:140, 判别器损失:1.3387322425842285, 生成器损失:0.811163067817688.
在这里插入图片描述
Epoch:160, 判别器损失:1.1281094551086426, 生成器损失:0.7557946443557739.

在这里插入图片描述
Epoch:180, 判别器损失:1.369300365447998, 生成器损失:0.5207887887954712.

在这里插入图片描述

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于TensorFlow的一维序列数据集的GAN代码示例: ```python import tensorflow as tf import numpy as np # 设置参数 num_steps = 10000 batch_size = 128 lr_generator = 0.002 lr_discriminator = 0.002 input_dim = 1 hidden_dim = 32 display_step = 1000 # 定义生成器 def generator(x, reuse=False): with tf.variable_scope('Generator', reuse=reuse): h1 = tf.layers.dense(x, hidden_dim, activation=tf.nn.relu) h2 = tf.layers.dense(h1, hidden_dim, activation=tf.nn.relu) out = tf.layers.dense(h2, input_dim) return out # 定义判别器 def discriminator(x, reuse=False): with tf.variable_scope('Discriminator', reuse=reuse): h1 = tf.layers.dense(x, hidden_dim, activation=tf.nn.relu) h2 = tf.layers.dense(h1, hidden_dim, activation=tf.nn.relu) out = tf.layers.dense(h2, 1) return out # 定义输入占位符 X = tf.placeholder(tf.float32, shape=[None, input_dim]) # 定义生成器和判别器的损失函数 gen_sample = generator(X) disc_real = discriminator(X) disc_fake = discriminator(gen_sample, reuse=True) gen_loss = -tf.reduce_mean(tf.log(disc_fake)) disc_loss = -tf.reduce_mean(tf.log(disc_real) + tf.log(1. - disc_fake)) # 分别定义生成器和判别器的优化器 gen_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="Generator") disc_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="Discriminator") gen_opt = tf.train.AdamOptimizer(lr_generator).minimize(gen_loss, var_list=gen_vars) disc_opt = tf.train.AdamOptimizer(lr_discriminator).minimize(disc_loss, var_list=disc_vars) # 定义会话并初始化变量 sess = tf.Session() sess.run(tf.global_variables_initializer()) # 训练GAN模型 for i in range(num_steps): # 获取数据并进行训练 x = np.random.normal(0, 1, size=[batch_size, input_dim]) _, dl = sess.run([disc_opt, disc_loss], feed_dict={X: x}) _, gl = sess.run([gen_opt, gen_loss], feed_dict={X: x}) # 显示损失 if i % display_step == 0: print('Step %d: Generator Loss: %f, Discriminator Loss: %f' % (i, gl, dl)) sess.close() ``` 在该代码中,我们使用了一个简单的一维正态分布作为数据集。生成器定义了一个两个隐藏层的全连接神经网络,判别器也定义了一个两个隐藏层的全连接神经网络。损失函数使用了GAN中常用的交叉熵损失函数,并使用Adam优化器进行优化。在训练过程中,我们通过随机生成一些正态分布的数据批次进行训练。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值