本文想从数据流的方式走一遍多模态大模型推理流程,但不包含vit和llm具体的计算流程,因为里面基本是常见的attention计算方式。attention的计算方式可以参考《Attention Is All You Need》算法详解
一、MLLM的基础架构
一般MLLM由三大块结构组成,Vision Encoder,Vision Adapter, LLM。如下图所示

数据流经过MLLM到输出结果的流程如下
- 图片输入->图片预处理->patch embedding(加入绝对位置信息)->vit(加入相对位置编码 2d rope)->adapter 层-> 图片features
- text->tokenizer->text features
- text features 和图片features按照输入的顺序排列好->llm(加入相对位置编码1d rope)->输出结果
假设输入数据由图片+text(prompt)组成,具体的
例如:"<image_pad> 图片中有几个人?"
为了举例简化这里省去了,这种特殊token。
二、图片处理流程
2.1 图片预处理
不同模型有不同的处理方式,大致为了两类。
qwen为代表,直接将图片resize到28的倍数(因为图片经过vit和adapter层后,长宽各会压缩28倍,方便计算),然后整图送入vit中
llava为代表,将图片resize到固定大小,然后将图片切块送入vit中,切图示例图如下

文章下面都以llava的切图方式来举例,实例化实际的计算维度。
图片大小为896x896,一个子图大小为448x448,那切子图的个数为4,维度为4, 3, 448, 448, 加上全局图,维度为5, 3, 448, 448
维度写法为B, C, H, W,拿一张输入图来说,这里的B就是一张图的子图或者子图加全局图的大小。
2.2 patch embedding
把预处理好的图片,通过conv+reshape或者patchify+linear层将图片映射成feature维度,方便后续与text的feature进行拼接。
最终模型是按照16x16个为一个feature来计算的。conv kernel size, stride 都为16。
例如:输入patch embedding的维度为5, 3, 448, 448, 经过patch embedding后5, 28x28, 768, 768为vit输入的hidden size大小

2.3 计算绝对位置编码
绝对位置编码是一个训练参与学习更新,评测是已经学习好的一个字典。
假设这里的字典大小为2, length, hidden_size,
2为width,height两个维度对应的位置信息
length为训练时设置的长度,一般不会扩展,即输入长度超了,位置容易错乱。如果要扩展,一般采用插值方式扩展的。但这种方式可以支持的扩展幅度较小
总共需要的位置编码id为5, 28x28, 2, 2表示width,height两个维度。位置编码示例图如下

根据这个位置编码id,从上面训练好的字典中查询28x28个位置对应的embedding表示,得到一个5, 2, 28x28, hidden_size维度的位置编码,把width,height两个维度相加后,得到维度为5, 28x28, hidden_size的位置编码,为最终的位置编码。
绝对位置编码之间和上面的patch embedding结果相加,得到有位置编码的feature。
2.4 vit 位置编码
这里不介绍vit的具体结构和计算方式,你可以简单的理解成一堆attention结构堆积就好了,具体的attention计算可以参考文章《Attention Is All You Need》算法详解。输入5, 28x28, hidden_size, 输出也是5, 28x28, hidden_size。
note:B维度不进行信息上的交流,所以以裁切方式处理,子图和全局图在vit中,相互是没有信息交流的。还有输入和输出feature数量是一样的。
这里的位置编码是相对位置编码,采用的是2D-RoPE,即考虑到图片width,height两个维度。且这里引入位置编码不同于2.3,这里是在每一层都会在q和k进行位置编码的计算。2D-RoPE的计算方法查看RoPE通俗讲解
前面提到输出维度还是5, 28x28, hidden_size。
经过pool层或者adapter层,把前面的feature下采样并维度对齐到llm的输入维度。例如下采样2x2并对齐llm的输入维度llm_hiddensize,维度变成5, 14x14, llm_hiddensize
三、获取文本feature并和图片feature融合
利用tokenizer把文本拆成词表中的token,并用token id表示。这一步会把对应的视觉token的位置用占位符占用。
对应的token id通过查找对应的embedding获取文本feature。对应的视觉占位符也用adapter输出的feature代替。
剩下的计算逻辑就同llm的训练逻辑了。
这里采用的是1D rope,且是在每一层的q、k中引入的。1D-RoPE的计算方法查看RoPE通俗讲解