tensorflow2 tf2 GAN算法生成图片

生成对抗网络,原理很简单,但效果出奇的好,

文章的代码是从网上找的资源使用,数据太难收集了,代码运行5次以后就能有明显的效果了,但是数据量有限,后续进步就有限了

代码所用的数据,模型和生成测试图片部分借鉴了网上的,懒得收集写,但不知道谁写的,很多文章都是一样的,也没法感谢了

gan的思路很直接,一个生成图片的生成器,一个判断图片真伪的判断器

用真图片和生成器生成的假图片去优化判断器

然后用生成器生成的假图片去糊弄判断器,用成功糊弄的结果去优化生成器

两个模型竞争,共同进步

缺点:

训练过程中很不稳定,修改一下参数希望更快或者更加精细,反而直接崩掉

而且很容易就走入误区,生成结果很差时容易直接崩掉,长时间训练也无法改善

训练使用的图片

生成的图片

代码结构

 代码:

GitHub - cjs199/gan

from argparse import Action
import tensorflow as tf
import glob
import numpy as np
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from PIL import Image
from tensorflow.keras import layers, datasets, optimizers, losses, Sequential, Model


# 需要放在tensorflow调用前 , 动态显存,不要全部占用
os.environ["TF_FORCE_GPU_ALLOW_GROWTH"] = "true"
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
    tf.config.experimental.set_memory_growth(gpu, True)


class Generator(Model):
    # 生成器网络类
    def __init__(self):
        super(Generator, self).__init__()
        self.conv1 = layers.Conv2DTranspose(
            filter * 8, 4, 1, 'valid', use_bias=False)
        self.bn1 = layers.BatchNormalization()
        self.conv2 = layers.Conv2DTranspose(
            filter * 4, 4, 2, 'same', use_bias=False)
        self.bn2 = layers.BatchNormalization()
        self.conv3 = layers.Conv2DTranspose(
            filter * 2, 4, 2, 'same', use_bias=False)
        self.bn3 = layers.BatchNormalization()
        self.conv4 = layers.Conv2DTranspose(
            filter * 1, 4, 2, 'same', use_bias=False)
        self.bn4 = layers.BatchNormalization()
        self.conv5 = layers.Conv2DTranspose(3, 4, 2, 'same', use_bias=False)

    def call(self, inputs, training=None):
        x = inputs
        x = tf.reshape(x, (x.shape[0], 1, 1, x.shape[1]))
        x = tf.nn.leaky_relu(x)
        x = tf.nn.leaky_relu(self.bn1(self.conv1(x), training=training))
        x = tf.nn.leaky_relu(self.bn2(self.conv2(x), training=training))
        x = tf.nn.leaky_relu(self.bn3(self.conv3(x), training=training))
        x = tf.nn.leaky_relu(self.bn4(self.conv4(x), training=training))
        x = self.conv5(x)
        x = tf.tanh(x)
        return x


class Discriminator(Model):
    # 判别器类
    def __init__(self):
        super(Discriminator, self).__init__()
        self.conv1 = layers.Conv2D(filter, 4, 2, 'valid', use_bias=False)
        self.bn1 = layers.BatchNormalization()
        self.conv2 = layers.Conv2D(filter * 2, 4, 2, 'valid', use_bias=False)
        self.bn2 = layers.BatchNormalization()
        self.conv3 = layers.Conv2D(filter * 4, 4, 2, 'valid', use_bias=False)
        self.bn3 = layers.BatchNormalization()
        self.conv4 = layers.Conv2D(filter * 8, 3, 1, 'valid', use_bias=False)
        self.bn4 = layers.BatchNormalization()
        self.conv5 = layers.Conv2D(filter * 16, 3, 1, 'valid', use_bias=False)
        self.bn5 = layers.BatchNormalization()
        self.pool = layers.GlobalAveragePooling2D()
        self.flatten = layers.Flatten()
        self.fc = layers.Dense(1)

    def call(self, inputs, training=None):
        x = tf.nn.leaky_relu(self.bn1(self.conv1(inputs), training=training))
        x = tf.nn.leaky_relu(self.bn2(self.conv2(x), training=training))
        x = tf.nn.leaky_relu(self.bn3(self.conv3(x), training=training))
        x = tf.nn.leaky_relu(self.bn4(self.conv4(x), training=training))
        x = tf.nn.leaky_relu(self.bn5(self.conv5(x), training=training))
        x = self.pool(x)
        x = self.flatten(x)
        x = self.fc(x)
        return x


def create_data():
    # 加载所有图片的路径
    img_path_arr = glob.glob(r'.\faces\*.jpg')
    all_image_paths = [str(path) for path in list(img_path_arr)]

    def handler(img_path):
        image = tf.io.read_file(img_path)
        image = tf.io.decode_jpeg(image, channels=3)
        image = tf.image.resize(image, [64, 64])
        return tf.cast(tf.cast(image, dtype=tf.float64) / 127.5 - 1, dtype=tf.float64)

    return tf.data.Dataset.from_tensor_slices(all_image_paths).map(handler).batch(batch_size)


def save_result(val_out, val_block_size, image_path, color_mode):
    def preprocess(img):
        img = ((img + 1.0) * 127.5).astype(np.uint8)
        return img
    preprocesed = preprocess(val_out)
    final_image = np.array([])
    single_row = np.array([])
    for b in range(val_out.shape[0]):
        # concat image into a row
        if single_row.size == 0:
            single_row = preprocesed[b, :, :, :]
        else:
            single_row = np.concatenate(
                (single_row, preprocesed[b, :, :, :]), axis=1)
        # concat image row to final_image
        if (b+1) % val_block_size == 0:
            if final_image.size == 0:
                final_image = single_row
            else:
                final_image = np.concatenate((final_image, single_row), axis=0)
            # reset single row
            single_row = np.array([])
    if final_image.shape[2] == 1:
        final_image = np.squeeze(final_image, axis=2)
    Image.fromarray(final_image).save(image_path)


batch_size = 8 * 12
filter = 64
learning_rate = 0.002    # 学习率
epochs = 30000
index = 0
z_dim = 100
if __name__ == '__main__':
    tf.test.is_gpu_available()
    # 创建数据
    np_image_arr = create_data()
    # 生成器,根据一些随机数,生成一个图像,输入4,100 维,4表示个数,100是随机数
    generator = Generator()
    generator.build(input_shape=(4, z_dim))
    # 判断器,判断是真还是假
    discriminator = Discriminator()
    discriminator.build(input_shape=(None, 64, 64, 3))
    # 确定学习率
    g_optimizer = tf.optimizers.Adam(learning_rate=learning_rate, beta_1=0.5)
    d_optimizer = tf.optimizers.Adam(learning_rate=learning_rate, beta_1=0.5)
    is_training = True
    for epoch in range(epochs):
        # 生成随机数,以供生成器生成
        uniform_data = tf.random.uniform(
            [batch_size, z_dim], minval=-1., maxval=1.)
        for step, true_img in enumerate(np_image_arr):
            # 虽然每次都会拉取 batch_size 个参数,但是最后一批数据不足 batch_size 时,将会少于
            cut_uniform_data = uniform_data[0: true_img.shape[0]]
            # 训练判断器
            with tf.GradientTape() as tape:
                # 生成器生成图片
                generator_fake_img = generator(cut_uniform_data, is_training)
                # 判断器判断
                # 判断生成器生成的假图片,判断器判断对错的结果
                fake_img_true_or_false = discriminator(
                    generator_fake_img, is_training)
                # 判断生成器生成的真图片,判断器判断对错的结果
                true_img_true_or_false = discriminator(true_img, is_training)
                # 计算损失
                # 判断假图片判断错误的损失
                fake_img_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=fake_img_true_or_false,
                                                                        labels=tf.zeros_like(fake_img_true_or_false))
                fake_img_loss = tf.reduce_mean(fake_img_loss)
                # 判断真图片判断错误的损失
                true_img__loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=true_img_true_or_false,
                                                                         labels=tf.ones_like(true_img_true_or_false))
                true_img__loss = tf.reduce_mean(true_img__loss)
                d_loss = fake_img_loss + true_img__loss
            # 更新调参
            grads = tape.gradient(d_loss, discriminator.trainable_variables)
            d_optimizer.apply_gradients(
                zip(grads, discriminator.trainable_variables))
            # 训练生成器
            with tf.GradientTape() as tape:
                # 生成器生成假图
                fake_image = generator(cut_uniform_data, is_training)
                # 判断器判断假图中被判断为真的图片
                fake_image_true_or_false = discriminator(
                    fake_image, is_training)
                # 依据,生成器生成的假图片,成功欺骗判断器判断为真
                fake_image_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=fake_image_true_or_false,
                                                                          labels=tf.ones_like(fake_image_true_or_false))
                g_loss = tf.reduce_mean(fake_image_loss)
            # 更新调参
            grads = tape.gradient(g_loss, generator.trainable_variables)
            g_optimizer.apply_gradients(
                zip(grads, generator.trainable_variables))
        # 每次结束,打印一下损失
        print(epoch, '判断器损失:', float(d_loss),
              '生成器损失:', float(g_loss))

        # 准备生成演示图片
        uniform_data = tf.random.uniform([100, z_dim])
        # 生成假图片
        fake_image = generator(uniform_data, training=False)
        # 加载保存路径
        img_path = os.path.join('images', 'gan-%d.png' % index)
        index += 1
        # 处理图片,并保存
        save_result(fake_image.numpy(), 10, img_path, color_mode='P')

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GAN(Generative Adversarial Networks)是一种深度学习算法,用于生成与训练数据类似的新数据。GAN包括两个神经网络:生成器和判别器。生成器从随机噪声中生成新的数据样本,而判别器则评估这些样本是否与训练数据匹配。这两个网络相互竞争,并在训练过程中不断改进,直到生成生成的样本与真实数据的差异最小化。 TensorFlow是一种流行的深度学习框架,其中包含了GAN的实现。TensorFlow提供了一些内置的GAN模型,包括DCGAN、CGAN、WGAN等,同时也支持用户自定义GAN模型。 要使用TensorFlow实现GAN,你需要定义生成器和判别器的架构,以及损失函数和优化器。然后,你可以将真实数据与生成生成的数据输入到判别器中进行训练,以提高判别器的准确性和生成生成的样本的质量。最终,你可以使用生成生成与训练数据类似的新数据。 下面是一个简单的TensorFlow GAN实现示例: ``` import tensorflow as tf from tensorflow.keras import layers # 定义生成器 def make_generator_model(): model = tf.keras.Sequential() model.add(layers.Dense(256, use_bias=False, input_shape=(100,))) model.add(layers.BatchNormalization()) model.add(layers.LeakyReLU()) model.add(layers.Dense(512, use_bias=False)) model.add(layers.BatchNormalization()) model.add(layers.LeakyReLU()) model.add(layers.Dense(784, activation='tanh')) return model # 定义判别器 def make_discriminator_model(): model = tf.keras.Sequential() model.add(layers.Dense(512, input_shape=(784,))) model.add(layers.LeakyReLU()) model.add(layers.Dropout(0.3)) model.add(layers.Dense(256)) model.add(layers.LeakyReLU()) model.add(layers.Dropout(0.3)) model.add(layers.Dense(1)) 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): noise = tf.random.normal([BATCH_SIZE, 100]) with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: generated_images = generator(noise, training=True) real_output = discriminator(images, training=True) fake_output = discriminator(generated_images, 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_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data() train_images = train_images.reshape(train_images.shape[0], 784).astype('float32') train_images = (train_images - 127.5) / 127.5 # 将像素值归一化到[-1, 1]之间 BUFFER_SIZE = 60000 BATCH_SIZE = 256 train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE) # 创建生成器和判别器 generator = make_generator_model() discriminator = make_discriminator_model() # 训练GAN模型 EPOCHS = 50 for epoch in range(EPOCHS): for image_batch in train_dataset: train_step(image_batch) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值