多模态大模型技术详解(图像分块、特征对齐)

news2024/9/21 19:46:49

多模态

  • 多模态发展
  • 图像预处理
    • 自适应图像切割
    • 弥补语义损失
  • 视觉编码器
  • 视觉文本特征对齐
    • 线性映射或MLP
    • Cross Attention
    • Perceiver Resampler
    • Q-Former(Querying Transformer)
      • 模型结构
      • 表示学习
  • 大语言模型

这篇文档主要讲解目前比较流行的缝合式的多模态大模型的基本模块。缝合式多模态大模型的架构:包括视觉编码器、视觉文本对齐层、大语言模型,流程主要是通过视觉编码器提取图像特征,再通过视觉文本对齐层将图像和文本特征对齐,也包括对视觉特征的在提取,主要是为了减少视觉 token 的数量,然后将视觉特征和文本特征一起输入到大模型中获取结果。涉及到的技术主要包括以下几个点:

  1. 图像预处理:从刚开始直接对图像进行缩放到固定尺寸到现在的保持图像宽高比的同时将图像切分为多块进行处理;
  2. 视觉编码器:目前比较常用的是使用 CLIP 训练的 ViT 图像编码器以及 SigLip 图像编码器;
  3. 视觉映射器:主要作用是将图像特征映射到与文本特征同样的维度、减少视觉 token 的数量;
  4. 大语言模型:学习图像和文本特征的关系,输出结果。

CLIP
Flamingo
BLIP(BLIP2、InstructBLIP)
BEIT(BEIT-2、BEIT-3)
LLaVA(LLaVA1.5、LLaVA-Next)
MiniGPT4
mPLUG(mPLUG-Owl1-3、mPLUG-DocOwl)
Qwen-VL
DeepSeek-VL
Idefics2
InternVL
MiniCPM-V

多模态发展

第一代:支持的图像分辨率非常低(224×224),研发的重心主要聚焦在模态对齐的原型验证上(CLIP、Flamingo、BLIP2、LLaVA、MiniGPT4、mPLUG-Owl)

第二代:从研发的角度主要是要为LMM增加目标定位的能力,相比粗粒度的图像内容问答,增加目标定位能力是多模态 LMM 能够在Agent、机器人、自动驾驶、安防巡检等场景中落地实用的必要前提(LLaVA1.5、Qwen-VL)

关键问题:

  1. 高分辨率输入的支持:2代LMM的分辨率基本都处在336~448之间
  2. 图文模态间的竞争:几乎所有的工作都回避了语言模型能力下降的问题
  3. 多模态的Scaling Law:缝合路线的天花板是否已经出现

第三代:支持高分辨率的文档图像

图像预处理

图像分辨率的问题:从一开始的图像分辨率固定为224,接下来图像分辨率增加至336-448,到最后支持1344的分辨率,基本上可以支持大部分的图片。

为什么需要支持高分辨率,分辨率不高带来的问题有哪些:

  1. 对于一些文档图像(字符密集图像),如果不考虑宽高比强制缩放至 448x448 会对其中的文本信息造成影响,导致对图像中的文本信息不能很好的理解,也就会影响最后的回答,比如 OCR 任务、VQA任务、信息抽取任务等。

为什么不一开始就支持很大的分辨率,主要制约因素是训练的成本和语言模型的窗口的大小:

  1. 图像分辨率高,图像编码后的图像 token 越多,对应的训练成本就越高

  2. 刚开始的语言模型的窗口大小普遍在1K 左右,过长的图像 token 长度会压缩文本输入的空间,导致问答能力下降

    比如 224 x 224 的图像,patch size 为 14,则编码后的图像 token 数就是 224 x 224 14 x 14 = 256 \frac{224x224}{14x14}=256 14x14224x224=256 ,同样分辨率 448 的图像,对应图像 token 数是 1024,如果是 1344x896 的图像,首先分为 3x2=6 的 448x448 的图像块,总的图像 token 数就是 6x1024=6144。一刚开始的语言模型支持的窗口大小压根就不能支持高分辨率的图像,随着后续语言模型的窗口大小越来越大,才能支持更大分辨率的图像。

目前是怎么解决高分辨率的问题的: 自适应图像切割 + 全局图像,Mini-Monkey 认为对图像切割之后会对图像中的目标或文字的语义造成损失,提出了弥补语义损失的自适应分割。

自适应图像切割

在这里插入图片描述

自适应图像切割(混合分辨率支持)(LLaVA-Next、QwenVL-plus/max、InternVL、MiniCPM-V),以 InternVL2 的代码进行分析,其他的图像处理方式会有一些差别,但基本差不多。

  1. 首先预定义一些宽高比,可支持多种切割方式
    target_ratios = set(
        (i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1)
        if i * j <= max_num and i * j >= min_num
    )
    
  2. 然后从这些宽高比中找到与原图宽高比最接近的一个,用于对图像切分
    def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
        best_ratio_diff = float('inf')
        best_ratio = (1, 1)
        area = width * height
        for ratio in target_ratios:
            target_aspect_ratio = ratio[0] / ratio[1]
            ratio_diff = abs(aspect_ratio - target_aspect_ratio)
            if ratio_diff < best_ratio_diff:
                best_ratio_diff = ratio_diff
                best_ratio = ratio
            elif ratio_diff == best_ratio_diff:
                if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
                    best_ratio = ratio
        return best_ratio
    
  3. 然后根据找到的宽高比对图像进行缩放,这样可以保证原图的宽高比。然后再切分为多个 448x448 的小块
    target_width = image_size * target_aspect_ratio[0]
    target_height = image_size * target_aspect_ratio[1]
    blocks = target_aspect_ratio[0] * target_aspect_ratio[1]
    
    # resize the image
    resized_img = image.resize((target_width, target_height))
    processed_images = []
    for i in range(blocks):
        box = (
            (i % (target_width // image_size)) * image_size,
            (i // (target_width // image_size)) * image_size,
            ((i % (target_width // image_size)) + 1) * image_size,
            ((i // (target_width // image_size)) + 1) * image_size
        )
        # split the image
        split_img = resized_img.crop(box)
        processed_images.append(split_img)
    
  4. 增加全局图像,把原图缩放至 448x448
    if use_thumbnail and len(processed_images) != 1:
        thumbnail_img = image.resize((image_size, image_size))
        processed_images.append(thumbnail_img)
    
  5. 最后将所有的图像块堆叠在一起
    pixel_values = [transform(image) for image in images]
    pixel_values = torch.stack(pixel_values)		# (N, H, W, C)
    

最终,把多个分块后的图像输入到图像编码中提取图像特征。

弥补语义损失

Mini-Monkey

考虑到对图像切割之后会对图像中的目标或文字的语义造成损失,提出了弥补语义损失的自适应分割。
在这里插入图片描述
在原始的分块基础上又增加了一种分块方法,该方法从预先定义的宽高比中选择一种与先前分割不相等、不成比例的宽高比作为候选,从中选择一种最优宽高比对图像进行切分。再和自适应切割、全图缩放拼接在一起作为输入到图像编码中的图像块。这样可以缓解由于切割带来的语义损失,

new_target_ratios = []
   for i in target_ratios:
       if prior_aspect_ratio[0]%i[0] or prior_aspect_ratio[1]%i[1]:
           new_target_ratios.append(i)
       else:
           continue

视觉编码器

  • ViT(使用CLIP预训练的)、SigLip(使用sigmoid损失函数)
  • 混合图像编码器(SigLip+SAM)(DeepSeek-VL)
  • ResNet

视觉文本特征对齐

作用:

  1. 对齐视觉特征和文本特征的维度

  2. 减少视觉特征的 token 数

    由于分辨率支持的越来越高,视觉特征的 token 数也越来越多,虽然大语言模型可以支持上万的 token,但是视觉 token 太多会压缩文本特征的表征。另一方面,由于图像特征的稀疏性,有必要减少视觉 token,提炼出更重要的特征。

线性映射或MLP

在视觉特征较少的时候,不需要减少视觉特征,可简单的使用一个线性层或MLP对齐视觉特征和文本特征的维度,然后视觉特征和文本特征拼接输入到大模型中。

比如 DeepSeek-Vl、LlaVA、mPLUG-Owl3 采用的这种方式,InternVL2 采用 Pixel Shuffle + MLP 来减少视觉 token 数并对齐文本特征维度。

Cross Attention

有些多模态大模型,仅仅使用一个 Cross Attention 来减少视觉特征的 token数。通过定一个固定数量的可学习的 queries,通过和视觉特征进行交叉注意,来提取视觉特征。

比如 mPLUG-Owl1、mPLUG-Owl2、MiniCPM-V 采用的这种方式,

mPLUG-Owl

Perceiver Resampler

Flamingo 提出了 Perceiver Resampler

在这里插入图片描述
在这里插入图片描述
首先定义固定数量的可学习的 queries,然后通过和视觉编码器提取出的特征通过 resampler 输出固定长度的视觉特征。具体操作可以看以下的伪代码。其目的是为了将变长的特征数量使用固定长度的特征来表示。

def perceiver_resampler( 
	x_f, 				# The [T, S, d] visual features (T=time, S=space)
	time_embeddings, 	# The [T, 1, d] time pos embeddings.
	x, 					# R learned latents of shape [R, d]
	num_layers, 		# Number of layers
):
	"""The Perceiver Resampler model."""
	# Add the time position embeddings and flatten.
	x_f = x_f + time_embeddings 
	x_f = flatten(x_f) # [T, S, d] -> [T * S, d]
	# Apply the Perceiver Resampler layers.
	for i in range(num_layers):
		# Attention.
		x = x + attention_i(q=x, kv=concat([x_f, x]))
		# Feed forward.
		x = x + ffw_i(x)
	return x

Q-Former(Querying Transformer)

BLIP2提出了Q-Former,旨在减少视觉特征的维度并提取出与文本更相关的视觉特征。

Q-Former 通过预先定义一个可学习的固定长度的 queries,通过与图像特征的交叉注意力来学习 queries 的表示,这个学到的 queries 就是提取出的图像特征,并且通过与文本的交互,这个特征也是与文本最相关的。
在这里插入图片描述

模型结构

在这里插入图片描述

Q-Former 的网络结构如上图所示,包括图像 Transformer 和 文本Transformer ,这两个模块的 self attention 共享特征, 图像编码器输入为可学习的 queries 和 图像编码器输出的图像特征,主要是通过 queries 学习图像特征的表示,文本 Transformer 可以作为文本编码器也可以作为文本解码器。

可学习的 queries 通过 self attention 可以相互交互,并通过 cross attention 与图像特征交互。除此之外,queries 还可以通过 self attention 与输入的文本交互。在 BLIP2 中,queries 的长度设置为 32, 维度设置为 768,可以大大减少图像特征的 token 数。queries 也可以根据需要设置不同的大小。

使用 BERTbase 的预训练权重初始化 QFormer,而交叉注意力层是随机初始化的。

表示学习

在这里插入图片描述

在表示学习阶段,将 Q-Former 与冻结的图像编码器链接,使用图像-文本对进行训练,最终让 queries 可以学习到提取文本信息量最大的视觉表示。主要通过优化三个预训练目标来学习:图像-文本对比学习、基于图像的文本生成、图像-文本匹配。

图像-文本对比学习(ITC)

图像文本对比学习学习对齐图像表示和文本表示,使它们的互信息最大化。通过将正对的图像-文本相似度与负对的图像文本相似度进行对比来实现。首先将图像 Transformer 的输出 queries 表示与文本 Transformer 输出的文本表示对齐,由于 queries 包含多个向量,所以先计算每个向量和文本表示的相似度,选择得分最高的作为图像-文本的相似度。在这一部分,queries 和文本不允许相互看到,避免信息泄漏。

这里为什么要计算得分最高的一个作为图像-文本的相似度呢?在BLIP和CLIP的图像-文本对比学习是有区别的。在CLIP里边,N个图像和N个文本最终图像编码器和文本编码器输出的N个图像向量和N个文本向量,可以直接计算出N个图像和N个文本的相似度。
在这里插入图片描述
在BLIP2中,因为需要学习使用 queries 来表示图像特征,而每个 queries 包含 32 个向量,所以需要计算出 queries 中每个向量和文本向量的相似度,BLIP2 选择最高的那个作为一张图和文本的相似度。

基于图像的文本生成(ITG)

基于图像的文本生成损失基于给定的输入图像来训练 Q-Former 的文本 Transformer (文本解码器)生成文本。由于图像编码器和文本解码器不能直接交互,需要通过 queries 先从图像特征中提取与文本相关联的信息,然后输入到文本解码器中和文本一起生成文本。在这一部分,由于是生成文本,所以在注意力掩码部分,queries 可以互相看见,但不能看见文本。每个文本 token 可以看见 queries 及其之前的文本 token 。

图像-文本匹配(ITM)

图像-文本匹配目的是学习图像和文本表示之间的细粒度对齐。是一个二分类任务,要求模型预测图像-文本对是匹配还是不匹配。这一部分使用双向自注意力掩码,所有的 queries 和文本都可以互相关注。使用图像 Transformer 输出的 queries 来获得图像和文本交互的信息,然后将每个query 输入到线性分类器中获得分数,并取所有 query 的评分分数作为图像-文本的输出分数。

通过这三个训练目标,Q-Former 就可以提取出与文本信息相关的视觉特征了。

BLIP2-Q-Former 相关源码

@classmethod
def init_Qformer(cls, num_query_token, vision_width, cross_attention_freq=2):
    encoder_config = BertConfig.from_pretrained("bert-base-uncased")
    encoder_config.encoder_width = vision_width
    # insert cross-attention layer every other block
    encoder_config.add_cross_attention = True
    encoder_config.cross_attention_freq = cross_attention_freq
    encoder_config.query_length = num_query_token
    Qformer = BertLMHeadModel.from_pretrained(
        "bert-base-uncased", config=encoder_config
    )
    query_tokens = nn.Parameter(
        torch.zeros(1, num_query_token, encoder_config.hidden_size)
    )
    query_tokens.data.normal_(mean=0.0, std=encoder_config.initializer_range)
    return Qformer, query_tokens

大语言模型

在这里插入图片描述

部分多模态大模型会对大语言模型针对视觉特征的融入做一些模型上的改造,比如:

  • 门控交叉注意力(Flamingo)
    在这里插入图片描述
    在这里插入图片描述

  • Hyper Attention(mPLUG-Owl3)
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式—装饰者模式

一、什么是装饰者模式 装饰者模式是一种结构型设计模式&#xff0c;它允许你动态地向对象添加新的行为而不影响其原有的行为。它在运行时给对象动态地添加一些额外的职责&#xff0c;通常是在原有的行为基础上&#xff0c;通过装饰器进行一些修饰&#xff0c;实现了更加灵活的代…

【软考】流水线

目录 一、指令控制方式1.1 说明1.2 顺序方式1.3 重叠方式1.4 流水方式 二、流水线的种类三、流水的相关处理3.1 说明3.2 RISC 中采用的流水技术3.2.1 超流水线(Super Pipe Line)技术3.2.2 超标量(Super Scalar)技术3.2.3 超长指令字(Very Long Instruction Word&#xff0c;VLI…

阿一网络安全之log4j2漏洞CVE-2021-44228复现

漏洞简介 Apache Log4j 2 是对 Log4j 的升级&#xff0c;它⽐其前身 Log4j 1.x 提供了显 着改进&#xff0c;并提供了 Logback 中可⽤的许多改进&#xff0c;同时修复了 Logback 架构中的⼀些固有问题。 2021 年 12 ⽉&#xff0c;在 Apache Log4j2 中发现了⼀个 0-day 漏洞。 …

倒计时7天!MoonBit 游戏挑战赛即将开启!

基于 Wasm4 框架的 MoonBit 游戏开发指南 MoonBit 即将面向全国举办“编程创新挑战赛”&#xff0c;并包含游戏赛道。本教程将介绍本次比赛中使用的框架 Wasm4&#xff0c;以及如何使用 MoonBit 在 Wasm4 框架中编写游戏。相关赛事详情见文末。 如果你曾访问过 mooncakes 或我们…

这本大模型书太香了!全方位解析LLM-Agent 第一本给程序员看的AI Agent图书!

AI Agent火爆到什么程度&#xff1f; OpenAI创始人奥特曼预测&#xff0c;未来各行各业&#xff0c;每一个人都可以拥有一个AI Agent&#xff1b;比尔盖茨在2023年层预言&#xff1a;AI Agent将彻底改变人机交互方式&#xff0c;并颠覆整个软件行业&#xff1b;吴恩达教授在AI…

从0-1开发一个Vue3前端系统页面-10.博客页面优化及子菜单设计

注意&#xff1a; 本项目已将前端源码同步上传至Gitee&#xff0c;项目已开源&#xff0c; 仅供参考&#xff0c;不涉及商用&#xff0c;不得用其牟利&#xff0c;著作权归本人所有。 本系列后期只会对重要部分代码进行注释&#xff0c;难点会同步更新至专栏 开发遇到的问题_不…

linux df -h时没有查到root盘,root文件夹带着锁或者叉号的解决办法

文章目录 一、前言二、来龙去脉1、2、给root文件赋予权限3 、这个时候df -h 查看就可以看到root文件了 总结 一、前言 当时装的双系统&#xff0c;自认为会学习很多linux相关课程&#xff0c;买了个1T的固态&#xff0c;ubuntu上分了很多&#xff0c;结果显而易见&#xff0c;…

UE5学习笔记16-游戏模式中的一些事件,如何改变网格体和摄像头的碰撞

一、OnPostLogIn&#xff1a;此事件在玩家成功登录游戏后被调用 二、HandleStartingNuwplayer&#xff1a;在OnPostLogIn事件后被调用&#xff0c;可以用来定义新进入的玩家会发生什么 三、Spawn Default PawnAtTransform&#xff1a;这个事件触发游戏中实际的Pawn生成 四、…

bash: /home/xxx/anaconda3/bin/conda: No such file or directory

一背景 最近把conda 移动后&#xff0c;出现了一堆bug&#xff0c;目前pip不能使用&#xff0c;在此记录一下解决方案。 二报错信息 bash: /home/xxx/anaconda3/envs/yolov10/bin/pip3 /home/xxx/.conda/envs/yolov10/bin/python: bad interpreter: No such file or directo…

Leetcode 100.101.110.199 二叉树相同/对称/平衡 C++实现

Leetcode 100. 相同的树 问题&#xff1a;给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 /*** Definition for a binary tree node.* struct T…

多媒体技术(1.1)之图像分辨率

「分辨率」这个概念还有「解析度」等说法&#xff0c;所以能从字面上看出来&#xff0c;它描述的其实就是图像包含多少细节、有多「清晰」。但具体到怎么用数字来描述一个图像有多少细节&#xff0c;就有很多个描述的角度&#xff0c;于是「分辨率」有很多种意思。 相机的分辨…

代码随想录算法训练营day29 | 贪心算法 | 134.加油站、135.分发糖果、860.柠檬水找零、406.根据身高重建队列

文章目录 134.加油站思路小结 135.分发糖果思路拓展——环形分糖小结 860.柠檬水找零思路 406.根据身高重建队列思路小结 今天是贪心算法专题第三天&#xff0c;直接上题目 134.加油站 建议&#xff1a;本题有点难度&#xff0c;不太好想&#xff0c;推荐大家熟悉一下方法二 …

STM32基础篇:定时器 × 输入捕获

通道的概念 如下图右半部分&#xff0c;为定时器的总体结构框图&#xff1a; 可以看出&#xff0c;在时基单元下方&#xff0c;有四个长条形的结构&#xff0c;我们将其称之为&#xff1a;通道1~通道4&#xff1b;每一个通道都会连接一个IO引脚&#xff08;对应左半部分IO引脚…

OZON什么产品好卖丨OZON婴儿用具产品

Top1 摇铃 Деревянная стойка тренажер Монтессори для мобилей и игрушек для новорожденных / развивающая дуга 商品id&#xff1a;1557614414 月销量&#xff1a;707 OZON婴儿用具…

MSSQL 手工注入(第一关)

简介 SQL注入是一种安全漏洞&#xff0c;通过它可以执行意外的SQL命令或访问数据库中的信息。MSSQL注入通常发生在应用程序将用户输入作为SQL查询的一部分执行时&#xff0c;而没有对输入进行适当的验证或清理。 以下是MSSQL手工注入的流程&#xff1a; 一、打开靶场选择第一关…

进阶岛 多模态模型部署微调实践

一、任务介绍 follow 教学文档和视频使用QLoRA进行微调模型&#xff0c;复现微调效果&#xff0c;并能成功讲出梗图.尝试使用LoRA&#xff0c;或调整xtuner的config&#xff0c;如LoRA rank&#xff0c;学习率。看模型Loss会如何变化&#xff0c;并记录调整后效果(选做&#x…

【Electron】桌面应用开发启动直接打开一个网址或者浏览器打开一个网址

【Electron】桌面应用开发启动时直接打开一个网址或者跳转浏览器打开一个网址 前一篇有写过 Electron 桌面应用开发快速入门到打包Windows应用程序 但是现在需要程序打开的时候直接打开一个链接&#xff0c;在程序的窗口打开或者直接跳转浏览器打开 一、启动时直接打开一个网…

后端完成api顺序

contoroller层 Service层 点击getById&#xff0c;如果没有getById函数就先声明一个 然后完成函数体 db层 数据访问对象.数据库方法 //作用是提供对数据库中特定表的操作方法

【Hot100】LeetCode—437. 路径总和 III

目录 1- 思路前缀和哈希表dfs 2- 实现⭐437. 路径总和 III——题解思路 3- ACM 实现 题目连接&#xff1a;437. 路径总和 III 1- 思路 前缀和哈希表dfs ① 前缀和 求二叉树的前缀和&#xff0c;每求一次用一个 sum 传参记录更新 ② 哈希表 key 为前缀和 &#xff0c;value…

k8s集群部署(sealos)

目录 部署Ubuntu22和k8s环境 环境准备 虚拟机安装ubantu 配置hosts 配置静态ip地址 配置国内阿里云的源 Master节点安装sealos软件 启用root和允许ssh远程连接 禁用firewalld和iptables 关闭交换分区 配置ipvs功能 配置时间同步 使用sealos部署k8s集群 增加K8s的ma…