前言
Hi大家好,我叫延捷,是一名计算机视觉算法工程师,也是叉烧的老朋友了。我们计划发布一系列关于多模态大模型的文章,帮助大家快速、精准地了解多模态大模型的前世今生,并且深入各个多模态大模型领域优秀的工作,希望能给大家一个脉络性的盘点,一起学习,共同进步。
上一期我们介绍了在多模态大模型领域相当火热Gemini系列,分享了Google在多模态大模型领域的一些经典工作,并且也会介绍笔者非常喜欢的一个工作Mini-Gemini。本期则会详细给大家介绍“小而美”的MiniCPM-V工作。同样地我并不会过多列举一些不必要的论文细节和指标,而是会着重讲述:
同样相信大家会从本文中收获不少。
《MiniCPM-V: A GPT-4V Level MLLM on Your Phone》(2024)
MiniCPM-V其实也是一个多模态大模型的系列,跟LLaVA、Qwen-VL等不同,MiniCPM-V系列的设计哲学是在性能和效率之间实现良好的平衡,主打的方向是少参数、推理快速、可端侧运行,旨在用更少的参数达到那些大参数模型的效果。由于本篇论文的主角是MiniCPM-Llama3-V 2.5(为方便下面笔者就简称为MiniCPM-V 2.5),并且MiniCPM-V的其他系列也没有释放paper,这里我们就从MiniCPM-V 2.5入手,介绍当今2B和8B模型领域的强力好手。
MiniCPM-V 2.5的核心依然是使用了当下最流行、最有效的Visual Encoder + Projector + LLM的经典架构。笔者认为MiniCPM-V 2.5的核心亮点有三:一是在图像输入处理端,AnyRes技术的基础上,参考LLaVA-UHD的工作,精细化地使用了自适应视觉编码(Adaptive Visual Encoding),使得输入图像的切分子图能与视觉编码器的预训练尺寸更好地适配,并且尽可能地减少resize对原始图像高宽比的改变,降低因为图像扭曲导致的失真,保持整个图像信息分布的一致性;二是在tokenizer端,使用Spatial Schema把各个子图像的img tokens进行包装和区分;三是在训练端,在pre-traning中也采用了分阶段的训练策略,递进式地进行预训练。下面我们就来详细介绍MiniCPM-V 2.5这个工作。
模型结构方面,Visual Encoder采用了SigLIP,Projector采用了跟Qwen-VL系列一样的单层cross-attention结构,基于固定数量的img queries来压缩视觉编码器得到的visual tokens,LLM则使用了经典的LLaMA-3
MiniCPM-V 2.5模型架构图,Projector层采用了和Qwen-VL类似的当层cross-attn压缩visual tokens,图像输入端采用自适应视觉编码尽可能保持了原始的高宽比
MiniCPM-V 2.5中的Projector层具体使用的是叫Perceiver Resampler的结构,笔者认为这个结构应该是类似Flamingo提到的Perceiver Resampler结构,并且跟Qwen-VL一样仅使用了单层cross-attention来进行视觉信息的压缩&归纳,在MiniCPM-V 2.5中使用64/96个learnable queries对应2.4B/8B模型
在Flamingo中提出了Perceiver Resampler的架构,使用cross-attention抽象出需要的视觉特征,MiniCPM-V中固定为单层cross-attn
训练策略方面,采用Pre-Traning,Supervised Fine-Tuning,RLAIF-V的三阶段策略;
A. 一阶段Pre-Training:主要用来对齐视觉编码层和图文对齐层,在Pre-Training阶段MiniCPM-V 2.5区分了3个子阶段来精细化训练,在下面Highlights我们将详细介绍;
B. 二阶段SFT:主要食用高质量数据(包括人类标注数据和模型生成数据)来进一步提升模型的对话回答能力,具体来说二阶段SFT中会训练所有的参数,并且使用自适应视觉编码;在数据方面分为两类数据,第一类是专注于增强模型的基础识别能力的QA/caption数据集,响应长度较短,第二类是用来增强模型生成详细响应和提高遵循指令能力的数据集,包含了长响应以及复杂交互的数据集;在整个SFT中,会把这两部分数据串联后依次输入模型进行训练,可以简单认为就是先训练第一类,后训练第二类;这也比较符合大多MLLM在SFT阶段的训练思路:优先训练常识能力,指令跟随和复杂交互最后训练;
C. 三阶段RLAIF-V:主要为了降低模型生成幻觉,采用基于强化学习的技术来训练的,具体来说使用较高的温度对同一个输入生成多样性的回答,再用LLM提取每个回答的子声明(atomic claims),再用固定的MLLM来进行yes/no判别,最后归纳子声明为每个回答打分,这样就可以对一个输入生成一组<好回答&坏回答>,最后用DPO技术基于此进行偏好学习;
MiniCPM-V 2.5中RLAIF-V的详细流程图
Highlights:
# 图像编码器的预训练尺寸
vit_width = 448
vit_height = 448
# ViT的patch_size, 一般都默认为14
patch_size = 14
_, height, width = input_image.shape
# 若图片的像素小于448*448, 则按当前高宽比resize到448*448
if width*height < vit_width*vit_height:
ratio = width / height
height = int(vit_height / math.sqrt(ratio))
width = int(height * ratio)
# 保证图片能被patch_size整除
else:
width = max(round(width / patch_size) * patch_size, patch_size)
height = max(round(height / patch_size) * patch_size, patch_size)
# 最大的切分次数, MiniCPM-V 2.5的论文中使用的是9
max_crop_num = 9
# 计算大致的切分次数N, 候选切分次数为[N-1,N,N+1]
slice_base = min(width*height // vit_width*vit_height, max_crop_num)
slice_num_list = [slice_base-1, slice_base, slice_base+1]
# 遍历得到所有可能的切分方案, [2,4], [1,8], [8,1], [3,3],......
candidate_grid = []
for slice_num in slice_num_list:
for x in range(1, slice_num+1):
if slice_num % x == 0:
y = slice_num // x
candidate_grid.append([x, y])
# 图像编码器ViT预训练尺寸高宽比
vit_ratio = vit_width / vit_height
best_grid = [1, 1]
best_error = math.inf
for grid in candidate_grid:
cur_grid_width = width // grid[0]
cur_grid_height = height // grid[1]
# 当前切分方案的子图高宽比和ViT预训练高宽比的误差, 越小越好
cur_error = abs(log(cur_grid_width / cur_grid_height) - log(vit_ratio))
if cur_error < best_error:
best_grid = grid
best_error = cur_error
# 最佳切分方案
width_grid, height_grid = best_grid
# 最佳切分方案的小图尺寸、高宽比
sub_width = width / width_grid
sub_height = height / height_grid
sub_ratio = sub_width / sub_height
# 让小图的 高*宽 尽可能接近 448*448, 并且保持高宽比不变
sub_height = vit_height / math.sqrt(sub_ratio)
sub_width = sub_height * sub_ratio
# 保证小图的高宽都能被patch_size整除
sub_width = max(round(sub_width / patch_size) * patch_size, patch_size)
sub_height = max(round(sub_height / patch_size) * patch_size, patch_size)
# 最后反推出原图需要resize的尺寸
refine_width = sub_width * width_grid
refine_height = sub_height * height_grid
refine_image = input_image.resize((refine_width, refine_height))
# 最后还要留存一份原始图像resize到切分子图尺寸的结果, 也要放到图像编码器中
ori_resize_image = input_image.resize((sub_width, sub_height))
MiniCPM-V 2.5自适应视觉编码结构图,核心就是尽可能少改变高宽比,并且保证切图后的子图跟视觉编码器ViT预训练高宽比尽量一致
对比LLaVA-NeXT中提出的AnyRes,可以看出自适应视觉编码更加灵活、多样,能够更好地处理一些高宽比较为极端的输入(比如文档图片,屏幕截图等)
自适应视觉编码与LLaVA-NeXT中AnyRes中实现方案的对比
LLaVA-UHD中关于自适应视觉编码的消融实验,证实了该精细化图像处理策略的有效性
LLaVA-UHD中关于Spatial Schema自适应视觉编码的消融实验,证实了添加简单的token来引入子图之间2维位置关系的有效性
MiniCPM-V 2.5中用到的数据集分布
笔者认为MiniCPM-V 2.5中在Pre-Training使用的训练策略,有点类似warmup的思路,逐步增加输入图像的分辨率,这种从粗粒度到细粒度的训练思路还是挺值得借鉴的。
同样在数据处理方面MiniCPM-V 2.5的paper也给出了几个相当务实的操作,具体如下:
Caption Rewriting:使用LLM来进行对那些低质量图文对进行改写,这个现在基本上也是所有MLLM处理noisy的captioning数据的标准操作;
Data Packing:文中提到不同的数据源可能数据的长度差异巨大,可能会导致不同batches之间真实tokens有较大的差异,从而造成内存/显存浪费,为了解决这个问题,使用了data packing策略,把多个样本打包成单一的一个序列,并且对末尾的样本做截断,保证每个输入模型样本的真实长度一致。为了降低不同样本之间的干扰,还修改了position ids和引入attention mask来规避干扰。
Multilingual Generalization:为了解决小众语言收集数据的难度,MiniCPM-V 2.5采用的方案是在Pre-Training只用英文+中文进行预训练,在SFT阶段收集轻量但高质量的多语言数据来进行fine-tuning,这也基本上是标准操作了。
https://arxiv.org/pdf/2408.01800
https://modelbest.feishu.cn/wiki/BMLhweBeZiiGlkkPq34clXgIn0c
https://arxiv.org/pdf/2403.11703(LLaVA-UHD)
进技术交流群请添加AINLP小助手微信(id: ainlp2)
请备注具体方向+所用到的相关技术点 关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括LLM、预训练模型、自动生成、文本摘要、智能问答、聊天机器人、机器翻译、知识图谱、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLP小助手微信(id:ainlp2),备注工作/研究方向+加群目的。