type
status
date
slug
summary
tags
category
icon
password

前言

本文将从Motivation的角度来理解Qwen2-VL的设计。

Architecture

总体来看Qwen2-VL是一个decode-only的多模态架构。图片、视频通过ViT变为序列特征(后面统称为visual features或visual token)。随后visual features和text features在输入层面进行拼接,作为input-embeddings,再输入到causal transformers中。监督目标任为language loss(visual token的位置不参与loss计算)。从计算层面,与常规decoder-only语言模型的差异在于输入多了visual token。
notion image
Q:如何把视觉信息嵌入到一个纯 decoder-only 的语言建模框架中
我们将从3个层面理解Qwen2-VL的设计。
  • Visual Tokenization
  • Multimodal Sequence Construction
  • Multimodal Position Encoding

Visual Tokenization

Qwen2-VL通过vision encoder将视觉输入(图片、视频)变为visual features。架构层面vision encoder包含两个部分:
  • Vision Transformer (
  • PatchMerger (4x压缩visual token, merge spatial)。不做这个压缩视觉token太长了,对decode-only架构负担太大。
区别于一些早年的多模态模型,Qwen2-VLViT有以下两点区别:
  • 支持原生分辨率的输入(Native Resolution Input,参考论文NaViT),
  • ViT的参数参与训练。
在文章:莫叶何竹🍀莫叶何竹🍀多模态模型如何处理任意分辨率输入——Tiling与Packing技术详解 | 莫叶何竹🍀我们讨论过,ViT本身是支持动态分辨率推理的,但需要考虑到:
  1. 位置编码需要支持多分辨率。
  1. 任意分辨率输入的batch化问题。
针对第一点,Qwen2-VL采用2D-RoPE。具体算法细节可参考我之前的博客:
莫叶何竹🍀莫叶何竹🍀Step by Step: Understanding ROPE | 莫叶何竹🍀
针对第二点,作者精心设计了image_processing,以便ViT用packing的方式对多分辨率的输入进行并行推理。下面来看具体是怎么做的。

Image Processing

符号说明
symbol
value
width patch size
14
height patch size
14
temporal patch size
2
merge size
2
input image shape
any resolution
满足约束resize后的image shape
3D grid size
Qwen2-VL 并不是分别为 image 和 video 设计两套 encoder,而是从一开始就将二者统一建模为 spatio-temporal patches。这使得后续的 ViT、packing 与 PatchMerger 可以完全复用同一套逻辑。
核心关键在于对图片引入temporal维度,将2D的Patchify扩展到3D的Patchify
为了能够被3D的patch size整除,且满足最小pixel、最大pixel、能被merge size整除的约束,对图片进行smart resize
  • 维度做resize
  • temporal 维度做repeat
  • 为width、height维度的patch size
  • 为temporal维度的patch size
  • 为merge size
为了便于3D卷积计算,转为Channel-first的形式
对于固定分辨率的场景,到这一步就可以了。但Qwen2-VL支持动态分辨率输入。为了提升并行能力,采用packing技巧 (需引入block-wise attention mask),将不同尺度的图片融合成一个大矩阵。 为了方便描述,定义
  • 图片在temporal维度有多少个patch (对于video这里不一定是1)
  • ,图片在height维度有多少个patch
  • ,图片在width维度有多少个patch
虽然不同分辨率的宽高不同,但经过前文的resize、repeat处理他们的patch size是相同的。因此可以将宽高的两个自由度降级到patch数量的一个自由度。具体做法
通过上述处理后,不同分辨率图片对应的不同 (这个就是该图片在encoder中的sequence length),其他维度都相同,因此可以在所在的维度进行拼接。随后用packing的技巧进行并行计算。
从实现上看,这一步本质上是将: 不同长度的视觉序列转化为一个大序列 + block-wise attention mask,从而避免 padding 带来的大量无效计算。
为了便于理解,简单说明一下patchify (是一个3D的Conv,kernel size和stride为)的维度变化
问题到这里还没结束,Qwen2-VL为了压缩visual token数量,还引入了一个PatchMerger的模块。PatchMerger的功能是将空间相邻位置的token特征进行拼接(只merge了spatial,没有merge temporal),再降维到原始维度 (形式上类似 pixel unshuffle)
从上面的流程来看,可以预先在数据处理阶段完成数据的排布,这样在PatchMerger阶段只需做Reshape和Linear。 此时
注:Qwen2-VL代码实现中会额外将这几个维度flatten,在ViT中再reshape回来
对于video的处理和上述类似。 总体来看,Qwen2-VL的image processing是一个非常工程化的实现,它解决了任意分辨率图片的batch化(对于DataLoader)和并行推理(对于visual encoder)问题,并简化了patch merger的处理链路,值得借鉴。

Multimodal Sequence Construction

有了visual features怎么让LLM理解呢?常用的方法有2个:
  • 给LLM额外引入cross attention层,如flamingo
  • LLM保持decoder-only,将visual features与text features在输入层完成拼接。
Qwen2-VL采用的是第二个方案,下面来具体说明。
为区分visual features和text features,Qwen2-VL引入<|vision_start|><|vision_end|>这里特殊字段,用于包裹visual features。
以对话的data format为例,下面是一个简单的示例,我们来step by step看看它是如何变成decoder的input embedding。
它能分成3段:
第一段:纯文本
分词结果为:
根据语言模型(decoder)的embedding layer变成text features,记作
第二段:<|image_pad|>
<|image_pad|> 在 tokenizer 层面是一个 可扩展占位符,其 token 数量与视觉 encoder 输出的 visual token 数量一致,在 embedding 构造阶段被对应的 visual features 直接替换,将第二段的visual features记作
第三段:纯文本
分词结果为:
通过语言模型(decoder)的embedding layer变成text features,记作
通过以上处理,多模态的输入变成了3段features 。将其以token维度进行拼接,得到多模态embedding
从上可知,对decoder-only的多模态方案而言,visual token 与 text token 的特征在self-attention中融合,在自回归的生成过程中,所有的visual features都是context的一部分(这也是为什么要做PatchMerger的工程考虑,否则的话context太长,太占显存资源了)。

Multimodal Position Encoding

通过上述过程,Qwen2-VL将图片和文本建模为一个多模态的token序列,送入到decode-only的Causal Transformers中进行建模。从形式看,模型已经同时看到“视觉和语言信息”。
然而与文本token不同,visual并非仅具有1维的线性关系。每一个visual token隐式的包含(temporal,height,width)3维坐标。若依旧沿用语言模型1D位置编码(如RoPE),这些多维结构信息在映射到线性序列时将不可避免地被折叠,模型只能感知到 token 的相对先后顺序,而无法区分其在时空结构中的相对关系。
因此,为了在decode-only的架构下同时建模文本的1维序列结构和visual的时空结构,Qwen2-VL将原有的1D-RoPE扩展到3D的M-RoPE,显式的将3维的位置信息注入到self-attention中(本质上在Q/K引入维度解耦的旋转变换)。
不太熟悉RoPE,如何用维度解耦的方式扩展RoPE到高维,可参考我之前的博客,也可参考作者论文:
莫叶何竹🍀莫叶何竹🍀Step by Step: Understanding ROPE | 莫叶何竹🍀
下面来看具体如何给多模态输入构建时空索引。
 
notion image
前文提到,图片/视频经过encoder后变成了visual特征序列,维度为
其中
我们再来看在这个长度为的特征序列中,每一个位置对应的空间位置索引。
不妨假定输入为视频
其spatial的索引如下
 
notion image
展平后的sequence索引如下,这个索引信息可以理解为以视频本身作为坐标系的内部索引
notion image
当将视频的特征与文本特征拼接时,需要给上面的索引加上offset
以下面的prompt为例
<|image_pad|> 是一个placeholder,用于插入视频特征或图片特征
他能分为3段
第一段:文本:
假定其分词结果为
可以得到各个token第一段的3D-RoPE索引
<|im_start|>
(0, 0, 0)
system
(1, 1, 1)
\nYou
(2, 2, 2)
are
(3, 3, 3)
a
(4, 4, 4)
helpful
(5, 5, 5)
assistant
(6, 6, 6)
.
(7, 7, 7)
<|im_end|>
(8, 8, 8)
\n
(9, 9, 9)
<|im_start|>
(10, 10, 10)
user
(11, 11, 11)
\n
(12, 12, 12)
<|vision_start|>
(13, 13, 13)
本质上text token 在三维空间里沿着对角线排列。这么设计的动机是:text 没有 preferred axis,把 text 嵌入到 3D 空间的一条对角线上不会引入axis preference。
第二段:<|image_pad|> 对应vision feature
已知第一段的最终索引是13,因此第二段从14开始,offset是14 (注意3个轴都要平移这个offset, 确保text盒vision在任一轴不会重叠)
notion image
第三段:文本
假定其分词结果为
第二段的最终索引是17,因此第3段从18开始,从而可得到第三段的3D索引
|vision_end|>
(18, 18, 18)
Describe
(19, 19, 19)
this
(20, 20, 20)
image
(21, 21, 21)
.
(22, 22, 22)
<|im_end|>
(23, 23, 23)
\n
(24, 24, 24)
<|im_start|>
(25, 25, 25)
assistant
(26, 26, 26)
至此,统一用时空索引来编码文本 token 与视觉 token的位置。尽管它们在序列中仍以一维形式输入Transformer,但在 self-attention 计算时,其Q/K的旋转角度由各自的时空坐标(temporal, height, width)共同决定,从而使注意力权重同时感知序列顺序与视觉结构。

小结

本文从Motivation与实现逻辑的角度,对 Qwen2-VL 的整体架构进行了拆解与分析,以此基础再去看论文和源码就相对容易了。文本并未罗列论文中的实验设置和benchmark结果,感兴趣的读者可以深入阅读。
 
多模态模型如何处理任意分辨率输入——Tiling与Packing技术详解(part2)Nougat 深度剖析
Loading...