【生成对抗网络】GAN入门与代码实现(二)

生成对抗网络系列
【生成对抗网络】GAN入门与代码实现(一)
【生成对抗网络】GAN入门与代码实现(二)
【生成对抗网络】基于DCGAN的二次元人物头像生成(TensorFlow2)
【生成对抗网络】ACGAN的代码实现

上篇博客:【生成对抗网络】GAN入门与代码实现(一)
本篇主要介绍简单GAN的另一种实现方法(不使用卷积),依然使用TensorFlow2进行搭建,主要运用了TensorFlow2中的求导机制进行自定义训练,自由度更高。对比上篇博客中的实现方法可加深对GAN的编写理解。

1 导包

import tensorflow as tf # 2.3版本
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
import os
import matplotlib.pyplot as plt
%matplotlib inline

2 数据准备

我们使用MNIST手写数据集作为训练生成的数据。

# 加载数据
(train_images,train_labels),(_,_) = tf.keras.datasets.mnist.load_data() # train_images的shape为(60000,28,28)
# 把数据改为float类型,然后归一化,目的是使数据落在0的周围,因为激活函数在0的周围能发挥好的作用
train_images = train_images.reshape(train_images.shape[0],28,28,1).astype('float32') # numpy方法,重塑shape为(60000,28,28,1)
train_images = (train_images - 127.5)/127.5 # 把0-255的数据范围变为-1到1之间

定义相关参数。

BATCH_SIZE = 300    # batch大小
BUFFER_SIZE = 60000 # 训练集有6w张图片

EPOCHS = 300    # 批次数量
noise_dim = 100 # 随机数的维度

将原数据创建为Dataset数据,便于训练。

datasets = tf.data.Dataset.from_tensor_slices(train_images)
# <TensorSliceDataset shapes: (28, 28, 1), types: tf.float32>
datasets = datasets.shuffle(BUFFER_SIZE).batch(BATCH_SIZE) # 在全部范围内做一个乱序,设置一个batch为256
# <BatchDataset shapes: (None, 28, 28, 1), types: tf.float32>
# 测试datasets:
for item in datasets:
    print(item.shape)
    print(type(item))
    break
# (300, 28, 28, 1) # batch为300 图片为28*28的单通道照片
# <class 'tensorflow.python.framework.ops.EagerTensor'>    
    

3 生成器模型

输入100维的随机向量,输出一张(28,28,1)维的图片。

def generator_model():
    
    generator = keras.models.Sequential([
        keras.layers.Input(shape=(100,)), # 输入为长度100点随机向量
        keras.layers.Dense(256),
        keras.layers.LeakyReLU(alpha = 0.2),
        keras.layers.BatchNormalization(momentum = 0.8),
        keras.layers.Dense(512),
        keras.layers.LeakyReLU(alpha = 0.2),
        keras.layers.BatchNormalization(momentum = 0.8),
        keras.layers.Dense(1024),
        keras.layers.LeakyReLU(alpha = 0.2),
        keras.layers.BatchNormalization(momentum = 0.8),
        keras.layers.Dense(np.prod((28,28,1)),activation='tanh'),
        keras.layers.Reshape((28,28,1)) #  将向量重塑shape为(28,28,1),输出图片
    ])
    
    return generator

4 判别器模型

输入图片,输出1维的判定结果(最后没有使用激活函数)。

def discriminator_model():

    discriminator = keras.models.Sequential([
        keras.layers.Flatten(), # 将输入的多维数据展平为一维
        keras.layers.Dense(512),
        keras.layers.LeakyReLU(alpha = 0.2),
        keras.layers.Dense(256),
        keras.layers.LeakyReLU(alpha = 0.2),
        keras.layers.Dense(1)
    ])
    
    return discriminator
    

5 编写损失函数,定义优化器

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) 
# 因为判别器最后没有使用激活 所以我们添加from_logits=True

判别器损失:

判别器的目标是让真实图片判别为1,生成的图片判别为0,因此损失函数中真实图片与1比较,生成图片与0比较,从而计算损失。

# 求判别器损失的函数
def discriminator_loss(real_out,fake_out):
    real_loss = cross_entropy(tf.ones_like(real_out),real_out) # 真实图片的输出与1比较
    fake_loss = cross_entropy(tf.zeros_like(fake_out),fake_out) # 生成图片的输出与0比较
    return real_loss + fake_loss

生成器损失:

生成器的目标是使得自己生成的图片在判别器中判别为1(真实),因此损失函数中需要与1对比。

# 求生成器损失的函数
def generator_loss(fake_out):
    fake_loss = cross_entropy(tf.ones_like(fake_out),fake_out)
    return fake_loss

定义优化器:

learning_rate:0.0002

beta_1:0.5

# 优化器
generator_opt = tf.keras.optimizers.Adam(2e-4,0.5)
discriminator_opt = tf.keras.optimizers.Adam(2e-4,0.5)

参数简介:

learning_rate:一个张量,浮点值,或者是一个tf.keras.optimizer .schedules时间表。LearningRateSchedule,或者一个不带参数并返回要使用的实际值的可调用对象,即学习速率。默认为0.001。

beta_1:一个浮点值或一个常量浮点张量,或者一个不带参数并返回实际值的可调用对象。一阶矩的指数衰减率估计。默认为0.9

6 获取模型&定义训练批次函数

generator = generator_model() # 获取生成器模型
discriminator = discriminator_model() # 获取判别器模型

定义训练函数,使用Tensorflow中的自动求导与根据梯度更新参数的方法来训练生成器与判别器。

@tf.function
# 接收一个批次的图片,对其进行训练
def train_step(images):
    noise = tf.random.normal([BATCH_SIZE,noise_dim]) # 生成BATCH_SIZE个长度为100的随机向量
    # images 是真实图片的输入
    # noise 是噪声输入
    
    with tf.GradientTape() as gen_tape,tf.GradientTape() as disc_tape:
        real_out = discriminator(images,training = True) # 输出真实图片在判别器中的判别结果
        gen_image = generator(noise,training = True)    # 用随机向量在生成器中生成图片
        fake_out = discriminator(gen_image,training = True) # 输出生成图片在判别器中的判别结果
        # 调用步骤5中的方法,计算损失
        gen_loss = generator_loss(fake_out) 
        disc_loss = discriminator_loss(real_out,fake_out)
    # 自动计算机损失函数关于自变量(模型参数)的梯度    
    gradient_gen = gen_tape.gradient(gen_loss,generator.trainable_variables)
    gradient_disc = disc_tape.gradient(disc_loss,discriminator.trainable_variables)
    # 根据梯度更新参数
    generator_opt.apply_gradients(zip(gradient_gen,generator.trainable_variables))
    discriminator_opt.apply_gradients(zip(gradient_disc,discriminator.trainable_variables))

7 定义可视化方法

为了在训练的过程中查看生成器输出图片的效果,我们定义6个100维度的随机数来检测训练过程中的生成器模型,使用matlibplot中的方法绘制图片。

num_example_to_generate = 6 # 用于绘图过程中生成图片的数量

seed = np.random.normal(0,1,(num_example_to_generate,noise_dim)) # 生成6个长度为100的随机向量
# 画图函数
def generate_plot_image(test_noise):

    pre_image = generator(test_noise,training = False) # 用生成器,生成手写图片
    # print(pre_image.shape) # (6,28,28,1)
    fig = plt.figure(figsize=(16,3)) # figsize:指定figure的宽和高,单位为英寸
    for i in range(pre_image.shape[0]):   # pre_image的shape的第一个维度就是个数,这里是6
        plt.subplot(1,6,i+1) # 几行几列的 第i+1个图片(从1开始)
        plt.imshow((pre_image[i,:,:,:] + 1)/2) # 加1除2: 将生成的-1~1的图片弄到0-1之间,
        plt.axis('off') # 不要坐标
    plt.show()

8 主训练方法

训练epochs次,每次epoch中从dataset依次取出batch个数据调用步骤6中的方法进行训练,每次epoch结束后调用步骤7中的方法绘制几张图片查看生成器的生成效果。

# 训练(主方法)
def train(dataset,epochs):
    for epoch in range(1,epochs+1): # 总过训练epochs次
        print("epoch:",epoch)
        for image_batch in dataset: # 从数据集中遍历所有batch
            train_step(image_batch)# 训练一个batch
            print(".",end="")
        generate_plot_image(seed) # 绘图,使用前面定义的随机数seed在生成器中生成图片并展示

9 开始训练

train(datasets,EPOCHS) 

10 训练结果

epoch 1:
在这里插入图片描述
epoch 10:
在这里插入图片描述
epoch 20:
在这里插入图片描述
epoch 50:
在这里插入图片描述
epoch 100:
在这里插入图片描述
epoch 290:
在这里插入图片描述

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
生成对抗网络GAN)是深度学习领域的一项重要技术,利用GAN可以有效地生成复杂的样本数据,例如图像、音频等。在本文中将介绍如何用pytorch搭建GAN,并对其进行详细的解释。 GAN网络由生成器和判别器两部分组成。生成器接受随机噪声作为输入,通过反向传递训练来生成逼真的样本,而判别器则负责对输入样本进行判断,判断其是否是真实样本。两部分交替训练,并不断优化生成器和判别器的参数,最终可以得到生成器生成逼真样本的能力。 搭建GAN需要先定义生成器和判别器的网络结构,其中生成器可以使用反卷积,而判别器可以使用卷积神经网络。此外,在搭建过程中还需要定义一些超参数,如学习率、训练轮数等。 在开始训练GAN之前,需要先准备好数据集,并对其进行预处理,例如归一化、降噪等。然后对生成器和判别器设置优化器,并开始训练。在训练过程中需要注意调整超参数以达到更好的效果。 最后,在训练结束后需要对GAN进行评估,可以通过计算生成样本与真实样本之间的差别来确定生成器的性能并对其进行改进。 总之,利用pytorch搭建入门GAN需要先定义网络结构和超参数,并使用适当的优化器进行训练,最终可以生成逼真的样本。同时,需要注意调整超参数以达到更好的效果,并对GAN进行评估和改进。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值