前言
现在这里留个坑,记录自己学习LAPGAN的经过,首先附上论文.pdf,源代码
(touch)LAPGAN.py
虽然论文源代码不是tensorflow的 但是其网络结构的设计是互通的。
代码
这次的经验是失败的,把失败的结构发出来当个反面教材,原因是没有按照论文的方法做,噪声的生成采用的是个十层的随机噪声,并且判别器没有采用W距离判别器,因此生成的图片完全不成样子,所以想要生成高质量的图片采用WGAN的方法也是必须的
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, losses
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.python.keras import backend as K
from tensorflow.keras.utils import plot_model
from IPython.display import Image
import cv2
import PIL
import json, os
import sys
import labelme
import labelme.utils as utils
import glob
import itertools
class GAN():
def __init__(self, # 定义全局变量
):
self.img_shape = (32, 32, 3)
self.save_path = r'C:\Users\Administrator\Desktop\photo'
self.img_path = r'C:\Users\Administrator\Desktop\photo'
self.batch_size = 100
self.test_size = 200
self.sample_interval = 1
self.epoch = 200
self.num_classes = 10
self.train_mode=0#0为从头训练 1为继续训练 不推荐继续训练 用本文的代码训练容易直接崩溃
# 建立GAN模型的方法
self.bulid()
def bulid_generator(self,divisor,mode): # 生成器
inputs =keras.Input(shape=(int(self.img_shape[0] / divisor), int(self.img_shape[1] / divisor), self.num_classes))
if mode == 0:
x = layers.Flatten()(inputs)
x = layers.Dense(1200)(x)
x = layers.Activation(activation='relu')(x)
x = layers.Dense(1200)(x)
x = layers.Activation(activation='relu')(x)
x = layers.Dense(int(np.prod(self.img_shape)/(divisor**2)))(x)
x = layers.Reshape([int(self.img_shape[0] / divisor), int(self.img_shape[1] / divisor), self.img_shape[2]])(x)
else:
x = layers.Conv2DTranspose(128, (2,2), strides=1, padding='same', activation=None)(inputs)
x = layers.BatchNormalization()(x)
x = layers.Activation(activation='relu')(x)
x = layers.Conv2DTranspose(128, (2, 2), strides=1, padding='same', activation=None)(x)
x = layers.BatchNormalization()(x)
x = layers.Activation(activation='relu')(x)
x = layers.Conv2DTranspose(self.img_shape[2], (2, 2), strides=1, padding='same', activation=None)(x)
m = layers.MaxPooling2D((2,2))(x)
m = layers.UpSampling2D((2,2))(m)
x = layers.subtract([x,m])
outputs = layers.Activation(activation='sigmoid')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
return model
def build_discriminator(self,divisor,kenel_size,mode):
inputs =keras.Input(shape=(int(self.img_shape[0] / divisor), int(self.img_shape[1] / divisor), self.img_shape[2]))
if mode == 0:
x = layers.Flatten()(inputs)
x = layers.Dense(600)(x)
x = layers.LeakyReLU(alpha=0.2)(x)
x = layers.Dense(600)(x)
x = layers.Dropout(0.5)(x)
x = layers.LeakyReLU(alpha=0.2)(x)
else :
x = layers.Conv2D(128, kenel_size, padding='same')(inputs)
x = layers.BatchNormalization()(x)
x = layers.LeakyReLU(alpha=0.2)(x)
x = layers.Conv2D(128, kenel_size, padding='same')(x)
x = layers.BatchNormalization()(x)
x = layers.LeakyReLU(alpha=0.2)(x)
x = layers.Flatten()(x)
print(x)
x = layers.Dropout(0.5)(x)
x = layers.Dense(self.num_classes+1)(x)
outputs = layers.Activation(activation='softmax')(x)
model = keras.Model(inputs=inputs,outputs=outputs)
return model
def bulid_encoder(self): # 网络 o为真 1位假
# i0,i1,i2,i3=inputs #0到3 分别是顶到底
inputs = keras.Input(shape=(int(self.img_shape[0] ), int(self.img_shape[1]), self.img_shape[2]))
i3 = layers.MaxPooling2D(2, 2)(inputs)
o3= layers.UpSampling2D((2, 2))(i3)
h3= layers.subtract([inputs, o3])
i2= layers.MaxPooling2D(2, 2)(i3)
o2 =layers.UpSampling2D((2, 2))(i2)
h2 = layers.subtract([i3, o2])
x = layers.MaxPooling2D(2, 2)(i2)
o1= layers.UpSampling2D((2, 2))(x)
h1 = layers.subtract([i2, o1])
model = keras.Model(inputs=inputs,outputs=[x,h1,h2,h3])
return model #输出作为差值的图 和标签的残差图
def build_decorder(self):
input0 = keras.Input((int(self.img_shape[0] / 8), int(self.img_shape[1] / 8), self.img_shape[2]))
input1 = keras.Input((int(self.img_shape[0] / 4), int(self.img_shape[1] / 4), self.img_shape[2]))
input2 = keras.Input((int(self.img_shape[0] / 2), int(self.img_shape[1] / 2), self.img_shape[2]))
input3 = keras.Input((int(self.img_shape[0] / 1), int(self.img_shape[1] / 1), self.img_shape[2]))
x = layers.UpSampling2D((2,2))(input0)
x = layers.add([x,input1])
x = layers.UpSampling2D((2,2))(x)
x = layers.add([x, input2])
x = layers.UpSampling2D((2, 2))(x)
outputs = layers.add([x, input3])
model = keras.Model(inputs=[input0,input1,input2,input3],outputs=outputs)
return model
def bulid(self): # 建立GAN模型
self.generator_model0 = self.bulid_generator(divisor=8,mode=0) #生成底层噪声
self.generator_model1 = self.bulid_generator(divisor=4,mode=1)
self.generator_model2 = self.bulid_generator(divisor=2,mode=1)
self.generator_model3 = self.bulid_generator(divisor=1,mode=1) #生成顶层噪声
self.encoder = self.bulid_encoder()
self.decoder = self.build_decorder()
#-------------------------------------------------------------------------------
input0 = keras.Input((int(self.img_shape[0] / 8), int(self.img_shape[1] / 8), self.num_classes))
input1 = keras.Input((int(self.img_shape[0] / 4), int(self.img_shape[1] / 4), self.num_classes))
input2 = keras.Input((int(self.img_shape[0] / 2), int(self.img_shape[1] / 2), self.num_classes))
input3 = keras.Input((int(self.img_shape[0] / 1), int(self.img_shape[1] / 1), self.num_classes))
self.discriminator_model0 = self.build_discriminator(divisor=8, kenel_size=(2, 2),mode=0)
self.discriminator_model1 = self.build_discriminator(divisor=4, kenel_size=(3, 3),mode=1)
self.discriminator_model2 = self.build_discriminator(divisor=2, kenel_size=(3, 3),mode=2)
self.discriminator_model3 = self.build_discriminator(divisor=1, kenel_size=(3, 3),mode=3)
#-------------------------------------------------------------------------------
gan_img0 = self.generator_model0(input0)
gan_img1 = self.generator_model1(input1)
gan_img2 = self.generator_model2(input2)
gan_img3 = self.generator_model3(input3)
output0 = self.discriminator_model0(gan_img0)
output1 = self.discriminator_model1(gan_img1)
output2 = self.discriminator_model2(gan_img2)
output3 = self.discriminator_model3(gan_img3)
self.model0 = keras.Model(inputs=input0, outputs=output0)
self.model1 = keras.Model(inputs=input1, outputs=output1)
self.model2 = keras.Model(inputs=input2, outputs=output2)
self.model3 = keras.Model(inputs=input3, outputs=output3)
def model_compile(self):
self.discriminator_model0.compile(loss='categorical_crossentropy',optimizer=keras.optimizers.Adam(0.0001, 0.00001),metrics=['categorical_accuracy'])
self.discriminator_model0.trainable = False # 使判别器不训练
self.model0.compile(optimizer=keras.optimizers.Adam(0.0001, 0.00001), loss='categorical_crossentropy', )
self.discriminator_model1.compile(loss='categorical_crossentropy',optimizer=keras.optimizers.Adam(0.0001, 0.00001),metrics=['categorical_accuracy'])
self.discriminator_model1.trainable = False # 使判别器不训练
self.model1.compile(optimizer=keras.optimizers.Adam(0.0001, 0.00001), loss='categorical_crossentropy', )
self.discriminator_model2.compile(loss='categorical_crossentropy',optimizer=keras.optimizers.Adam(0.0001, 0.00001),metrics=['categorical_accuracy'])
self.discriminator_model2.trainable = False # 使判别器不训练
self.model2.compile(optimizer=keras.optimizers.Adam(0.0001, 0.00001), loss='categorical_crossentropy', )
self.discriminator_model3.compile(loss='categorical_crossentropy',optimizer=keras.optimizers.Adam(0.0001, 0.00001),metrics=['categorical_accuracy'])
self.discriminator_model3.trainable = False # 使判别器不训练
self.model3.compile(optimizer=keras.optimizers.Adam(0.0001, 0.00001), loss='categorical_crossentropy', )
self.model0.summary()
self.model1.summary()
self.model2.summary()
self.model3.summary()
def load_data(self):
(train_images, train_labels), (test_images, test_labels) = keras.datasets.cifar10.load_data()
train_images,test_images = (train_images /255),(test_images/255)
if (self.img_shape[2]==1):
train_images = np.expand_dims(train_images, axis=-1)
test_images = np.expand_dims(test_images, axis=-1)
train_idx = np.arange(0,train_images.shape[0],1)
print('img train number:', train_images.shape)
print('img test number: ', test_images.shape)
return train_images,train_labels,train_idx,test_images,test_labels
def noise_generate(self,batch_size,divisor,labels):#噪声生成器
noise = np.random.normal(0, 1, (batch_size, int(self.img_shape[0]/divisor), int(self.img_shape[1]/divisor), self.num_classes)) # 生成标准的高斯分布噪声
n_labels = keras.utils.to_categorical(labels, num_classes=self.num_classes)
n_labels = n_labels.reshape(batch_size, 1, 1, self.num_classes)
noise = noise * n_labels#相乘后只有特定标签对应的层存在噪声
return noise
def train(self):
self.model_compile()
train_images,train_labels,train_idx,test_images,test_labels = self.load_data() # 读取数据
fake = np.ones((self.batch_size))*(self.num_classes)#判别为假 对应12
fake = keras.utils.to_categorical(fake,num_classes=self.num_classes+1)
step = int(train_images.shape[0] / self.batch_size) # 计算步长
print('step:', step)
for epoch in range(self.epoch):
train_idx = (tf.random.shuffle(train_idx)).numpy() # 每个epoch打乱一次
print('val_acc', self.pred(mode=1, test_images=test_images, test_labels=test_labels))
if epoch % self.sample_interval == 0:#保存图片
self.generate_sample_images(epoch)
for i in range(step):
idx = train_idx[i * self.batch_size:i * self.batch_size + self.batch_size] # 生成索引
imgs = train_images[idx] # 读取索引对应的图片
labels = train_labels[idx]
#---------------------------------------------------------------生成标准的高斯分布噪声
noise0 = self.noise_generate(self.batch_size, divisor=8, labels=labels)
noise1 = self.noise_generate(self.batch_size, divisor=4, labels=labels)
noise2 = self.noise_generate(self.batch_size, divisor=2, labels=labels)
noise3 = self.noise_generate(self.batch_size, divisor=1, labels=labels)
gan_img0 = self.generator_model0.predict(noise0) # 通过噪声生成图片
gan_img1 = self.generator_model1.predict(noise1)
gan_img2 = self.generator_model2.predict(noise2)
gan_img3 = self.generator_model3.predict(noise3)
img0,img1,img2,img3 = self.encoder(imgs)
# ---------------------------------------------------------------
labels=keras.utils.to_categorical(labels,num_classes=self.num_classes+1)#生成标签
total_img0 = tf.concat((gan_img0, img0), axis=0)
total_img1 = tf.concat((gan_img1, img1), axis=0)
total_img2 = tf.concat((gan_img2, img2), axis=0)
total_img3 = tf.concat((gan_img3, img3), axis=0)
total_labels=tf.concat((fake,labels),axis=0)
# ----------------------------------------------训练判别器
discriminator0_loss = self.discriminator_model0.train_on_batch(total_img0, total_labels)
discriminator1_loss = self.discriminator_model1.train_on_batch(total_img1, total_labels)
discriminator2_loss = self.discriminator_model2.train_on_batch(total_img2, total_labels)
discriminator3_loss = self.discriminator_model3.train_on_batch(total_img3, total_labels)
# ----------------------------------------------- 训练生成器
generator0_loss = self.model0.train_on_batch(noise0, labels)
generator1_loss = self.model1.train_on_batch(noise1, labels)
generator2_loss = self.model2.train_on_batch(noise2, labels)
generator3_loss = self.model3.train_on_batch(noise3, labels)
print("epoch:%d step:%d [discriminator_loss 0~3: %f,%f,%f,%f, acc 0~3: %.2f%%, %.2f%%, %.2f%%, %.2f%%] [generator_loss 0~3: %f,%f,%f,%f]" % (
epoch, i, discriminator0_loss[0],discriminator1_loss[0],discriminator2_loss[0],discriminator3_loss[0],
100 * discriminator0_loss[1], 100 * discriminator1_loss[1],100 * discriminator2_loss[1],100 * discriminator3_loss[1],
generator0_loss,generator1_loss,generator2_loss,generator3_loss))
self.model0.save(self.save_path+'/LAPGAN0.h5') # 每个epoch存储模型
self.model1.save(self.save_path+'/LAPGAN1.h5')
self.model2.save(self.save_path+'/LAPGAN2.h5')
self.model3.save(self.save_path+'/LAPGAN3.h5')
print('save model')
def generate_sample_images(self, epoch):
row, col = 5, 5 # 行列的数字
labels = np.random.randint(0,self.num_classes,(row * col))
noise0 = self.noise_generate(row * col, divisor=8, labels=labels) # 生成噪声
noise1 = self.noise_generate(row * col, divisor=4, labels=labels)
noise2 = self.noise_generate(row * col, divisor=2, labels=labels)
noise3 = self.noise_generate(row * col, divisor=1, labels=labels)
gan_img0 = self.generator_model0.predict(noise0)
gan_img1 = self.generator_model1.predict(noise1)
gan_img2 = self.generator_model2.predict(noise2)
gan_img3 = self.generator_model3.predict(noise3)
gan_imgs = self.decoder([gan_img0,gan_img1,gan_img2,gan_img3])
print(gan_imgs.shape)
fig, axs = plt.subplots(row, col) # 生成画板
idx = 0
for i in range(row):
for j in range(col):
axs[i, j].imshow(gan_imgs[idx, :, :]) #cmap='gray')
axs[i, j].axis('off')
idx += 1
fig.savefig(self.img_path + "/%d.png" % epoch)
plt.close() # 关闭画板
def pred(self,mode,test_images=None,test_labels=None):
if (mode==0):#测试
model = keras.models.load_model(self.save_path)
print('loading model')
generator = keras.Model(inputs=model.layers[1].input, outputs=model.layers[1].output)
discriminator = keras.Model(inputs=model.layers[2].input, outputs=model.layers[2].output)
generator.summary()
discriminator.summary()
for i in range(10): #测试生成器
label = i
noise = self.noise_generate(1, label)
img = np.squeeze(generator.predict([noise]))
plt.imshow(img)
plt.show()
elif(mode==1): #验证集
print('testing')
step=int(test_images.shape[0]/self.test_size)
val_acc=0
for i in range(step):
pred=self.discriminator_model3(test_images[i*self.test_size:(i+1)*self.test_size])
pred=pred.numpy()
pred[:,(self.num_classes)]=0
pred=tf.argmax(pred,axis=-1)
pred=keras.utils.to_categorical(pred,num_classes=self.num_classes+1)
labels=keras.utils.to_categorical(test_labels[i*self.test_size:(i+1)*self.test_size],num_classes=self.num_classes+1)
acc=1-tf.reduce_mean(tf.abs(pred-labels))
val_acc+=acc
val_acc=val_acc/step
return val_acc.numpy()
else:
pass
if __name__ == '__main__':
GAN = GAN()
GAN.train()
GAN.pred(mode=0)