tensorflow keras LAPGAN CIFAR10数据集

前言

现在这里留个坑,记录自己学习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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值