完整笔记:http://www.gwylab.com/note-flow_based_model.html
李宏毅老师的视频教程:/www.bilibili.com/video/av46561029/?p=59
——————————————————————————————————

前言

· Flow-based模型的不同之处

从去年GLOW提出之后,我就一直对基于流(flow)的生成模型是如何实现的充满好奇,但一直没有彻底弄明白,直到最近观看了李宏毅老师的教程之后,很多细节都讲解地比较清楚,就想好好写篇笔记来梳理一下流模型的运作原理。

首先来简单介绍一下流模型,它是一种比较独特的生成模型——它选择直接直面生成模型的概率计算,也就是把分布转换的积分式()给硬算出来。要知道现阶段其他较火的生成模型,要么采用优化上界或采用对抗训练的方式去避开概率计算,从而寻找近似逼近真实分布的方法,但是流模型选择了一条硬路(主要是通过变换Jacobian行列式)来求解,在后文会详细介绍。

流模型有一个非常与众不同的特点是,它的转换通常是可逆的。也就是说,流模型不仅能找到从A分布变化到B分布的网络通路,并且该通路也能让B变化到A,简言之流模型找到的是一条A、B分布间的双工通路。当然,这样的可逆性是具有代价的——A、B的数据维度必须是一致的。

A、B分布间的转换并不是轻易能做到的,流模型为实现这一点经历了三个步骤:最初的NICE实现了从A分布到高斯分布的可逆求解;后来RealNVP实现了从A分布到条件非高斯分布的可逆求解;而最新的GLOW,实现了从A分布到B分布的可逆求解,其中B分布可以是与A分布同样复杂的分布,这意味着给定两堆图片,GLOW能够实现这两堆图片间的任意转换。

下面就是流模型学习笔记的正文,尽可能较简明地讲解清楚流模型的运行机制。

——————————————————————————————————————————————————————

1. Flow-based Model的建模思维

首先来回顾一下生成模型要解决的问题:

如上图所示,给定两组数据z和x,其中z服从已知的简单先验分布π(z)(通常是高斯分布),x服从复杂的分布p(x)(即训练数据代表的分布),现在我们想要找到一个变换函数f,它能建立一种z到x的映射,使得每对于π(z)中的一个采样点,都能在p(x)中有一个(新)样本点与之对应。

如果这个变换函数能找到的话,那么我们就实现了一个生成模型的构造。因为,p(x)中的每一个样本点都代表一张具体的图片,如果我们希望机器画出新图片的话,只需要从π(z)中随机采样一个点,然后通过,得到新样本点x,也就是对应的生成的具体图片。

所以,接下来的关键在于,这个变换函数f如何找呢?我们先来看一个最简单的例子。

如上图所示,假设z和x都是一维分布,其中z满足简单的均匀分布:,x也满足简单均匀分布:

那么构建z与x之间的变换关系只需要构造一个线性函数即可:x=f(z)=2z+1。

下面再考虑非均匀分布的更复杂的情况:

如上图所示,π(z)与p(x)都是较为复杂的分布,为了实现二者的转化,我们可以考虑在很短的间隔上将二者视为简单均匀分布,然后应用前边方法计算小段上的,最后将每个小段变换累加起来(每个小段实际对应一个采样样本)就得到最终的完整变换式f。

如上图所示,假设在[?′,?′+∆?]上π(z)近似服从均匀分布,在[x′,x′+∆x]上p(x)也近似服从均匀分布,于是有?(?′ )∆?=?(?′ )∆?(因为变换前后的面积/即采样概率是一致的),当∆x与∆?极小时,有:

又考虑到有可能是负值(如下图所示),而都为非负,所以的实际关系为:

下面进一步地做推广,我们考虑z与x都是二维分布的情形。

如上图所示,z与x都是二维分布,左图中浅蓝色区域表示初始点方向上移动Δ,在方向上移动Δ所形成的区域,这一区域通过映射,形成右图所示x域上的浅绿色菱形区域。其中,二维分布π(z)与p(x)均服从简单均匀分布,其高度在图中未画出(垂直纸面向外)。

因为蓝色区域与绿色区域具有相同的体积,所以有:

其中代表行列式计算,它的计算结果等于上图中浅绿色区域的面积(行列式的定义)。下面我们将移至左侧,得到:

即:

很小时,有:

即:

其中表示f运算的雅各比行列式,根据雅各比行列式的逆运算,我们得到:

其中代表从x变换为z的变换式,即:

至此,我们得到了一个比较重要的结论:如果z与x分别满足两种分布,并且z通过函数f能够转变为x,那么z与x中的任意一组对应采样点之间的关系为:

那么基于这一结论,再带回到生成模型要解决的问题当中,我们就得到了Flow-based Model(流模型)的初步建模思维。

如上图所示,为了实现间的转化,待求解的生成器G的表达式为:

基于前面推导,我们有中的样本点与中的样本点间的关系为:

其中

所以,如果的目标式能够通过上述关系式求解出来,那么我们就实现了一个完整的生成模型的求解。Flow-based Model就是基于这一思维进行理论推导和模型构建,下面将会详细解释Flow-based Model的求解过程。

2. Flow-based Model的理论推导&架构设计

我们关注一下上一章中引出的式子:

将其取log,得到:

现在,如果想直接求解这个式子有两方面的困难。第一个困难是,是不好计算的——由于的Jacobian矩阵一般维度不低(譬如256*256矩阵),其行列式的计算量是异常巨大的,所以在实际计算中,我们必须对的Jacobian行列式做一定优化,使其能够在计算上变得简洁高效。第二个困难是,表达式中出现了,这意味着我们要知道长什么样子,而我们的目标是求G,所以这需要巧妙地设计G的结构使得也是好计算的。

下面我们来逐步设计G的结构,首先从最基本的架构开始构思。考虑到必须是存在的且能被算出,这意味着G的输入和输出的维度必须是一致的并且G的行列式不能为0。然后,既然可以计算出来,而的目标表达式只与有关,所以在实际训练中我们可以训练对应的网络,然后想办法算出G来并且在测试时改用G做图像生成。

如上图所示,在训练时我们从真实分布中采样出,然后去训练,使得通过生成的满足特定的先验分布;接下来在测试时,我们从z中采样出一个点,然后通过G生成的样本就是新的生成图像。

接下来开始具体考虑G的内部设计,为了让可以计算并且G的Jacobian行列式也易于计算,Flow-based Model采用了一种称为耦合层(Coupling Layer)的设计来实现。

如上图所示,z和x都会被拆分成两个部分,分别是前1~d维和后d+1~D维。从z变化为x的计算式为:z的1~d维直接复制(copy)给x的1~d维;z的d+1~D维分别通过F和H两个函数变换为,然后通过的仿射计算(affine)传递给x。综上,由z传给x的计算式可以写为:

其逆运算的计算式,即由x传给z的计算式,可以非常方便地推导出来为:

上面我们说明了,这样设计的耦合层能快速计算出,下面我们来说明,其在G的Jacobian行列式的计算上也是非常简便。

上图展示了G的Jacobian行列式的计算矩阵。首先由于直接传递给所以Jacobian矩阵的左上角区域是单位矩阵I,然后完全不受影响,所以Jacobian矩阵的右上角区域是零矩阵O,这导致Jacobian矩阵的左下角区域的值对Jacobian矩阵行列式的计算没有影响,也就无需考虑。最后我们关注Jacobian矩阵的右下角区域,由于),所以只有在的情况下,而在,所以Jacobian矩阵的右下角区域是一个对角矩阵。

最终,该G的Jacobian的行列式计算式就表示为:

这确实是一个易于计算的简单表达式。接下来可以考虑,由于上述措施对G做了诸多限制,导致G的变换能力有限,所以我们可以堆叠多个G,去增强模型的变换拟合能力。

如上图所示,我们将多个耦合层堆叠在一起,从而形成一个更完整的生成器。但是这样会有一个新问题,就是最终生成数据的前d维与初始数据的前d维是一致的,这会导致生成数据中总有一片区域看起来像是固定的图样(实际上它代表着来自初始高斯噪音的一个部分),我们可以通过将复制模块(copy)与仿射模块(affine)交换顺序的方式去解决这一问题。

如上图所示,通过将某些耦合层的copy与affine模块进行位置上的互换,使得每一部分数据都能走向copy->affine->copy->affine的交替变换通道,这样最终的生成图像就不会包含完全copy自初始图像的部分。值得说明的是,在图像生成当中,这种copy与affine模块互换的方式有很多种,下面举两个例子来说明:

上图展示了两种按照不同的数据划分方式做copy与affine的交替变换。左图代表的是在像素维度上做划分,即将横纵坐标之和为偶数的划分为一类,和为奇数的划分为另外一类,然后两类分别交替做copy和affine变换(两两交替);右图代表的是在通道维度上做划分,通常图像会有三通道,那么在每一次耦合变换中按顺序选择一个通道做copy,其他通道做affine(三个轮换交替),从而最终变换出我们需要的生成图形出来。

更进一步地,如何进行copy和affine的变换能够让生成模型学习地更好,这是一个可以由机器来学习的部分,所以我们引入W矩阵,帮我们决定按什么样的顺序做copy和affine变换,这种方法叫做1×1 convolution(被用于知名的GLOW当中)。1×1 convolution只需要让机器决定在每次仿射计算前对图片哪些区域实行像素对调,而保持copy和affine模块的顺序不变,这实际上和对调copy和affine模块顺序产生的效果是一致的。

这种对调的原理非常简单,如上图所示举例,假设我们需要将(3,1,2)向量替换成(1,2,3)向量,只需要将w矩阵定义为图中所示矩阵即可。下面我们看一下,将w引入flow模型之后,对于原始的Jacobian行列式的计算是否会有影响。

对于每一个3*3维划分上的仿射操作来说,由我们可以得到f的Jacobian行列式的计算结果为:

代入到整个含有d个3*3维的仿射变换矩阵当中,得到最终的Jacobian行列式的计算结果就为:,如下图所示:

因此,引入1×1 convolution后的G的Jacobian行列式计算依然非常简单,所以引入1×1 convolution是可取的,这也是GLOW这篇Paper最有突破和创意的地方。

综上,关于Flow-based Model的理论讲解和架构分析就全部结束了,它通过巧妙地构造仿射变换的方式实现不同分布间的拟合,并实现了可逆计算和简化雅各比行列式计算的功能和优点,最终我们可以通过堆叠多个这样的耦合层去拟合更复杂的分布变化(如上图所示),从而达到生成模型需要的效果。

【FLOW学习笔记】流模型(Flow-based Model)详解相关推荐

  1. SNMP学习笔记之SNMP 原理与实战详解

    原文地址:http://freeloda.blog.51cto.com/2033581/1306743 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...

  2. 【学习笔记】sed 命令及参数详解

    sed 命令及参数详解 标签:Sed 文章目录 sed 命令及参数详解 一.简介 二.基本用法 2.1. 三种方式 2.2. 常用选项 2.3. 命令体的组成 2.3.1. 定位文本部分 2.3.2. ...

  3. RT-Thread学习笔记|TCS34725 RGB 颜色识别传感器详解

    rt-thread是什么? RT-Thread 是一个集实时操作系统(RTOS)内核.中间件组件和开发者社区于一体的技术平台,组件完整丰富.高度可伸缩.简易开发.超低功耗.高安全性的物联网操作系统.R ...

  4. pytorch学习笔记(十二):详解 Module 类

    Module 是 pytorch 提供的一个基类,每次我们要 搭建 自己的神经网络的时候都要继承这个类,继承这个类会使得我们 搭建网络的过程变得异常简单. 本文主要关注 Module 类的内部是怎么样 ...

  5. 吴恩达深度学习笔记(114)-RNN梯度消失问题详解

    https://www.toutiao.com/a6652968074712449550/ 2019-02-10 14:34:53 循环神经网络的梯度消失(Vanishing gradients wi ...

  6. HTML学习笔记3:HTML基本骨架详解

    在HTML笔记1中,我简单介绍了HTML抽象的基本框架,其实,HTML的基本骨架部分还有更多内容需要了解,这一节,咱们就详细学习HTML的基本骨架. 打开sublime编辑器,输入html:xt 图1 ...

  7. Django学习笔记之Django ORM Aggregation聚合详解

    在当今根据需求而不断调整而成的应用程序中,通常不仅需要能依常规的字段,如字母顺序或创建日期,来对项目进行排序,还需要按其他某种动态数据对项目进行排序.Djngo聚合就能满足这些要求. 以下面的Mode ...

  8. [转]iOS5 ARC学习笔记:strong、weak等详解

    iOS5中加入了新知识,就是ARC,其实我并不是很喜欢它,因为习惯了自己管理内存.但是学习还是很有必要的. 在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都 ...

  9. Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...

  10. nginx 访问图片404_Nginx学习笔记(二、Nginx配置文件详解) - 被猪附身的人

    nginx的启停控制 1.Nginx信号控制: nginx中可以通过发送信号的方式来控制服务器的启停等,但要达成这些操作首先要知道nginx的PID. 获取pid的方式有两种: 利用linux的ps命 ...

最新文章

  1. mysql 优化器算法_SQL 查询优化器底层原理解析【MySQL 篇】
  2. 用FFT求信号相位谱
  3. 编写函数,可以接收任意多个整数并输出其中的最大值和所有整数之和。
  4. boost::log模块测试检查插入不会使容器中的现有元素无效
  5. 区块链BAAS平台:公共或私人区块链编程以用于各种用途
  6. 鸿蒙系统替代iOS,华为横空出世!鸿蒙系统,能否替代安卓IOS?
  7. linux系统怎么装搜狗输入法_Ubuntu系统安装搜狗(sougou for linux)输入法详细教程...
  8. css 滚动条样式_那些你总是记不住但又总是要用的css
  9. C# interface 理解 数据库统一接口
  10. 关于php变量的赋值和引用的区别
  11. Linux中级之ansible配置(playbook)
  12. Moodle 安装出现访问空白和open_basedir问题
  13. 速达 从xp系统换成win7
  14. 华为NCE网管配置EPLAN
  15. websocket前端向后端传数据时出现Buffer
  16. 从一道题理解什么是java的引用
  17. 咻商跨境电商获悉报告指广州深圳跨境电商运营人才需求激增
  18. 仿bilibili微信小程序3
  19. AI笔记: 数学基础之向量组的线性表示与线性相关
  20. 九个UPS不间断电源常见故障分析

热门文章

  1. 【KiCad7.0入门教程】----- 软件安装配置
  2. 在线翻译泄露:再次证明数据泄密无处不在
  3. python量化交易:Joinquant_量化交易基础【一】:初识量化交易
  4. 新未来大学英语视听说教程
  5. 不要在浮躁的世界里迷失自己!
  6. 6-1漏洞利用-FTP漏洞利用
  7. SQLserver服务器修复,SqlServer数据库损坏后的修复过程
  8. python之数据分析与展示(numpy、matplotlib、pandas)
  9. Python爬虫入门实战1:获取CSDN个人博客文章目录及阅读量数据
  10. 微信视频号(短内容)上线内测2020年1月21日晚上线开放入口在哪里?