$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

那些说不完的 GAN - Generative Adversarial Networks

  在 2014 年之前,最广泛使用的机器学习方式是监督学习( Supervised Learning )。在特定的分类任务中,经过训练之后,监督学习通常能够得到比人类更高的准确性。然而,监督学习过于依赖人类为每个输入设置想要的输出并且有些模型需要大量的训练数据集。于是,许多研究人员开始研究无监督学习。

  Ian Goodfellow 于 2014 年正式提出对抗生成网络( Generative Adversarial Networks )的概念,相较于传统建模困难的生成式网络,通过无监督学习的方式,GAN 使得生成式网络的发展取得了前所未有的进步。

  GAN 基于博弈论思想,其中含有两个模块:生成器( Generator )和判别器( Discriminator )。

  在生成器当中,隐式定义了一个概率分布P_model(X),在 GAN 不断训练的过程中,生成器会不断调整自己的概率分布P_model(X)来不断靠近真实数据的概率分布P_data(X)。尽管生成器不一定可以计算密度函数。在判别器中,判别器会检查来自生成器的样本 X 并返回概率估计 D(x;θ(D)) 表示 X 是真还是假。

  在传统的机器学习中,已知某一组数据的分布类型,但是却不了解具体的参数,此时就可以通过定义一个模型,通过训练来学习参数。而 GAN 可以在不知道数据初始分布类型的情况下,自动学习原始数据集的分布。

  使用 mnist 手写数据集来写一个简单的 GAN,使得生成器网络可以对任意输出入的噪声,产生相应的数字图片。

#代码参考来源:https://blog.csdn.net/qq_36758914/article/details/104613596
#tensorflow 2.10.0, Python 3.9

import tensorflow as tf
import keras
from keras import layers, datasets
import matplotlib.pyplot as plt

#超参数的定义
Batch_Size = 128
Epoches = 100
Noise_Dim = 100 #噪音的数量
Learning_Rate = 0.0001
Buffer_Size = 60000
seed = tf.random.normal([16, Noise_Dim])  # 16组随机数组,每组含100个随机数,用来生成16张图片。


#获取mnist数据集并对数据进行处理
(train_images, train_labels), (_, _) = datasets.mnist.load_data()
train_images = train_images / 255.0     #数据归一化
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
#在第一个维度进行切分,生成 train_images.shape[0] 多的 tensord dataset
datasets = tf.data.Dataset.from_tensor_slices(train_images)
#从Buffer_Size大小的数据中随机选取填充缓冲区实现选取,合并成 Batch_Size大小
datasets = datasets.shuffle(Buffer_Size).batch(Batch_Size)

#建立生成器
def Generator():
    model = keras.Sequential([
        layers.Dense(256, input_shape=(100,), use_bias= False),
        layers.BatchNormalization(),
        layers.LeakyReLU(),

        layers.Dense(512, use_bias=False),
        layers.BatchNormalization(),
        layers.LeakyReLU(),

        layers.Dense(28*28*1, use_bias=False, activation='tanh'),
        layers.BatchNormalization(),

        layers.Reshape((28,28,1))
    ])
    return model

#建立判别器
def Discriminator():
    model = keras.Sequential([
        layers.Flatten(),

        layers.Dense(512, use_bias=False),
        layers.BatchNormalization(),
        layers.ReLU(),

        layers.Dense(256, use_bias=False),
        layers.BatchNormalization(),
        layers.ReLU(),

        layers.Dense(1)
    ])
    return model

#定义各自的优化函数
generator_opt = keras.optimizers.Adam(Learning_Rate)
discriminator_opt = keras.optimizers.Adam(Learning_Rate)

#定义损失函数,二进制交叉熵适用于二分类问题
cross_entropy = keras.losses.BinaryCrossentropy(from_logits=True)

def discriminator_loss(real_out, fake_out):
    #real_out是判别器对数据集图片的输出,fake_out是判别器对生成图片的输出
    real_loss = cross_entropy(tf.ones_like(real_out), real_out)
    fake_loss = cross_entropy(tf.zeros_like(fake_out), fake_out)
    return real_loss + fake_loss

def generator_loss(fake_out):
    return cross_entropy(tf.ones_like(fake_out), fake_out)

#实例化生成器和判别器
generator = Generator()

discriminator = Discriminator()

#定义模型训练过程
def train():
    for epoch in range(Epoches):
        for image_batch in datasets:
            #生成随机数来生成图片
            noise = tf.random.normal([Batch_Size, Noise_Dim])

            with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
            #等价于:gen_tape = tf.GradientTape(), disc_tape = tf.GradientTape()
                real_out = discriminator(image_batch, training=True)

                gen_image = generator(noise, training=True)
                fake_out = discriminator(gen_image, training=True)

                gen_loss = generator_loss(fake_out)
                disc_loss = discriminator_loss(real_out, fake_out)
            #进行梯度的计算与更新
            gradient_gen = gen_tape.gradient(gen_loss, generator.trainable_variables)
            gradient_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
            generator_opt.apply_gradients(zip(gradient_gen, generator.trainable_variables))
            discriminator_opt.apply_gradients(zip(gradient_disc, discriminator.trainable_variables))
            print('starting ...')
        if(epoch%10 == 0):
            print('Epoch:{}'.format(epoch))
            generate_plot_image(generator, seed)

def generate_plot_image(gen_model, test_noise):
    pre_images = gen_model(test_noise, training=False)
    fig = plt.figure(figsize=(4, 4))
    for i in range(pre_images.shape[0]):
        plt.subplot(4, 4, i+1)
        plt.imshow((pre_images[i, :, :, 0] + 1)/2, cmap='gray')
        plt.axis('off')
    plt.show()

if __name__ == '__main__':
    train()

 GAN 训练结果;

 

posted @ 2023-09-13 10:59  素衣叹风尘  阅读(23)  评论(0)    收藏  举报