Qwen2-VL笔记
qwen2-vl中说:“We have retained the Qwen-VL framework, which integrates vision encoders and language models.”,但是代码上qwen2-vl和qwen-vl的模型结构并不一致,除了动态分辨率和旋转位置编码外,连接部分用的是一层mlp(类似于llava的结构),而不是qwen-vl的类q-former
今天来分享一下最近大火的qwen2-vl模型,据说刷新各个榜单(感觉现在出个模型就是刷榜),看看有哪些特别的地方吧。
一、背景
目前的大型视觉语言模型(LVLM)的相关研究已经很多了,但是标准LVLM将输入图像编码为固定分辨率(例如224×224)进行处理,或者先缩放再填充的方法,但是这种方法会限制模型在不同尺度下捕捉信息的能力,导致高分辨率图像中细节信息的丢失。
目前的LVLM训练的时候通常会冻结类clip的视觉编码器,但是clip能否产生足够的视觉编码信息也值得怀疑,特别是在复杂推理任务和处理图像复杂细节方面。有研究尝试通过在LVLM训练中微调视觉编码器,并且已经取得了改善效果。为了进一步增强模型对不同分辨率的适应能力,我们在LVLM训练过程中引入了动态分辨率训练,在ViT中采用二维旋转位置嵌入(RoPE),使模型能够更好地捕捉不同空间尺度的信息。
视频本质上是一系列的图像帧,文本本质上是一维的,而现实环境则存在于三维空间中。当前模型中使用的一维位置嵌入显著限制了它们有效建模三维空间和时间动态的能力。所以我们开发了多模态旋转位置嵌入(MRoPE),采用独立组件表示时间和空间信息,提高模型理解和与世界互动的能力。
与LLM相比,LVLM在模型大小和数据量方面的scaling研究不足。
所以Qwen2-VL主要提升在:1、在各种分辨率和比例下的视觉理解效果最好;2、能够理解超过20分钟长度的视频;3、具备先进的推理和决策能力,可以与手机、机器人等硬件集成;4、支持多语言。
总的来说,Qwen2-VL的创新包括支持动态分辨率、ViT中采用二维旋转位置嵌入(RoPE)、设计了多模态旋转位置嵌入。
二、模型架构
保留了Qwen-VL的模型框架,不同尺寸的模型中视觉编码器保持不变(6.7B的参数量,不理解既然研究scaling,为什么不把视觉编码器一起scaling了,llm的scaling有什么好研究的)
模型结构方面的几个升级:
1、动态分辨率的支持
为了可以处理任意分辨率的图像,移除了绝对位置编码,引入了相对位置编码(2D-RoPE)。推理阶段,不同分辨率的图像被打包成一个序列。为了减少视觉token的数量,vit之后加入了一个简单的mlp层,将相邻的2 × 2token压缩成一个token。视觉token开头和结尾放置特殊的<|vision_start|>和<|vision_end|>token。224 × 224的图像经过patch_size=14的ViT编码后,进入LLM之前压缩为66个标记(224/14 = 16,16*16/4 + 2=66)。
2、多模态旋转位置嵌入(M-RoPE)
将原本的旋转位置编码拆解为时间、高度和宽度。对于文本输入,使用相同的位置ID,使得M-RoPE在功能上等同于1D-RoPE;在处理图像时,每个视觉标记的时间ID保持不变,而根据标记在图像中的位置为高度和宽度组件分配不同的ID;对于视频(视为帧序列),每帧的时间ID递增,而高度和宽度组件遵循与图像相同的ID分配模式。在模型输入包含多个模态的情况下,每个模态的位置编号通过将前一个模态的最大位置ID加一来初始化(意思就是图像+文本的话,文本的坐标直接在图像最大的位置后面+1)。
3、统一的图像和视频理解
为了保证对视频数据和图像数据的理解,Qwen2-VL将视频数据和图像数据混合进行训练,以每秒两帧的速度对视频进行采样。并使用深度为2的3D卷积处理视频输入,使模型能够处理3D数据而不是2D patch。为保持一致性,每个图像被视为两个相同的帧。为了在长视频处理的计算需求与整体训练效率之间达到平衡,我们动态调整每个视频帧的分辨率,将每个视频的总标记数量限制为16384。
三、训练过程
与Qwen-VL训练过程相同,也是三阶段的训练策略。训练数据包括图像文本对、OCR数据、交错的图像文本数据、视觉问答数据等多种数据,来源包括网页、开源数据、合成数据。
1、第一阶段
利用图像-文本对训练视觉编码器和连接层。使用了600B的token(假设一张图片66个token,一句文本相同,那是大约5B条数据?随便估计一下),llm从qwen2初始化,视觉编码器从DFN 的 ViT(苹果的一个模型)初始化,将原始绝对位置编码替换成RoPE-2D。训练数据包含图像分类和OCR数据。
2、第二阶段
训练所有参数。使用800B token。这一阶段引入更高质量的混合图像-文本内容,包含多种任务和纯文本数据。
3、第三阶段
训练语言模型和连接层。数据包含多种任务,多种格式的对话数据,已经agent训练数据。具体的数据格式这里就不放了,感兴趣的可以去看一下。
四、评估
评估包括视觉感知、文档理解、多语言图像识别、视频理解和agent能力,效果处于sota水平。对比结果就不说了,总的来说就是自己模型能力很强。感觉这里应该和llava对比一下,个人想看看这么多数据训练的结果差距有多大。值得注意的是Qwen2-VL加强了模型作为agent的能力,后面是真的想用在各种硬件中吧。
五、消融实验
1、动态分辨率
对比动态分辨率和固定分辨率之前的性能,固定分辨率是将模型进行等比例缩放,确保输入token数量恒定。实验表明调整图像大小只会小幅影响模型效果(这里指的应该是576-3136)。没有一个固定的分辨率可以在所有测试中性能最高,相比动态分辨率token更少的同时效果始终很好。
个人感觉这个没什么道理,动态分辨率的1924 token和1600 token相比也只是高了一点点,甚至一个点都不到。不过有意思的是,这个实验说明如果计算资源足够,想要追求最好的性能的话,推理的时候可以先将图片同比例放大再进行推理。
2、M-RoPE
与 1D-RoPE 相比,使用 M-RoPE 在下游任务中取得了更好的性能,尤其是在视频基准测试中。
感觉这个也没什么道理,M-RoPE除了MathVista、MMB提升相对明显一点,其余的对于图片的能力没多大提升,视频数据的测试影响大一些。
3、模型规模
随着模型规模和数据的提升,模型效果会持续提升。
感觉模型和数据的规模比本文提出的动态分辨率、M-RoPE影响更大,这个结果也算是验证了LVLM也存在模型规模和数据的sacling,有点遗憾的是没有视觉编码器scaling的信息。
六、结论
本文介绍了 Qwen2-VL,开源了多个尺寸的模型,多模态场景中和GPT-4o 和 Claude3.5-Sonnet的能力相似,超越了其它开源的LVLM 模型。Qwen2-VL引入了简单的动态分辨率和多模态旋转位置嵌入(M-RoPE),支持多语言和agent能力。
七、代码
1、数据预处理
width, height = image.size
min_pixels = ele.get(“min_pixels”, MIN_PIXELS)
max_pixels = ele.get(“max_pixels”, MAX_PIXELS)
resized_height, resized_width = smart_resize(
height,
width,
factor=size_factor,
min_pixels=min_pixels,
max_pixels=max_pixels,
)
image = image.resize((resized_width, resized_height))
def smart_resize(
height: int, width: int, factor: int = IMAGE_FACTOR, min_pixels: int = MIN_PIXELS, max_pixels: int = MAX_PIXELS
) -> tuple[int, int]:
if max(height, width) / min(height, width) > MAX_RATIO:
raise ValueError(
f"absolute aspect ratio must be smaller than {MAX_RATIO}, got {max(height, width) / min(height, width)}"
)
h_bar = max(factor, round_by_factor(height, factor))
w_bar = max(factor, round_by_factor(width, factor))
if h_bar * w_bar > max_pixels:
beta = math.sqrt((height * width) / max_pixels)
h_bar = floor_by_factor(height / beta, factor)
w_bar = floor_by_factor(width / beta, factor)
elif h_bar * w_bar < min_pixels:
beta = math.sqrt(min_pixels / (height * width))
h_bar = ceil_by_factor(height * beta, factor)
w_bar = ceil_by_factor(width * beta, factor)
return h_bar, w_bar
首先要求图像的长宽比不能超过200,然后对图像进行缩放。缩放后长和宽的像素点都要是28的倍数,并且总的像素点在4 * 28 * 28至16384 * 28 * 28之间,不然就缩放到这之间,并且尽量维持原始的长宽比。
2、动态分辨率
class Qwen2VisionTransformerPretrainedModel(Qwen2VLPreTrainedModel):
def init(self, config) -> None:
super().init(config)
self.spatial_merge_size = config.spatial_merge_size
self.patch_embed = PatchEmbed(
patch_size=config.patch_size,
temporal_patch_size=config.temporal_patch_size,
in_channels=config.in_channels,
embed_dim=config.embed_dim,
)
...
def forward(self, hidden_states: torch.Tensor, grid_thw: torch.Tensor) -> torch.Tensor:
hidden_states = self.patch_embed(hidden_states)
rotary_pos_emb = self.rot_pos_emb(grid_thw)
cu_seqlens = torch.repeat_interleave(grid_thw[:, 1] * grid_thw[:, 2], grid_thw[:, 0]).cumsum(
dim=0, dtype=torch.int32
)
cu_seqlens = F.pad(cu_seqlens, (1, 0), value=0)
for blk in self.blocks:
hidden_states = blk(hidden_states, cu_seqlens=cu_seqlens, rotary_pos_emb=rotary_pos_emb)
return self.merger(hidden_states)
...
这里的动态分辨率的原理很简单,之前是视觉编码器用的都是绝对位置编码,绝对位置编码是一个固定大小的矩阵,所以图片需要被切分成固定数量的patch。这里使用了相对位置编码,不需要固定大小的矩阵了,所以patch可以任意调整,所以就支持动态分辨率了。
3、多模态旋转位置嵌入(M-RoPE)
这段代码比较长,感兴趣的自己去看一下。
4、模型结构
class PatchMerger(nn.Module):
def init(self, dim: int, context_dim: int, spatial_merge_size: int = 2) -> None:
super().init()
self.hidden_size = context_dim * (spatial_merge_size**2)
self.ln_q = LayerNorm(context_dim, eps=1e-6)
self.mlp = nn.Sequential(
nn.Linear(self.hidden_size, self.hidden_size),
nn.GELU(),
nn.Linear(self.hidden_size, dim),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.mlp(self.ln_q(x).view(-1, self.hidden_size))
return x
最后vit出来的结果经过了一个PatchMerger处理,这个类将视觉编码的结果经过一个一层的mlp,投射到hidden_size大小。
八、总结
qwen2-vl中说:“We have retained the Qwen-VL framework, which integrates vision encoders and language models.”,但是代码上qwen2-vl和qwen-vl的模型结构并不一致,除了动态分辨率和旋转位置编码外,连接部分用的是一层mlp(类似于llava的结构),而不是qwen-vl的类q-former结构。
文章的消融实验的结果感觉并不支持文章的创新点,动态分辨率和多模态旋转位置编码并没有很大的性能提升。不过文章并没有对比相对位置编码和绝对位置编码效果的影响,动态分辨率哪里用的应该也都是旋转位置编码,感觉这个实验可以做一下试试。旋转位置编码和绝对位置编码在处理不同大小的图片时哪个效果更好?
还有一个点是要是有qwen2-vl和llava的对比就更好了,不过模型结构类似,更大的数据量效果应该会更好吧。要是效果不明显,则可能是视觉编码器使用LVLM训练的方法可能并不如对比学习先训练视觉编码器,再冻结训练LVLM。
更多推荐
所有评论(0)