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

多模态介绍

模态是什么:可以理解成模态就是数据类型,比如图像、文本、视频、语音等。

什么是单模态:单模态就是一个模型的输入或输出都是一种类型,比如输入图像,输出分类结果;输入图像,输出分割结果;输入文本,输出文本等,这些都是单模态。

什么是多模态:多模态可以是在输入端存在多种模态,也可以是在输出段存在多种模态,也可以是输入一种模态,输出另一种模态。比如输入包含图像和文本,输出文本(LayoutLM、CLIP、BLIP2等);输入文本,输出图像(文生图模型);输入图像,输出文本(图生文模型)。

本文主要是针对输入是图像和文本,输出是文本的多模态模型,并且主要针对使用预训练的图像编码器和文本编码器的缝合模型的多模态大模型。除了缝合层的多模态模型外还存在一些原生的多模态大模型,这些模型一开始就把多种模型输入到模型中,使用一个模型来理解学习多种模态之间的关系。

缝合式多模态大模型的架构:包括视觉编码器、视觉文本对齐层、大语言模型,流程主要是通过视觉编码器提取图像特征,再通过视觉文本对齐层将图像和文本特征对齐,也包括对视觉特征的在提取,主要是为了减少视觉 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-3mPLUG-DocOwl
Qwen-VL
DeepSeek-VL
Idefics2
InternVL
MiniCPM-V
CogVLM2

多模态发展

根据多模态大模型可以支持的分辨率可以分为以下三个阶段:

第一阶段:支持的图像分辨率非常低(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

视觉编码器

对于切分好的图像 (N,H,W,C) 使用卷积核和步长都是 patch_size 、输出通道是 embed_dim 的卷积对图像进行 embedding,获得 (N, H/patch_size, W/patch_size, embed_dim) 的图像特征,然后把 HW 展平,则获得 (N, L, D) 的特征向量,其中 L = H/patch_size x W/patch_size,D=embed_dim。这样图像特征就可以输入到 Transformer 中进行计算了。

  • CLIP-ViT

    CLIP的训练需要大的 batch size 和 大量的计算资源,可能会甚至导致不稳定训练问题。所以针对这些问题,出现了一些对 CLIP 的改进,可以支持小 batch size 的训练,比如 SigLip;结合一些新技术训练 CLIP,比如 EVA-CLIP。

  • SigLip

    使用sigmoid损失函数训练的 CLIP-ViT

  • EVA-CLIP

    使用预训练的 EVA 初始化 CLIP、表示学习、LAMB 优化器随机丢弃输入 tokens、flash attention

  • 混合图像编码器(SigLip+SAM)(DeepSeek-VL)。减少计算资源的消耗。

视觉文本特征对齐

作用:

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

  2. 减少视觉特征的 token 数

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

线性映射或MLP

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

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

InternVL-Pixel Shuffle

像素重组(pixel shuffle)操作。像素重组是一种用于图像超分辨率的技术,通过调整张量的形状和维度来实现图像的缩放。具体步骤包括:

  1. 获取输入张量的尺寸。
  2. 根据比例因子调整张量的形状。
  3. 交换张量的维度和使张量连续。
  4. 再次调整张量的形状。
  5. 根据版本选择是否交换回原始维度。

最终,代码返回经过像素重组操作后的张量 x。

这里比例因子为 0.5 则表示,输入的图像特征向量的宽和高都缩小一半,像素重组到维度方向上。这样就可以减少图像特征的 token 数了。

  def pixel_shuffle(self, x, scale_factor=0.5):
      n, w, h, c = x.size()
      # N, W, H, C --> N, W, H * scale, C // scale
      x = x.view(n, w, int(h * scale_factor), int(c / scale_factor))
      # N, W, H * scale, C // scale --> N, H * scale, W, C // scale
      x = x.permute(0, 2, 1, 3).contiguous()
      # N, H * scale, W, C // scale --> N, H * scale, W * scale, C // (scale ** 2)
      x = x.view(n, int(h * scale_factor), int(w * scale_factor),
                 int(c / (scale_factor * scale_factor)))
      if self.ps_version == 'v1':
          warnings.warn("In ps_version 'v1', the height and width have not been swapped back, "
                        'which results in a transposed image.')
      else:
          x = x.permute(0, 2, 1, 3).contiguous()
      return x

Cross Attention

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

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

mPLUG-Owl

MultiHeadAttention

使用单层的 MultiHeadAttention 来学习固定数量的特征向量。

Qwen-VL、MiniCPM-V 采用这种方式。

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

Conv + SwiGLU

CogVLM2
https://github.com/THUDM/CogVLM2
https://arxiv.org/abs/2408.16500

CogVLM2 使用的包含一个 2×2 卷积层和一个 SwiGLU 模块的适配器。这种设计通过卷积层将 ViT 输出的序列长度减少到其原始大小的四分之一。随后,SwiGLU 模块将这些特征与语言表示对齐,实现了保持关键图像信息的近无损变换,同时提高了计算效率。

class GLU(nn.Module):
    def __init__(self, config, in_features):
        super().__init__()
        self.linear_proj = nn.Linear(in_features, config.hidden_size, bias=False)
        self.norm1 = nn.LayerNorm(config.hidden_size)
        self.act1 = nn.GELU()
        self.act2 = nn.functional.silu
        self.dense_h_to_4h = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
        self.gate_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
        self.dense_4h_to_h = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)

    def forward(self, x):
        x = self.linear_proj(x)
        x = self.act1(self.norm1(x))
        x = self.act2(self.gate_proj(x)) * self.dense_h_to_4h(x)
        x = self.dense_4h_to_h(x)
        return x


class EVA2CLIPModel(nn.Module):
    def __init__(self, config):
        super().__init__()
        vision_config = Namespace(**config.vision_config)
        self.patch_embedding = PatchEmbedding(vision_config)
        self.transformer = Transformer(vision_config)
        self.linear_proj = GLU(config, in_features=vision_config.hidden_size)
        self.conv = nn.Conv2d(in_channels=vision_config.hidden_size, out_channels=vision_config.hidden_size, kernel_size=2, stride=2)
        self.boi = nn.Parameter(torch.zeros(1, 1, config.hidden_size))
        self.eoi = nn.Parameter(torch.zeros(1, 1, config.hidden_size))

    def forward(self, images: "tensor(B, C, H, W)") -> "tensor(B, L, D)":
        x = self.patch_embedding(images)
        x = self.transformer(x)
        x = x[:, 1:]

        b, s, h = x.shape
        grid_size = int(s**0.5)
        x = x.view(b, grid_size, grid_size, h).permute(0, 3, 1, 2)
        x = self.conv(x)

        x = x.flatten(2).transpose(1, 2)
        x = self.linear_proj(x)
        boi = self.boi.expand(x.shape[0], -1, -1)
        eoi = self.eoi.expand(x.shape[0], -1, -1)
        x = torch.cat((boi, x, eoi), dim=1)
        return x

H-Reducer

在这里插入图片描述
mPLUG-DowOwl1.5:
https://arxiv.org/abs/2403.12895
https://github.com/X-PLUG/mPLUG-DocOwl

mPLUG-DowOwl1.5 采用 H-Reducer 来作为图像文本适配器。既减少了视觉序列的长度,又保留了空间信息。H-Reducer 由卷积层和全连接层组成,卷积层用于减少序列长度,全连接层用于将视觉特征投影到语言嵌入空间。由于文档图像中的大多数文本信息是从左到右排列的,因此水平文本信息通常在语义上是连贯的。因此,将卷积层的核大小和步长设置为 1x4,以聚合水平的视觉特征。

class MplugDocOwlHReducerModel(PreTrainedModel):
    def __init__(self, config, language_hidden_size):
        super().__init__(config)
        self.config = config
        self.ln_q = torch.nn.LayerNorm(self.config.hidden_size, eps=1e-6)
        self.conv_shape = (int(self.config.conv_shape.split('x')[0]), int(self.config.conv_shape.split('x')[1])) # 
        self.conv_patch=self.conv_shape[0]*self.conv_shape[1]
        ## feature interaction with a conv layer
        self.reducer_before = torch.nn.Sequential(
            nn.Conv2d(self.config.hidden_size, self.conv_patch*self.config.hidden_size, kernel_size=self.conv_shape, stride=self.conv_shape, bias=True),
            nn.GELU()
        )
        ## reduce visual feature length with a conv layer
        self.reducer = nn.Conv2d(self.config.hidden_size, self.config.hidden_size, kernel_size=self.conv_shape, stride=self.conv_shape, bias=True)    
        ## align visual features with language embedding with fc
        self.visual_fc = torch.nn.Linear(self.config.hidden_size, language_hidden_size)
        self.vit_eos = torch.nn.Parameter(torch.randn(1, 1, language_hidden_size))

        self.post_init()

    def forward(
        self,
        encoder_hidden_states=None
    ):
        r"""
        encoder_hidden_states  (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, `optional`):
            batch_size is the number of all images (global+crop) in a batch
            Sequence of hidden-states at the output of the last layer of the encoder.
        """
        encoder_hidden_states = encoder_hidden_states[:,1:,:] # remove the first cls token 
        B, L, C = encoder_hidden_states.shape # B, 1024=(448/14)^2, 1024

        ## feature interaction with a conv layer
        encoder_hidden_states = rearrange(encoder_hidden_states, 'B (H W) D -> B D H W', H=int(math.sqrt(L)))
        hidden_states = self.reducer_before(encoder_hidden_states) # B 4D H W/4
        ## reduce seq length with a conv layer
        hidden_states = rearrange(hidden_states, 'B (X D) H W -> B D H (W X)', X=self.conv_patch) # B 4D H W/4 -> B D H W
        sequence_output = self.reducer(hidden_states) # B,C,H,W -> B,C,H/conv_shape[0],W/(conv_shape[1])
        sequence_output = sequence_output.flatten(2).transpose(1, 2)  # B,C,H/conv_shape[0],W/(conv_shape[1]) -> B,C,L/conv_patch -> B,L/conv_patch,C
        sequence_output = sequence_output.transpose(0, 1).contiguous() # L/conv_patch, B, C
        ## align visual features with language embedding with fc
        sequence_output = self.visual_fc(sequence_output) # L/conv_patch, B, h
        sequence_output = sequence_output.transpose(0, 1).contiguous() # B, s/4, h
        sequence_output = torch.cat([sequence_output, self.vit_eos.repeat(B, 1, 1)], dim=1)

        return sequence_output

DocCompressor

在这里插入图片描述
mPLUG-DowOwl2:
https://arxiv.org/abs/2409.03420
https://github.com/X-PLUG/mPLUG-DocOwl

mPLUG-DowOwl2 在 H-Reducer 后增加了 DocCompressor 再进一步减少视觉 token,以支持处理多图片。该方法使用全局图像作为 query,与全局图对应位置的切割图作为 key 和 value,通过两层的 cross attention 获取压缩后的视觉特征,这样每张图像仅仅使用一个小图的 token 数即可表示,大大减少了视觉 token,从而可以同时处理更多的图片。

大语言模型

在这里插入图片描述

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

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

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

预训练和微调

不同的多模态模型的训练方法不太一样,但基本上都差不多,基本流程大部分都是:

  1. 首先训练对齐层,使得对齐层能更好的表示视觉特征;
  2. 然后将对齐层和 LLM 一起训练(或者对齐层和视觉编码器一起训练);
  3. 最后所有参数一起训练,使得整个模型可以更好的理解视觉和文本。

BLIP2

第一阶段

从冻结的图像编码器引导视觉语言表示学习。(见文章 Q-Former 部分)

第二阶段

从冻结的语言模型引导视觉语言生成学习。
在这里插入图片描述
BLIP2 尝试了两种类型的 LLM:基于解码器的和基于编码器-解码器的。对于基于解码器的 LLM,使用语言建模损失进行预训练,其中冻结的 LLM 的任务是根据 Q-Former 的视觉表示生成文本。对于基于编码器-解码器的 LLM,使用前缀语言建模损失进行预训练,将文本分为两部分。前缀文本与视觉表示连接,作为LLM编码器的输入。后缀文本被用作 LLM 解码器的生成目标

数据集:129M 图像(COCO、Visual Genome、CC3M、CC12M、SBU和115M 的 LAION400M)除此之外,使用 BLIP 的 CapFilt 方法为网络图像创建合成标题作为训练数据:BLIP-Large 字幕模型生成 10 个字幕,并根据 CLIP ViT-L/14 模型产生的图像-文本相似性对合成字幕和原始 Web 字幕进行排名。将每张图像的前两个字幕作为训练数据,并在每个预训练步骤中随机采样一个。

InternVL2

第一阶段

训练参数:对齐层 MLP
数据集:包括图像摘要、视觉问答、检测、定位、OCR(使用 PaddleOCR 识别的中文的 Wukong 和 英文的LaionCOCO);爬取和手动解析来自 uworldkaptesttestbankagasatOmniCorpus
在这里插入图片描述

第二阶段

训练参数:全部参数 ViT + MLP + LLM
数据集:5M的高质量双语数据集、视频数据(EgoTaskQA, Mementos, STAR, NTU RGB+D, VideoChat2IT, and LSMDC-QA)、医学数据(Medical-Diff-VQA, Pathology-VQA, PMC-CaseReport, PMC-VQA, Slake, and VQA-RAD)、手写字数据(SROIE, FUNSD, and POIE)、ShareGPT-4o

在这里插入图片描述
翻译数据:使用现有的大语言模型,对数据集进行翻译,如果数据集原始是英文,可以将此数据集翻译成其他语言(比如中文)。由于英文数据集比较多,中文数据集比较少,使用此方法可以扩大中文数据集,增强模型在中文上的效果。

MiniCPM-V

在这里插入图片描述

预训练

利用大规模图像-文本对进行 MLLM 预训练。这一阶段的主要目标是将视觉模块(即视觉编码器和压缩层)与LLM的输入空间对齐,并学习基本的多模态知识。

在这里插入图片描述

  1. 第一阶段

    训练参数:训练 Shared Compression Layer(交叉注意力),主要连接视觉编码器和 LLM,其他模块参数冻结。保持视觉编码器图像大小224x224。
    数据集:从上表中的图像字幕数据中随机选择 200M 数据。执行数据清理以去除相关性差和格式错误的文本数据的图像-文本对,确保数据质量。

  2. 第二阶段:扩展预训练的视觉编码器的输入分辨率

    训练参数:将图像分辨率从224×224扩展到448×448。训练整个视觉编码器,使其他参数冻结。

    数据集:从上表中的图像字幕数据中选择了 200M 数据

  3. 第三阶段:使用自适应视觉编码策略训练视觉模块,该策略可以进一步适应任何纵横比的高分辨率输入

    训练参数:训练 Shared Compression Layer 和视觉编码器以适应语言模型嵌入空间。LLM 保持冻结以避免来自相对低质量的预训练数据的扰乱。

    数据集:与之前只有图像字幕数据的阶段不同,在高分辨率预训练阶段,还引入了 OCR 数据来增强视觉编码器的 OCR 能力。

微调

在从预训练中学习基础能力后,在高质量的视觉问答数据集上执行监督微调 (SFT),以进一步从人工注释中学习知识和交互能力。

训练参数:所有参数

数据集:利用实验室或 GPT-4 等强模型注释的高质量数据集。分为两部分:第 1 部分侧重于增强模型的基本识别能力,而第 2 部分旨在增强它们在生成详细响应和遵循人类指令方面的能力。具体来说,part-1 数据由响应长度相对较短的传统 QA/captioning 数据集组成,有助于增强模型的基本识别能力。相比之下,part-2 包含具有具有复杂交互的长响应的数据集,无论是在文本还是多模态上下文中。在SFT期间,这两个部分数据被连接起来并依次输入到模型中。将 Cauldron 数据集中的 2M 数据集成到多模态知识增强中,在 36 种语言上集成了 90K 多语言数据,以提高多语言对话能力。

在这里插入图片描述

RLAIF-V

MLLM 通常容易出现幻觉问题,产生不符合输入图像的响应。这个问题极大地限制了 MLLM 的广泛应用,尤其是在高风险的情况下,例如自动驾驶和视障组的辅助。为了解决幻觉问题,还采用了最近的RLAIF-V方法,其中关键是从开源模型中获得可扩展的高质量反馈,用于直接偏好优化(DPO)。

在这里插入图片描述
用于幻觉减少的RLAIF-V框架。(1) 响应生成使用策略模型为指令生成多个响应。(2) 反馈收集以分而治之的方式评估每个响应的正确性。(3) DPO在偏好数据集上优化模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CharlesWu123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值