July5rd_GAN系列学习笔记

1.基础入门,构建判别网络和生成判别网络,分别对判别和生成训练。

from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
class GAN():
    def __init__(self):
        self.img_rows=28#定义图片属性
        self.img_cols=28
        self.channels=1
        self.img_shape=(self.img_rows,self.img_cols,self.channels)#shape是元组属性值
        self.latent_dim=100#随机生成input的形状属性值
        optimizer=Adam(0.0002,0.5)#确定模型优化器参数属性值
        self.discriminator=self.build_discriminator()#此类的评判标准由此类的动作函数生成
        self.discriminator.compile(loss='binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])#对评判标准的结果进行验证准确度
        self.generator=self.build_generator()#模型的生成者
        gan_input=Input(shape=(self.latent_dim,))#定义此类模型的输入层形状
        img=self.generator(gan_input)#将输入送到生成者去生成图片
        self.discriminator.trainable=False#此时只生成图片,不进行评判和两者改进
        validity=self.discriminator(img)#评判生成的图片
        self.combined=Model(gan_input,validity)#建立输入到评判结果的模型
        self.combined.compile(loss='binary_crossentropy',optimizer=optimizer)#模型编译
    def build_generator(self):
        model=Sequential()
        model.add(Dense(256,input_dim=self.latent_dim))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        
        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'))#全连接层,28*28*1个神经元
        model.add(Reshape(self.img_shape))#变成图片的形状
        
        noise=Input(shape=(self.latent_dim,))
        img=model(noise)#建立了从输入100维随机向量》》》》到28,28,1大小的图片》》》生成模型
        return Model(noise,img)
    def build_discriminator(self):
        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'))#输出是一个维度,并用sigmoid映射到0到1
        img=Input(shape=self.img_shape)
        validity=model(img)#建立了从输入28,28,1图片》》》到输出一个维度的》》》》判别模型
        return Model(img,validity)
    def train(self,epochs,batch_size=128,sample_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train=x_train/127.5-1#将图片像素值映射到-1到1
        x_train=np.expand_dims(x_train,axis=3)#输入时2维tensor,映射到三维,加了第三维1,表示1个通道
        valid=np.ones((batch_size,1))#batch——size大小的全是1的标签
        fake=np.zeros((batch_size,1))#batch_size大小全是0的标签
        for epoch in range(epochs):
            #训练判别网络
            idx=np.random.randint(0,x_train.shape[0],batch_size)#从train训练集里面随机找出batc——size大小(这么多个)的索引值
            imgs=x_train[idx]#取出1个batch大小的图片
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))#正态分布生成batch_size个100维向量作为输入
            gen_imgs=self.generator.predict(noise)#用生成model的predict方法(model内部方法)将输入进行生成输出
            d_loss_real=self.discriminator.train_on_batch(imgs,valid)#输入真实图片和标签全1》》到判别model,》》计算判别模型的loss
            d_loss_fake=self.discriminator.train_on_batch(gen_imgs,fake)#输入假的图片和标签全0》》到判别model,》计算判别模型的loss
            d_loss=0.5*np.add(d_loss_real,d_loss_fake)#将两者损失结合作为总损失
            #训练生成网络
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            g_loss=self.combined.train_on_batch(noise,valid)#如果输入噪音的输出是1,则正确,输入噪音输出是0,则生成网络需要改进,所以loss累加
            print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))#说明生成网络的性能
            if epoch %sample_interval==0:
                self.sample_images(epoch)
    def sample_images(self,epoch):#画出25张图片
        r,c=5,5
        noise=np.random.normal(0,1,(r*c,self.latent_dim))
        gen_imgs=self.generator.predict(noise)
        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__':
    if not os.path.exists('./images'):
        os.makedirs('./images')
    gan=GAN()
    gan.train(epochs=3000,batch_size=256,sample_interval=50)
            

 2.DCGAN的全称是Deep Convolutional Generative Adversarial Networks ,意即深度卷积对抗生成网络。

#DCGAN
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
class DCGAN():
    def __init__(self):
        self.latent_dim=100#输入形状属性
        
        self.img_rows=28
        self.img_cols=28
        self.channels=1
        self.img_shape=(self.img_rows,self.img_cols,self.channels)#生成形状属性
        
        self.num_classes=10##输出形状属性
        
        optimizer=Adam(0.0002,0.5)#模型的参数设置
        
        self.generator=self.build_generator()#创建生成模型的结构
        z=Input(shape=(self.latent_dim,))
        img=self.generator(z)
        
        #构建判别网络
        self.discriminator=self.build_discriminator()#创建评判模型的结构
        self.discriminator.compile(loss=['binary_crossentropy'],optimizer=optimizer,metrics=['accuracy'])
        
        #构建生成判别网络,此时内部的判别网络不train,只改变生成那块网络的参数
        self.discriminator.trainable=False#此时不训练评判,只进行评判输出
        valid=self.discriminator(img)#评判输出
        self.combined=Model(z,valid)# conbine是生成模型和判别模型的结合,生成到评判结果输出
        self.combined.compile(loss='binary_crossentropy',optimizer=optimizer)
    def build_generator(self):
        model=Sequential()
        model.add(Dense(32*7*7,activation='relu',input_dim=self.latent_dim))
        model.add(Reshape((7,7,32)))#1维数字输入》》》》三维图像输入
        
        #开始卷积操作7,7,32
        model.add(Conv2D(64,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))#7,7,64
        
        model.add(UpSampling2D())#上采样
        model.add(Conv2D(128,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))#14,14,128
        
        model.add(UpSampling2D())#上采样
        model.add(Conv2D(64,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))#28,28,64
        
        model.add(Conv2D(self.channels,kernel_size=3,padding='same'))
        model.add(Activation('tanh'))#28,28,1
        
        model.summary()
        
        noise=Input(shape=(self.latent_dim,))
        img=model(noise)
        
        return Model(noise,img)
    def build_discriminator(self):
        model=Sequential()
        model.add(Conv2D(32,kernel_size=3,strides=2,input_shape=self.img_shape,padding='same'))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))#14,14,32
        
        model.add(Conv2D(64,kernel_size=3,strides=2,padding='same'))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))#7,7,64
        
        model.add(ZeroPadding2D(((0,1),(0,1))))
        model.add(Conv2D(128,kernel_size=3,strides=2,padding='same'))
        model.add(BatchNormalization(momentum=0.8))#4,4,128
        model.add(LeakyReLU(alpha=0.2))
        model.add(GlobalAveragePooling2D())#1,1,128
        
        model.add(Dense(1,activation='sigmoid'))#1
        
        model.summary()
        
        img=Input(shape=(self.img_shape))
        validity=model(img)
        
        return Model(img,validity)
    def train(self,epochs,batch_size=128,save_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train=x_train/127.5-1
        x_train=np.expand_dims(x_train,axis=3)
        valid=np.ones((batch_size,1))
        fake=np.zeros((batch_size,1))
        for epoch in range(epochs):
            #训练判别模型
            idx=np.random.randint(0,x_train.shape[0],batch_size)
            imgs=x_train[idx]
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            gen_img=self.generator.predict(noise)
            d_loss_real=self.discriminator.train_on_batch(imgs,valid)
            d_loss_fake=self.discriminator.train_on_batch(gen_img,fake)
            d_loss=0.5*np.add(d_loss_real,d_loss_fake)
            
            #利用生成判别网络模型,来训练生成模型,因为此时判别trainable=False
            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))

            if epoch % save_interval == 0:
                self.save_imgs(epoch)
    def save_imgs(self, epoch):
        r, c = 5, 5
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        gen_imgs = self.generator.predict(noise)
        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/mnist_%d.png" % epoch)
        plt.close()


if __name__ == '__main__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    dcgan = DCGAN()
    dcgan.train(epochs=20000, batch_size=256, save_interval=50)

        
        

 3.CGAN一种带条件约束的GAN,在生成模型(D)和判别模型(G)的建模中均引入条件变量y(conditional variable y)。简单来讲,普通的GAN输入的是一个N维的正态分布随机数,而CGAN会为这个随机数添上标签,其利用Embedding层将正整数(索引值)转换为固定尺寸的稠密向量,并将这个稠密向量与N维的正态分布随机数相乘,从而获得一个有标签的随机数。

#CGAN,两个输入multiply,两个输出
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
class CGAN():
    def __init__(self):
        self.latent_dim=100

        self.img_rows=28
        self.img_cols=28
        self.channels=1
        self.img_shape=(self.img_rows,self.img_cols,self.channels)

        self.num_classes=10

        optimizer=Adam(0.002,0.5)

        #判别模型
        losses=['binary_crossentropy','sparse_categorical_crossentropy']
        self.discriminator=self.build_discriminator()
        self.discriminator.compile(loss=losses,optimizer=optimizer,metrics=['accuracy'])

        #(生成判别)模型
        self.generator=self.build_generator()
        noise=Input(shape=(self.latent_dim,))
        label=Input(shape=(1,))
        img=self.generator([noise,label])
        self.discriminator.trainable=False
        valid,target_label=self.discriminator(img)
        self.combined=Model([noise,label],[valid,target_label])
        self.combined.compile(loss=losses,optimizer=optimizer)
    def build_generator(self):
        model=Sequential()
        model.add(Dense(256,input_shape=(self.latent_dim,)))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        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))#输出,img
        
        label=Input(shape=(1,),dtype='int32')
        label_embedding=Flatten()(Embedding(self.num_classes,self.latent_dim)(label))#将的0~9映射到100维的稠密向量,将输入的0~9标签*对应的稠密向量,再latten
        noise=Input(shape=(self.latent_dim,))
        model_input=multiply([noise,label_embedding])#输入noise,label_embedding
        img=model(model_input)
        model.summary()
        return Model([noise, label], img)
    def build_discriminator(self):
        model=Sequential()
        model.add(Flatten(input_shape=self.img_shape))
        model.add(Dense(512))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(512))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.4))
        model.add(Dense(512))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.4))
        
        label=Input(shape=(1,),dtype='int32')
        img=Input(shape=self.img_shape)#输入label,img
        
        features=model(img)#模型输入img
        
        validity=Dense(1,activation='sigmoid')(features)#判别真伪,一维
        label=Dense(self.num_classes,activation='softmax')(features)#判别0~9
        return Model(img,[validity,label])
    def train(self,epochs,batch_size=128,sample_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train=(x_train.astype(np.float32)-127.5)/127.5
        x_train=np.expand_dims(x_train,axis=3)
        y_train=y_train.reshape(-1,1)
        valid=np.ones((batch_size,1))
        fake=np.zeros((batch_size,1))
        for epoch in range(epochs):
            idx=np.random.randint(0,x_train.shape[0],batch_size)
            imgs,labels=x_train[idx],y_train[idx]#真实
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            sampled_labels=np.random.randint(0,10,(batch_size,1))#生成
            gen_img=self.generator.predict([noise,sampled_labels])
            
            d_loss_real=self.discriminator.train_on_batch(imgs,[valid,labels])
            d_loss_fake=self.discriminator.train_on_batch(gen_img,[fake,sampled_labels])
            d_loss=0.5*np.add(d_loss_real,d_loss_fake)
            
            g_loss=self.combined.train_on_batch([noise,sampled_labels],[valid,sampled_labels])
            print ("%d [D loss: %f, acc.: %.2f%%, op_acc: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[3], 100*d_loss[4], g_loss[0]))

            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                
    def sample_images(self,epoch):
        r,c=2,5
        noise=np.random.normal(0,1,(r*c,100))
        sampled_labels=np.arange(0,10).reshape(-1,1)
        gen_imgs=self.generator.predict([noise,sampled_labels])
        gen_imgs=0.5*gen_imgs+0.5#-1~1映射到0~1
        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].set_title("Digit: %d" % sampled_labels[cnt])
                axs[i,j].axis('off')
                cnt += 1
        fig.savefig("images/%d.png" % epoch)
        plt.close()
if __name__ == '__main__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    cgan = CGAN()
    cgan.train(epochs=20000, batch_size=256, sample_interval=200)

        
        

                  
    
    

 4.ACGAN相当于是DCGAN和CGAN的结合,将深度卷积网络和标签带入到GAN当中。

from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
class ACGAN():
    def __init__(self):
        self.latent_dim=100
        self.img_shape=(28,28,1)
        self.classes=10
        #判别模型
        self.discriminator=self.build_discriminator()
        self.discriminator.compile(loss=['binary_crossentropy','sparse_categorical_crossentropy'],optimizer=Adam(0.002,0.5),metrics=['accuracy'])
        #生成判别模型
        self.generator=self.build_generator()
        self.discriminator.trainable=False
        noise=Input(shape=(self.latent_dim,))
        label=Input(shape=(1,))
        
        valid,target_label=self.discriminator(self.generator([noise,label]))
        self.combined=Model([noise,label],[valid,target_label])
        self.combined.compile(loss=['binary_crossentropy','sparse_categorical_crossentropy'],optimizer=Adam(0.002,0.5))
    def build_generator(self):
        model=Sequential()
        model.add(Dense(32*7*7,activation='relu',input_dim=self.latent_dim))
        model.add(Reshape((7,7,32)))
        
        model.add(Conv2D(64,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))
        
        model.add(UpSampling2D())
        model.add(Conv2D(128,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))
        
        model.add(UpSampling2D())
        model.add(Conv2D(64,kernel_size=3,padding='same'))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Activation('relu'))
        
        model.add(Conv2D(1, kernel_size=3, padding="same"))
        model.add(Activation("tanh"))
        model.summary()
        noise = Input(shape=(100,))
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, 100)(label))

        model_input = multiply([noise, label_embedding])
        img = model(model_input)

        return Model([noise, label], img)
    def build_discriminator(self):

        model = Sequential()
        # 28,28,1 -> 14,14,16
        model.add(Conv2D(16, kernel_size=3, strides=2, input_shape=self.img_shape, padding="same"))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        # 14,14,16 -> 8,8,32
        model.add(Conv2D(32, kernel_size=3, strides=2, padding="same"))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        model.add(BatchNormalization(momentum=0.8))
        # 8,8,32 -> 4,4,64
        model.add(ZeroPadding2D(padding=((0,1),(0,1))))
        model.add(Conv2D(64, kernel_size=3, strides=2, padding="same"))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        model.add(BatchNormalization(momentum=0.8))
        # 4,4,64 -> 4,4,128
        model.add(Conv2D(128, kernel_size=3, strides=1, padding="same"))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        model.add(GlobalAveragePooling2D())

        img = Input(shape=self.img_shape)

        features = model(img)

        validity = Dense(1, activation="sigmoid")(features)
        label = Dense(10, activation="softmax")(features)

        return Model(img, [validity, label])
    def train(self,epochs,batch_size=128,sample_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train = (x_train.astype(np.float32) - 127.5) / 127.5
        x_train = np.expand_dims(x_train, axis=3)
        y_train = y_train.reshape(-1, 1)

        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))
        for epoch in range(epochs):
            idx=np.random.randint(0,x_train.shape[0],batch_size)
            imgs,labels=x_train[idx],y_train[idx]
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            sampled_labels=np.random.randint(0,10,(batch_size,1))
            gen_imgs=self.generator.predict([noise,sampled_labels])
            
            d_loss_real=self.discriminator.train_on_batch(imgs,[valid,labels])
            d_loss_fake=self.discriminator.train_on_batch(gen_imgs,[fake,sampled_labels])
            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)
            g_loss = self.combined.train_on_batch([noise, sampled_labels], [valid, sampled_labels])
            print ("%d [D loss: %f, acc.: %.2f%%, op_acc: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[3], 100*d_loss[4], g_loss[0]))

            if epoch % sample_interval == 0:
                self.sample_images(epoch)


    def sample_images(self, epoch):
        r, c = 2, 5
        noise = np.random.normal(0, 1, (r * c, 100))
        sampled_labels = np.arange(0, 10).reshape(-1, 1)

        gen_imgs = self.generator.predict([noise, sampled_labels])
        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].set_title("Digit: %d" % sampled_labels[cnt])
                axs[i,j].axis('off')
                cnt += 1
        fig.savefig("images/%d.png" % epoch)
        plt.close()
        
    def save_model(self):

        def save(model, model_name):
            model_path = "saved_model/%s.json" % model_name
            weights_path = "saved_model/%s_weights.hdf5" % model_name
            options = {"file_arch": model_path,
                        "file_weight": weights_path}
            json_string = model.to_json()
            open(options['file_arch'], 'w').write(json_string)
            model.save_weights(options['file_weight'])

        save(self.generator, "generator")
        save(self.discriminator, "discriminator")

if __name__ == '__main__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    acgan = ACGAN()
    acgan.train(epochs=1000, batch_size=256, sample_interval=200)

 5.SRGAN其主要的功能就是输入一张低分辨率图片,生成高分辨率图片。 

 

#SRGAN可以提升图像分辨率
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
from tensorflow.keras.applications.vgg19 import VGG19

import scipy 
from glob import glob
import numpy as np
import matplotlib.pyplot as plt
class DataLoader():
    def __init__(Self,dataset_name,img_res=(128,128)):
        self.dataset_name=dataset_name
        self.img_res=img_res
    def load_data(self,batch_size=1,is_testing=False):
        data_type='train' if not is_testing  else 'test'
        path=glob('./%s/*'%(self.dataset_name))
        batch_images=np.random.choice(path,size=batch_size)
        imgs_hr=[]
        imgs_lr=[]
        for img_path in batch_images:
            img=self.imread(img_path)
            h,w=self.img_res
            low_h,low_w=int(h/4),int(w/4)
            img_hr=scipy.misc.imresize(img,self.img_res)
            img_lr=scipy.misc.imresize(img,(low_h,low_w))
            if not is_testing and np.random.random()<0.5:
                img_hr=np.fliplr(img_hr)#图像左右翻转
                img_lr=np.fliplr(img_lr)
            imgs_hr.append(img_hr)
            imgs_lr.append(img_lr)
        imgs_hr=np.array(imgs_hr)/127.5-1
        imgs_lr=np.array(imgs_lr)/127.5-1
        return imgs_hr,imgs_lr
    def imread(self,path):
        return scipy.misc.imread(path,model='RGB').astype(np.float)
                

class SRGAN():
    def __init__(self):
        #低分辨率的图像shape
        self.channels=3
        self.lr_height=128
        self.lr_width=128
        self.lr_shape=(self.lr_height,self.lr_width,self.channels)
        #高分辨率的图像shape
        self.hr_height=self.lr_height*4
        self.hr_width=self.lr_width*4
        self.hr_shape=(self.hr_height,self.hr_width,self.channels)
        
        self.n_residual_blocks=16#16个残差卷积快
        optimizer=Adam(0.002,0.5)
        #创建VGG模型,用于提取图像特征
        self.vgg=self.build_vgg()
        self.vgg.trainable=False
        #数据集#*******************************************************
        self.dataset_name='DIV'
        self.data_loader=DataLoader(dataset_name=self.dataset_name,img_res=(self.hr_height,self.hr_width))
        patch=int(self.hr_height/2**4)
        self.disc_path=(path,patch,1)
        #判别模型
        self.discriminator=self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])
        self.discriminator.summary()
        #生成判别模型
        self.generator=self.build_generator()
        self.generator.summary()
        img_lr=Input(shape=self.lr_shape)
        fake_lr=self.generator(img_lr)
        fake_featurs=self.vgg(fake_lr)
        self.discriminator.trainable=False
        validity=self.discriminator(fake_hr)
        self.combined=Model(img_lr,[validity,fake_features])
        self.combined.compile(loss=['binary_crossentropy','mse'],loss_weights=[5e-1,1],optimizer=optimizer)
        
        
    def build_vgg(self):
        vgg=VGG19(weights='imagenet')
        vgg.outputs=[vgg.layers[9].output]# 建立VGG模型,只使用第9层的特征
        img=Input(shape=self.hr_shape)
        img_features=vgg(img)
        return Model(img,img_features)
    def build_generator(self):
        def residual_block(layer_input,filters):
            d=Conv2D(filters,kernel_size=3,strides=1,padding='same')(layer_input)
            d=BatchNormalization(momentun=0.8)(d)
            d=Activation('relu')(d)
            d=Conv2D(filters,kernel_size=3,strides=1,pading='same')(d)
            d=BatchNormalization(momentum=0.8)(d)
            d=Add()([d,layer_input])
            return d
        def deconv2d(layer_input):
            u=UpSampling2D(size=2)(layer_input)
            u=Conv2D(256,kernel_size=3,strides=1,padding='same')(u)
            u=Activation('relu')(u)
            return u
        #第一部分,低分辨率图像进入后会经过一个卷积+RELU函数
        img_lr=Input(shape=self.lr_shape)
        c1=Conv2D(64,kernel_size=9,strides=1,padding='same')(img_lr)
        c1=Activation('relu')(c1)
        
        # 第二部分,经过16个残差网络结构,每个残差网络内部包含两个卷积+标准化+RELU,还有一个残差边。
        r = residual_block(c1, 64)
        for _ in range(self.n_residual_blocks - 1):
            r = residual_block(r, 64)
        c2=Conv2D(64,kernel_size=3,strides=1,padding='same')(c1)
        c2=BatchNormalization(momentum=0.8)(c2)
        c2=Add()([c2,c1])
        # 第三部分,上采样部分,将长宽进行放大,两次上采样后,变为原来的4倍,实现提高分辨率。
        u1=deconv2d(c2)
        u2=deconv2d(u1)
        gen_hr=Conv2D(self.channels,kernal_size=9,strides=1,padding='same',activation='tanh')(u2)
        return Model(img_lr,gen_hr)
    def build_discriminatior(self):
        def d_block(layer_input,filters,strides=1,bn=True):
            d=Conv2D(filters,kernel_size=3,strides=strides,padding='same')(layer_input)
            d=LeakyReLU(alpha=0.2)(d)
            if bn:
                d=BatchNormalization(momentum=0.8)(d)
            return d
        d0=Input(shape=self.hr_shape)
        d1=d_block(d0,64,bn=False)
        d2=d_block(d1,64,strides=2)
        d3=d_block(d2,128)
        d4=d_block(d3,128,strides=2)
        d5=d_block(d4,256)
        d6=d_block(d5,256,strides=2)
        d7=d_block(d6,512)
        d8=d_block(d7,512,strides=2)
        d9=Dense(64*16)(d8)
        d10=LeakyReLU(alpha=0.9)(d9)
        validity=Dense(1,activation='sigmoid')(d10)
        return Model(d0,validity)
    def scheduler(self,models,epoch):
        if epoch%20000 ==0 and epoch !=0:
            for model in models:
                lr=K.get_value(model.optimizer.lr)
                K.set_value(model.optimizer.lr,lr*0.5)
            print('lr cahnge to {}'.format(lr*0.5))
    def train(self,epochs,init_epochs,batch_size=1,sample_interval=50):
        start_time=datatime.datatime.now()
        if init_epoch!=0:
            self.generator.load_weights("weights/%s/gen_epoch%d.h5" % (self.dataset_name, init_epoch),skip_mismatch=True)
            self.discriminator.load_weights("weights/%s/dis_epoch%d.h5" % (self.dataset_name, init_epoch),skip_mismatch=True)
        for epoch in range(init_epoch,epochs):
            self.scheduler([self.combined,self.discriminator],epoch)
            imgs_hr,imgs_lr=self.data_loader.load_data(batch_size)
            fake_hr=self.generator.predict(imgs_lr)
            valid=np.ones((batch_size,)+self.disc_patch)
            fake=np.zeros((batch_size,)+self.disc_patch)
            #训练判别网络的参数
            d_loss_real=self.discriminator.train_on_batch(imgs_hr,valid)
            d_loss_fake=self.discriminator.train_on_batch(fake_hr,fake)
            #训练生成网络的参数,重新拿一张照片,因为上一张是判别网络训练过的图片
            imgs_hr,img_lr=self.data_loader.load_data(batch_size)
            valid=np.ones((batch_size,)+self.disc_patch)
            img_features=self.vgg.predict(img_hr)
            g_loss=self.combined.train_on_batch(img_lr,[valid,image_features])
            print(d_loss,g_loss)
            elapsed_time = datetime.datetime.now() - start_time
            print ("[Epoch %d/%d] [D loss: %f, acc: %3d%%] [G loss: %05f, feature loss: %05f] time: %s " \
                                                                        % ( epoch, epochs,
                                                                            d_loss[0], 100*d_loss[1],
                                                                            g_loss[1],
                                                                            g_loss[2],
                                                                            elapsed_time))
            
            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                # 保存
                if epoch % 500 == 0 and epoch != init_epoch:
                    os.makedirs('weights/%s' % self.dataset_name, exist_ok=True)
                    self.generator.save_weights("weights/%s/gen_epoch%d.h5" % (self.dataset_name, epoch))
                    self.discriminator.save_weights("weights/%s/dis_epoch%d.h5" % (self.dataset_name, epoch))

    def sample_images(self, epoch):
        os.makedirs('images/%s' % self.dataset_name, exist_ok=True)
        r, c = 2, 2

        imgs_hr, imgs_lr = self.data_loader.load_data(batch_size=2, is_testing=True)
        fake_hr = self.generator.predict(imgs_lr)

        imgs_lr = 0.5 * imgs_lr + 0.5
        fake_hr = 0.5 * fake_hr + 0.5
        imgs_hr = 0.5 * imgs_hr + 0.5

        titles = ['Generated', 'Original']
        fig, axs = plt.subplots(r, c)
        cnt = 0
        for row in range(r):
            for col, image in enumerate([fake_hr, imgs_hr]):
                axs[row, col].imshow(image[row])
                axs[row, col].set_title(titles[col])
                axs[row, col].axis('off')
            cnt += 1
        fig.savefig("images/%s/%d.png" % (self.dataset_name, epoch))
        plt.close()

        for i in range(r):
            fig = plt.figure()
            plt.imshow(imgs_lr[i])
            fig.savefig('images/%s/%d_lowres%d.png' % (self.dataset_name, epoch, i))
            plt.close()

if __name__ == '__main__':
    gan = SRGAN()
    gan.train(epochs=6,init_epoch = 0, batch_size=1, sample_interval=50)
    

#预测
model = build_generator()
model.load_weights(r"weights\DIV\gen_epoch38500.h5")
before_image = Image.open(r"before.png")

new_image = Image.new('RGB', before_image.size, (128,128,128))
new_image.paste(before_image)

new_image = np.array(new_image)/127.5 - 1
new_image = np.expand_dims(new_image,axis=0)
fake = (model.predict(new_image)*0.5 + 0.5)*255

fake = Image.fromarray(np.uint8(fake[0]))

fake.save("out.png")
fake.show()

  

6.LSGAN,无论是判别模型的训练,还是生成模型的训练,都需要将交叉熵更改为均方差。

#LSGAN
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np

class LSGAN():
    def __init__(self):
        self.latent_dim=100
        self.img_rows=28
        self.img_cols=28
        self.channels=1
        self.img_shape=(self.img_rows,self.img_cols,self.channels)
        self.num_classes=10
        optimizer=Adam(0.002,0.5)
        self.discriminator=self.build_discriminator()
        self.discriminator.compile(loss='mse',optimizer=optimizer,metrics=['accuracy'])
        #创建生成判别模型
        self.generator=self.build_generator()
        z=Input(shape=(self.latent_dim,))
        img=self.generator(z)#生成
        
        self.discriminator.trainable=False
        
        valid=self.discriminator(img)#判别
        self.combined=Model(z,valid)#生成判别
        self.combined.compile(loss='mse',optimizer=optimizer)#对于生成,不用看准确率
    def build_generator(self):
        model=Sequential()
        model.add(Dense(256,input_dim=self.latent_dim))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        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))
        
        noise=Input(shape=(self.latent_dim,))#输入
        img=model(noise)#输出
        return Model(noise,img)#模型
    def build_discriminator(self):
        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))
        
        img=Input(shape=self.img_shape)
        validity=model(img)
        
        return Model(img,validity)
    def train(self,epochs,batch_size=128,sample_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train=(x_train.astype(np.float32)-127.5)/127.5
        x_train=np.expand_dims(x_train,axis=3)
        valid=np.ones((batch_size,1))
        fake=np.zeros((batch_size,1))
        for epoch in range(epochs):
            idx=np.random.randint(0,x_train.shape[0],batch_size)
            imgs=x_train[idx]
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            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_real,d_loss_fake)
            
            #重新生成数据训练生成网络
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            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))

            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)

        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__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    gan = LSGAN()
    gan.train(epochs=3000, batch_size=512, sample_interval=200)

                  

7.COGAN耦合生成式对抗网络,其内部具有一定的耦合,可以对同一个输入有不同的输出。 

#LSGAN
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
import scipy



class COGAN():
    def __init__(self):
        self.latent_dim=100
        self.img_rows=28
        self.img_cols=28
        self.channels=1
        self.img_shape=(self.img_rows,self.img_cols,self.channels)
        self.num_classes=10
        self.d1,self.d2=self.build_discriminators()#返回两个评判对象
        self.d1.compile(loss='binary_crossentropy',optimizer=Adam(0.002,0.5),metrics=['accuracy'])
        self.d2.compile(loss='binary_crossentropy',optimizer=Adam(0.002,0.5),metrics=['accuracy'])
        
        self.g1,self.g2=self.build_generators()
        z=Input(shape=(self.latent_dim,))
        img1=self.g1(z)
        img2=self.g2(z)#生成
        self.d1.trainable=False
        self.d2.trainable=False
        valid1=self.d1(img1)
        valid2=self.d2(img2)#判别
        self.combined=Model(z,[valid1,valid2])
        self.combined.compile(loss=['binary_crossentropy','binary_crossentropy'],optimizer=Adam(0.002,0.5))
    def build_generators(self):
        noise=Input(shape=(self.latent_dim,))
        x=Dense(32*7*7,activation='relu',input_dim=self.latent_dim)(noise)
        x=Reshape((7,7,32))(x)
        x=Conv2D(64,kernel_size=3,padding='same')(x)
        x=BatchNormalization(momentum=0.8)(x)
        x=Activation('relu')(x)
        x=UpSampling2D()(x)
        x=Conv2D(128,kernel_size=3,padding='same')(x)
        x=BatchNormalization(momentum=0.8)(x)
        x=Activation('relu')(x)
        x=UpSampling2D()(x)
        x=Conv2D(128,kernel_size=3,padding='same')(x)
        x=BatchNormalization(momentum=0.8)(x)
        feature_repr=Activation('relu')(x)
        model=Model(noise,feature_repr)#公共生成模型
        #生成模型1
        g1=Conv2D(64,kernel_size=1,padding='same')(feature_repr)
        g1=BatchNormalization(momentum=0.8)(g1)
        g1=Activation('relu')(g1)
        g1=Conv2D(64,kernel_size=3,padding='same')(g1)
        g1=BatchNormalization(momentum=0.8)(g1)
        g1=Activation('relu')(g1)
        g1=Conv2D(64,kernel_size=1,padding='same')(g1)
        g1=BatchNormalization(momentum=0.8)(g1)
        g1=Activation('relu')(g1)
        g1=Conv2D(self.channels,kernel_size=1,padding='same')(g1)
        img1=Activation('tanh')(g1)
        #生成模型2
        g2=Conv2D(64,kernel_size=1,padding='same')(feature_repr)
        g2=BatchNormalization(momentum=0.8)(g2)
        g2=Activation('relu')(g2)
        g2=Conv2D(64,kernel_size=3,padding='same')(g2)
        g2=BatchNormalization(momentum=0.8)(g2)
        g2=Activation('relu')(g2)
        g2=Conv2D(64,kernel_size=1,padding='same')(g2)
        g2=BatchNormalization(momentum=0.8)(g2)
        g2=Activation('relu')(g2)
        g2=Conv2D(self.channels,kernel_size=1,padding='same')(g2)
        img2=Activation('tanh')(g2)
        return Model(noise,img1),Model(noise,img2)
    def build_discriminators(self):
        img=Input(shape=self.img_shape)
        x=Conv2D(64,kernel_size=3,strides=2,padding='same')(img)
        x=BatchNormalization(momentum=0.8)(x)
        x=Activation('relu')(x)
        x=Conv2D(128,kernel_size=3,strides=2,padding='same')(img)
        x=BatchNormalization(momentum=0.8)(x)
        x=Activation('relu')(x)
        x=Conv2D(64,kernel_size=3,strides=2,padding='same')(img)
        x=BatchNormalization(momentum=0.8)(x)
        x=GlobalAveragePooling2D()(x)
        feature_repr=Activation('relu')(x)
        model=Model(img,feature_repr)#公共判别部分
        img1=Input(shape=self.img_shape)
        img2=Input(shape=self.img_shape)
        img1_embedding=model(img1)
        img2_embedding=model(img2)
        #判别1
        validity1=Dense(1,activation='sigmoid')(img1_embedding)
        #判别2
        validity2=Dense(1,activation='sigmoid')(img2_embedding)
        return Model(img1,validity1),Model(img2,validity2)
    def train(self,epochs,batch_size=128,sample_interval=50):
        (x_train,y_train),(x_test,y_test)=mnist.load_data()
        x_train=(x_train.astype(np.float32)-127.5)/127.5
        x_train=np.expand_dims(x_train,axis=3)
        x1=x_train[:int(x_train.shape[0]/2)]#前面一半数据训练生成判别1
        x2=x_train[int(x_train.shape[0]/2):]#后面数据
        x2=scipy.ndimage.interpolation.rotate(x2,90,axes=(1,2))#第二部分数据旋转90度
        valid=np.ones((batch_size,1))
        fake=np.zeros((batch_size,1))
        for epoch in range(epochs):
            idx=np.random.randint(0,x1.shape[0],batch_size)
            imgs1=x1[idx]
            imgs2=x2[idx]
            noise=np.random.normal(0,1,(batch_size,self.latent_dim))
            gen_imgs1=self.g1.predict(noise)
            gen_imgs2=self.g2.predict(noise)
            #评判损失
            d1_loss_real=self.d1.train_on_batch(imgs1,valid)
            d2_loss_real=self.d2.train_on_batch(imgs2,valid)
            d1_loss_fake=self.d1.train_on_batch(gen_imgs1,fake)
            d2_loss_fake=self.d2.train_on_batch(gen_imgs2,fake)
            d1_loss=0.5*np.add(d1_loss_real,d1_loss_fake)
            d2_loss=0.5*np.add(d2_loss_real,d2_loss_fake)
            #生成评判损失
            g_loss=self.combined.train_on_batch(noise,[valid,valid])
            print ("%d [D1 loss: %f, acc.: %.2f%%] [D2 loss: %f, acc.: %.2f%%] [G loss: %f]" \
                % (epoch, d1_loss[0], 100*d1_loss[1], d2_loss[0], 100*d2_loss[1], g_loss[0]))

            if epoch % sample_interval == 0:
                self.sample_images(epoch)

    def sample_images(self, epoch):
        r, c = 4, 4
        noise = np.random.normal(0, 1, (r * int(c/2), 100))
        gen_imgs1 = self.g1.predict(noise)
        gen_imgs2 = self.g2.predict(noise)
        gen_imgs = np.concatenate([gen_imgs1, gen_imgs2])

        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/mnist_%d.png" % epoch)
        plt.close()


if __name__ == '__main__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    gan = COGAN()
    gan.train(epochs=30000, batch_size=256, sample_interval=200)

 8.CycleGAN,从图片到图片,可以转换风格 

#CYCLEGAN
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input,Dense,Reshape,Flatten,Dropout,BatchNormalization,Activation,ZeroPadding2D,LeakyReLU,UpSampling2D,Conv2D,GlobalAveragePooling2D,Embedding,multiply
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
#https://github.com/keras-team/keras-contrib>>>>cmd进入文件python setup.py install》》》keras_contrib和keras_contrib.egg-info复制到python环境的Lib下的site-packages中
from keras_contrib.layers.normalization.instancenormalization import InstanceNormalization

from tensorflow.keras import layers

import datetime
#载入数据
import cv2
from glob import glob
import numpy as np
class DataLoader():
    def __init__(self,dataset_name,img_res=(128,128)):
        self.dataset_name=dataset_name
        self.img_res=img_res
    def load_data(self,domain,batch_size=1,is_testing=False):#domain:A,B
        data_type='train%s'%domain if not is_testing else 'test%s'%domain
        path=glob('./%s/%s/*'%(self.dataset_name,data_type))
        batch_images=np.random.choice(path,size=batch_size)
        imgs=[]
        for img_path in batch_images:
            img=self.imread(img_path)
            if not is_testing:
                img=cv2.resize(img,self.img_res)
                if np.random.random()>0.5:
                    img=np.fliplr(img)#随机左右翻转
            else:
                img=cv2.resize(img,self.img_res)
            imgs.append(img)
        imgs=np.array(imgs)/127.5-1.
        return imgs
    def load_batch(self,batch_size=1,is_testing=False):
        data_type='train' if not is_testing else 'test'
        path_A=glob('./%s/%sA/*'%(self.dataset_name,data_type))
        path_B=glob('./%s/%sB/*'%(self.dataset_name,data_type))
        self.n_batches=int(min(len(path_A),len(path_B))/batch_size)#可以分几个batch
        total_samples=self.n_batches*batch_size
        path_A=np.random.choice(path_A,total_samples,replace=False)##确保两种的样本数一致
        path_B=np.random.choice(path_B,total_samples,replace=False)#并打乱图像顺序
        for i in range(self.n_batches-1):#遍历每一个batch
            batch_A=path_A[i*batch_size:(i+1)*batch_size]
            batch_B=path_B[i*batch_size:(i+1)*batch_size]
            imgs_A,imgs_B=[],[]
            for img_A,img_B in zip(batch_A,batch_B):
                img_A=self.imread(img_A)
                img_B=self.imread(img_B)
                img_A=cv2.resize(img_A,self.img_res)
                img_B=cv2.resize(img_B,self.img_res)
                if not is_testing and np.random.random()>0.5:
                    img_A=np.fliplr(img_A)
                    img_B=np.fliplr(img_B)
                imgs_A.append(img_A)
                imgs_B.append(img_B)
        imgs_A=np.array(imgs_A,dtype=np.float32)/127.5-1
        imgs_B=np.array(imgs_B,dtype=np.float32)/127.5-1
        yield imgs_A,imgs_B
    def load_img(self,path):
        img=self.imread(self,path)
        img=cv2.resize(img,self.img_res)
        img=img/127.5-1
        return img[np.newaxis,:,:,:]
    def imread(self,path):
        img=cv2.imread(path)
        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
        return img
        
#resnet网络
IMAGE_ORDERING='channels_last'
def one_side_pad(x):
    x=ZeroPadding2D((1,1),data_format=IMAGE_ORDERING)(x)
    if IMAGE_ORDERING=='channels_first':
        x=Lambda(lambda x:x[:,:,:-1,:-1])(x)
    elif IMAGE_ORDERING=='channel_last':
        x=Lambda(lambda x:x[:,:-1,:-1,:])(x)
    return x
def identity_block(input_tensor,kernel_size,filter_num,block):
    conv_name_base='res'+block+'_branch'
    in_name_base='in'+block+'_branch'
    x=ZeroPadding2D((1,1),data_format=IMAGE_ORDERING)(input_tensor)
    x=Conv2D(filter_num,(3,3),data_format=IMAGE_ORDERING,name=conv_name_base+'2a')(x)
    x=InstanceNormalization(axis=3,name=in_name_base+'2a')(x)
    x=Activation('relu')(x)
    
    x=ZeroPadding2D((1,1),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(filter_num,(3,3),data_format=IMAGE_ORDERING,name=conv_name_base+'2c')(x)
    x=InstanceNormalization(axis=3,name=in_name_base+'2c')(x)
    
    x=layers.add([x,input_tensor])#残差边,
    x=Activation('relu')(x)
    return x
def get_resnet(input_height,input_width,channel):
    img_input=Input(shape=(input_height,input_width,3))#128,128,3
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(img_input)
    x=Conv2D(64,(7,7),data_format=IMAGE_ORDERING)(x)
    x=InstanceNormalization(axis=3)(x)
    x=Activation('relu')(x)#128,128,64
    
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(128,(7,7),data_format=IMAGE_ORDERING,strides=2)(x)
    x=InstanceNormalization(axis=3)(x)
    x=Activation('relu')(x)#64,64,128
    
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(256,(7,7),data_format=IMAGE_ORDERING,strides=2)(x)
    x=InstanceNormalization(axis=3)(x)
    x=Activation('relu')(x)#32,32,256
    
    for i in range(9):
        x=identity_block(x,3,256,block=str(i))
        
    x=(UpSampling2D((2,2),data_format=IMAGE_ORDERING))(x)#64,64,256
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(128,(7,7),data_format=IMAGE_ORDERING)(x)
    x=InstanceNormalization(axis=3)(x)
    x=Activation('relu')(x)#64,64,128
    
    x=(UpSampling2D((2,2),data_format=IMAGE_ORDERING))(x)
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(64,(7,7),data_format=IMAGE_ORDERING)(x)
    x=InstanceNormalization(axis=3)(x)
    x=Activation('relu')(x)#128,128,64
    
    x=ZeroPadding2D((3,3),data_format=IMAGE_ORDERING)(x)
    x=Conv2D(channel,(7,7),data_format=IMAGE_ORDERING)(x)
    x=Activation('tanh')(x)
    model=Model(img_input,x)
    return model#128,128,3
class CycleGAN():
    def __init__(self):
        self.img_rows=128
        self.img_cols=128
        self.channels=3
        self.img_shape=(self.img_rows,self.img_cols,self.channels)
        self.dataset_name='monet2photo'
        self.data_loader=DataLoader(dataset_name=self.dataset_name,img_res=(self.img_rows,self.img_cols))
        patch=int(self.img_rows/2**4)
        self.disc_patch=(patch,patch,1)
        self.lambda_cycle=5
        self.lambda_id=2.5
        optimizer=Adam(0.002,0.5)
        #判别网络
        self.d_A=self.build_discriminator()
        self.d_B=self.build_discriminator()
        self.d_B.summary()
        self.d_A.compile(loss='mse',optimizer=optimizer,metrics=['accuracy'])
        self.d_B.compile(loss='mse',optimizer=optimizer,metrics=['accuracy'])
        #生成网络
        self.g_AB=self.build_generator()
        self.g_BA=self.build_generator()
        self.g_AB.summary()
        img_A=Input(shape=self.img_shape)
        img_B=Input(shape=self.img_shape)
        fake_B=self.g_AB(img_A)#真A》》》》》假B
        fake_A=self.g_BA(img_B)#真B》》》》》假A
        reconstr_A=self.g_BA(fake_B)#真A》》》》》假B》》》》》假A
        reconstr_B=self.g_AB(fake_A)#真B》》》》》假A》》》》》假B
        img_A_id=self.g_BA(img_A)#真A》》》》》》假A
        img_B_id=self.g_AB(img_B)#真B》》》》》》假B
        #生成判别模型
        self.d_A.trainable=False
        self.d_B.trainable=False
        valid_A=self.d_A(fake_A)
        valid_B=self.d_B(fake_B)
        #******************************************************************************
        self.combined=Model(inputs=[img_A,img_B],outputs=[valid_A,valid_B,reconstr_A,reconstr_B,img_A_id,img_B_id])
        self.combined.compile(loss=['mse','mse','mae','mae','mae','mae'],loss_weights=[0.5,0.5,self.lambda_cycle,self.lambda_cycle,self.lambda_id,self.lambda_id],optimizer=optimizer)
    def build_generator(self):
        model=get_resnet(self.img_rows,self.img_cols,self.channels)
        return model
    def build_discriminator(self):
        def conv2d(layer_input,filters,f_size=4,normalization=True):
            d=Conv2D(filters,kernel_size=f_size,strides=2,padding='same')(layer_input)
            if normalization:
                d=InstanceNormalization()(d)
            d=LeakyReLU(alpha=0.2)(d)
            return d
        img=Input(shape=self.img_shape)#128,128,3
        d1=conv2d(img,64,normalization=False)#64,64,64
        d2=conv2d(d1,128)#32,32,128
        d3=conv2d(d2,256)#16,16,256
        d4=conv2d(d3,512)#8,8,512
        validity=Conv2D(1,kernel_size=3,strides=1,padding='same')(d4)
        return Model(img,validity)
    def scheduler(self,models,epoch):# 每隔100个epoch,学习率减小为原来的1/2
        if epoch%100==0 and epoch!=0:
            for model in models:
                lr=K.get_value(model.optimizer.lr)
                K.set_value(model.optimizer.lr,lr*0.5)
            print("lr change to {}".format(lr*0.5))
    def train(self,init_epoch,epochs,batch_size=1,sample_interval=50):
        start_time=datetime.datetime.now()
        valid=np.ones((batch_size,)+self.disc_patch)
        fake=np.zeros((batch_size,)+self.disc_patch)
        if init_epoch!=0:
            self.d_A.load_weights("weights/%s/d_A_epoch%d.h5" % (self.dataset_name, init_epoch))#,skip_mismatch=True)
            self.d_B.load_weights("weights/%s/d_B_epoch%d.h5" % (self.dataset_name, init_epoch))#,skip_mismatch=True)
            self.g_AB.load_weights("weights/%s/g_AB_epoch%d.h5" % (self.dataset_name, init_epoch))#,skip_mismatch=True)
            self.g_BA.load_weights("weights/%s/g_BA_epoch%d.h5" % (self.dataset_name, init_epoch))#,skip_mismatch=True)
        for epoch in range(init_epoch,epochs):
            self.scheduler([self.combined,self.d_A,self.d_B],epoch)
            for batch_i,(imgs_A,imgs_B) in enumerate(self.data_loader.load_batch(batch_size)):
    
                fake_B=self.g_AB.predict(imgs_A)
                fake_A=self.g_BA.predict(imgs_B)
                #判别网络的损失
                dA_loss_real=self.d_A.train_on_batch(imgs_A,valid)
                dA_loss_fake=self.d_A.train_on_batch(fake_A,fake)
                dA_loss=0.5*np.add(dA_loss_real,dA_loss_fake)
                
                dB_loss_real=self.d_B.train_on_batch(imgs_B,valid)
                dB_loss_fake=self.d_B.train_on_batch(fake_B,fake)
                dB_loss=0.5*np.add(dB_loss_real,dB_loss_fake)
                
                d_loss=0.5*np.add(dA_loss,dB_loss)
                #生成网络的损失
                g_loss=self.combined.train_on_batch([imgs_A,imgs_B],[valid,valid,imgs_A,imgs_B,imgs_A,imgs_B])
                elapsed_time = datetime.datetime.now() - start_time

                print ("[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %3d%%] [G loss: %05f, adv: %05f, recon: %05f, id: %05f] time: %s " \
                                                                        % ( epoch, epochs,
                                                                            batch_i, self.data_loader.n_batches,
                                                                            d_loss[0], 100*d_loss[1],
                                                                            g_loss[0],
                                                                            np.mean(g_loss[1:3]),
                                                                            np.mean(g_loss[3:5]),
                                                                            np.mean(g_loss[5:6]),
                                                                            elapsed_time))

                if batch_i % sample_interval == 0:
                    self.sample_images(epoch, batch_i)
                    if epoch % 5 == 0 and epoch != init_epoch:
                        os.makedirs('weights/%s' % self.dataset_name, exist_ok=True)
                        self.d_A.save_weights("weights/%s/d_A_epoch%d.h5" % (self.dataset_name, epoch))
                        self.d_B.save_weights("weights/%s/d_B_epoch%d.h5" % (self.dataset_name, epoch))
                        self.g_AB.save_weights("weights/%s/g_AB_epoch%d.h5" % (self.dataset_name, epoch))
                        self.g_BA.save_weights("weights/%s/g_BA_epoch%d.h5" % (self.dataset_name, epoch))

    def sample_images(self, epoch, batch_i):
        os.makedirs('images/%s' % self.dataset_name, exist_ok=True)
        r, c = 2, 2

        imgs_A = self.data_loader.load_data(domain="A", batch_size=1, is_testing=True)
        imgs_B = self.data_loader.load_data(domain="B", batch_size=1, is_testing=True)

        fake_B = self.g_AB.predict(imgs_A)
        fake_A = self.g_BA.predict(imgs_B)

        gen_imgs = np.concatenate([imgs_A, fake_B, imgs_B, fake_A])

        gen_imgs = 0.5 * gen_imgs + 0.5

        titles = ['Original', 'Translated', 'Reconstructed']
        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])
                axs[i, j].set_title(titles[j])
                axs[i,j].axis('off')
                cnt += 1
        fig.savefig("images/%s/%d_%d.png" % (self.dataset_name, epoch, batch_i))
        plt.close()




if __name__ == '__main__':
    gan = CycleGAN()
    gan.train(init_epoch=5, epochs=100, batch_size=1, sample_interval=200)

#预测
from PIL import Image
model=get_resnet(None,None,3)
model.load_weights(r'weights\monet2photo\g_AB_epoch5.h5')
img=np.array(Image.open(r'D:\DeepLearning\monet2photo\testA\00020.jpg').resize([256,256]))/127.5 - 1
img = np.expand_dims(img,axis=0)
fake = (model.predict(img)*0.5 + 0.5)*255

face = Image.fromarray(np.uint8(fake[0]))
face.show()

  

posted @ 2020-07-05 11:18  Turing-dz  阅读(230)  评论(0编辑  收藏  举报