llava1.5笔记

之前的llava模型以简单的结构,优秀的能力成为了大多数图文多模态大模型的标准结构。今天看看同样的作者在llava基础上开发的llava 1.5又有哪些改进,通过这些改进也可以帮我们找找解决问题的思路。
一、引言和背景
llava模型在很多下游任务和基准测试上取得了优异的成绩,尤其是在对话式视觉推理,但是在单词或者短语回答的传统视觉问答上的效果不如后来的InstructBLIP等模型。到底是模型结构的差异还是训练数据的差异并不清楚,这篇文章就来整体、细致的分析一下llava模型,并做一些改进。之前的已经发现mlp的结构和学术任务相关的VQA数据对于提高多模态理解能力十分有效。
现在llava 1.5做了如下改进:1、提高分辨率输入,一方面将单张图片的分辨率从224提高至336,另一方面将图片进行切分,可以处理更高分辨率的图片。这种方法可以提高模型的细节感知能力,减少幻觉;2、训练数据中既包含长文本推理和短文本视觉推理可以提高模型对于多模态问题的写作能力;3、对数据随机下采样至75%左右并不会明显的降低模型的能力,说明后续可以通过数据压缩策略进一步提升llava的训练流程;4、发现扩展数据集也可以提高模型能力。
二、模型
在这里插入图片描述

模型结构还是之前的llava模型结构,但是做了一些小修改。1、将视觉-语言连接器由线性投影修改成一个两层的mlp;2、将224分辨率的视觉编码器修改为336的视觉编码器。其余还是llava的模型。
三、数据
为了提高llava模型处理简短回答的问题,llava 1.5选择在VQA数据的末尾添加一个明确的格式提示:“Answer the question using a single word or phrase. ”。这样可以显著提高llava模型在短文本回答时的能力。
进一步添加了面向学术任务的VQA数据集,增强模型的细节感知能力。增加区域级别的VQA数据集,可以提高模型对于细粒度视觉的定位能力。
预训练数据llava 1.5与llava相同,但是因为分辨率的提升,训练时间是llava的两倍。
四、数据处理
在这里插入图片描述

将224分辨率的clip换成336分辨率的clip可以提高模型的能力,但是clip最高只支持336分辨率。为了可以处理更高分辨率的图片,llava提出一种方法,将图片进行切分,分别进行编码后合并。为了解决切分-编码-合并带来的失真,对整张图片进行下采样,并于合并后的特征拼接。这种方法可以处理任意分辨率的图片。
五、模型评估
评估部分就不多说了,整体的意思是作者之前提出了几个方法可以提升模型效果,模型在各个测试上效果很好。
六、总结
1、对数据随机采样,模型效果并没有明显的降低,说明llava 1.5的数据效率较高;
2、提高分辨率,多模态模型的幻觉显著减少。如果训练数据中文本描述很详细,超出了视觉编码器能处理的细节,并且这部分数据比较多的话模型就会产生幻觉;
3、llava 1.5具有一定的组合能力,即可以分别在不同任务的数据集上进行训练,一定程度上可以泛化到需要组合不同任务的复杂任务上。
七、代码
class LlavaLlamaForCausalLM(LlamaForCausalLM, LlavaMetaForCausalLM):

def forward(…):
if inputs_embeds is None:
(…) = self.prepare_inputs_labels_for_multimodal(…)

模型这里首先会通过prepare_inputs_labels_for_multimodal函数对输入进行处理

class LlavaMetaForCausalLM(ABC):

def prepare_inputs_labels_for_multimodal(…):

if image_aspect_ratio == ‘anyres’:
num_patch_width, num_patch_height = get_anyres_image_grid_shape(
image_sizes[image_idx],
self.config.image_grid_pinpoints,
self.get_vision_tower().config.image_size
)
image_feature = image_feature.view(num_patch_height, num_patch_width, height, width, -1)

#prepare_inputs_labels_for_multimodal函数里面如果image_aspect_ratio == ‘anyres’,即输入图像是任意分辨率的话,
则将图片进行切分,切分成num_patch_height * num_patch_width个patch

def get_anyres_image_grid_shape(image_size, grid_pinpoints, patch_size):
if type(grid_pinpoints) is list:
possible_resolutions = grid_pinpoints
else:
possible_resolutions = ast.literal_eval(grid_pinpoints)
width, height = select_best_resolution(image_size, possible_resolutions)
return width // patch_size, height // patch_size

get_anyres_image_grid_shape函数计算在最佳分辨率下,图片在横轴和纵轴上分别被切成几个patch。

def select_best_resolution(original_size, possible_resolutions):
original_width, original_height = original_size
best_fit = None
max_effective_resolution = 0
min_wasted_resolution = float(‘inf’)

for width, height in possible_resolutions:
    scale = min(width / original_width, height / original_height)
    downscaled_width, downscaled_height = int(original_width * scale), int(original_height * scale)
    effective_resolution = min(downscaled_width * downscaled_height, original_width * original_height)
    wasted_resolution = (width * height) - effective_resolution

    if effective_resolution > max_effective_resolution or \
              (effective_resolution == max_effective_resolution and wasted_resolution < min_wasted_resolution):
        max_effective_resolution = effective_resolution
        min_wasted_resolution = wasted_resolution
        best_fit = (width, height)

return best_fit

select_best_resolution函数在多个可能的分辨率中找到一个能够有效利用图像像素的分辨率。

1、不太理解这里图像的处理方法,一般对于图像的切分不应该放在数据处理中来做吗?这里为什么放在模型中处理呢?
2、另外文章中说一张图片切分成4块,这里并没有定义几块,也没有找到对整张图片缩放的函数。
3、数据处理的时候LazySupervisedDataset已经通过clip的preprocessor对图片进行了切分、缩放的处理成目标大小,后面还如何进行切分缩放呢?
这些问题后面会再分析,也会看看其他的模型,类似的方法是如何处理的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值