来自课程GAN生成对抗网络精讲 tensorflow2.0代码实战 全网最简洁易懂的GAN课程
的代码
tensorflow版本为2.0
升级版本看https://blog.csdn.net/qq_43620967/article/details/108835207
jupyter 文件
链接:https://pan.baidu.com/s/1PR4phiKAEoK4sAAmTWR18A
提取码:z9od
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import glob
import os
tf.__version__
Out[104]: ‘2.3.1’
输入
(train_images,train_labels),(_,_)=tf.keras.datasets.mnist.load_data()
train_images.shape
Out[106]: (60000, 28, 28)
60000张图,都是28*28 像素
train_images.dtype
Out[107]: dtype(‘uint8’)
数据预处理
train_images=train_images.reshape(train_images.shape[0],28,28,1).astype('float32')
train_images.shape
Out[109]: (60000, 28, 28, 1)
train_images=(train_images-127.5)/127.5#归一化 到【-1,1】
BATCH_SIZE=256
BUFFER_SIZE=600000
datasets=tf.data.Dataset.from_tensor_slices(train_images)
datasets=datasets.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
datasets
Out[114]: <BatchDataset shapes: (None, 28, 28, 1), types: tf.float32>
第一维度表示个数
生成器模型
def generator_model():
model=tf.keras.Sequential()
model.add(layers.Dense(256,input_shape=(100,),use_bias=False))
#Dense全连接层,input_shape=(100,)长度100的随机向量,use_bias=False,因为后面有BN层
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())#激活
#第二层
model.add(layers.Dense(512,use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())#激活
#输出层
model.add(layers.Dense(28*28*1,use_bias=False,activation='tanh'))
model.add(layers.BatchNormalization())
model.add(layers.Reshape((28,28,1)))#变成图片 要以元组形式传入
return model
辨别器模型
def discriminator_model():#输入图片
model=keras.Sequential()
model.add(layers.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))#输出数字,>0.5真实图片
return model
loss函数
cross_entropy=tf.keras.losses.BinaryCrossentropy(from_logits=True)#from_logits=True因为最后的输出没有激活
判别器损失函数
def discriminator_loss(real_out,fake_out):#辨别器的输出 真实图片判1,假的图片判0
real_loss=cross_entropy(tf.ones_like(real_out),real_out)
fake_loss=cross_entropy(tf.zeros_like(fake_out),fake_out)
return real_loss+fake_loss
生成器损失函数
def generator_loss(fake_out):#希望fakeimage的判别输出fake_out判别为真
return cross_entropy(tf.ones_like(fake_out),fake_out)
优化器
generator_opt=tf.keras.optimizers.Adam(1e-4)#学习速率
discriminator_opt=tf.keras.optimizers.Adam(1e-4)
EPOCHS=100
noise_dim=100 #长度为100的随机向量生成手写数据集
num_exp_to_generate=16 #每步生成16个样本
seed=tf.random.normal([num_exp_to_generate,noise_dim]) #生成随机向量观察变化情况
训练
generator=generator_model()
discriminator=discriminator_model()
定义批次训练函数
def train_step(images):
noise=tf.random.normal([BATCH_SIZE,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)
#训练过程
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))
可视化
def generator_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) #从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 dataset:
train_step(image_batch)
#print('.',end='')
print('第'+str(epoch+1)+'次训练结果')
generator_plot_image(generator,seed)
train(datasets,EPOCHS)
结果
第1次训练结果
第100次训练结果