CGAN——生成0-9数字图像(Tensorflow+mnist)

1、简介

  • 传统的GAN或者其他的GAN都是通过一堆的训练数据,最后训练出了生成网络,随机输入噪声最后产生的数据是这些训练数据类别中之一,无法提前预测生成的是哪个类别。
  • 如果需要定向指定生成某些数据,比如想生成飞机,数字9等指定类别的图片,就需要利用CGAN——条件生成对抗网络
  • 本文利用CGAN,输入带有标签的数字图像,训练后,再生成对应标签的图像。
  • 数据集:mnist
  • 框架:tensorflow

2、代码

  • import numpy as np
    from keras.models import Sequential, Model
    from keras.layers import Dense, LeakyReLU, BatchNormalization, Reshape
    from keras.layers import Input, Embedding, Flatten, multiply, Dropout
    from keras.datasets import mnist
    from keras.optimizers import Adam
    import matplotlib.pyplot as plt
    import matplotlib
    
    
    # 条件对抗生成网络
    class CGAN():
        def __init__(self):
            # 写入输入维度
            self.img_rows = 28  # 行
            self.img_cols = 28  # 列
            self.img_channel = 1  # 通道数
            self.img_shape = (self.img_rows, self.img_cols, self.img_channel)  # 尺寸
    
            self.num_classes = 10  # 类别数
            self.latent_dim = 100  # 噪声大小
    
            optimizer = Adam(0.0002, 0.5)  # 优化器,学习率0.0002
    
            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,
                                  metrics=['accuracy'])
    
        # 生成器
        def build_generator(self):
            model = Sequential()  # 定义网络层
    
            # 第一层
            model.add(Dense(256, input_dim=self.latent_dim))  # 全连接层,256个神经元,输入维度100
            model.add(LeakyReLU(alpha=0.2))  # 激活层
            model.add(BatchNormalization(momentum=0.8))  # BN层,动量0.8
    
            # 第二层
            model.add(Dense(512))  # 全连接层
            model.add(LeakyReLU(alpha=0.2))  # 激活层
            model.add(BatchNormalization(momentum=0.8))  # BN层,动量0.8
    
            # 第三层
            model.add(Dense(1024))  # 全连接层
            model.add(LeakyReLU(alpha=0.2))  # 激活层
            model.add(BatchNormalization(momentum=0.8))  # BN层,动量0.8
    
            # 输出层
            model.add(Dense(np.prod(self.img_shape), activation='tanh'))  # 计算图像尺寸,激活函数tanh
            model.add(Reshape(self.img_shape))  # Reshape层,输入的是噪声,需要的是图像,转换为图像
    
            model.summary()  # 记录参数情况
    
            # 定义输入
            noise = Input(shape=(self.latent_dim,))  # 生成器的输入维度
            label = Input(shape=(1,), dtype='int32')  # 生成器的标签维度,1维,类型int
    
            # 使输入Y和X的维度一致。将10个种类的label映射到latent_dim维度
            label_embedding = Flatten()(Embedding(self.num_classes, self.latent_dim)(label))  # 输入维度,输出维度,转换的变量label
            # Flatten() 将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)))  # 全连接层,512个神经元,输入维度784
            model.add(LeakyReLU(alpha=0.2))  # 激活层
    
            # 第二层
            model.add(Dense(512))  # 全连接层
            model.add(LeakyReLU(alpha=0.2))  # 激活层
            model.add(Dropout(0.4))  # Dropout层,防止过拟合,提高泛化性
    
            # 第三层
            model.add(Dense(512))  # 全连接层
            model.add(LeakyReLU(alpha=0.2))  # 激活层
            model.add(Dropout(0.4))  # Dropout层,防止过拟合,提高泛化性
    
            # 输出层
            model.add(Dense(1, activation='sigmoid'))
    
            model.summary()  # 记录参数情况
    
            # 定义输入
            img = Input(shape=self.img_shape)  # 输入图片
            label = Input(shape=(1,), dtype='int32')  # 输入标签
    
            # 使输入Y和X的维度一致。Flatten() 将100维转化为(None, 784),这里None会随着batch而改变
            label_embedding = Flatten()(Embedding(self.num_classes, np.prod(self.img_shape))(label))  # 输入维度,输出维度,转换的变量label
            flat_img = Flatten()(img)
    
            # 将图片和类别合并
            model_input = multiply([flat_img, label_embedding])  # 合并方法:对应位置相乘
    
            # 模型输出结果
            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
    
            # 将标签大小变为60000*1
            Y_train = Y_train.reshape(-1, 1)  # -1自动计算第0维的维度空间数
    
            # 写入 真实输出 与 虚假输出
            valid = np.ones((batch_size, 1))  # 每行为一张图片
            fake = np.zeros((batch_size, 1))  # 每行为一张图片
            # imgs shape(batch_size, 28, 281)
            # labels shape(32, 1)
    
            for epoch in range(epochs):
                # 训练判别器
                # 从0~60000随机获取batch_size个索引数
                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))  # 产生随机噪声
    
                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_real, d_loss_fake)
    
                # 训练生成器
                sample_label = np.random.randint(0, 10, batch_size).reshape(-1, 1)  # 随机生成样本标签
    
                # 固定判别器,训练生成器——在联合模型中
                g_loss = self.combined.train_on_batch([noise, sample_label], valid)  # 生成器随机生成的图像和随机产生的标签,骗过判别器
    
                # 绘制进度图
                print("%d [D loss: %f, acc: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], d_loss[1] * 100, g_loss[0]))
    
                # 每50次保存图像
                if (epoch + 1) % sample_interval == 0:
                    self.sample_images(epoch)
    
                # 每训练5000次保存模型
                if (epoch + 1) % 5000 == 0:
                    self.save_models(epoch)
    
        def sample_images(self, epoch):
            r, c = 2, 5  # 输出 2行5列的10张指定图像
            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])
    
            # Rescale images -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(f"images/sd{epoch+1}.png")  # 文件路径和代码文件同目录
            plt.close()
    
        def save_models(self, epoch):
            self.generator.save(f"models/generator_epoch_{epoch+1}.h5")
            self.discriminator.save(f"models/discriminator_epoch_{epoch+1}.h5")
            self.combined.save(f"models/combined_epoch_{epoch+1}.h5")
    
    
    if __name__ == '__main__':
        matplotlib.use('TkAgg')  # 设置后端为TkAgg
        cgan = CGAN()
        # 训练轮数20000,一次处理32张图片,每200保存一次生成的已知标签的生成图像
        cgan.train(epochs=20000, batch_size=32, sample_interval=200)
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: CGAN,全称为Conditional Generative Adversarial Networks,是一种在生成对抗网络(GAN)的基础上进行优化的算法,它可以根据传入的条件信息来生成特定类型的数据。在这个算法中,生成器和判别器都会接收一个额外的条件输入参数。 TensorFlow是一个广泛使用的深度学习框架,它提供了各种各样的函数和类来简化CGAN模型的实现过程。以下是一个使用TensorFlow实现CGAN的代码示例: ``` import tensorflow as tf import numpy as np # 定义生成器和判别器的输入形状 noise_dim = 100 label_dim = 10 # 定义生成器的函数 def make_generator_model(): model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(256, input_dim=noise_dim + label_dim, activation='relu')) model.add(tf.keras.layers.BatchNormalization()) model.add(tf.keras.layers.Dense(512, activation='relu')) model.add(tf.keras.layers.BatchNormalization()) model.add(tf.keras.layers.Dense(28 * 28 * 1, activation='sigmoid')) model.add(tf.keras.layers.Reshape((28, 28, 1))) return model # 定义判别器的函数 def make_discriminator_model(): model = tf.keras.Sequential() model.add(tf.keras.layers.Flatten(input_shape=(28, 28, 1))) model.add(tf.keras.layers.Dense(512, activation='relu')) model.add(tf.keras.layers.Dense(256, activation='relu')) model.add(tf.keras.layers.Dense(1, activation='sigmoid')) return model # 定义损失函数 cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) def discriminator_loss(real_output, fake_output): real_loss = cross_entropy(tf.ones_like(real_output), real_output) fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output) total_loss = real_loss + fake_loss return total_loss def generator_loss(fake_output): return cross_entropy(tf.ones_like(fake_output), fake_output) # 定义优化器 generator_optimizer = tf.keras.optimizers.Adam(1e-4) discriminator_optimizer = tf.keras.optimizers.Adam(1e-4) # 定义训练过程 @tf.function def train_step(images, labels): noise = tf.random.normal([batch_size, noise_dim]) with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: fake_labels = tf.random.uniform([batch_size, 1], maxval=label_dim, dtype=tf.int32) fake_labels = tf.one_hot(tf.reshape(fake_labels, [-1]), label_dim) generated_images = generator(tf.concat([noise, fake_labels], axis=1), training=True) real_output = discriminator(tf.concat([images, labels], axis=1), training=True) fake_output = discriminator(tf.concat([generated_images, fake_labels], axis=1), training=True) gen_loss = generator_loss(fake_output) disc_loss = discriminator_loss(real_output, fake_output) gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables) gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables) generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)) discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) # 进行训练 EPOCHS = 100 batch_size = 128 generator = make_generator_model() discriminator = make_discriminator_model() for epoch in range(EPOCHS): for i in range(train_images.shape[0]//batch_size): images = train_images[i*batch_size:(i+1)*batch_size] labels = train_labels[i*batch_size:(i+1)*batch_size] train_step(images, labels) # 生成一些带有特定标签的图像 noise = tf.random.normal([10, noise_dim]) cond_labels = np.eye(label_dim)[np.arange(10)] generated_images = generator(tf.concat([noise, cond_labels], axis=1), training=False) ``` 上面的代码中,我们定义了生成器和判别器的模型结构和优化器。在训练过程中,我们使用TensorFlow的`GradientTape`记录损失函数的梯度,并根据反向传播算法来更新模型的参数,最终得到一个可以生成特定标签图像CGAN模型。 ### 回答2: CGAN是一种生成对抗网络,可以用来生成符合特定条件(如标签)的图像Tensorflow作为一款流行的神经网络框架,可以实现CGAN网络。本文将介绍如何使用tensorflow实现CGAN的简单示例代码。 首先,我们需要准备数据集和标签。这里我们以MNIST手写数字数据集为例,选择其中的数字4和9作为我们的标签。我们使用tensorflow内置的MNIST数据集,然后创建两个新的数据集,一个只包含数字4的图片,另一个只包含数字9的图片。 接下来,我们需要编写CGAN网络的模型。我们假设生成器和判别器都是以卷积神经网络作为基础。 生成器是一个卷积神经网络,输入为一个噪声向量和标签,输出为一个28x28的图像。为了获得更好的效果,我们采用了ResNet的结构。 判别器是另一个卷积神经网络,输入为一个28x28的图像和标签,输出为一个二元值,表示输入是否是真实的图像。同时,我们也采用了ResNet的结构来提高判别器的性能。 我们将生成器和判别器组合起来,并使用交叉熵损失函数来优化网络的性能。 最后,我们需要编写训练代码,对生成器和判别器进行训练。我们使用Adam优化器,对损失函数进行优化,并将生成图像保存在本地文件夹中。 在运行训练代码之后,我们可以得到生成生成的样本图像,观察生成图像是否符合我们的标签条件,以此来评估CGAN网络的性能。 以上就是使用tensorflow实现CGAN网络的简单示例代码,该代码可以用于生成符合特定条件的图像。当然,如果要应用到更复杂的数据集和场景中,需要对代码进行相应的修改和优化。 ### 回答3: CGAN是一种深度学习模型,它能够生成新的图像数据,同时还能对生成图像的样式进行控制。在TensorFlow中实现CGAN的代码实例如下: 首先,需要加载一些必要的库,如numpy,matplotlib和tensorflow: import numpy as np import matplotlib.pyplot as plt import tensorflow as tf 接着,定义生成器和判别器网络。生成器网络将输入的随机向量转化成一张图像,而判别器网络则将输入的图像打上真或假的标签: def generator_model(): model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(7*7*256, input_shape=(100,))) model.add(tf.keras.layers.Reshape((7, 7, 256))) model.add(tf.keras.layers.BatchNormalization()) model.add(tf.keras.layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same')) model.add(tf.keras.layers.BatchNormalization()) model.add(tf.keras.layers.LeakyReLU()) model.add(tf.keras.layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same')) model.add(tf.keras.layers.BatchNormalization()) model.add(tf.keras.layers.LeakyReLU()) model.add(tf.keras.layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', activation='tanh')) return model def discriminator_model(): model = tf.keras.Sequential() model.add(tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1])) model.add(tf.keras.layers.LeakyReLU()) model.add(tf.keras.layers.Dropout(0.3)) model.add(tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same')) model.add(tf.keras.layers.LeakyReLU()) model.add(tf.keras.layers.Dropout(0.3)) model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(1)) return model 接下来,我们定义CGAN的训练过程。由于本次训练中将会用到真实图像生成图像,因此需要定义d_loss和g_loss,使之能够同时对真实图像生成图像进行优化: @tf.function def train_step(images, labels): noise = tf.random.normal([BATCH_SIZE, LATENT_DIM]) with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: generated_images = generator([noise, labels], training=True) real_output = discriminator([images, labels], training=True) fake_output = discriminator([generated_images, labels], training=True) gen_loss = generator_loss(fake_output) disc_loss = discriminator_loss(real_output, fake_output) gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables) gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables) generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)) discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) 在定义好train_step之后,我们可以通过循环来进行训练。在每个epoch结束后,我们会将生成生成的示例图像和损失输出到终端: def train(dataset, epochs): for epoch in range(epochs): for image_batch, label_batch in dataset: train_step(image_batch, label_batch) display.clear_output(wait=True) generate_and_save_images(generator, epoch + 1, test_labels) print ('Time for epoch {} is {} sec'.format(epoch + 1, time.time()-start)) display.clear_output(wait=True) generate_and_save_images(generator, epochs, test_labels) train(train_dataset, EPOCHS) 最后是完整的训练代码:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恣睢s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值