理解生成对抗网络(GAN)的基本原理及工作方式

生成对抗网络(GAN)的基本原理与工作方式

生成对抗网络(GAN)是一种用于生成新数据的无监督学习模型。它由一个生成器(Generator)和一个鉴别器(Discriminator)组成,两者相互对抗并逐渐改进,使得生成器能够生成更逼真的假数据。下面将详细介绍GAN的算法原理、公式推导、计算步骤,以及附上Python代码示例和解释。

算法原理

生成对抗网络的目标是学习数据的真实分布,从而能够生成与真实数据相似的新样本。假设我们的数据来自一个未知的分布P_data(X),生成器通过学习这个分布以生成假数据。鉴别器则被训练用于区分真实数据和由生成器生成的假数据。

生成器的目标是最大化鉴别器无法区分真假数据的概率,即最大化:

$L(G, D) = E_{x \sim P_data}[log(D(x))] + E_{z \sim P_z}[log(1 – D(G(z)))]$

这里,G表示生成器,D表示鉴别器,x表示真实数据,z表示从先验分布P_z中随机采样的噪声变量。

同时,鉴别器的目标是最小化其对真实数据和假数据的误差,即最小化:

$L(G, D) = -E_{x \sim P_data}[log(D(x))] – E_{z \sim P_z}[log(1 – D(G(z)))]$

通过交替训练生成器和鉴别器,GAN可以实现生成更逼真数据的目标。

公式推导

首先,我们定义生成器的输入为z,通过一个生成函数G(z)生成假数据。鉴别器的输入为x,通过一个判断函数D(x)判断输入数据的真实性。

我们假设判别函数D(x)是一个二分类问题,使用sigmoid函数将输入映射到0-1之间的概率值。那么,判断输入为真实数据的概率可以表示为:

$P(y=1|x) = D(x)$

判断输入为假数据的概率可以表示为:

$P(y=0|G(z)) = D(G(z))$

代入交叉熵损失函数,可以得到鉴别器的损失函数为:

$L(D) = E_{x \sim P_data}[log(D(x))] + E_{z \sim P_z}[log(1 – D(G(z)))]$

生成器的目标是最大化判别器无法区分真假数据的概率,也就是最小化判别器的损失函数。所以生成器的损失函数为:

$L(G) = -E_{z \sim P_z}[log(1 – D(G(z)))]$

最终,GAN的目标是最小化生成器和鉴别器的总损失函数$L(G, D) = L(D) + L(G)$。

计算步骤

  1. 初始化生成器G和鉴别器D的参数。
  2. 循环训练生成器和鉴别器:
  3. 从真实数据分布中随机采样一批真实数据。
  4. 从先验分布P_z中随机采样一批噪声变量。
  5. 使用生成器G生成一批假数据。
  6. 计算鉴别器D的损失函数,并更新D的参数。
  7. 计算生成器G的损失函数,并更新G的参数。

通过多次迭代训练,生成器能够生成与真实数据分布相似的数据。

Python代码示例

下面是一个简单的基于MNIST数据集的生成对抗网络的Python代码示例。首先,需要导入相关的库和模块:

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers

接下来,定义生成器和鉴别器的网络结构:

def build_generator():
    model = tf.keras.Sequential()
    model.add(layers.Dense(256, input_shape=(100,), use_bias=False))
    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(28*28*1, use_bias=False, activation='tanh'))
    model.add(layers.Reshape((28, 28, 1)))
    return model

def build_discriminator():
    model = tf.keras.Sequential()
    model.add(layers.Flatten(input_shape=(28, 28, 1)))

    model.add(layers.Dense(512, use_bias=False))
    model.add(layers.LeakyReLU())

    model.add(layers.Dense(256, use_bias=False))
    model.add(layers.LeakyReLU())

    model.add(layers.Dense(1, use_bias=False, activation='sigmoid'))
    return model

generator = build_generator()
discriminator = build_discriminator()

接下来,定义损失函数和优化器:

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))

最后,训练模型并生成新样本:

def train(dataset, epochs):
    for epoch in range(epochs):
        for image_batch in dataset:
            train_step(image_batch)

        # 每训练一轮生成并保存一张示例图片
        noise = tf.random.normal([1, 100])
        generated_image = generator(noise, training=False)

        # 保存图片
        plt.imshow(generated_image[0, :, :, 0], cmap='gray')
        plt.savefig('generated_image_epoch_{}.png'.format(epoch+1))
        plt.close()

# 加载MNIST数据集
(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5

# 创建数据集并进行训练
BUFFER_SIZE = 60000
BATCH_SIZE = 256
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
EPOCHS = 50
train(train_dataset, EPOCHS)

这段代码中,首先加载MNIST数据集并进行预处理。然后,在每轮训练的结束生成一张示例图片,并将其保存下来。最后,通过调用train函数进行模型的训练。

以上是生成对抗网络(GAN)的基本原理、算法推导、计算步骤和Python代码示例的详细解释。通过生成对抗网络,我们能够不断改进生成器和鉴别器,从而生成更逼真的新样本。

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/824955/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球