2020机器学习GAN(2)

作者: zidea | 来源:发表于2020-02-24 20:25 被阅读0次
naruto_vs_sasuke.png

今天目标是介绍一下 GAN 是如何做到输出图片的这个样任务。在 GAN 中分别有两个阶段,在生成阶段就是固定生成器来训练判别器,而在判别阶段中固定判别器来训练生成器,这个可能和大家理解显得约有不同,但是其实都一样的。

gan_002.jpeg

生成阶段

例如我们可以让机器生成图片或生成文章,这些都是 GAN 那首好戏。在 GAN 我们见到都是在生成阶段由 generator 生成图像或文字。

vector \rightarrow NN \, Generator \rightarrow images(sentence)
也就是我们给 generator 输入服从某种分布随机具有一定维度的向量,generator 就会输出张图片或文字。不同于之前机器只是做预测和分类任务,今天 GAN 可以生产一些东西,不过你会问到除了有趣这些又有什么用呢?

这样结果不可控制的生成,看起来的确是没有什么用的,如果我们能够控制输出就好,这一点是可以做到,随后会介绍我们如何控制 generator 输出来得到我们想要的图像或文字。

屏幕快照 2020-03-03 上午6.20.23.png

我们同过输入向量某一个值控制输入,例如修改值来改变输出卡通人物头发的颜色,更改她们的表情,这些都是可以做到的。

判别阶段

  1. 固定住首先生成器使用服从一定分布的提取具有一定维度的向量,向量维度可以由你来定,20、50 和 100 都可以。生成图像,
  2. 我们固定住判别器,开始训练生成器,这个阶段应该属于判别阶段

可以把判别器和生成器整合为一个模型,网络模型前半部分是生成器,后半部分是判别器,假设他们个 5 层,在中间输出一个高维向量(图像的维度),在训练生成器时候,我们需要网络后半部分固定住。如果不固定住后端网络,只要后端给出高分就达到预期的效果。

生成器和判别器

屏幕快照 2020-03-03 上午6.51.11.png

在 GAN 的架构中通常会有两部分组成分别是 Generator 和 Discriminator

  • NN(神经网络,随后我们就用 NN 表示神经网络) 分别是 Generator(生成器)
    vector \rightarrow Generator \rightarrow image

  • 在 Discriminator 输入一张图,然后会给输入进行打分
    image \rightarrow Generator \rightarrow scalar

  • 先固定住生成器(Generator) 也就是固定住 Generator 参数,然后输入服从一定分布的随机向量 \{z^1,z^2,\dots,z^m\} 给 Generator 来生成图片

  • 然后从准备好的 \{x^1,x^2,\dots,x^m\} 数据集中抽取图片,如果图片就要准备一些你要生成图片类似,加下来将真实图片和Generator 生成图片输入到 Discriminator,并给真实图片较高分和给 generator 生产的图较低的分数,通过使用数据进行训练 Discriminator 来提高 Discriminator 的鉴别能力。

    更新判别器
    在实践中,我们希望当真实图片输入到 Discriminator 时候,希望他能给分数越接近 1 越好,反之越接近 0 越好。
  • 然后固定住 Discriminator 然后调节 Generator 的参数来努力骗过 Discriminator 来获取高分

naruto_002.jpg

\{ \widetilde{x}^1,\widetilde{x}^2,\dots,\widetilde{x}^m\}\widetilde{x}^i = G(z^i)
这些 Generator 根据输入向量生成图片表示为\widetilde{x}^i
\widetilde{V} = \frac{1}{m}\sum_{i=1}^m \log D(x^i) + \frac{1}{m} \sum_{i=1}^m \log (1 - D(\widetilde{x}^i))
这是 Discriminator 的目标函,期望\widetilde{V} 值越大越好,数当输入真实图片x^i到 D 我们希望 \frac{1}{m}\sum_{i=1}^m \log D(x^i) 值越大越好,而输入\widetilde{x}^i 希望D(\widetilde{x}^i) 越小越好,从而会的得到一个较大\widetilde{V}

\theta_d \leftarrow \theta_d + \eta \nabla \widetilde{V} (\theta_d)
有了目标函数,我们就可以朝着目标不断更新参数\theta_d 训练完 Discriminator 我们就可以开始训练 Generator 了。我们可以再随机抽取 m 个\{z^1,z^2,\dots,z^m\},下面式子就是 G 用向量z^i输出图片,将图片输入判别函数D 希望他给出高分,这就是训练 G 的目标。

naruto_003.jpg

\widetilde{V} = \frac{1}{m} \sum_{i=1}^m \log D(G(z^i))
\theta_g \leftarrow \theta_g + \eta \nabla \widetilde{V} (\theta_g)

这里对抗意思,大家都是用做赝品和鉴别专家来比喻generator和discriminator。其实他们鸣人和佐助的关系,相辅相成共同进步

Discriminator(判别器)

我们可能会问为什么判别器不自己生产图片呢?他已经知道什么样图片是真的,什么样图片是伪造的了。判别器是接受图片或文本输入然后会输出一个分数,也就是判别器给这个
我们想生成器通常是一个一个 component(在图像里就是像素)地生产,而且批次独立,这样就在生成阶段很难考虑到像素像素之间的关系。而判别器时候却不同,他接收一张图片作为输入,这样从整体来审核一张图好坏

\widetilde{x} = \arg \max_{x \in X} D(x)

不过现在Discriminator 只是知道凡是生成器就是不好,其实也就是只有正例样本,我们需要准备一些反例样本告诉判别器什么样是不好的除了是生成器伪造那些图片和文本以外。

先开一下跑的结果


随机生产 200 迭代 400 迭代 2000 迭代 19000 迭代
# coding=utf-8
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 os
import numpy as np

class GAN():
    def __init__(self):
        # --------------------------------- #
        #   行28,列28,也就是mnist的shape
        # --------------------------------- #
        self.img_rows = 28
        self.img_cols = 28
        self.channels = 1
        # 28,28,1
        self.img_shape = (self.img_rows, self.img_cols, self.channels)
        self.latent_dim = 100
        # adam优化器
        optimizer = Adam(0.0002, 0.5)
        # 初始化判别器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
            optimizer=optimizer,
            metrics=['accuracy'])
        # 创建生成器
        self.generator = self.build_generator()
        
        gan_input = Input(shape=(self.latent_dim,))
        img = self.generator(gan_input)
        # 在训练generate的时候,固定住 discriminator 
        self.discriminator.trainable = False
        # 对生成的假图片进行预测
        validity = self.discriminator(img)
        # input
        self.combined = Model(gan_input, 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))

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

        img = Input(shape=self.img_shape)
        validity = model(img)
        # 输出模型
        return Model(img, validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        # 获得数据
        (X_train, _), (_, _) = mnist.load_data()

        # 进行标准化
        X_train = X_train / 127.5 - 1.
        X_train = np.expand_dims(X_train, axis=3)

        # 创建标签
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # --------------------------- #
            #   随机选取batch_size个图片
            #   对discriminator进行训练
            # --------------------------- #
            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))
            # 生成器创建图片
            gen_imgs = self.generator.predict(noise)
            
            # 开始训练判别器,输入真实图片给判别器传入 valid 高分告诉这是真实图片
            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)

            # --------------------------- #
            #  训练generator
            # --------------------------- #
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))
            g_loss = self.combined.train_on_batch(noise, valid)
            print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))

            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)

        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__':
    if not os.path.exists("./images"):
        os.makedirs("./images")
    gan = GAN()
    gan.train(epochs=30000, batch_size=256, sample_interval=200)

相关文章

  • 2020机器学习GAN(2)

    今天目标是介绍一下 GAN 是如何做到输出图片的这个样任务。在 GAN 中分别有两个阶段,在生成阶段就是固定生成器...

  • 2020机器学习GAN(5)

    参考李宏毅老师分享 先解释一下根据样本进行生成图片,然后把图片每一个像素都看成其一个特征,那么图片就是存在一个高维...

  • 2020机器学习GAN(8)

    为什么不用 Discriminator 生成图片 其实 Discriminator 会从整体来考量图片好坏假设我们...

  • 2020机器学习GAN(1)

    在 2018 年,深度学习掀起 GAN 的潮流,在许多领域都已经有了应用,而且基于 GAN 项目五花八门。早在**...

  • 2020机器学习GAN(F)

    训练 好现在定义好判别器模型和生成模型,而且定义好优化器这里梯度下降使用 Adam 给以较小学习率。在开始训练前我...

  • 2020机器学习GAN(3)

    代码讲解 今天 tensorflow2.0 实现一个简单全连接实现 GAN。我们先回忆在做机器学习一般流程,然后我...

  • 2020机器学习GAN(6)

    我们就是找到一个 G ,这个 G 可以让和之间的 JSDiv 距离尽量小。 回忆一下我们在 GAN 中任务,就是找...

  • 2020机器学习GAN(CGAN) (9)

    CGAN(Conditonal Generation GAN) 什么是 CGAN 呢?之前我们 GAN 生成图片是...

  • 2020机器学习GAN(WGAN) (9)

    我们之前都用 JS 散度来衡量两笔数据之间差异,今天我们就来先讨论一下 JS 散度作为衡量工具是否合适的问题。我们...

  • [GAN学习系列3]采用深度学习和 TensorFlow 实现图

    在之前的两篇 GAN 系列文章--[GAN学习系列1]初识GAN以及[GAN学习系列2] GAN的起源中简单介绍了...

网友评论

    本文标题:2020机器学习GAN(2)

    本文链接:https://www.haomeiwen.com/subject/ozyiqhtx.html