Smiling & Weeping

                ---- 你已春风摇曳,我仍一身旧雪

1.GAN的基本思想

GAN全称对抗生成网络,顾名思义是生成模型的一种,而他的训练则是一种对抗博弈状态中的。下面我们举例来解释一下GAN的基本思想。

  假如你是一名篮球运动员,你想在下次比赛中得到上场的机会。

  于是在每一次训练赛之后你跟教练沟通:

  你:教练,我想打篮球

  教练:(看了看你平时篮球成绩后)...不,你不想

  (但你并没有绝望,通过跟其他人对比,返现自己运球比较差,于是你苦练了一段时间)

  你:教练,我想

  教练:(没等话说完)...你,你,你想上天

  (但你仍没有绝望,你发现大家投篮很准,于是你苦练了一段时间的投篮)

  你:教练,我想打 lan qiu

  教练:(教练看了看你,叹了口气)恩,想法不错,继续想别停

  (但你仍没有绝望,你发现自己身体不够强壮,被人一碰就倒,于是你去跑健身房)

  ...

  通过这样不断的努力和被拒绝,你终于在某一次训练赛之后得到教练的‘赞赏’,获得了    “上场”的机会

  值得一提的是在这个过程中,所有的候选球员都在不断地进步和提升。因而教练也要  不断地通过对比场上球员和候补球员来学习分辨哪些球员是真正可以上场的,并且要“观察”得比球员更频繁。随着大家的成长教练也会会变得越来越严格。

  现在,大家对于GAN的思想应该有了感性的认识了,下一步进一步窥探GAN的结构和思想

2.GAN浅析

2.1 GAN的基本结构

GAN的主要结构包括一个生成器G(Generator)和一个判别器D(Discriminator)

在上面的例子中的球员相当于生成器,我们需要他在球场上能有好的表现。二球员一开始都是初学者,这个时候就需要一个教练来指导他们训练,告诉他们训练的怎么样,直到真的能够达到上场的标准。而这个教练就相当于判别器。

我们现在拥有大量的手写数字的数据集,我们希望通过GAN生成一些能够以假乱真的手写数字。主要由如下两个部分组成:

1.定义一个模型来作为生成器(图中青色部分Generator),能够输入一个向量,输出手写数字大小的像素图像。

2.定义一个分类器来作为判别器(图中红色部分Discriminator)用来判断图片是真的还是假的(或者说是来自数据集中的还是声称其中的),输入为手写图片,输出为判别图片的标签。

2.2 GAN的训练方式

前面已经定义了一个生成器(Generator)来生成手写数字,一个判别器(Discriminator)来判别手写数字是否是真实的,和一些真实的手写数字数据集。那么我们怎么样来进行训练呢?

2.2.1 关于生成器

对于生成器,输入需要一个n维度向量,输出为图片像素大小的图片。因而首先我们需要得到输入的向量。

Tips: 这里的生成器可以是任意可以输出图片的模型,比如最简单的全连接神经网络,又或者是反卷积网络等。这里大家明白就好。

这里输入的向量我们将其视为携带输出的某些信息,比如说手写数字为数字几,手写的潦草程度等等。由于这里我们对于输出数字的具体信息不做要求,只要求其能够最大程度与真实手写数字相似(能骗过判别器)即可。所以我们使用随机生成的向量来作为输入即可,这里面的随机输入最好是满足常见分布比如均值分布,高斯分布等。

Tips: 假如我们后面需要获得具体的输出数字等信息的时候,我们可以对输入向量产生的输出进行分析,获取到哪些维度是用于控制数字编号等信息的即可以得到具体的输出。而在训练之前往往不会去规定它。

2.2.2 关于判别器

对于判别器不用多说,往往是常见的判别器,输入为图片,输出为图片的真伪标签。

Tips: 同理,判别器与生成器一样,可以是任意的判别器模型,比如全连接网络,或者是包含卷积的网络等等。

2.2.3 如何训练

上面进一步说明了生成器和判别器,接下来说明如何训练。

基本流程如下:

  • 初始化判别器D的参数d 和 生成器G的参数g
  • 从真实样本中采样m个样本{x1, x2, ..., xm}, 从先验分布噪声样本{z1, z2, ..., zm}并通过生成器获取m个生成样本{x'1, x'2, ..., x'm}。固定生成器G,训练判别器D尽可能好地准确判别真实样本和生成样本,尽可能大地区分正确样本和生成的样本。
  • 循环k次更新判别器之后,使用较小的学习率来更新一次生成器的参数,训练生成器使其尽可能较小生成样本与真实样本之间的差距,也相当于尽量使得判别器判别错误。
  • 多次更新迭代之后,最终理想情况是使得判别器判别不出样本来自于生成器的输出还是真实的输出。亦即最终样本判别概率均为0.5.

Tips: 之所以要训练k次判别器,再训练生成器,是因为要先拥有一个好的判别器,使得能够教好地区分出真实样本和生成样本之后,才好更为准确地对生成器进行更新。更直观的理解可以参考下图:

注:图中的黑色虚线表示真实的样本的分布情况,蓝色虚线表示判别器判别概率的分布情况,绿色实线表示生成样本的分布。 Z表示噪声, Z 到 x 表示通过生成器之后的分布的映射情况。

我们的目标是使用生成样本分布(绿色实线)去拟合真实的样本分布(黑色虚线),来达到生成以假乱真样本的目的。

可以看到在(a)状态处于最初始的状态的时候,生成器生成的分布和真实分布区别较大,并且判别器判别出样本的概率不是很稳定,因此会先训练判别器来更好地分辨样本。
通过多次训练判别器来达到(b)样本状态,此时判别样本区分得非常显著和良好。然后再对生成器进行训练。
训练生成器之后达到(c)样本状态,此时生成器分布相比之前,逼近了真实样本分布。
经过多次反复训练迭代之后,最终希望能够达到(d)状态,生成样本分布拟合于真实样本分布,并且判别器分辨不出样本是生成的还是真实的(判别概率均为0.5)。也就是说我们这个时候就可以生成出非常真实的样本啦,目的达到。

3. 训练相关理论基础

前面用了大白话来说明了训练的大致流程,下面会从交叉熵开始说起,一步步说明损失函数的相关理论,尤其是论文中包含min,max的公式如下图5形式:

图5 min max公式


判别器在这里是一种分类器,用于区分样本的真伪,因此我们常常使用交叉熵(cross entropy)来进行判别分布的相似性,交叉熵公式如下图6所示:

图6 交叉熵公式

Tips: 公式中 pi和 qi 为真实的样本分布和生成器的生成分布。由于交叉熵是非常常见的损失函数,这里默认大家都较为熟悉,就不进行赘述了。

在当前模型的情况下,判别器为一个二分类问题,因此可以对基本交叉熵进行更具体地展开如下图7所示:

图7 二分类交叉熵

Tips: 其中,假定 y1 为正确样本分布,那么对应的( 1−y1 )就是生成样本的分布。 D 表示判别器,则 �(�1) 表示判别样本为正确的概率, ((1−�(�1)) 则对应着判别为错误样本的概率。这里仅仅是对当前情况下的交叉熵损失的具体化。相信大家也还是比较熟悉。

将上式推广到N个样本后,将N个样本相加得到对应的公式如下:

图8 N个样本的情况时

OK,到目前为止还是基本的二分类,下面加入GAN中特殊的地方。

对于GAN中的样本点 �� ,对应于两个出处,要么来自于真实样本,要么来自于生成器生成的样本  ( 这里的 � 是服从于投到生成器中噪声的分布)。

其中,对于来自于真实的样本,我们要判别为正确的分布 �� 。来自于生成的样本我们要判别其为错误分布。将上面式子进一步使用概率分布的期望形式写出(为了表达无限的样本情况,相当于无限样本求和情况),并且让 �� 为 1/2 且使用 �(�) 表示生成样本可以得到如下图8的公式:

图8 GAN损失函数期望形式表达

OK,现在我们再回过头来对比原本的的 min�max� 公式,发现他们是不是其实就是同一个东西呢!:-D

图9 损失函数的min max表达

我们回忆一下上面2.2.3中介绍的流程理解一下这里的 min�max� 。

    • 这里的 �(�,�)相当于表示真实样本和生成样本的差异程度。
    • 先看 max��(�,�) 。这里的意思是固定生成器G,尽可能地让判别器能够最大化地判别出样本来自于真实数据还是生成的数据。
    • 再将后面部分看成一个整体令 � = max��(�,�) ,看 min��,这里是在固定判别器D的条件下得到生成器G,这个G要求能够最小化真实样本与生成样本的差异。
    • 通过上述min max的博弈过程,理想情况下会收敛于生成分布拟合于真实分布。
 
 
在我眼中的你,灿如春华,姣如秋月
文章到此结束,我们下次再见--<-<-<@

通俗理解GAN -- 基础认知的更多相关文章

  1. Effective Java通俗理解(持续更新)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  2. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  3. Effective Java通俗理解(上)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  4. CNN笔记:通俗理解卷积神经网络【转】

    本文转载自:https://blog.csdn.net/v_july_v/article/details/51812459 通俗理解卷积神经网络(cs231n与5月dl班课程笔记) 1 前言 2012 ...

  5. 通俗理解LDA主题模型

    通俗理解LDA主题模型 0 前言 印象中,最開始听说"LDA"这个名词,是缘于rickjin在2013年3月写的一个LDA科普系列,叫LDA数学八卦,我当时一直想看来着,记得还打印 ...

  6. CNN笔记:通俗理解卷积神经网络

    CNN笔记:通俗理解卷积神经网络 2016年07月02日 22:14:50 v_JULY_v 阅读数 250368更多 分类专栏: 30.Machine L & Deep Learning 机 ...

  7. 关于MQ 消息队列的通俗理解和 rabbitMQ 使用

    消息队列,一听很高大上,现在很多分布式系统都在用这个消息中间件 网上一搜, 说的都是些原理. 说下我的通俗理解, 你网上买了, 快递员给你投递, 会出现什么问题呢? 1  你不定时在家, 快递员 来了 ...

  8. 范式通俗理解:1NF、2NF、3NF和BNCF

    https://blog.csdn.net/wyh7280/article/details/83350722 范式通俗理解:1NF.2NF.3NF和BNCF原创hongiii 最后发布于2018-10 ...

  9. 通俗理解Android事件分发与消费机制

    深入:Android Touch事件传递机制全面解析(从WMS到View树) 通俗理解Android事件分发与消费机制 说起Android滑动冲突,是个很常见的场景,比如SliddingMenu与Li ...

  10. 关于MySQL中的自联结的通俗理解

    关于MySQL中的自联结的通俗理解 前言:最近在通过SQL必知必会这本书学习MySQL的基本使用,在学习中也或多或少遇到了点问题,我也正好分享给大家,我的这篇博客用到的所有表格的代码都是来自SQL必知 ...

随机推荐

  1. [FAQ] Quasar BEX Bridge 通信方式 this.$q.bex 未定义的问题

      Bridge 是一个基于 Promise 的事件系统,在BEX的所有部分之间共享,允许在你的Quasar App中监听事件,从其它部分发出它们. 你可以使用 $q.bex 从你的 Quasar A ...

  2. WPF 框架开发 ColumnDefinition 和 RowDefinition 的代码在哪

    我的 VisualStudio 在更新到 2022 就构建不通过 WPF 仓库,提示我在 Grid 的代码里面找不到 ColumnDefinitionCollection 和 RowDefinitio ...

  3. The instance of entity type 'Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.

    The instance of entity type 'Model' cannot be tracked because another instance with the same key val ...

  4. 07 mapping索引操作

    目录 版本 获取健康值 获取所有索引的信息 创建索引 1. 自动推导 2. 自定义 判断索引是否存在 新增字段 新增记录 查询记录 获取mapping信息 删除索引 添加别名 查看别名 索引备份数据 ...

  5. Linux — 进程管理

    进程创建 进程通过fork()创建的大致过程: #include <stdio.h> #include <stdlib.h> #include <sys/types.h& ...

  6. P3193 [HNOI2008] GT考试 题解

    之前学矩阵乘的时候做的题,当时因为不会\(kmp\)搜索一稀里糊涂过去了,现在填个坑. 头图 是\(Logos\)! P3193 [HNOI2008] GT考试 题链:洛谷 题库 题目大意: 求有多少 ...

  7. Review社区PR的方式

    有时候review社区改动较大的PR时,在github上看不太方便,需要把相应的pr,apply到本地,记录下常用的方式 # 添加pr仓库 git remote add ${upstream_name ...

  8. Java RMI遇到的Connection refused to Host: 127.x.x.x/192.x.x.x/10.x.x.x问题解决方法

    问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可能大家的host是10 ...

  9. c++ 记一次把qrencode源码生成动态库的尝试

    在网上搜二维码库:qrencode,源码下载:https://github.com/fukuchi/libqrencode 我的是windows环境,IDE是vs2022. 建立一个动态库的空工程. ...

  10. 1.Prism

    Region(区域)在程序编写的过程中我们肯定会遇到在一个区域上显示不同的内容,这些内容可能属于不同窗口,之前是弄个panel,需要显示哪个窗口就给让panel显示. 1.定义区域2.提供对区域的访问 ...