Advertisement

【GANs】Conditional Generative Adversarial Nets

阅读量:

【GANs】Conditional Generative Adversarial Nets

  • 2 CGAN
    • 2.1 CGAN简介

      • 前言
      • 流程图
      • 目标函数
    • 2.2 CGAN代码

2 CGAN

2.1 CGAN简介

条件生成对抗网络(Conditional GANs)是一种先进的深度学习模型框架

本文提出了一种基于条件生成对抗网络(CGAN)的改进方法。针对条件生成对抗网络(CGAN)模型而言:在构建模型时,在输入数据中引入了对应的标签信息,并将标签信息同时加入到生成器(G)和判别器(D)的输入端。随后通过分别设计两种不同的训练策略完成了两组有条件属性下的实验验证。即根据给定的特定属性或类别标签(y),结合随机噪声或其他分布信息来生成相应的样本数据。

1.mnist数据集作为输入标签创建特定数字图像的任务。
2.在多模态学习场景中识别与训练数据无关的关键特征。

前言

在先前介绍的无条件GAN架构中,生成的数据具有不可控性特征。通过代码运行结果可以看出,该网络仅能输出范围限定在0 \sim 9之间的整数。然而,在这种情况下,我们无法确定具体是哪一个数值。值得注意的是,在本文研究的基础上提出了一种基于class label的新方法:本文提出的基于class label的CGAN模型能够精准地生成指定类别的数字图像。

在one-to-many映射模型中,在image tag问题中存在挑战:一张图片可能带有多个tag;传统方法难以处理这种多标签情况;基于这一需求,在图像识别领域提出了基于条件生成的概率模型:将图像视为condition variable,并通过基于condition prediction distribution的方法建立一对多的映射关系。

CGAN在图像修复、多模态深度学习等多个领域中均有应用。目前在这些研究领域内已取得了较为深入的发展。

流程图

请添加图片描述

*D判别器除了输入图像之外还引入了y标签。
其中包含的维度与x一致,并且这是因为模型内部采用了嵌入处理。
随后将生成的图像的一半作为输入与其他特征结合后供给D判别器。

目标函数

GAN
\begin{align} {^{min}_{\space\space\space G}} {^{max}_{\space\space\space D}} V(D,G)=E_{x \sim P_{data}(x)}[logD(x)] + E_{z \sim P_{z}(z)}[log(1-D(G(z)))] \end{align}
CGAN
\begin{align} {^{min}_{\space\space\space G}} {^{max}_{\space\space\space D}} V(D,G)=E_{x \sim P_{data}(x)}[logD(x|y)] + E_{z \sim P_{z}(z)}[log(1-D(G(z|y)))] \end{align}
可以看出,CGAN引入条件y,在已知y条件的情况下计算样本x的特征分布。

2.2 CGAN代码

复制代码
    # -*- coding = utf-8 -*-
    # @Time    : 2022/9/27 14:05
    # @Author  : VvV
    # @File    : CGAN_2014.py
    import numpy as np
    import matplotlib.pyplot as plt
    from tensorflow.keras.models import Sequential, Model
    from tensorflow.keras.layers import Dense, LeakyReLU, BatchNormalization, Reshape
    from tensorflow.keras.layers import Input, Embedding, Flatten, multiply, Dropout
    from tensorflow.keras.datasets import mnist
    from tensorflow.keras.optimizers import Adam
    
    
    class CGAN():
    def __init__(self):
        # 写入输入维度
        self.img_rows = 28
        self.img_cols = 28
        self.img_channels = 1
        self.img_shape = (self.img_rows, self.img_cols, self.img_channels)
    
        self.num_classes = 10    # 类别数
        self.latent_dim = 100
    
        optimizer = Adam(0.0002, 0.5)
        self.generator = self.build_generator()
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss=['binary_crossentropy'],
                                   optimizer=optimizer,
                                   metrics=['accuracy'])
    
        self.discriminator.trainable = False
        noise = Input(shape=(100,))
        label = Input(shape=(1,))
    
        img = self.generator([noise, label])
    
        valid = self.discriminator([img, label])
    
        self.combined = Model([noise, label], valid)
        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'))
        model.add(Reshape(self.img_shape))
    
        model.summary()      # 记录参数情况
    
        noise = Input(shape=self.latent_dim)
        label = Input(shape=(1,), dtype='int32')
    
        label_embedding = Flatten()(Embedding(self.num_classes, self.latent_dim)(label))  # 将10个种类(词向量种类)的label映射到latent_dim=100维
        # 将100维转化为(None,100),这里的None会随着batch而改变。
    
        model_input = multiply([noise, label_embedding])  # 合并方法:指定对应位置相乘
    
        img = model(model_input)    # 生成图片
        return Model([noise, label], img)  # 输入按noise和label,合并由内部完成。
    
    def build_discriminator(self):
        model = Sequential()
        model.add(Dense(512, input_dim=np.prod(self.img_shape)))  # 784个输入神经元
        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))
        model.add(Dense(1, activation='sigmoid'))   # activation
    
        model.summary()
        img = Input(shape=self.img_shape)
        label = Input(shape=(1,), dtype='int32')
    
        # label与img 的shape不同
        label_embedding = Flatten()(Embedding(self.num_classes, np.prod(self.img_shape))(label))
        # label_embedding shape (None, 784)
        flat_img = Flatten()(img)
    
        model_input = multiply([flat_img, label_embedding])  # 完成对应元素相乘,shape(None, 784)
    
        validity = model(model_input)  # 获取输出概率结果
    
        return Model([img, label], validity)  # 注意:合并和维度操作是由模型内部完成
    
    def train(self, epochs, batch_size=128, sample_interval=50):
        # 获取数据集
        (X_train, Y_train,), (_, _) = mnist.load_data()
    
        # 将获取到的图像转化为(-1,1)
        X_train = (X_train.astype(np.float32) - 127.5) / 127.5
        X_train = np.expand_dims(X_train, axis=3)
        # 将60000*28*28维度的图像拓展为60000*28*28*1
    
        # 将Y_train reshape成60000*1
        Y_train = Y_train.reshape(-1, 1)  # -1自动计算第0维的维度空间数
    
        # 写入 真实输出 与 虚假输出
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))
    
        for epoch in range(epochs):
    
            # 训练判别器
    
            # 从0-6w中随机获取batch_size个索引数
            idx = np.random.randint(0, X_train.shape[0], batch_size)
            imgs, labels = X_train[idx], Y_train[idx]
            # 完成随机获取batch_size个图像对应的标签
            # imgs shape (batch_size,28,28,1)
            # labels shape (32,1)
    
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))
            # 符合正态分布, shape (batch_size,100)
    
            gen_imgs = self.generator.predict([noise, labels])
    
            d_loss_real = self.discriminator.train_on_batch([imgs, labels], valid)
            d_loss_fake = self.discriminator.train_on_batch([gen_imgs, labels], fake)
            d_loss = 0.5*np.add(d_loss_fake, d_loss_real)
    
            # 训练生成器
            sampled_label = np.random.randint(0, 10, batch_size).reshape(-1, 1)
            # 固定鉴别器,训练生成器 在联合模型中
            g_loss = self.combined.train_on_batch([noise, sampled_label], 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 = 2, 5
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        sampled_labels = np.arange(0, 10).reshape(-1, 1)
    
        gen_imgs = self.generator.predict([noise, sampled_labels])
    
        # Rescale image 0 - 1
        gen_imgs = 0.5 * gen_imgs + 0.5
    
        fig, axs = plt.subplots(r, c)
        cnt = 0
        for i in range(r):
            for j in range(c):
                axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].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__':
    cgan = CGAN()
    cgan.train(epochs=20000, batch_size=32, sample_interval=200)

tree

复制代码
    test
    │  CGAN_2014.py
    └─ images
在这里插入图片描述

全部评论 (0)

还没有任何评论哟~