Advertisement

GANs Generative Adversarial Networks Explained

阅读量:

作者:禅与计算机程序设计艺术

1.简介

近年来成为机器学习领域 hottest 的生成对抗网络(GAN)模型之一

本文旨在帮助读者全面了解GANs的基础概念及其相关术语,并深入探讨其工作原理及其实现方案。通过实际案例分析以及结合具体应用场景的探讨,使读者全面掌握GAN的工作机制及其应用价值

2.基本概念术语

2.1 概念

2.1.1 GANs 概览

Generative Adversarial Networks (GANs) is a relatively new deep learning model. It mainly achieves its purpose through the use of a generative network (Generative Network) to replace traditional discriminative networks (Discriminative Network), with the aim of supplementing the data acquisition challenges faced by conventional machine learning methods.

什么叫做数据缺失问题呢?如何界定数据缺失问题?它指的是在现实中存在的数据缺少相应的标签或者不具备可供训练机器学习模型的关键特征。当遇到这种情况时,则可以通过GAN模型系统性地构建高质量、具有创新性的模拟样本集合来补充这一缺口。

基于此,GANs 实际上是一种生成模型的方法论。它能够将源数据映射至或重构为相应的目标分布,并训练出相应的模型参数。从而使得人工标注数据的需求得以缓解;例如,在医疗诊断中用于辅助诊断分析,在图像处理领域用于图像合成与修复,在文本生成方面则用于内容创作与优化。

2.1.2 生成模型概览

生成模型也被称作解码器网络(Decoder-Based Model),这类技术的主要应用是用于生成逼真图像的图像(Image)。其主要功能是在给定输入随机变量时(Input Random Variables),预测相应的样本实例(Sample Instances)。作为无监督学习技术的一种工具,在GANs中扮演着重要角色(Role in GANs)。它通过识别潜在的模式结构(Patterns Structure)来推导出多样化的样本数据(Diverse Sample Data)。这种技术的核心目标是探索可能性空间中的潜在分布特征(Distribution Features)以实现高质量数据生成。

生成模型的目标函数主要采用最大似然估计方法,在这一过程中我们通常会基于以下假设:真实数据集是遵循某个特定的概率分布产生的。因此,在设计生成模型时应尽可能模拟该概率分布的行为模式,并通过优化过程使其能够更好地反映这一分布特征。此外,在实际应用中为了保证生成样本的质量目标得以实现,则需对模型参数进行系统性训练工作,在这一训练过程中我们不仅关注于使生成样本的均值与真实数据相匹配而且也会特别注重其方差特性的一致性。

2.1.3 判别模型概览

判别系统是一种鉴別架构,在接受输入數據時旨在判定這些數據來源於何处的概率分佈;其主要依據為數據之間的差異性強弱來評估它們屬於不同分佈的可能性;该系统主要应用于评估生成系统的输出结果,并判断所生成的数据样本是否符合现实;在此过程中, 判別系統與生成功能需進行對峙訓練, 直至生成功能能达到完美騙骗效果, 使錯誤判定率降至零

判别模型的目标函数一般使用交叉熵损失函数,用于评估生成数据样本与真实数据之间的区分能力。

2.2 术语

2.2.1 信息论基础

首先要了解一下信息论基础,因为 GANs 利用了信息论的一些概念。

Entropy : 在信息论领域中,在概率论和统计学中用(英语:entropy)来衡量一个随机变量的所有可能状态的平均不确定性。这一概念为我们提供了一个量化评估信息不确定性的工具,并且它也能够帮助我们评估系统所处状态的可能性范围大小——这就是所谓的"无知"状态。

假设一个事件 A 发生的概率值为某一数值 p_A ,其信息熵的计算公式表示为 H=-\log_{2} p_A 。亦即,在该事件发生的可能性很低的情况下(即 p_A 较小),其信息熵值将会较大;反过来,在该事件发生的可能性很高(即 p_A 较大)的情况下,则其信息熵值会相应减小。

基于香农定律可知,在自然界中具有最大熵特性的随机事件必然是不可避免的现象。由于任何自然现象的发生都是无法避免的

  1. Mutual Information : 当两个随机变量X和Y之间存在相互作用时, 我们称X对Y所具有的"互信息"关系为I(X;Y). 互信息表征了两个随机变量之间的依赖性, 其计算公式如下所示:

该处求和运算针对所有可能的变量 x 和 y 进行操作,并将每个变量对 (x, y) 的联合发生概率乘以其自然对数(ln)再相加得到结果;右侧分为两项:第一项为 P(x,y)/(P(x)P(y)) 作为分母的部分;第二项为左侧求和的结果。其中将左侧的第一项定义为配对熵概念;右侧则被定义为互信息量。

互信息作为一种衡量两个随机变量间相互依赖关系的有力方法。该方法不仅考虑到两个随机变量之间的独立性、相关性以及统计依赖性,并且在衡量这些复杂关系方面具有显著优势。

  1. KL-divergence : KL 散度是由另一个分布 P 和一个分布 Q 构成的距离指标。其值为非负,并且仅在两个分布相等(P=Q)时其值为零。Kullback-Leibler 散度的具体定义如下:

上式左侧累加表示,在每一个i的位置上分别计算P与Q的概率值,并将其与自然对数相乘。
右侧的意义在于:当P与Q为同一分布时,则KL散度为零;若P与Q为不同分布,则KL散度将大于零。

KL散度是一个用于评估两个概率分布之间差异程度的量化工具。其数值仅在两个分布完全一致时达到最小值零。

2.2.2 深度学习基础

下列是深度学习相关术语:

  1. Neuron : 神经元构成深层网络的基础单元,并具备计算能力,在接收输入信号后进行处理,并通过激活函数判断是否传递信号。

  2. Layer : 层是多个神经元按照特定连接结构组织起来的网络模块。

  3. Activation Function : 激活函数是使神经元产生响应的行为,在神经网络中起到传递信号的关键作用。这些常用的激活函数包括sigmoid、tanh以及ReLU等,在实际应用中各有特点以满足不同的需求。

  4. Loss Function : 损失函数用于评估预测值与实际值之间的差异,并旨在最小化这一差异。典型的损失函数包括均方误差和交叉熵误差等。

Optimization Algorithm : 该算法旨在执行网络参数更新的过程,并其主要功能是确定使损失函数最小化的一组参数。包括但不限于梯度下降法、Adagrad和Adam等典型优化算法。

  1. Backpropagation : 反向传播是一种用于神经网络训练的方法,在由输入层、隐藏层以及输出层层之间构成的网络结构中执行操作。该过程通过使误差自输出端往输入端逐级传递,并沿着网络中的反向路径传递至输入端来实现信息的反馈传播。

3.核心算法原理

3.1 两阶段结构

一般来说,GANs 的模型由两个子模型组成,即生成器和判别器。

生成器网络与判别器网络间展开了一场竞争,在此竞争中双方的性能均达到了最佳水平。两者协同致力于创造特定类型的样本实例。

这一过程可以用下图所示的两阶段结构来描述。

生成阶段(Generation Phase) : 在这一阶段中, 通过使用生成模块, 我们将这些虚假图像输入到判别器中进行验证, 判别器旨在识别这些图像是否为真实存在的. 而我们的目标则是让这个过程尽可能蒙骗判别器, 使其无法准确地区分出哪些图像是真的, 哪些是虚假的.

鉴别阶段(Discrimination Phase) : 此鉴别阶段由鉴别器网络识别出真图与假图。该鉴别器网络旨在辨别真图与假图的区别,并通过此机制引导生成器网络产出质量更高的图像。

3.2 生成器网络

生成器网络也被称为生成网络或解码器网络,并被用来生成新图像的一种神经网络模型。其主要目标是通过学习过程使随机噪声能够在统计特性上几乎一致地映射至与真实图像分布的空间中,并最终成功地生成逼真的图像。

生成网络包含三层结构:编码器、解码器以及关键中间状态。编码器接收原始输入数据,并经过多组卷积操作和平滑化处理来提取出特征描述。随后使用全连接层将这些特征转化为生成网络的关键中间状态。解码器接收关键中间状态,并利用多组卷积操作和平滑化技术最终重构回与原始图像相同的空间尺寸。

下图展示了生成网络的工作流程。

  1. 输入层 :最初阶段接收并处理原始输入信息。
  2. 编码器(Encoder) :通过多层卷积和池化操作提取并整合关键特征。
  3. 中间层 :在编码器输出基础上建立层次化的表征。
  4. 解码器(Decoder) :基于中间表示进行逆向推导以重建与输入尺寸相同的图像。
  5. 输出层 :生成网络经过一系列运算后输出结果还原到原始输入的数据形式中。

3.2.1 抽样

生成器网络在训练过程中会遇到一些难以处理的局部极值点这些问题会显著增加训练难度为了缓解这一挑战在GAN模型中采用了拉普拉斯抽样(Laplace sampling)方法这种方法能有效改善图像质量尤其在默认情况下生成器网络可能无法产生均匀分布且具有明显边缘特征的图像为此通常会采用拉普拉斯抽样的手段以达到更好的效果

拉普拉斯抽样法的过程如下:

  1. 在生成网络的输出中采用等比例分布的方式进行取样操作后产出一张图片。
  2. 将卷积核应用于图片以实现模糊化处理,则其结果即为经过处理后得到的光滑度较高的图像。
  3. 将上述所得结果输入到判别网络中,则其会对该图像做出鉴定,并判断其是否为真实存在的图像。

3.3 判别器网络

判别型神经元组网也可称为鉴真型神经元组网或分辩型神经元组网,在深度学习领域中具有重要地位

判别器网络由三层结构构成:编码器、中间层和解码器。编码器接收输入数据后,经过一系列卷积和池化层处理后生成特征表示。随后,经全连接层将特征映射至判别网络的中间状态表达。解码器接收此中间状态并经输出层生成判别结果包括「真」与「假」两类判断结论。

下图展示了判别器网络的工作流程。

  1. 输入层:接收图像作为输入。
  2. 编码器(Encoder):执行卷积运算和池化操作以提取出图像的关键信息。
  3. 中间层:经过全连接层的处理得到中间表示。
  4. 输出层:生成分类结果,并分为‘真’类和‘假’类两种类别。

3.3.1 判别损失函数

判别器网络旨在通过提升生成图像的判别结果「真」的概率达到最大值;同时要求真实图像样本被分类为「真」的概率也需达到最大值;因此,在构建判别损失函数的过程中,请特别注意符号的选择与配置。

常用的判别损失函数有以下几种:

  1. 交叉熵损失函数:

其中,
判别器网络对于真实图像的输出结果用 D(x) 表示;
而对于生成图像而言,
则使用 1-D(G(z)) 来表示其判别结果;
此外,
在潜在空间中引入噪声变量 z

交叉熵(Cross-Entropy)损失是一种被广泛应用于鉴别任务中的关键指标。它通过评估生成样本与真实样本之间的差距,并将这一差距转化为一个单调递增的形式来优化模型性能。这种优化方法使得判别器在整个训练过程中能够保持更为稳定的性能状态。

  1. 基于互信息的损失函数:

\mathcal{L}_{D}= - \frac {1}{2} \mathbb {E}_{x}\left[ \operatorname {KL}\!\left( q (x)\,\|\,p (x) \right) \right] - \frac {1}{2} \mathbb {E}_{x\sim p (x)}\left[ \operatorname {KL}\!\left( q (x)\,\|\,r (x) \right) ) ] + {\operatorname {JS}}( q (X)\,\|\,p(X)) + {\operatorname {JS}}( q(X)\,\|\,r(X))

这种鉴别式损失函数融合了互信息、KL散度和Jensen-Shannon散度。它能够用于评估生成样本与真实样本之间的差异程度,并且相较于交叉熵损失函数具有显著区别,在有效抑制分布之间差异方面表现更为突出。

  1. 基于 Wasserstein 距离的损失函数:

其中

该判别损失函数以 Wasserstein 距离为理论基础构建,在图像空间中实现了生成图像与真实图像之间差异的最大化,并对生成样本与真实样本之间的距离进行惩罚。

3.4 GANs 的训练过程

GANs 的训练阶段主要由两个模块(生成器网络和判别器网络)互相竞争并协同工作以实现目标——即生成与实际图像极为相似的新图像。这两个模块通过不断优化各自的性能,在对抗关系中共同进步。

  1. 初始化:首先固定生成器网络的参数。
  2. 训练判别器网络:在由真实图像与生成图像组成的混合数据集上对判别器网络进行训练。
  3. 训练生成器网络:使该模型能够在每次迭代中产出更加逼真的图像样本。
  4. 迭代:持续进行这一过程直至生成图像的质量达到预期标准。

4.具体实现

4.1 TensorFlow 实现

TensorFlow 包含了 tf.keras API,并使用户能够轻松构建GAN模型。tf.keras 具备自动求导功能,并包含多种神经网络层及其参数管理机制。以下将通过 TensorFlow 提供的一个GAN模板代码示例来讲解GAN的基本原理及其实现过程。

复制代码
    import tensorflow as tf
    
    class MyGANModel(tf.keras.Model):
    def __init__(self):
        super(MyGANModel, self).__init__()
    
        # Define the discriminator model for real images and fake images separately
        self.discriminator_real = Discriminator()
        self.discriminator_fake = Discriminator()
    
        # Define the generator model to create new images similar to those in training set
        self.generator = Generator()
    
    @tf.function
    def train_step(self, image):
        # Generate random noise from a normal distribution using tensor of shape [batch_size, latent_dim]
        noise = tf.random.normal([BATCH_SIZE, LATENT_DIM])
    
        with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
            generated_image = self.generator(noise, training=True)
    
            # Get predictions on real data and fake data using discriminators respectively
            prediction_real = self.discriminator_real(image, training=True)
            prediction_fake = self.discriminator_fake(generated_image, training=True)
    
            # Calculate loss function based on these predictions and optimize corresponding models
            loss_gen = generator_loss(prediction_fake)
            loss_disc = discriminator_loss(prediction_real, prediction_fake)
    
            gradients_of_generator = gen_tape.gradient(loss_gen, self.generator.trainable_variables)
            gradients_of_discriminator = disc_tape.gradient(loss_disc, 
                                                              self.discriminator_real.trainable_variables + self.discriminator_fake.trainable_variables)
    
        self.optimizer_generator.apply_gradients(zip(gradients_of_generator, self.generator.trainable_variables))
        self.optimizer_discriminator.apply_gradients(zip(gradients_of_discriminator, self.discriminator_real.trainable_variables + self.discriminator_fake.trainable_variables))
    
    def fit(self, dataset):
        for step, image in enumerate(dataset):
            self.train_step(image)
    
    # Define two loss functions used during training
    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)
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

4.2 PyTorch 实现

PyTorch中的GAN模型模板能够基于nn.Module类来实现。举个例子说明具体实现细节时会遇到哪些问题及解决方案。

复制代码
    import torch
    from torch import nn
    
    
    class Discriminator(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = nn.Sequential(
            nn.Linear(IMAGE_SHAPE, HIDDEN_UNITS),
            nn.ReLU(),
            nn.Linear(HIDDEN_UNITS, NUM_CLASSES)
        )
    
    def forward(self, inputs):
        logits = self.model(inputs)
        probas = nn.functional.softmax(logits, dim=-1)
        return probas
    
    
    class Generator(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = nn.Sequential(
            nn.Linear(LATENT_DIM, HIDDEN_UNITS),
            nn.ReLU(),
            nn.Linear(HIDDEN_UNITS, IMAGE_SHAPE)
        )
    
    def forward(self, z):
        output = self.model(z)
        return output
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

上面代码编码了两组子网络:判别网络包含线性层-ReLU激活模块-线性层结构;生成网络包含线性层-ReLU激活模块-线性层部分。基于forward()接口实现前向传播逻辑:输入数据通过模型计算出判别结果(真实与否)

在训练过程中,我们通过以下代码实现:

复制代码
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    epochs = EPOCHS
    batch_size = BATCH_SIZE
    learning_rate = LEARNING_RATE
    
    generator = Generator().to(device)
    discriminator = Discriminator().to(device)
    
    criterion = nn.BCEWithLogitsLoss()
    optim_g = torch.optim.Adam(generator.parameters(), lr=learning_rate)
    optim_d = torch.optim.Adam(discriminator.parameters(), lr=learning_rate)
    
    for epoch in range(epochs):
    for batch_idx, data in enumerate(dataloader):
        # Prepare input and target tensors
        images, _ = data
        images = images.to(device)
    
        # Sample random noise and generate fake images
        noise = torch.randn((batch_size, LATENT_DIM)).to(device)
        fake_images = generator(noise).detach()
    
        # Compute outputs of both networks
        pred_real = discriminator(images)
        pred_fake = discriminator(fake_images)
    
        # Compute losses between predictions and actual results
        loss_d = criterion(pred_real[:, 0].mean(), 1.) + criterion(pred_fake[:, 0].mean(), 0.)
    
        optim_d.zero_grad()
        loss_d.backward()
        optim_d.step()
    
        # Update generator network by first obtaining output of fake images from discriminator and then updating its weights
        fake_images = generator(noise)
        pred_fake = discriminator(fake_images)
        loss_g = criterion(pred_fake[:, 0].mean(), 1.)
    
        optim_g.zero_grad()
        loss_g.backward()
        optim_g.step()
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

在代码中首先初始化判别器与生成器模型,在随后的过程中分别配置优化算法与定义损失函数。接着遍历训练数据集,在每一次迭代中更新判别器与生成器的参数。其中采用的是二元交叉熵损失函数(Binary Cross Entropy Loss),其输出层对应于 NUM_CLASSES 个类别概率。由于我们仅关心真实类别(True)的概率分布情况,在计算损失时仅需关注该类别对应的概率值即可完成相应的训练过程。

5. 实际应用案例

5.1 图像生成

GANs 在图像生成领域已获得广泛应用。例如,在左图中,左侧的图像生成网络产生了与右侧原始图像相对应的新图像。

  1. 手写数字生成网络(Generative Adversarial Nets)

GANs 早期在 19世纪中期提出,在该领域取得了重要的进展。当时,该方法应用在图像处理、语音识别、机器翻译等领域。由于手写数字数据集庞大,且采用的是黑白图像,传统的机器学习方法效果不佳。GANs 的出现改善了机器学习模型的生成性能。目前,很多深度学习模型都是通过 GANs 实现图像生成。如 DCGAN、BigGAN 等。DCGAN 的训练策略是将真实图片训练为 GANs 的标准图像,同时使用生成网络将随机噪声映射为图像。生成网络可以生成逼真的图像,而判别网络则可以区分真实图片和生成图片。

  1. 动漫头像生成网络(Pix2pix)

Pix2pix 采用两个独立的网络架构来完成风格转换任务。其中前一网络接收原始图像作为输入并输出其通道数量、尺寸大小以及样式特征。随后另一网络基于前一输出结果生成与原始图像截然不同的新图像。具体而言生成模块则由一系列卷积层和反卷积层构成并最终输出一张RGB分辨率的彩色图。为了判断所生成图片的真实性判别器则由多个卷积层及池化操作构成并将输入的图像分成两部分分别用于判断是否为真实图片以及生成图片

  1. 风格迁移生成网络(CycleGAN)

CycleGAN由一系列网络组成,在A域( photographs)与B域( artworks)之间实现了图像风格迁移功能。该系统包含两个生成器和两个判别器。其中生成器负责将A域的图像映射到B域,并生成具有特定风格的新图像。判别器则通过评估生成器的质量并提供判别可能性来判断其有效性。此外,在实现两域间转换的同时CycleGAN还支持任意两领域间的映射关系

  1. 比特位转色彩生成网络(StarGAN)

StarGAN 由多个 GAN 组成,在单张输入图像中提取颜色特征并生成与之具有相同属性的新图像。其生成网络通过一系列卷积层与上采样层构建,在接收原始图像作为输入后输出 RGB 颜色通道的图像。判别器则由一系列卷积层与池化操作构成,在接收原始域图像与生成域图像作为输入信息后,分别计算并返回两个概率值:一个表示来源域(如真实数据或生成数据)的概率评估。

5.2 图像语义生成

在视觉符号化处理(Image Captioning)领域中,GANs能够用于创建描述图像内容的文本描述。相较于仅仅生成图片而言,视觉符号化处理通常需要更为复杂的模型架构以实现较为精确的效果。

全部评论 (0)

还没有任何评论哟~