模型简介
模型特点
模型能力
使用案例
🚀 ViCA-7B:视觉空间认知助手
ViCA-7B 是一款专门为室内视频环境中的视觉空间推理而微调的视觉语言模型。它基于 LLaVA-Video-7B-Qwen2 架构构建,使用了新提出的 ViCA-322K 数据集进行训练,该数据集强调结构化空间注释和基于复杂指令的推理任务。ViCA-7B 在 VSI-Bench 基准测试中取得了最先进的性能,超越了包括 GPT-4o 和 Gemini-1.5 Pro 在内的专有模型以及更大的开源基线模型。

你可能也对我们的另一个项目 ViCA2 感兴趣。请参考以下链接:
🚀 快速开始
ViCA-7B 是一个强大的视觉语言模型,可用于室内视频环境中的视觉空间推理任务。你可以按照下面的推理示例代码,快速体验 ViCA-7B 在 VSI-Bench 问题上的应用。
✨ 主要特性
- 先进架构:基于 LLaVA-NeXT 框架,采用 Qwen2-7B 作为语言骨干,SigLIP 作为视觉编码器。
- 高效训练:采用固定长度的视觉标记化、轻量级投影器进行多模态对齐、使用 DeepSpeed 进行高效分布式训练以及混合精度计算(fp16)等策略。
- 优质数据集:在 ViCA-322K 和 ViCA-thinking-2.68k 两个互补数据集上进行微调,提升空间推理和逐步推理能力。
- 卓越性能:在 VSI-Bench 基准测试中取得了最佳的整体性能,超越了多个基线模型。
📦 安装指南
运行推理代码前,你需要安装必要的依赖库:
pip install git+https://github.com/LLaVA-VL/LLaVA-NeXT.git
💻 使用示例
基础用法
# This inference script is adapted from:
# https://huggingface.co/lmms-lab/LLaVA-Video-7B-Qwen2
# pip install git+https://github.com/LLaVA-VL/LLaVA-NeXT.git
from llava.model.builder import load_pretrained_model
from llava.mm_utils import get_model_name_from_path, process_images, tokenizer_image_token
from llava.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN, IGNORE_INDEX
from llava.conversation import conv_templates, SeparatorStyle
from PIL import Image
import requests
import copy
import torch
import sys
import warnings
from decord import VideoReader, cpu
import numpy as np
import json
from tqdm import tqdm
import os
warnings.filterwarnings("ignore")
def load_video(video_path, max_frames_num,fps=1,force_sample=False):
if max_frames_num == 0:
return np.zeros((1, 336, 336, 3))
vr = VideoReader(video_path, ctx=cpu(0),num_threads=1)
total_frame_num = len(vr)
video_time = total_frame_num / vr.get_avg_fps()
fps = round(vr.get_avg_fps()/fps)
frame_idx = [i for i in range(0, len(vr), fps)]
frame_time = [i/fps for i in frame_idx]
if len(frame_idx) > max_frames_num or force_sample:
sample_fps = max_frames_num
uniform_sampled_frames = np.linspace(0, total_frame_num - 1, sample_fps, dtype=int)
frame_idx = uniform_sampled_frames.tolist()
frame_time = [i/vr.get_avg_fps() for i in frame_idx]
frame_time = ",".join([f"{i:.2f}s" for i in frame_time])
spare_frames = vr.get_batch(frame_idx).asnumpy()
# import pdb;pdb.set_trace()
return spare_frames,frame_time,video_time
pretrained = 'nkkbr/ViCA'
model_name = "llava_qwen"
device = "cuda"
device_map = "auto"
tokenizer, model, image_processor, max_length = load_pretrained_model(pretrained, None, model_name, torch_dtype="bfloat16", device_map=device_map) # Add any other thing you want to pass in llava_model_args
model.eval()
from datasets import load_dataset
vsi_bench = load_dataset("nyu-visionx/VSI-Bench")
vsi_bench = vsi_bench['test']
data_curr = vsi_bench[1000]
video_path = f"[VIDEO PATH]"
max_frames_num = 64
video,frame_time,video_time = load_video(video_path, max_frames_num, 1, force_sample=True)
video = image_processor.preprocess(video, return_tensors="pt")["pixel_values"].cuda().to(torch.bfloat16)
video = [video]
conv_template = "qwen_1_5"
# time_instruciton = f"The video lasts for {video_time:.2f} seconds, and {len(video[0])} frames are uniformly sampled from it. These frames are located at {frame_time}.Please answer the following questions related to this video."
time_instruciton = ""
question = DEFAULT_IMAGE_TOKEN + f"\n{time_instruciton}\n\n"
question += f"These are frames of a video.\n\n"
question += f"Question: {data_curr['question']}\n"
if data_curr['options'] is not None:
question += '\n'.join(data_curr['options']) + "\n"
question += f"Answer with the option’s letter from the given choices directly.\n"
else:
question += f"Please answer the question using a single word or phrase.\n"
print(f"Prompt:\n{question}")
conv = copy.deepcopy(conv_templates[conv_template])
conv.append_message(conv.roles[0], question)
conv.append_message(conv.roles[1], None)
prompt_question = conv.get_prompt()
input_ids = tokenizer_image_token(prompt_question, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to(device)
cont = model.generate(
input_ids,
images=video,
modalities= ["video"],
do_sample=False,
temperature=0,
max_new_tokens=1024,
)
text_outputs = tokenizer.batch_decode(cont, skip_special_tokens=True)[0].strip()
print(repr(text_outputs))
📚 详细文档
模型架构与训练策略
ViCA-7B 基于 LLaVA-NeXT 框架构建,使用 Qwen2-7B 作为语言骨干,SigLIP 作为视觉编码器。
关键训练特性
- 固定长度的视觉标记化:每个视频统一采样为 64 帧,每帧编码为 210 个视觉标记,每个示例共 13,440 个视觉标记,确保跨批次的一致内存使用和稳定优化。
- 通过轻量级投影器进行多模态对齐:一个简单的基于 MLP 的投影器将视觉嵌入映射到语言嵌入空间,实现视频内容和文本提示在训练和推理过程中的有效融合。
- 使用 DeepSpeed 进行高效分布式训练:使用 DeepSpeed ZeRO-3 Offload 在 8× NVIDIA H100 80GB GPU 上进行训练,对全参数和优化器状态进行跨设备分区,支持大批次大小并最小化 GPU 内存开销。
- 混合精度计算(fp16):采用 混合精度训练(fp16) 加速计算并减少内存使用,同时结合 ZeRO-3 分区进一步提高训练可扩展性。
训练持续了 55 小时,涵盖了基础和复杂空间推理子集。
训练动态
图 2: ViCA-7B 微调期间的训练损失、学习率调度和梯度范数曲线。这些曲线展示了在 DeepSpeed ZeRO-3 设置下的稳定优化过程和顺利收敛。
数据集
ViCA-7B 在两个互补的数据集上进行微调:
- ViCA-322K:一个大规模数据集,涵盖了基础空间推理任务(如对象距离、大小、数量、出现顺序)和涉及自然语言问题与场景理解的复杂空间推理任务。该数据集是模型空间推理能力的核心。
- ViCA-thinking-2.68k:一个专注于指令调整的数据集,用于增强模型在输出最终答案之前生成逐步推理轨迹的能力,支持更具可解释性和认知一致性的响应生成。
有关详细信息,请参考上述链接的各个数据集页面。
评估:VSI-BENCH 基准测试
图 3: ViCA-7B 和基线模型在 VSI-Bench 上的定量比较。ViCA-7B 在数值和多项选择任务中均取得了最佳的整体性能。
复杂空间推理(CSR)数据的影响
配置 | 平均得分 |
---|---|
仅基础数据 (281K) | 55.35 |
包含 CSR 的完整数据 (322K) | 60.56 |
CSR(复杂空间推理)增强了模型的泛化能力并 加速了学习,在中间检查点有显著的性能提升(例如,在 50 - 55% 时提升 2.02)。
数据规模与性能
在使用 5% → 60% 的数据时,性能显著提升。在 80% 之后,性能提升趋于平稳,表明数据集与模型容量匹配良好。
图 4: ViCA-7B 在不同训练数据规模(从 5% 到 100%)下的性能。完整数据集(包括复杂空间推理,CSR)始终优于仅使用基础数据的配置。值得注意的是,增强了 CSR 的模型在 50% 到 55% 之间得分提升了 2.02,在全规模下最终性能提升了 4.75。超过 80% 后性能趋于平稳,表明数据集与模型容量相匹配。
中间检查点和评估输出
为了支持详细分析和可重复性,我们提供了两组中间检查点,这些检查点在训练数据每增加 5% 时保存。这些模型进行了单轮训练,有助于理解训练过程中性能的演变。
我们还发布了每个检查点对应的 原始评估输出(例如,.json
预测文件)。用于生成这些输出的评估脚本可在我们的 GitHub 仓库 中找到。
完整数据集(ViCA-322K:基础 + CSR)
该系列对应于完整的训练集,包括基础空间推理和复杂空间推理(CSR):
数据使用比例 | 检查点 | 数据使用比例 | 检查点 |
---|---|---|---|
5% | nkkbr/ViCA-5p |
55% | nkkbr/ViCA-55p |
10% | nkkbr/ViCA-10p |
60% | nkkbr/ViCA-60p |
15% | nkkbr/ViCA-15p |
65% | nkkbr/ViCA-65p |
20% | nkkbr/ViCA-20p |
70% | nkkbr/ViCA-70p |
25% | nkkbr/ViCA-25p |
75% | nkkbr/ViCA-75p |
30% | nkkbr/ViCA-30p |
80% | nkkbr/ViCA-80p |
35% | nkkbr/ViCA-35p |
85% | nkkbr/ViCA-85p |
40% | nkkbr/ViCA-40p |
90% | nkkbr/ViCA-90p |
45% | nkkbr/ViCA-45p |
95% | nkkbr/ViCA-95p |
50% | nkkbr/ViCA-50p |
100% (本仓库) | nkkbr/ViCA |
原始评估输出可在 此处 找到。
仅基础子集(ViCA-322K:基础)
该系列仅在 ViCA-322K 的基础空间推理子集上进行训练,不包含任何 CSR 示例:
数据使用比例 | 检查点 | 数据使用比例 | 检查点 |
---|---|---|---|
5% | nkkbr/ViCA-base-5p |
55% | nkkbr/ViCA-base-55p |
10% | nkkbr/ViCA-base-10p |
60% | nkkbr/ViCA-base-60p |
15% | nkkbr/ViCA-base-15p |
65% | nkkbr/ViCA-base-65p |
20% | nkkbr/ViCA-base-20p |
70% | nkkbr/ViCA-base-70p |
25% | nkkbr/ViCA-base-25p |
75% | nkkbr/ViCA-base-75p |
30% | nkkbr/ViCA-base-30p |
80% | nkkbr/ViCA-base-80p |
35% | nkkbr/ViCA-base-35p |
85% | nkkbr/ViCA-base-85p |
40% | nkkbr/ViCA-base-40p |
90% | nkkbr/ViCA-base-90p |
45% | nkkbr/ViCA-base-45p |
95% | nkkbr/ViCA-base-95p |
50% | nkkbr/ViCA-base-50p |
100% | nkkbr/ViCA-base |
原始评估输出可在 此处 找到。
按数据源的检查点
虽然完整的 ViCA-322K 数据集由我们整理,但底层视频和相关元数据来自三个不同的室内视频数据集:
为了更好地理解每个数据源对模型性能的贡献,我们在 ViCA-322K 的子集上对 ViCA-7B 进行了微调,这些子集仅使用每个数据源的数据。对于每个子集,我们提供了使用可用数据的 10% 增量 进行训练的检查点,从 10% 到 100%。
所有检查点也提供了相应的 原始评估输出(例如,.json
预测文件)。
ARKitScenes 仅数据源检查点
数据使用比例 | 检查点 | 数据使用比例 | 检查点 |
---|---|---|---|
10% | nkkbr/ViCA-ARKitScenes-10p |
60% | nkkbr/ViCA-ARKitScenes-60p |
20% | nkkbr/ViCA-ARKitScenes-20p |
70% | nkkbr/ViCA-ARKitScenes-70p |
30% | nkkbr/ViCA-ARKitScenes-30p |
80% | nkkbr/ViCA-ARKitScenes-80p |
40% | nkkbr/ViCA-ARKitScenes-40p |
90% | nkkbr/ViCA-ARKitScenes-90p |
50% | nkkbr/ViCA-ARKitScenes-50p |
100% | nkkbr/ViCA-ARKitScenes |
📄 原始评估输出:ARKitScenes 结果
ScanNet++ 仅数据源检查点
数据使用比例 | 检查点 | 数据使用比例 | 检查点 |
---|---|---|---|
10% | nkkbr/ViCA-ScanNetPP-10p |
60% | nkkbr/ViCA-ScanNetPP-60p |
20% | nkkbr/ViCA-ScanNetPP-20p |
70% | nkkbr/ViCA-ScanNetPP-70p |
30% | nkkbr/ViCA-ScanNetPP-30p |
80% | nkkbr/ViCA-ScanNetPP-80p |
40% | nkkbr/ViCA-ScanNetPP-40p |
90% | nkkbr/ViCA-ScanNetPP-90p |
50% | nkkbr/ViCA-ScanNetPP-50p |
100% | nkkbr/ViCA-ScanNetPP |
📄 原始评估输出:ScanNet++ 结果
ScanNet 仅数据源检查点
数据使用比例 | 检查点 | 数据使用比例 | 检查点 |
---|---|---|---|
10% | nkkbr/ViCA-ScanNet-10p |
60% | nkkbr/ViCA-ScanNet-60p |
20% | nkkbr/ViCA-ScanNet-20p |
70% | nkkbr/ViCA-ScanNet-70p |
30% | nkkbr/ViCA-ScanNet-30p |
80% | nkkbr/ViCA-ScanNet-80p |
40% | nkkbr/ViCA-ScanNet-40p |
90% | nkkbr/ViCA-ScanNet-90p |
50% | nkkbr/ViCA-ScanNet-50p |
100% | nkkbr/ViCA-ScanNet |
📄 原始评估输出:ScanNet 结果
额外探索
时间指令
在提示中包含 64 帧的时间戳会略微 降低 性能,这表明模型未能有效利用时间对齐,并且受到指令冗长的负面影响。
图 5: 在 VSI-Bench 上,添加明确的帧时间戳(64 个值)会降低模型性能,表明模型无法利用时间对齐,并且对提示长度敏感。
更多帧
将输入从 64 帧增加到 128 帧,视觉标记数量翻倍(从 13,440 到 26,880),但 性能没有提升,这凸显了模型对固定标记长度的过拟合和架构的灵活性不足。
图 6: 64 帧和 128 帧输入的比较。尽管视觉标记数量翻倍,但性能保持不变,表明模型对固定长度输入过拟合,并且对可变长度序列的适应性有限。
🔧 技术细节
模型指标
属性 | 详情 |
---|---|
模型类型 | 视觉语言模型 |
训练数据 | ViCA-322K、ViCA-thinking-2.68k |
基础模型 | lmms-lab/LLaVA-Video-7B-Qwen2 |
评估基准 | VSI-Bench |
评估结果
ViCA-7B 在 VSI-Bench 基准测试中的评估结果如下:
任务类型 | 数据集 | 指标 | 值 | 名称 | 验证状态 |
---|---|---|---|---|---|
视觉问答 | VSI-Bench | 得分 | 60.56 | 平均 | 未验证 |
视觉问答 | VSI-Bench | MRA | 68.81 | 对象数量 | - |
视觉问答 | VSI-Bench | MRA | 57.01 | 绝对距离 | - |
视觉问答 | VSI-Bench | MRA | 79.17 | 对象大小 | - |
视觉问答 | VSI-Bench | MRA | 75.14 | 房间大小 | - |
视觉问答 | VSI-Bench | 准确率 | 58.45 | 相对距离 | - |
视觉问答 | VSI-Bench | 准确率 | 42.56 | 相对方向 | - |
视觉问答 | VSI-Bench | 准确率 | 34.54 | 路线规划 | - |
视觉问答 | VSI-Bench | 准确率 | 68.77 | 出现顺序 | - |
📄 许可证
本项目采用 Apache-2.0 许可证。
💡 潜在应用
ViCA-7B 支持广泛的基于空间的多模态应用:
- 室内导航助手
- 机器人规划和空间查询
- 智能房间布置和 AR 布局分析
- 具身 AI 智能体的场景理解
⚠️ 已知局限性
- 时间推理有限:无法有效利用时间指令。
- 帧缩放问题:模型期望固定的输入长度。
- 不支持深度/点云:仅支持 RGB 视频输入。
- 零样本泛化能力良好,但并非与任务无关。










