GAN原理简单讲解即代码实现

11 篇文章 0 订阅

GAN的基本原理其实非常简单,这里以生成图片为例进行说明。假设我们有两个网络,G(Generator)和D(Discriminator)。正如它的名字所暗示的那样,它们的功能分别是:
G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片,记做G(z)。
D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。
在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。这样,G和D构成了一个动态的“博弈过程”。
最后博弈的结果是什么?在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。
这样我们的目的就达成了:我们得到了一个生成式的模型G,它可以用来生成图片。
下面详细介绍一下过程:
第一阶段:固定「判别器D」,训练「生成器G」
我们使用一个还 OK 判别器,让一个「生成器G」不断生成“假数据”,然后给这个「判别器D」去判断。
一开始,「生成器G」还很弱,所以很容易被揪出来。
但是随着不断的训练,「生成器G」技能不断提升,最终骗过了「判别器D」。
到了这个时候,「判别器D」基本属于瞎猜的状态,判断是否为假数据的概率为50%。
第二阶段:固定「生成器G」,训练「判别器D」
当通过了第一阶段,继续训练「生成器G」就没有意义了。这个时候我们固定「生成器G」,然后开始训练「判别器D」。
「判别器D」通过不断训练,提高了自己的鉴别能力,最终他可以准确的判断出所有的假图片。
到了这个时候,「生成器G」已经无法骗过「判别器D」。
循环阶段一和阶段二
通过不断的循环,「生成器G」和「判别器D」的能力都越来越强。
最终我们得到了一个效果非常好的「生成器G」,我们就可以用它来生成我们想要的图片了。
举例:以MINIST手写数据集为例进行讲解:
在这里插入图片描述
GAN步骤:
1、生成器接收随机数并返回图像。
2、将生成的图像与从实际数据集中获取的图像流一起馈送到鉴别器中。
3、鉴别器接收真实和假图像并返回概率,0到1之间的数字,1表示真实性的预测,0表示假。
目的是把接收到的真实的图片识别出是图片的概率为1,把生成的图片识别为是图片的概率为0。这样就可以通过把生成器生成的图片识别为假,来训练生成器生成以假乱真的图片的能力。

训练GAN的技巧:
在开始训练发生器之前预先识别鉴别器将建立更清晰的梯度。
训练Discriminator时,保持Generator值不变。训Generator时,保持Discriminator值不变。这使网络能够更好地了解它必须学习的梯度。
GAN被制定为两个网络之间的游戏,重要(并且很难!)保持它们的平衡。如果生成器或鉴别器太好,GAN可能很难学习。
GAN需要很长时间才能训练。在单个GPU上,GAN可能需要数小时,在单个CPU上,GAN可能需要数天。

附上代码:

from __future__ import print_function, division
from keras.datasets import mnist
from keras.layers import Input, Dense, Reshape, Flatten, Dropout
from keras.layers import BatchNormalization, Activation, ZeroPadding2D
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.convolutional import UpSampling2D, Conv2D
from keras.models import Sequential, Model
from keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import numpy as np

class GAN():
    def __init__(self):
        self.img_rows = 28
        self.img_cols = 28
        self.channels = 1
        self.img_shape = (self.img_rows, self.img_cols, self.channels)
        self.latent_dim = 100

        optimizer = Adam(0.0002, 0.5)

        # Build and compile the discriminator
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
            optimizer=optimizer,
            metrics=['accuracy'])

        # Build the generator
        self.generator = self.build_generator()

        # The generator takes noise as input and generates imgs
        z = Input(shape=(self.latent_dim,))
        img = self.generator(z)

        # For the combined model we will only train the generator
        self.discriminator.trainable = False

        # The discriminator takes generated images as input and determines validity
        validity = self.discriminator(img)

        # The combined model  (stacked generator and discriminator)
        # Trains the generator to fool the discriminator
        self.combined = Model(z, validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)


    def build_generator(self):

        model = Sequential()

        model.add(Dense(256, input_dim=self.latent_dim))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Dense(512))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Dense(1024))
        model.add(LeakyReLU(alpha=0.2))
        model.add(BatchNormalization(momentum=0.8))
        model.add(Dense(np.prod(self.img_shape), activation='tanh'))
        model.add(Reshape(self.img_shape))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        img = model(noise)

        return Model(noise, img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Flatten(input_shape=self.img_shape))
        model.add(Dense(512))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(256))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(1, activation='sigmoid'))
        model.summary()

        img = Input(shape=self.img_shape)
        validity = model(img)

        return Model(img, validity)

    def train(self, epochs, batch_size=128, sample_interval=50):

        # Load the dataset
        (X_train, _), (_, _) = mnist.load_data()

        # Rescale -1 to 1
        X_train = X_train / 127.5 - 1.
        X_train = np.expand_dims(X_train, axis=3)

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            #  Train Discriminator
            # ---------------------

            # Select a random batch of images
            idx = np.random.randint(0, X_train.shape[0], batch_size)
            imgs = X_train[idx]

            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # Generate a batch of new images
            gen_imgs = self.generator.predict(noise)

            # Train the discriminator
            d_loss_real = self.discriminator.train_on_batch(imgs, valid)
            d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)
            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

            # ---------------------
            #  Train Generator
            # ---------------------

            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch(noise, valid)

            # Plot the progress
            print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))

            # If at save interval => save generated image samples
            if epoch % sample_interval == 0:
                self.sample_images(epoch)

    def sample_images(self, epoch):
        r, c = 5, 5
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        gen_imgs = self.generator.predict(noise)

        # Rescale images 0 - 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].axis('off')
                cnt += 1
        fig.savefig("images/%d.png" % epoch)
        plt.close()


if __name__ == '__main__':
    gan = GAN()
    gan.train(epochs=30000, batch_size=32, sample_interval=200)

上面的代码可以直接运行,途中需要下载数据集,需要的时间可能较长,或者也可以自己网上下载数据集:
https://s3.amazonaws.com/img-datasets/mnist.npz
并放在文件夹:C:\Users\你的用户名.keras\datasets
我的是:C:\Users\liush.keras\datasets
这是一个MINIST手写数据集,产生的图片:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
经过3万个epoch:
在这里插入图片描述
经过6万个epoch:
在这里插入图片描述

我从前往后选了几张,可以看出,网络产生的图片逐渐清晰。不过到后面,产生的图片貌似没有什么太大区别了。

接下来,结合代码,对GAN的细节原理进行说明讲解。

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 李宏毅是一位著名的机器学习专家,他在GAN(生成对抗网络)方面做出了重要贡献。GAN是一种包含两个神经网络的模型,一个称为生成器(Generator),另一个称为判别器(Discriminator)。GAN的目标是让生成器尽可能地生成与真实样本相似的数据。 在李宏毅的作业代码讲解中,他会介绍GAN的基本原理、算法和代码实现。首先,他会讲解生成器和判别器的结构和原理,包括生成器如何生成样本,以及判别器如何对生成的样本进行评价。 然后,李宏毅会详细解释GAN的损失函数和优化方法。他会讲解如何使用反向传播算法更新生成器和判别器的参数,以使它们在训练中达到更好的表现。此外,他还会解释GAN的训练过程中可能遇到的一些问题,并提供解决方法。 在代码方面,李宏毅会给出一个简单的实例,展示如何使用Python和深度学习框架(如TensorFlow或PyTorch)来实现一个基本的GAN模型。他会详细解释每个代码部分的功能和作用,并给出相应的代码注释,方便学习者理解。 总的来说,李宏毅的GAN网络作业代码讲解涵盖了GAN的基本原理、算法和实现细节。通过他的讲解,学习者可以更好地理解并应用GAN,从而在生成对抗网络领域取得更好的成果。 ### 回答2: 李宏毅是一位著名的机器学习和深度学习专家,他的GAN(生成对抗网络)网络作业代码讲解十分受欢迎。 GAN是一种由生成器和判别器组成的对抗性网络模型。生成器尝试生成与真实数据相似的新样本,而判别器则负责判断这些样本是真实的还是伪造的。GAN网络的训练过程是通过生成器和判别器之间的对抗来进行的。 在李宏毅的GAN网络作业代码讲解中,他通常会从基本概念开始讲解,介绍GAN网络的工作原理和训练过程。他会解释生成器和判别器的结构以及它们的作用,包括如何设计合适的神经网络模型实现生成器和判别器。 接着,他会具体解释代码中各部分的功能和实现细节。他会展示如何使用Python和深度学习框架(如Tensorflow)来编写GAN网络的代码,并演示如何处理数据、构建网络结构、定义损失函数和优化器等。 此外,李宏毅还会给出一些GAN网络的应用案例,例如生成图像、语音合成等。他会详细说明如何调整和优化代码,以实现更好的生成效果。 总之,李宏毅的GAN网络作业代码讲解是非常有帮助和详细的,对于想要深入了解和学习GAN网络的人来说,这是一份宝贵的学习资料。通过他的讲解,我们可以更好地理解和应用GAN网络,为自己的深度学习项目增添新的工具和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值