一起学算法(2):GAN

1、GAN概念

GAN(生成式对抗网络),无监督学习的一种,一般用于2分类,多适用于图片处理。

2、GAN结构(3句话)

在这里插入图片描述
(1)2个需训练的模型(生成模型和判别模型)
(2)第一个模型不断优化生成很像是真的假图片(随机噪声可看成是假图片)妄想骗过第二个模型。
(3)第二个模型不断优化把很像是真的假图片给判别为假。

3、GAN模型步骤

(1)用Kears生成2个模型(下面是一层的代码)

model = keras.Sequential()#Sequential 序贯模型是最简单的线性、从头到尾的结构顺序,不分叉,是多个网络层的线性堆叠
model.add(layers.Dense(256,input_shape=(100,),use_bias=False))#其中其使用input_shape=(100,),这个指的是输入一维的数据
model.add(layers.BatchNormalization())#BatchNormalization层:该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
model.add(layers.LeakyReLU())#非线性ReLU激活函数层

(2)计算两个模型的对数损失函数的交叉熵

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)  # 对数损失函数的实例化,当模型最后一层没有经过激活函数时 from_logits 设置为 True,否则为 False
real_loss = cross_entropy(tf.ones_like(real_out),real_out)#计算全真与real_out之间的交叉熵
fake_loss = cross_entropy(tf.ones_like(fake_out), fake_out)#计算全假与fake_out之间的交叉熵

(3)计算梯度

with tf.GradientTape() as gen_tape,tf.GradientTape() as disc_tape:#梯度定义
#计算梯度
gradien_gen=gen_tape.gradient(gen_loss,generator.trainable_variables)#计算生成器损失函数与生成器可训练参数的梯度
gradien_disc = disc_tape.gradient(disc_loss,discriminator.trainable_variables)

(4)训练模型

generator_opt = tf.keras.optimizers.Adam(1e-4)  # 生成优化器,学习率
discriminator_opt = tf.keras.optimizers.Adam(1e-4)
 #训练优化
generator_opt.apply_gradients(zip(gradien_gen,generator.trainable_variables))
discriminator_opt.apply_gradients(zip(gradien_disc,discriminator.trainable_variables))

4、GAN实现

import tensorflow as tf
from tensorflow import keras
from keras import layers
import matplotlib.pyplot as plt
import os

#3层生成器模型,直接采用全连接层,没有偏置
def generator_model():
    model = keras.Sequential()#Sequential 序贯模型是最简单的线性、从头到尾的结构顺序,不分叉,是多个网络层的线性堆叠
    model.add(layers.Dense(256,input_shape=(100,),use_bias=False))#其中其使用input_shape=(100,),这个指的是输入一维的数据
    model.add(layers.BatchNormalization())#BatchNormalization层:该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
    model.add(layers.LeakyReLU())#非线性ReLU激活函数层

    model.add(layers.Dense(512, use_bias=False))
    model.add(layers.BatchNormalization())  # BatchNormalization层:该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
    model.add(layers.LeakyReLU())

    model.add(layers.Dense(28*28*1, use_bias=False,activation='tanh'))#输出层
    model.add(layers.BatchNormalization())  # BatchNormalization层:该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
    #重组图片
    model.add(layers.Reshape((28,28,1)))

    return model

#3层辨别器模型,直接采用全连接层,没有偏置
def discriminator_model():
    model = keras.Sequential()
    model.add(layers.Flatten())#Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。

    model.add(layers.Dense(512, use_bias=False))
    model.add(layers.BatchNormalization())  # 标准化神经层的输出
    model.add(layers.LeakyReLU())

    model.add(layers.Dense(256, use_bias=False))
    model.add(layers.BatchNormalization())  # 标准化神经层的输出
    model.add(layers.LeakyReLU())

    model.add(layers.Dense(1))#输出层
    return model

#计算辨别器模型的交叉熵的损失
def discriminator_loss(real_out,fake_out):
    cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)  # 对数损失函数的实例化,当模型最后一层没有经过激活函数时 from_logits 设置为 True,否则为 False
    real_loss = cross_entropy(tf.ones_like(real_out),real_out)#计算全真与real_out之间的交叉熵
    fake_loss = cross_entropy(tf.ones_like(fake_out), fake_out)#计算全假与fake_out之间的交叉熵
    return real_loss + fake_loss

#根据假图片的输出来计算损失
def generator_loss(fake_out):
    cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)  # 当模型最后一层没有经过激活函数时 from_logits 设置为 True,否则为 False
    return cross_entropy(tf.ones_like(fake_out),fake_out)#计算全真与fake_out之间的交叉熵

#每一步的训练操作
def train_step(images):
    noise = tf.random.normal([num_exp_to_generate,noise_dim])

    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)

        gen_loss = generator_loss(fake_out)
        disc_loss = discriminator_loss(real_out,fake_out)
    #计算梯度
    gradien_gen = gen_tape.gradient(gen_loss,generator.trainable_variables)#计算生成器损失函数与生成器可训练参数的梯度
    gradien_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    #训练优化
    generator_opt.apply_gradients(zip(gradien_gen,generator.trainable_variables))
    discriminator_opt.apply_gradients(zip(gradien_disc,discriminator.trainable_variables))

def generate_plot_image(gen_model,test_noise):
    pre_images = gen_model(test_noise,training=False)
    fig = plt.figure(figsize=(4,4))#初始化画布
    for i in range(pre_images.shape[0]):
        plt.subplot(4,4,i+1)#i从0开始,但画图从1开始
        plt.imshow((pre_images[i,:,:,0]+1)/2,cmap='gray')
        plt.axis('off')#不显示坐标
    plt.show()

def train(dataset,epochs):
    for epoch in range(epochs):
        for image_batch in datasets:
            train_step(image_batch)
        generate_plot_image(generator, seed)

if __name__ == '__main__':
    #提示信息只保留warning和erro
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
    # 加载数据,第一个是训练样本,第二个是测试样本
    (train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
    # 转换图片数据类型,把UTF8转换为float,把3维升为4维(个数,长,宽,通道数)
    train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
    # 把0-255,转换范围到(-1)-1
    train_images = (train_images - 127.5) / 127.5

    BATCH_SIZE = 256#每一次训练的个数
    BUFFER_SIZE = 60000#总个数

    datasets = tf.data.Dataset.from_tensor_slices(train_images)
    datasets = datasets.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)#shuffle打乱,然后batch是每一次取多少个

    generator_opt = tf.keras.optimizers.Adam(1e-4)  # 生成优化器,学习率
    discriminator_opt = tf.keras.optimizers.Adam(1e-4)

    EPOCHS = 100#训练次数
    noise_dim = 100#
    num_exp_to_generate = 16

    seed = tf.random.normal([num_exp_to_generate, noise_dim])  # 从正态分布中输出随机值,16*100

    generator = generator_model()
    discriminator = discriminator_model()

    print("开始训练")
    train(datasets,EPOCHS)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

取不到名字的Z先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值