赞
踩
真没想到,距离视频生成上一轮的集中爆发(详见《Sora之前的视频生成发展史:从Gen2、Emu Video到PixelDance、SVD、Pika 1.0》)才过去三个月,没想OpenAI一出手,该领域又直接变天了
可当我接连扒出sora相关的10多篇论文之后,觉得sora和此前发布的视频生成模型有了质的飞跃(不只是一个60s),而是再次印证了大力出奇迹,大模型似乎可以在力大砖飞的情况下开始理解物理世界了,使得我司大模型项目组也愿意重新考虑开发视频生成的相关应用
本文主要分为三个部分(初步理解只看第一部分即可,深入理解看第二/三部分,更多细节则看第四部分)
总之,看本文之前,如果你人云亦云的来一句:sora就是DiT架构,我表示理解。但看完全文后你会发现
更多,则在该课里见:视频生成Sora的原理与复现 [全面解析且从零复现sora缩略版]
为方便大家更好的理解sora背后的原理,我们先来快速回顾下AI绘画的原理(理解了AI绘画,也就理解了sora一半)
以DALLE 2为例,如下图所示(以下内容来自此文:从CLIP、BLIP到DALLE、DALLE 2、DALLE 3、Stable Diffusion)
- CLIP训练过程:学习文字与图片的对应关系
如上图所示,CLIP的输入是一对对配对好的的图片-文本对(根据对应文本一条狗,去匹配一条狗的图片),这些文本和图片分别通过Text Encoder和Image Encoder输出对应的特征,然后在这些输出的文字特征和图片特征上进行对比学习- DALL·E2:prior + decoder
上面的CLIP训练好之后,就将其冻住了,不再参与任何训练和微调,DALL·E2训练时,输入也是文本-图像对,下面就是DALL·E2的两阶段训练:
阶段一 prior的训练:根据文本特征(即CLIP text encoder编码后得到的文本特征),预测图像特征(CLIP image encoder编码后得到的图片特征)
换言之,prior模型的输入就是上面CLIP编码的文本特征,然后利用文本特征预测图片特征(说明白点,即图中右侧下半部分预测的图片特征的ground truth,就是图中右侧上半部分经过CLIP编码的图片特征),就完成了prior的训练
推理时,文本还是通过CLIP text encoder得到文本特征,然后根据训练好的prior得到类似CLIP生成的图片特征,此时图片特征应该训练的非常好,不仅可以用来生成图像,而且和文本联系的非常紧(包含丰富的语义信息)
阶段二 decoder生成图:常规的扩散模型解码器,解码生成图像
这里的decoder就是升级版的GLIDE(GLIDE基于扩散模型),所以说DALL·E2 = CLIP + GLIDE
所以对于DALLE 2来说,正因为经过了大量上面这种训练,所以便可以根据人类给定的prompt画出人类预期的画作,说白了,可以根据text预测画作长什么样
最终,sora由三大Transformer组件组成(如果你还不了解transformer或注意力机制,请读此文):Visual Encoder(即Video transformer,类似下文将介绍的ViViT)、Diffusion Transformer、Transformer Decoder,具体而言
你会发现,上述整个过程,其实和SD的原理是有较大的相似性(SD原理详见此文《从CLIP、BLIP到DALLE、DALLE 2、DALLE 3、Stable Diffusion》的3.2节),当然,不同之处也有很多,比如视频需要一次性还原多帧、图像只需要还原一帧
网上也有不少人画出了sora的架构图
- 比如来自魔搭社区的
- 以及张俊林的
至于左下角的“image & video”的意思是图像和视频的联合训练「因为图片可看成单帧的视频,首帧单独表示就可以对单张图片进行编码了,更多可参考论文《Phenaki: Variable Length Video Generation From Open Domain Textual Description》」
至于左上角的“Long Time”指的是sora能生成长达60s的视频
首先,一个视频无非就是沿着时间轴分布的图像序列而已
但其中有个问题是,因为像素的关系,一张图像有着比较大的维度(比如250 x 250),即一张图片上可能有着5万多个元素,如果根据上一张图片的5万多元素去逐一交互下一张图片的5万多个元素,未免工程过于浩大(而且,即便是同一张图片上的5万多个像素点之间两两做self-attention,你都会发现计算复杂度超级高)
可能有同学问,这么做有什么好处呢?好处太多了
总之,基于 patches 的表示,使 Sora 能够对不同分辨率、持续时间和长宽比的视频和图像进行训练。在推理时,也可以可以通过在适当大小的网格中排列随机初始化的 patches 来控制生成视频的大小
如Tim Brooks所说,把各种各样的图片和视频,不管是宽屏的、长条的、小片的、高清的还是低清的,都把它们分割成一小块一小块的
接着,便可以根据输入视频的大小,训练模型认识不同数量的小块,从而生成不同分辨率/长宽比的视频
所以说,ViT本身就能够处理任意长宽比(不同长宽比相当于不同数量的图片patch),但谷歌的 Patch n’ Pack (NaViT)可以提供了一种更为高效的训练方法,关于NaViT的更多细节详见下文的介绍
而过去的图像和视频生成方法通常需要调整大小、进行裁剪或者是将视频剪切到标准尺寸,例如 4 秒的视频分辨率为 256x256。相反,该研究发现在原始大小的数据上进行训练,最终提供以下好处:
sora不是第一个把扩散模型和transformer结合起来用的模型,但是第一个取得巨大成功的,为何说它是结合体呢
总之,总的来说,Sora是一个在不同时长、分辨率和宽高比的视频及图像上训练而成的扩散模型,同时采用了Transformer架构,如sora官博所说,Sora is a diffusion transformer,简称DiT(当然,可能有朋友发现了,这句话说的过于简略,毕竟DiT还只是处理2D图像生成,且整个处理框架还处在VAE的框架之下,涉及到VAE encoder和VAE decoder)
关于DiT的更多细节详见下文第二部分介绍的DiT
首先,训练文本到视频生成系统需要大量带有相应文本字幕的视频,而通过CLIP技术给视频对齐的文本描述,有时质量较差,故为进一步提高文本-视频数据集的质量,研究团队将 DALL・E 3 中的重字幕(re-captioning)技术应用于视频
关于DALLE 3的重字幕技术更具体的细节请见此文的2.3节《AI绘画原理解析:从CLIP、BLIP到DALLE、DALLE 2、DALLE 3、Stable Diffusion》
其次,如之前所述,为了保证视频的一致性,模型层不是通过多个stage方式来进行预测,而是整体预测了整个视频的latent(即去噪时非先去噪几帧,再去掉几帧,而是一次性去掉全部帧的噪声)
但在视频内容的扩展上,比如从一段已有的视频向后拓展出新视频的训练过程中除了整体去噪生成之外,也可能引入了auto regressive的task,以帮助模型更好的进行视频特征和帧间关系的学习
更多可以参考下文Google的W.A.L.T工作,或下文“2.5.2 VDT的视频预测方案:把视频前几帧作为条件帧自回归预测下一帧”
OpenAI 发现,视频模型在经过大规模训练后,会表现出许多有趣的新能力。这些能力使 Sora 能够模拟物理世界中的人、动物和环境的某些方面。这些特性的出现没有任何明确的三维、物体等归纳偏差 — 它们纯粹是规模现象
对于“sora真的会模拟真实物理世界”这个问题,网上的解读非常多,很多人说sora是通向通用AGI的必经之路、不只是一个视频生成,更是模拟真实物理世界的模拟器,这个事 我个人觉得从技术的客观角度去探讨更合适,那样会让咱们的思维、认知更冷静,而非人云亦云、最终不知所云
首先,作为“物理世界的模拟器”,需要能够在虚拟环境中重现物理现实,为用户提供一个逼真且不违反「物理规律」的数字世界
比如苹果不能突然在空中漂浮,这不符合牛顿的万有引力定律;比如在光线照射下,物体产生的阴影和高光的分布要符合光影规律等;比如物体之间产生碰撞后会破碎或者弹开
其次,李志飞等人在《为什么说 Sora 是世界的模拟器?》一文中提到,技术上至少有两种方式可以实现这样的模拟器
虚幻引擎(Unreal Engine,UE)就是这种物理世界的模拟器
- 它内置了光照、碰撞、动画、刚体、材质、音频、光电等各种数学模型。一个开发者只需要提供人、物、场景、交互、剧情等配置,系统就能做出一个交互式的游戏,这种交互式的游戏可以看成是一个交互式的动态视频
- UE 这类渲染引擎所创造的游戏世界已经能够在某种程度上模拟物理世界,只不过它是通过人工数学建模及渲染而成,而非通过模型从数据中自我学习。而且,它也没有和语言代表的认知模型连接起来,因此本质上缺乏世界常识。而 Sora 代表的AI系统有可能避免这些缺陷和局限
不同于 UE 这一类渲染引擎,Sora 并没有显式地对物理规律背后的数学公式去“硬编码”,而是通过对互联网上的海量视频数据进行自监督学习,从而能够在给定一段文字描述的条件下生成不违反物理世界规律的长视频
与 UE 这一类“硬编码”的物理渲染引擎不同,Sora 视频创作的想象力来自于它端到端的数据驱动,以及跟LLM这类认知模型的无缝结合(比如ChatGPT已经确定了基本的物理常识)
最后值得一提的是,Sora 的训练可能用了 UE 合成的数据,但 Sora 模型本身应该没有调用 UE 的能力
注意,和sora相关的技术其实有非常多,但有些技术在本博客之前的文章中写过了(详见本文开头),则本部分不再重复,比如DDPM、ViT、DALLE三代、Stable Diffusion(包括潜在空间LDM)等等
通过上文提到过多次的此文《图像生成发展起源:从VAE、VQ-VAE、扩散模型DDPM、DETR到ViT、Swin transformer》可知
VQ-VAE的生成模式是pixcl-CNN +codebook,其中pixcl-CNN就是一个自回归模型
OpenAI 将pixcl-CNN换成GPT,再加上那会多模态相关工作的火热进展,可以考虑使用文本引导图像生成,所以就有了DALL·E
DALL·E和VQ-VAE-2一样,也是一个两阶段模型:
- Stage1:Learning the Visual Codebook
先是输入:一对图像-文本对(训练时),之后编码特征,具体编码时涉及到两个步骤
首先,文本经过BPE编码得到256维的特征
其次,256×256的图像经过VQ-VAE(将训练好的VQ-VAE的codebook直接拿来用),得到32×32的图片特征- Stage2:Learning the Prior
重构原图
将拉直为1024维的tokens,然后连上256维的文本特征,这样就得到了1280维的token序列,然后直接送入GPT(masked decoder)重构原图
受DALLE工作的启发,UC Berkeley于2021年4月推出VideoGPT,其对应的论文为《VideoGPT: Video Generation using VQ-VAE and Transformers》,其建立在VQ-VAE和GPT架构的基础之上,具体而言
VAE出来后有不少改进模型,总体而言可分为两大类:
首先,对于前者“连续Latent” 模型,3D卷积因为在重建第 帧的时候参考了之前的 帧,其实融入时间信息了,如果 可以拉到比较长的时间,那么对于维护生成图像的时间一致性是有帮助的。但是,仅靠CNN 卷积一般融入的历史比较短,很难融入较长时间的信息(说白了,在3D卷积之下,K难以设置的比较大),所以如果OpenAI直接用“连续Latent” 模型,还得有一些创新性的技术
其次,我们再考虑下后者“离散Latent”模型
所谓“离散Latent”,就是把“连续Latent”进行ID化,从实数向量通过一定方法转换成一个专属ID编号,这跟LLM里的字符串Tokenizer离散化过程是比较像的
如张俊林所说,一般对“连续Latent”离散化过程的基本思想如下图右侧所示
总之,”连续Latent”离散化过程,可以看成对图片片段聚类的过程,赋予的那个ID编号其实等价于聚类的类编号。目前的图像处理而言,Codeword通常在8000左右(如果再大效果反而不好),如此,问题就来了,这种聚类操作导致很多“大体相似,但细节不同”的图片被赋予相同的ID,这意味着细节信息的丢失,所以离散化操作是有信息损失的
那为何说sora采用MAGVIT-2的思路可能性比较低呢?如张俊林所说(对MAGVIT不了解的没事,下文会详细介绍MAGVIT)?
MAGVIT-2把输入视频帧分组之后
但「MAGVIG-v2把4帧最后压缩成一帧的Latent表示」的这个操作,所以它不仅在空间维度,同时也在时间维度上对输入进行了压缩,而这可能在输入层面带来进一步的信息损失,这种信息损失对于视频分类来说不是问题,但是对视频生成来说可能无法接受
其次,4帧压成1帧,这说明起码MAGVIG-v2的Latent编码是包含了“局部Time”信息的,这对于维护生成视频的时间一致性肯定有帮助,但因为仅靠CNN很难融入太长的历史信息,貌似只能融合短期的时间信息,对于维护“长时一致性”帮助很有限
故Sora采用MAGVIT的概率不大,为了能够生成长达60秒的视频,我们希望在VAE编码阶段,就能把长周期的历史信息融入到VAE编码里来,这肯定是有很大好处的
2022年5月,Wilson Yan, Danijar Hafner, Stephen James, Pieter Abbeel等人提出TECO模型(全称为Temporally Consistent Transformer,其对应论文为:Temporally Consistent Transformers for Video Generation)
TECO的结构如下图所示,核心由两个任务组成
且其有两个主要特点:
对Sora来说,如果对TECO适应性地改造一下,基本就可以把它能在VAE阶段就融合超长历史的能力吸收进来
经过上述改造,TECO在VAE Encoder阶段的基本思想就展示在下图中了
最后,如上图右下角所示,每帧视频经过TECO编码后,有一个“Space Latent”和一个“Time Latent”,两者并在一起就是这帧视频的VAE编码结果
这里可以再次看出,TECO的思路是增加信息,而不是以压缩减少信息为唯一目的的
在具体介绍ViViT之前,先说三个在其之前的工作
而Google于2021年5月提出的ViViT(其对应论文为:ViViT: A Video Vision Transformer)便要尝试在视频中使用ViT模型,且他们充分借鉴了之前3D CNN因式分解等工作,比如考虑到视频作为输入会产生大量的时空token,处理时必须考虑这些长范围token序列的上下文关系,同时要兼顾模型效率问题
故作者团队在空间和时间维度上分别对Transformer编码器各组件进行分解,在ViT模型的基础上提出了三种用于视频分类的纯Transformer模型,如下图所示
区别于常规的二维图像数据,视频数据相当于需在三维空间内进行采样(拓展了一个时间维度),有两种方法来将视频映射到token序列(说白了,就是从视频中提取token,而后添加位置编码并对token进行reshape得到最终Transformer的输入)
虽然ViViT可能除了第一帧,其它视频帧比如可以2帧为一组(即不仅在空间维度进行压缩,在时间维度也进一步压缩,通过CNN的3D卷积把时间维度的2帧输入压缩为1帧Patch),但考虑到时间维度的压缩会影响视频生成的质量,sora可能类似Latte那样,不做时间维度层面的压缩
故如张俊林所说,每张图片有两个Patch矩阵
所以,我们可以用一个的Patch,把同一个图片的Space Latent和Time Latent合并,压缩为一个Patch矩阵
这么做的好处有,首先,每张图片对应一个Patch矩阵,融合过程中既包含了空间信息,也包含了Long Time时间信息,信息保留非常充分。其次,如果要支持“图片&&视频联合训练”,那么首帧需要独立编码不能分组,这种方案因为没有视频帧分组过程,所以自然就支持“图片&&视频联合训练”
上文说过,Google在ViT模型的基础上提出了三种用于视频分类的纯Transformer模型,接下来,介绍下这三种模型
当然,由于论文中把一个没有啥技巧且计算复杂度高的模型作为模型1:简单地将从视频中提取的所有时空token,然后每个transformer层都对所有配对进行建模,类似Neimark_Video_Transformer_Network_ICCVW_2021_paper的工作(其证明了VTN可以高效地处理非常长的视频)
所以下述三个模型在论文中被分别称之为模型2、3、4
第二个模型如下图所示,该模型由两个串联的transformer编码器组成:
对应的代码如下(为方便大家一目了然,我不仅给每一行代码都加上了注释,且把代码分解成了8块,每一块代码的重点都做了细致说明)
- # 定义ViViT模型类
- class ViViT(nn.Module):
- def __init__(self, image_size, patch_size, num_classes, num_frames, dim=192, depth=4, heads=3, pool='cls', in_channels=3, dim_head=64, dropout=0.,
- emb_dropout=0., scale_dim=4):
- super().__init__() # 调用父类的构造函数
-
- # 检查pool参数是否有效
- assert pool in {'cls', 'mean'}, 'pool type must be either cls (cls token) or mean (mean pooling)'
- # 确保图像尺寸能被patch尺寸整除
- assert image_size % patch_size == 0, 'Image dimensions must be divisible by the patch size.'
- # 计算patch数量
- num_patches = (image_size // patch_size) ** 2
- # 计算每个patch的维度
- patch_dim = in_channels * patch_size ** 2
- # 将图像切分成patch并进行线性变换的模块
- self.to_patch_embedding = nn.Sequential(
- Rearrange('b t c (h p1) (w p2) -> b t (h w) (p1 p2 c)', p1=patch_size, p2=patch_size),
- nn.Linear(patch_dim, dim),
- )
为方便大家理解,我得解释一下上面中这行的含义: Rearrange('b t c (h p1) (w p2) -> b t (h w) (p1 p2 c)', p1=patch_size, p2=patch_size)
且为方便大家和我之前介绍ViT的文章前后连贯起来,故还是用的ViT那篇文章中的例子(此文的第4部分)16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 | 16*16 |
16*16 | |||||||||||||
16*16 | |||||||||||||
16*16 | |||||||||||||
... |
- # 位置编码
- self.pos_embedding = nn.Parameter(torch.randn(1, num_frames, num_patches + 1, dim))
- # 空间维度的cls token
- self.space_token = nn.Parameter(torch.randn(1, 1, dim))
- # 空间变换器
- self.space_transformer = Transformer(dim, depth, heads, dim_head, dim * scale_dim, dropout)
-
- # 时间维度的cls token
- self.temporal_token = nn.Parameter(torch.randn(1, 1, dim))
- # 时间变换器
- self.temporal_transformer = Transformer(dim, depth, heads, dim_head, dim * scale_dim, dropout)
-
- # dropout层
- self.dropout = nn.Dropout(emb_dropout)
- # 池化方式
- self.pool = pool
-
- # 最后的全连接层,用于分类
- self.mlp_head = nn.Sequential(
- nn.LayerNorm(dim),
- nn.Linear(dim, num_classes)
- )
- def forward(self, x):
- # 将输入数据x转换为patch embeddings
- x = self.to_patch_embedding(x)
- b, t, n, _ = x.shape # 获取batch size, 时间维度, patch数量
-
- # 在每个空间位置加上cls token
- cls_space_tokens = repeat(self.space_token, '() n d -> b t n d', b=b, t=t)
- x = torch.cat((cls_space_tokens, x), dim=2) # 在维度2上进行拼接
-
- x += self.pos_embedding[:, :, :(n + 1)] # 加上位置编码
- x = self.dropout(x) # 应用dropout
- # 将(b, t, n, d)重排为((b t), n, d),为了应用空间变换器
- x = rearrange(x, 'b t n d -> (b t) n d')
- x = self.space_transformer(x) # 应用空间变换器
- x = rearrange(x[:, 0], '(b t) ... -> b t ...', b=b) # 把输出重排回(b, t, ...)
- # 在每个时间位置加上cls token
- cls_temporal_tokens = repeat(self.temporal_token, '() n d -> b n d', b=b)
- x = torch.cat((cls_temporal_tokens, x), dim=1) # 在维度1上进行拼接
-
- x = self.temporal_transformer(x) # 应用时间变换器
- # 根据pool参数选择池化方式
- x = x.mean(dim=1) if self.pool == 'mean' else x[:, 0]
- # 通过全连接层输出最终的分类结果
- return self.mlp_head(x)
第二个模型如下图所示,会先计算空间自注意力(token中有相同的时间索引,相当于同一帧画面上的token元素),再计算时间的自注意力(token中有相同的空间索引,相当于不同帧下同一空间位置的token,比如一直在视频的左上角那一块的token块)
由于实验表明空间-时间自注意力或时间-空间自注意力的顺序并不重要,所以第三个模型的结构如下图所示,一半的头仅在空间轴上计算点积注意力,另一半头则仅在时间轴上计算,且其参数数量增加了,因为有一个额外的自注意力层
不过,该模型通过利用dot-product点积注意力操作来取代因式分解factorisation操作,通过注意力计算的方式来代替简单的张量reshape。思想是对于空间注意力和时间注意力分别构建对应的键、值,如下图所示(图源自萝卜社长)
在ViT之前,图像领域基本是CNN的天下,包括扩散过程中的噪声估计器所用的U-net也是卷积架构,但随着ViT的横空出世,人们自然而然开始考虑这个噪声估计器可否用Transform架构来代替
2022年12月,William Peebles(当时在UC Berkeley,Peebles在
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。