草庐IT

DALL·E 2 论文阅读笔记

Iron_lyk 2023-11-20 原文

《Hierarchical Text-Conditional Image Generation with CLIP Latents》

Paper: https://cdn.openai.com/papers/dall-e-2.pdf

Project: https://openai.com/product/dall-e-2

Author: OpenAI


闲言碎语

时间线:2021.01推出DALL·E,2021年底推出GLIDE,2022.04推出DALL·E 2

DALL·E 2的能力:“DALL·E 2 can create original, realistic images and art from a text description. It can combine concepts, attributes, and styles.”

  • 生成原创性的图片

  • 组合concepts、attributes,and styles

DALLE 2 的hierarchical:先生成64*64小分辨率图片,再利用一个模型上采样到256*256,再利用一个模型上采样到1024*1024。

DALLE 2就是: CLIP模型+GLIDE模型(一个基于diffusion model的文本图像生成方法);

DALLE2 暂时不开源,不全面开发API,github上有dalle-mini库(但跟DALLE2 好像没太大关系)


前置知识

图像生成的一些方法回顾:

  1. GAN

GAN的思想其实就是左右手互博,同时训练两个网络:生成器G和判别器D。

  • 优点:因为GAN的目标就是以假乱真,所以其生成图像的保真度比较高

  • 缺点:

  • 1)训练不够稳定,因为要同时训练两个网络;

  • 2)因为是以保真度为目标,所以生成图像的多样性较差;

  • 3)不是概率模型,它的生成都是隐式完成的。你不知道它做了什么,不知道遵循了什么分布,因此GAN在数学上不如后续的VAE、扩散模型优美。

  1. AE(Auto-encoder)

自编码器是很早的技术,目的是将高维的信息通过encoder压缩到一个低维的code内,然后再使用decoder对其进行重建,关于它的细节可参阅之前的文章:Auto-encoder系列

  1. VAE(Variational Auto-Encoder)

无论是AE,DAE,还是MAE,核心上都是学习bottleneck处这个特征的,然后去做目标检测、分割、分类这些下游任务,并不是去做生成的。原因就是中间特征c并不是一个概率分布,我们没法对它采样,它是一个用于重建的特征。因此就有了VAE,中间不再生成一个特征,而是生成一个分布(高斯)。

因为VAE学到的是一个概率分布,从分布里去抽样生成图像的多样性就会好很多。

VAE的本质思想是学习一个分布,而不是一个特征。后续的诸多工作也是基于这一本质思想进行展开的。

关于VAE的细节也可参阅之前的文章:Auto-encoder系列

  1. VQ-VAE(Vector Quantized Variational Auto-Encoder)

VQ-VAE 的核心思想是将连续的高维向量编码(例如语音信号、图像、视频等)离散化,从而减少模型的复杂度和存储需求。具体来说,VQ-VAE 通过将连续的编码向量映射到一组离散的“码本”(codebook)中的最近邻,从而将高维连续编码转换为低维的离散编码。在解码器中,这些离散编码被解码回原始的高维向量。

VQ-VAE就是将特征进行量化的VAE。相对于VAE,优化起来相对容易。codebook可以理解为聚类中心,有K*D个聚类中心。

但是VQ-VAE学习的是一个固定的codebook,因此无法像VAE一样做随机采样,因此VQ-VAE更像是VQ-AE。若想像VAE那样,就需要有一个prior网络。在VQ-VAE中,prior网络是一个用于生成离散码本(codebook)的神经网络。离散码本是一组预定义的离散向量,用于将连续的向量空间映射到一个离散的向量空间。这种离散化的表示方式使得VQ-VAE可以对输入数据进行高效地编码和解码。

具体来说,prior网络的输入是由编码器生成的连续向量,输出是一个由离散向量组成的码本。prior网络的训练目标是最小化输入向量和最近的码本向量之间的欧几里得距离,从而实现向量量化。在训练过程中,prior网络不仅学习生成码本,还学习将连续向量映射到码本中最近的向量。通过将编码器生成的连续向量量化为码本中最近的向量,VQ-VAE可以保留输入数据的局部结构信息,并且可以在编码和解码过程中实现高效的计算。因此,prior网络在VQ-VAE中起着非常重要的作用。

VQ-VAE 已经在许多领域得到了应用,包括图像生成、音频压缩、语音识别、自然语言处理等。DALL·E 第一版就是基于VQ-VAE做的。

  1. DALL-E

对于一个图像文本对,文本用BPE编码生成256维的特征,图像用现成的VQ-VAE(codebook)编码为32*32维的特征,然后将这两个特征拼接成一个1280维的序列,再输入至GPT中。

训练时,将1280维序列的部分遮住,让GPT进行预测。

推理时,只需要输入文本的特征(256维),让GPT自回归的做预测就行。

  1. Diffusion model

1)扩散模型的方法

扩散模型分为 forward diffusion 和 reverse diffusion 两个阶段。对于一个图像,forward diffusion 做的就是往中不断添加噪声,一共添加T次,最后得到

为什么叫“扩散”,这启发于热力学。热力学中有一个名词叫“diffusion”,如果有两个物质分别是高密度和低密度的,那高密度的物质会慢慢地向低密度的做扩散,最后达到一种平衡。在Diffusion model 中,这种“平衡”的体现就是 forward diffusion 过程最后得到的趋近于各向同性的正态分布

reverse diffusion过程要做的就是训练一个模型,使得从恢复至,然后再训练一个模型,使得从恢复至,以此类推直至恢复至。在reverse diffusion 过程中所有使用到的模型都是共享参数的,也就是说整体其实只有一个模型,只是需要抽样生成很多次。 因此扩散模型目前最大的不足就是:相比于其他生成模型,训练很慢,且推理是最慢的。因为对于一个随机采样的噪声,要往前推T次才能生成Image。此外,目前reverse diffusion 过程中的网络大部分选用的都是U-Net。

2)扩散模型的发展历程

扩散模型这个想法在2015年就有人提出来了,但是并不能训练很好,生成图像的效果并不如其他的生成模型,比如GAN等。直至2020年有一篇论文——DDPM对扩散模型的思想进行了改进,使得训练更方便,其核心思想是:在 reverse diffusion 过程中,给定,不去直接预测(训练起来很难),而是预测使变为的噪声。这将扩散模型的问题简化了很多,直接让网络去预测一个噪声即可(类似于ResNet中去预测一个残差),比如对于正态分布而言,就是预测均值和方差,DDPM作者还发现,将方差设为一个常数,只去预测均值的话,就已经可以使扩散模型生成很好的图像。

给U-Net中加入temporal embedding,目的是使 reverse diffusion 是一个 coarse-to-fine 的过程,让模型知道目前处于哪一步,希望在最开始先生成一些粗糙的信息,最后快结束时再生成一些细致的信息,即高频的信息(比如物体的边边角角)。损失函数就是:就是U-Net网络,t是temporal embedding,是前向过程中添加的噪声,是已知的,因此可以拿来当作Ground truth,目的是希望U-Net在每一步预测的噪声与前向过程中的相同。

DDPM与VAE其实是有相似之处,比如DDPM 也可以看做的一个 encoder-decoder 结构,分别对应forwar、reverse的过程。但他们也有不同,如下:

  • DDPM的前向过程是固定的,而VAE的encoder是学习的;

  • DDPM的每一步的特征维度都是相同的,而VAE的bottle neck的维度是比输入小很多的。

  • 扩散模型有 step 的概念,有很多步;VAE没有;

在DDPM 证明了扩散模型可以work很好之后,后续出现了很多工作,比如2021年OpenAI的这篇论文《Diffusion Models Beat GANs on Image Synthesis》。在这篇论文出现之前扩散模型生成的图像已经很逼真了,但是在各项指标上还比不过GAN,然后这篇论文提出了一个Classifier guidance方法来引导模型生成图片,使得生成的效果更好,并且只做25次采样即可实现。

Classifier guided diffusion的意思是:在训练diffusion的同时,再去训练一个图片分类器(classifier,一般是在ImageNet的加了noise的图片上训练)。这个classifier的作用是:有了后,就可以丢给classifier计算一个类别损失,也就是计算出了一个梯度来辅助U-Net的训练过程。这个梯度中暗含了中是否有这个物体,或者说当前的这个物体真不真实的信息,以此来告诉U-Net要在生成的图片中在颜色、纹理等要跟真实的物体匹配上。

这个操作的核心思想是利用梯度来引导diffusion的生成,它牺牲了一定的diversity,来换取生成图片的逼真性。这种思想提出来之后,后续有人思考不用classifier来当作引导信号,而是用CLIP来进行引导,这样文本和图像就可以联系起来了,不再用梯度,而是用文本来引导引导diffusion的采样和生成。所有的引导都是目标函数中的y,也就是输入不只是和t,同时还有一个condition(y),至于是什么就看你往里加入什么。

但是Classifier guided diffusion这类方法也有一个缺陷,就是:必须用另外一个模型来进行guidance,要么是pre-trained,要么是再训练一个,这样的话成本较高且不可控。因此就出现了后续的Classifier free guidance方法,GLIDE、DALLE·2、Imagen都是基于这类方法的思想。Classifier free guidance方法不想用之前的那种guidance,而是希望找到另外一种指导信号。它的思想就是在训练时同时做两个输出,一个有条件的,一个没条件的,最后就会知道二者的差距是多少,这样在测试时,在没有条件引导的情况下,也可以推测出有条件引导的输出是多少。但是这种训练成本也很高,同时要有两个输出。

GLIDE采用了classifier free guidance的扩散模型,可以实现很好的图像生成。OpenAI也因此摒弃了DALL·E用VQ-VAE的思路,在DALL·E 2中转而使用扩散模型来进行图像生成,也就是基于GLIDE,并在其之前加入了prior网络,以及一些层级生成的技巧等。


摘要

像CLIP这些对比学习的模型已经可以学习到很稳健的图像特征,既能捕捉语义信息,又能捕捉风格信息。这种良好特征只用来做分类就很可惜,因此为了借助于这种良好特征来完成图像生成任务,我们提出了一个两阶段的模型:a prior (给定一个文本,先用现成的CLIP模型生成对应的textual embedding,然后接下来用这个textual embedding生成image embedding的过程就叫做prior),and a decoder(基于image embedding生成图像)。此外,由于是text-to-image任务,因此可以基于CLIP,可以实现zero-shot。

作者发现: 显式地生成图像特征的这种方式(就是先从文本生成image embedding,再将其解码为Image),可以很显著地提升生成图像的diversity(多样性)

引言

对于一段话,DALLE 2是能够捕捉其中的层次关系,并在画图时也考虑进来的。比如给出下面这句话,DALLE 2 生成的图片,是真的把熊画在滑板之上了,也就是说捕捉到并解码出目标之间的关联关系的。

在DALLE 2这篇论文里,CLIP这个模型是锁住的,只是被用,没有被训练。DALLE 2模型的整体框架如下,虚线之上是CLIP 模型,虚线之下才是DALLE 2模型。unCLIP是指:CLIP的目的是从文本、图像中获取特征,本文的方法是为了从特征中还原出图像,因此叫unCLIP。

DALLE 2的训练数据是图像文本对(x, y),过程分以下两个阶段:

  • Prior阶段:对于一个文本x,经由fixed CLIP可以产生一个texual embedding(蓝色)和Image embedding(红色),产生的texual embedding经过 autoregressive或difussion的prior模型生成Image embedding,这一个阶段用刚才CLIP中生成的Image embedding对其做监督。这样做的目的是:等在做推理的时候,即使只有文本特征,也可以生成比较好的图像特征。

  • Decoder阶段:用于从Image embedding中解码出图像。

如果DALLE 2的输入是图像的话,会通过CLIP生成文本特征,然后再经过prior、decoder生成图像。

方法

训练集是图像x-文本y对。分别是图像x经过CLIP输出的image和text embedding。DALL-E 2的数学描述如下:

与x是一对一的关系,因为CLIP是锁住的,给定一个x,就只会输出一个。P(zi|y)对应的是prior网络,P(x, zi|y)对应的是decoder。

在decoder阶段,使用的是 CLIP 引导的diffusion,然后技巧使用了 classifier free guidance。用的只是CNN,没有用attention。

在prior阶段,作者尝试了两种方案:Autoregressive prior和Diffusion prior。值得注意的是在两种尝试中作者都使用了classifier free guidance,证明这种方法对生成任务确实有效。

Autoregressive prior:输入是文本特征,也有CLIP输出的图像特征,然后与DALL-E、GPT类似地把他们拼接起来,然后将图像特征遮住,去自回归的预测。但是OpenAI在CLIP的文章中就已提到,这种自回归做预测的模型,训练效率太低。

Diffusion prior:训练了一个 decoder-only Transformer,输入有很多,具体请看原文~

应用

DALL·E 2的几种应用场景:

  1. text-to-image

DALL·E 2可以生成各式各样的沙发,变换颜色、样式、位置

  1. image-to-image

给定一个图像,可以生成很多风格类似的图像(整体语义信息不变):

  1. 通过对两个图像的特征做内插,生成新图像

  1. 通过对两个文本的特征做内插,生成新图像

不足

1)DALL-E 2不能很好的将attribute绑定到 object 上。

比如下面这个图,object就是方块,属性就是颜色。给一句话:“a red cube on top of a blue cube”,GLIDE的效果要比DALL-E 2好很多。

作者解释很可能是使用CLIP的原因。虽然使用CLIP后可以是图像和文本的联系更紧密,这使得更容易去做文本生成图像的任务。但是CLIP模型学习的时候,只是考虑相似性,它只是去找红方块、蓝方块来把相似性提升到最高就行了,但是CLIP模型不了解"on top of"这种东西,不了解什么叫做“上下左右”,它从头到尾都在找物体间的相似性。

因此在做CLIP特征做下游任务的时候,就不能很好的区分object和其对应的attribute。

此外,在对图片进行重建时,decoder会将object的attribute混淆。

2)直接生成文字,效果很差

作者解释可能是使用BPE编码的原因,这种是词根词缀编码。但可能还有其他原因。

有关DALL·E 2 论文阅读笔记的更多相关文章

  1. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  2. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  3. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  4. ruby-on-rails - 在 irb 中阅读文档 - 2

    我怀念ipython的一件事是它有一个?为特定功能挖掘文档的运算符。我知道ruby​​有一个类似的命令行工具,但是我在irb中调用它非常不方便。ruby/irb有类似的东西吗? 最佳答案 Pry是IPython的Ruby版本,它支持?命令来查找有关方法的文档,但语法略有不同:pry(main)>?File.dirnameFrom:file.cinRubyCore(CMethod):Numberoflines:6visibility:publicsignature:dirname()Returnsallcomponentsofthef

  5. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板 - 2

    写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c

  6. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  7. ruby - 如何将 Vim 中的 "expand"文本转换成一种易于阅读的方式? - 2

    我经常使用嵌套数据结构,很多时候我必须从控制台手动分析它们。问题是它们全部打印在一行中。是否有一种简单的方法可以根据{,[,],}和逗号重新构造数据结构的显示,使其看起来像Ruby的pretty_print输出? 最佳答案 :%s/\([{,]\)/\1\r/gggVG=:setft=ruby呜呜呜 关于ruby-如何将Vim中的"expand"文本转换成一种易于阅读的方式?,我们在StackOverflow上找到一个类似的问题: https://stacko

  8. 计算机网络笔记:TCP三次握手和四次挥手过程 - 2

    TCP是面向连接的协议,连接的建立和释放是每一次面向连接的通信中必不可少的过程。TCP连接的管理就是使连接的建立和释放都能正常地进行。三次握手TCP连接的建立—三次握手建立TCP连接①若主机A中运行了一个客户进程,当它需要主机B的服务时,就发起TCP连接请求,并在所发送的分段中用SYN=1表示连接请求,并产生一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x。主机B收到A的连接请求报文,就完成了第一次握手。客户端发送SYN=1表示连接请求客户端发送一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x②主机B如果同意建立连接,则向主机A发送确认报

  9. 基于SpringBoot的线上日志阅读器 - 2

    软件特点部署后能通过浏览器查看线上日志。支持Linux、Windows服务器。采用随机读取的方式,支持大文件的读取。支持实时打印新增的日志(类终端)。支持日志搜索。使用手册基本页面配置路径配置日志所在的目录,配置后按回车键生效,下拉框选择日志名称。选择日志后点击生效,即可加载日志。windows路径E:\java\project\log-view\logslinux路径/usr/local/XX历史模式历史模式下,不会读取新增的日志。针对历史文件可以分页读取,配置分页大小、跳转。历史模式下,支持根据关键词搜索。目前搜索引擎使用的是jdk自带类库,搜索速度相对较低,优点是比较简单。2G日志全文搜

  10. ruby - 在使用 ruby​​ 中的 "mail"gem 阅读电子邮件时需要帮助 - 2

    我正在使用Watir进行自动化,它会创建一封我需要检查的电子邮件。有人指出电子邮件gem是执行此操作的最简单方法。我添加了以下代码,并且能够从我的收件箱中收到第一封电子邮件。require'mail'require'openssl'Mail.defaultsdoretriever_method:pop3,:address=>"email.someemail.com",:port=>995,:user_name=>'domain/username',:password=>'pwd',:enable_ssl=>trueendputsMail.first我是这个论坛的新手,有以下问题:如何获

随机推荐