1.概述
LLaVA 是一个由威斯康星大学麦迪逊分校、微软研究院和哥伦比亚大学的研究人员开发的大型语言和视觉助手。它是一个端到端训练的大型多模态模型,结合了视觉编码器和语言模型,用于通用的视觉和语言理解。
微软研究院、威斯康星大学的研究人员在LLaVA基础之上,继续开源了LLaVA-1.5版本。与前一代相比,LLaVA-1.5引入了跨模态连接器和特定格式的学术视觉问答数据集,全面提升了多模态理解和生成能力。
LLaVA-1.5在多模态理解和生成能力上实现了开源模型中的最高水平,可媲美GPT-4V效果。该模型由视觉模型、大语言模型和视觉语言连接器组成,其中视觉模型使用CLIPViT-L/336px提取图像特征,大语言模型使用Vicunav1.5理解文本内容。训练流程分为预训练和调优两个阶段,数据集覆盖视觉问答、语言对话等典型应用,使用约65万条多模态指令数据进行视觉指令调优。
为了评估LLaVA-1.5的性能,研究人员在MMEMM、BenchMM、SQA、POPE等11个知名数据平台中对视觉问答、自然语言处理、图像生成等进行了测试。结果显示,LLaVA-1.5皆实现了开源模型中的最高水平,可媲美GPT-4V效果。
接下来,本篇博客将为你详细介绍LLaVA的架构。我将从LLaVA的核心设计理念出发,逐步解析其如何通过结合视觉编码器和语言模型,实现对视觉和语言信息的深度理解和处理。通过本篇博客,你将获得对LLaVA架构的全面认识,理解它是如何在多模态人工智能领域中占据领先地位的。
github代码:https://github.com/haotian-liu/LLaVA
clip权重:openai/clip-vit-large-patch14-336 · HF Mirror
其他人写的教程:第一节 LLaVA模型安装、预测、训练详细教程-CSDN博客
其他人写的教程:多模态大模型 LLaVA 微调教程-大语言模型8 - vanilla阿草 - 博客园
其他人写的报错信息总结:https://zhuanlan.zhihu.com/p/656307174
2.论文
数据集构建
对于图像Xv及其相关联的Caption Xc,作者创建了一组问题Xq,其意图是指示助手描述图像内容。我们提示GPT-4编制此类问题列表。因此,将一个图像-文本对扩展为
Human:Xq Xv <STOP>Assistant:Xc<STOP>
尽管构建成本低廉,但这种简单的扩展版本在指令和响应方面缺乏多样性和深入的推理。
作者利用纯语言GPT-4或ChatGPT作为教师模型(两者都只接受文本作为输入)来创建涉及可视内容的指令遵循数据。具体地说,为了将图像编码成其视觉特征以提示纯文本GPT,作者使用了两种类型的符号表示:(i)字幕(Caption)通常从各种角度描述视觉场景;(ii)边界框通常定位场景中的对象,并且每个框编码对象概念及其空间位置。如下图所示。
作者使用COCO图像,生成三种类型的指令跟随数据。对于每种类型,作者首先手动设计一些示例。它们是在数据收集过程中唯一的人工注释,相当于few-shot。
- 首先,作者设计了一个对话,在助手和一个人之间询问关于这张照片的问题。回答的语气就好像助理看到了图像并回答了问题。询问关于图像的视觉内容的一组不同的问题,包括对象类型、对对象的计数、对象动作、对象位置、对象之间的相对位置。只考虑有明确答案的问题。
- 接着,为了包含丰富而全面的图像描述,作者创建了一个带有这种意图的问题列表。对于每个图像,我们从列表中随机抽取一个问题,让GPT-4生成详细的描述。
- 在此基础上,作者进一步打造深度推理题。答案通常需要遵循严格的逻辑,一步一步地推理。
架构
简单来说,按照数据的不同,LLaVA会分开处理:
- 文本:因为是大语言模型,文本按正常方法,给大模型处理即可
- 图片:使用CLIP-ViT转化为向量,再通过一个线性层Projection转换到大模型的理解空间,然后输入到大模型
模型的组成:
- 视觉编码器(Vision Encoder):LLaVa 架构的视觉部分是预训练的 CLIP 视觉编码器,具体来说是 ViT-L/14 变体。该组件通过 Transformer 层处理输入图像 (Xv) 以提取特征 (Zv),使模型能够有效地理解视觉信息。
- 大语言模型 (Vicuna):LLaVa 的语言能力依赖于 Vicuna,它是大型语言模型 (LLM) 的一种。Vicuna 根据输入语言指令 (Xq) 理解并生成语言响应 (Xa),补充视觉编码器的功能。
- 线性投影(Projection):此组件充当视觉特征 (Zv) 和语言模型的嵌入空间之间的桥梁。它将视觉特征转换为视觉标记 (Hv),并将其与语言模型的词嵌入空间对齐,以促进多模态对话
训练
stage1:预训练
在这个阶段中,保持视觉编码器和LLM权值不变,只训练线性层projection。这样,图像特征可以与预训练的大语言模型的词嵌入空间对齐。
stage2:fine-tuning
在这个阶段中,始终保持视觉编码器权值不变,并不断更新投影层和大语言模型的预训练权值。
数据集:
- 通过对158K language-image instruction-following数据集进行微调来开发Chatbot。在这三种类型的应答中,会话是多轮的,而另外两种是单轮的。
- Science QA:每个问题都以自然语言或图像的形式提供上下文。该助手以自然语言提供推理过程,并从多个选项中选择答案。
LLaVA-1.5
LLaVA-1.5 在 LLaVA 的基础上做了以下改动:
- 使用 CLIP-ViT-L-336px 视觉编码器替换原先的 CLIP-ViT-L/14
- 将原先的一层线性层替换为 MLP 层(两层线性层)
此外,为了支持更高的图像分辨率(可以提升模型的性能)且不影响 LLaVA-1.5 的推理效率,在 LLaVA-1.5 的基础上提出了 LLaVA-1.5-HD,它采用了创新的AnyRes策略,可以接受各种高分辨率的图像作为输入。具体步骤如下:
- 首先高分辨率图像被智能分割成多个小块(Patch),以便单独处理每个块。例如,CLIP-ViT-L/14型号的视觉编码器能够处理的最大分辨率为224x224像素。
- 同时,将高分辨率图像调整至视觉编码器能够处理的尺寸,并利用编码器对其进行编码。
- 将上面两步的结果拼接在一起作为视觉特征,输入到projection。
这个过程可以看做特征金字塔,如下图所示
3.代码
环境配置
conda create -n llava python=3.10 -y
conda activate llava
pip install --upgrade pip # enable PEP 660 support
pip install -e .
我们可以遵循官方的指示,安装环境。我这里直接使用CogVideoX的环境,可以直接使用。
权重方面,大家需要下载llava的权重,有1、1.5、1.6三个版本,每个版本又分7b等多个版本,我这里使用1.5-7b:
liuhaotian/llava-v1.5-7b at main
大模型权重:lmsys/vicuna-7b-v1.5 · HF Mirror
除此之外,还需要下载openai的clip模型,这是llava的视觉编码器部分,然后把config.json里面的相应位置做更改:
openai/clip-vit-large-patch14-336 · HF Mirror
推理
inference.py
输入:
What are the things I should be cautious about when I visit here?
我这里是直接按照官方文档里面的方法,自建了一个inference.py,代码如下:
需要注意的是,官方文档还有模型导入的代码,这部分不需要加进inference.py,如果加了模型会导两次!我就是在这里被坑惨了。
from llava.model.builder import load_pretrained_model
from llava.mm_utils import get_model_name_from_path
from llava.eval.run_llava import eval_model
model_path = "llava-v1.5-7b"
prompt = "What are the things I should be cautious about when I visit here?"
image_file = "datasets/view.jpg"
args = type('Args', (), {
"model_path": model_path,
"model_base": None,
"model_name": get_model_name_from_path(model_path),
"query": prompt,
"conv_mode": None,
"image_file": image_file,
"sep": ",",
"temperature": 0,
"top_p": None,
"num_beams": 1,
"max_new_tokens": 512
})()
eval_model(args)
文件位置如下图所示:
运行即可打印结果。
When visiting this location, which features a pier extending over a large body of water, there are a few things to be cautious about. First, be mindful of the weather conditions, as the pier may be affected by strong winds or storms, which could make it unsafe to walk on. Second, be aware of the water depth and any potential hazards, such as submerged rocks or debris, that could pose a risk to your safety. Additionally, be cautious of the presence of wildlife in the area, as there might be birds or other animals that could pose a threat or disturbance. Finally, be respectful of the environment and other visitors, and follow any posted rules or guidelines to ensure a safe and enjoyable experience for everyone.
具体来说,模型会直接调用run_llava.py里面的eval_model,接下来,我们一步步来看里面的代码。
代码解读
eval_model
run_llava.py里面的函数
具体来说,这部分负责处理提示词,主要操作就是将<image>这个占位符放入文本提示词中,最终qs=<image>提示词
qs = args.query # 提示词
image_token_se = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_TOKEN # '<im_start><image><im_end>'
if IMAGE_PLACEHOLDER in qs:
if model.config.mm_use_im_start_end:
qs = re.sub(IMAGE_PLACEHOLDER, image_token_se, qs)
else:
qs = re.sub(IMAGE_PLACEHOLDER, DEFAULT_IMAGE_TOKEN, qs)
else:
if model.config.mm_use_im_start_end:
qs = image_token_se + "\n" + qs
else:
qs = DEFAULT_IMAGE_TOKEN + "\n" + qs # <image>提示词
这部分是将system、user、assistant的信息拼接起来
conv = conv_templates[args.conv_mode].copy() # system
conv.append_message(conv.roles[0], qs) # user
conv.append_message(conv.roles[1], None) # assistant
prompt = conv.get_prompt() # 完整提示词
"A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions. USER: <image>
What are the things I should be cautious about when I visit here? ASSISTANT:"
处理图片
image_files = image_parser(args) # 地址
images = load_images(image_files)
image_sizes = [x.size for x in images]
images_tensor = process_images(
images