MiniCPM-V2.6:面壁智能端侧图像大模型
- 标题:MiniCPM-V: A GPT-4V Level MLLMonYourPhone
 - 时间:2024.8.03
 - 作者团队:面壁智能
 - 作者:Yuan Yao, Tianyu Yu, Ao Zhang, Chongyi Wang, Junbo Cui
 - 有用指数:⭐️⭐️⭐️⭐️⭐️
 - 贡献程度:⭐️⭐️⭐️⭐️⭐️
 - 简单评价:
 
- 优点:代码完备,基本无缝在自建场景开启训练;可配置化图片占据的token数量,如果场景需要建模视频,可直接配置减少一张图片token数量。
 - 缺点:目前只有和Qwen2对齐的节点,实际训练结果有些许不理想。
 
Existing Gap
作者认为现在模型参数都太大了,很难在端侧运行起来,于是他们的目标就是做一个小点的,能在quantize之后运行在端上且效果还不错的多模态大模型。
Proposed Solution
虽然目标是小模型,但是MiniCPM这次有在Qwen-2上训练的版本,本身并不算小,所以作者建议用Quantize之后的模型运行在端侧。本文的创新更多还是训练数据上的,其他方法是比较常见的。
目前大家做多模态大模型能够提升性能的常规操作是
- 提升训练时的图片分辨率;
 - 加大训练数据的量;
 - 调和训练数据的比例和优化训练过程。
 
MiniCPM的整体架构如下图所示

整体架构
- 图像切分(基本上对于高分辨率图片都得有类似步骤,比如LLaVA这里用的切分+pooling):使用adaptive visual encoding(下文会细讲)
 - Visual encoder:ViT
 - 模态对齐:一层cross-attention token压缩层对齐文本和视觉模态;
 - LLM
 
实现细节
Adaptive Visual Encoding
如何能建模高分辨率图片?切分+合并。理想状态是,合理切分图片以对齐ViT预训练的分辨率。
for image in _images:
  # 图片切分,默认配置最多切成9块
  image_patches = self.get_sliced_images(image, max_slice_nums)
  # 对patches进行normalization
  image_patches = [to_numpy_array(image).astype(np.float32) / 255 for image in image_patches]
  # standardization
  image_patches = [
      self.normalize(image=image, mean=self.mean, std=self.std, input_data_format=input_data_format)
          for image in image_patches
  ]
  # HWC转化成CHW,图像channel在前
  image_patches = [
      to_channel_dimension_format(image, ChannelDimension.FIRST, input_channel_dim=input_data_format) 
          for image in image_patches
  ]
  # 合并成新的图像数组
  for slice_image in image_patches:
    # 每一张图都变成了多个小patches
      new_images.append(self.reshape_by_patch(slice_image))
      tgt_sizes.append(np.array((slice_image.shape[1] // self.patch_size, slice_image.shape[2] // self.patch_size)))
Compression layer
上面这种做法有个明显的坏处就是,如果是多图输入,明显这个输入被放大了很多,如果直接把原始结果给到LLM,那么能装下的图片数量肯定很少。所以作者在这里加了一个compression layer,主要目的就是压缩直接产出的token数量。(他们源码还没更新到最新的模型,所以如果看源码到Huggingface上面看)。这个compression layer就是一个单层的cross attention layer,一般来说Resampler架构的架构,cross attention模块都是更新learnable Query。MiniCPM-V2.6在Qwen2 LM上默认对齐的Query embedding的size是64,就是一组slice(单张图)占用64个tokens。
训练过程
| Training | Stage | 目的 | Trainable modules | Data | 
|---|---|---|---|---|
| Pretraining | 1 | warmup compression layer 224x224分辨率  | 
      Compression layer only | 200M Image captioning | 
| 2 | extend the resolution of pretrained vision encoder | vision encoder(SigLIP-SoViT-400m/14) | Another 200M image captioning | |
| 3 | further adapt to high resolution with adaptive strategy | compression layer + vision encoder | OCR + image captioning | |
| SFT | 1 | downstream tasks | vision encoder + compression layer + LLM | 只用Human label过和GPT-4生成的数据做训练 | 
| DPO - RLAIF | 1 | reduce hallucination | 原文没写,但大部分的DPO主要训练的是LM和fusion模块 | 6k preference pairs | 
这里唯一的问题就是DPO阶段训练的参数没写,不知道训练了什么。常见的是训练LLM和模态Fusion模块(Compression layer),但这个确实没写。如果有知道的麻烦留个言。
DPO RLAIF就用SFT之后的Base Model,在High temperature下生成10个回复,然后先用LLaMA 3给回复划分claims,再针对这些claims中的每一个用LLaVA-next Yi-34B给这些claims打分,从而获得有打分分数的回复。训练的时候,会针对这10个回复sample出来一些pair,用这些pair的相对分数来决定reject和accept的数据集。
Results
部分Benchmark上在8B的size上能够实现这个大小下SOTA的结果,对于有需要压缩图片占用tokens数量的应用有比较高的应用价值。

Conclusion
总结来看面壁智能的这个release还是非常有诚意的,SFT的代码比较完善,基本上改改数据就能在应用场景里直接用上;其次由于他有这个compression的模块,对于图片压缩能力还是提升比较明显的。有需要多帧输入的也完全可以直接用上。注意这个MiniCPM-V2.6的代码要直接在Huggingface上看,开源的代码库还没更新到这个模型的代码。