代码如下
# by plus_left
from tensorflow.keras import Sequential,Model
from tensorflow.keras.layers import Dense, Reshape, Input, Flatten
from tensorflow.keras.layers import LeakyReLU, BatchNormalization
from tensorflow.keras.datasets import mnist
from tensorflow.keras.optimizers import Adam
import numpy as np
import matplotlib.pyplot as plt
class GAN():
def __init__(self):
self.latent_dim = 100
self.img_rows = 28
self.img_cols = 28
self.channel = 1
self.img_shape = (self.img_rows, self.img_cols, self.channel)
self.discriminator = self.build_discriminator() # 构建
optimizer = Adam(0.0002, 0.5)
self.discriminator.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
self.generator = self.build_generator() # generator 就可以完成由noise到img的生成
self.discriminator.trainable = False
z = Input(shape=(self.latent_dim,))
img = self.generator(z)
validity = self.discriminator(img)
self.combined = Model(z, validity)
self.combined.compile(loss='binary_crossentropy',optimizer=optimizer) # 完成了叠加模型的构建
def build_generator(self):
model=Sequential()
# 添加一层全连接层
model.add(Dense(256, input_dim=self.latent_dim)) # 输入噪声是一维含有100个元素的向量
model.add(LeakyReLU(alpha=0.2)) # 激活函数
model.add(BatchNormalization(momentum=0.8)) # BN层
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(1024))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(np.prod(self.img_shape), activation='tanh')) # 神经元个数(输出)等于图像尺寸乘积
model.add(Reshape(self.img_shape)) # reshape成图片形状 28*28*1
model.summary() # 记录各层参数情况
noise = Input(shape=(self.latent_dim,))
img = model(noise)
return Model(noise, img) # 返回输入为噪声,输出为预测图的Model
def build_discriminator(self):
# 需要输入图片 然后判别出真假 img——>label
model = Sequential()
model.add(Flatten(input_shape=self.img_shape)) # 将图像拉成一维
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(256))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(1, activation='sigmoid')) # 输出结果落入0-1概率区间
model.summary() # 记录参数情况
img = Input(shape=self.img_shape)
validity = model(img) # 将输入图输入模型之后预测出的输出概率
return Model(img, validity) # 由图像生成可能性
def train(self, epochs, batch_size=128, sample_interval=50):
# 获取mnist手写数字数据集
(X_train, _), (_, _) = mnist.load_data()
# shape : 60000*28*28
# 将图像值转化成 -1 到 1
X_train = X_train / 127.5 -1.
X_train = np.expand_dims(X_train, axis=3) # 扩展成60000*28*28*1的维度
valid = np.ones((batch_size, 1)) # 完成对batch个图像进行1标签的操作
fake = np.zeros((batch_size, 1)) # 完成对虚假图片的0标签
for epoch in range(epochs):
# ————————————————
# 训练判别器
# ————————————————
# 选择batch_size个图像样本 (随机
idx = np.random.randint(0, X_train.shape[0], batch_size)
imgs = X_train[idx] # batch_size*28*28*1 真实样本
noise = np.random.normal(0, 1, (batch_size, self.latent_dim))
# 使用生成器将noise生成img
gen_imgs = self.generator.predict(noise) # 完成了噪声生成图像 也就是 虚假图像
d_loss_real = self.discriminator.train_on_batch(imgs, valid)
d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)
d_loss = 0.5 * np.add(d_loss_fake, d_loss_real)
# 完成了对D判别器的训练
# ————————————————
# 训练生成器
# ————————————————
noise = np.random.normal(0, 1, (batch_size, self.latent_dim))
# 这里的噪声维度 : batch_size*100
g_loss = self.combined.train_on_batch(noise, valid)
print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))
# 每200轮保存一个batch图像
if epoch % sample_interval == 0:
self.sample_images(epoch)
def sample_images(self, epoch):
r, c = 5, 5
noise = np.random.normal(0, 1, (r * c, self.latent_dim))
gen_imgs = self.generator.predict(noise)
# 25*28*28*1
# Rescale images 0 - 1
gen_imgs = 0.5 * gen_imgs + 0.5
fig, axs = plt.subplots(r, c)
cnt = 0
for i in range(r):
for j in range(c):
axs[i, j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
axs[i, j].axis('off')
cnt += 1
fig.savefig("images/%d.png" % epoch)
plt.close()
if __name__ == '__main__':
gan = GAN()
gan.train(epochs=30000, batch_size=32, sample_interval=200)
视频手把手教学
代码讲解视频在b站
可以同步去看学习此内容
b站关于此代码讲解视频链接