• 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"weightsDIVgen_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'weightsmonet2photog_AB_epoch5.h5')
    img=np.array(Image.open(r'D:DeepLearningmonet2photo	estA0020.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()
    

      

  • 相关阅读:
    剑指Offer 28 对称的二叉树
    剑指Offer 54 二叉搜索树的第k大节点
    剑指Offer 41 数据流中的中位数
    剑指Offer 59 队列的最大值
    剑指Offer 12 矩阵中的路径
    剑指Offer 13 机器人的运动范围
    剑指Offer 42 连续子数组的最大和
    一句话总结随机森林
    一句话总结卷积神经网络
    一句话总结K均值算法
  • 原文地址:https://www.cnblogs.com/Turing-dz/p/13238247.html
Copyright © 2020-2023  润新知