📘 原文信息
- 项目名:GeoChat
- 副标题:Grounded Large Vision-Language Model for Remote Sensing
- 作者:Kartik Kuckreja*、Muhammad Sohail Danish*、Muzammal Naseer、Abhijit Das、Salman Khan、Fahad Khan(*共同一作)
- 机构:MBZUAI(IVAL Lab · Oryx 中心)、BITS Pilani、Australian National University、Linköping University
- 会议:CVPR 2024
- 首版日期:2023-11-28(arXiv:2311.15826)
- 开源日期:2024-02-28(代码 + 模型 + 数据 + 评测脚本)
- 仓库:https://github.com/mbzuai-oryx/GeoChat ↗
- 论文链接:https://arxiv.org/abs/2311.15826 ↗
- 官网:https://mbzuai-oryx.github.io/GeoChat ↗
- 模型:https://huggingface.co/MBZUAI/geochat-7B ↗
- 数据集:https://huggingface.co/datasets/MBZUAI/GeoChat_Instruct ↗(318K 指令)
- License:Apache-2.0(代码)、数据集遵循各自来源
- 代码规模:58 MB(主仓)+ 5 个 docs PDF(MODEL_ZOO / Data / Evaluation / LoRA / Customize_Component)+ Supplementary
一、为什么这篇值得读?#
如果说 2023 年是”通用 VLM”(LLaVA / MiniGPT-4 / InstructBLIP)的高潮,2024 年开始,学界和工业界都在问一个非常工程化的问题:
这些通用 VLM,放进”领域”还能用吗? 能不能在不丢通用能力的前提下,真的在某个垂直任务上做出 ground truth?
遥感(Remote Sensing / RS)就是一个特别合适的”试金石”:
- 图像分辨率极高,512×512 起步、动辄 1024×1024,通用 CLIP 的 224×224 / 336×336 直接欠采样;
- 目标小而密集,港口有几十条船、停车场有几十辆车,目标框常常是几十个起步;
- 方向任意,舰船、桥梁、房屋常常是旋转的,而非水平竖直;
- 领域知识重要,“码头""港口""储油罐”这些类目自然语言模型并不熟;
- 评测协议缺失,LLaVA-Bench 那一套并不能直接套到 RS。
MBZUAI Oryx 团队的 GeoChat(CVPR 2024)就是冲着这五个痛点去的。它做了三件很硬的事:
- 首个带 grounded 能力的 RS VLM——能输出”自然语言 + 目标框”交错出现的对话;
- 把 CLIP 拉到 504×504 高分辨率——通过位置编码插值,让小目标不再”被平均”;
- 构造了 318K 的 RS 多模态指令数据——把目标检测、VQA、场景分类、region caption、referring expression 全统一成一个
instruction-following形式。
更重要的是,GeoChat 没有重新发明轮子——它直接基于 LLaVA-1.5 架构,只做 LoRA fine-tune,3×A100 25 小时出活。这种”小代价,大效果”的工程范式,正是当前开源社区最值得学的。
本文按仓库的代码结构(geochat/model / geochat/serve / geochat/eval / geochat/train)和文档结构(README.md / docs/LoRA.md / docs/Evaluation.md / docs/Customize_Component.md / docs/Data.md),做一次重述与解读,重点回答:
- 为什么必须”领域化”,而不是直接用 LLaVA-1.5 跑 RS?(第 2 节)
- GeoChat 在 LLaVA-1.5 架构上”动了哪几刀”?(第 3 节)
- 318K GeoChat_Instruct 怎么来的?数据流水线是什么?(第 4 节)
- CLIP 怎么从 336 拉到 504?旋转框怎么训?(第 5 节)
- LoRA + DeepSpeed ZeRO-2 的训练配置实战(第 6 节)
- 7 个评测基准怎么跑?4 个 batch 脚本怎么拆?(第 7 节)
- 如果想换成 Qwen / InternVL / 自家 VLM,要改哪几行代码?(第 8 节)
- GeoChat 的局限与未来(第 9 节)
二、为什么通用 VLM 直接跑 RS 不灵?#
2.1 三个老毛病#
LLaVA-1.5 / MiniGPT-4 / InstructBLIP 这一代通用 VLM,默认的”看图 + 对话”思路,搬到 RS 上会同时遇到三道坎:
| 维度 | 通用 VLM 默认 | 遥感实际情况 |
|---|---|---|
| 输入分辨率 | 336×336 | 1024×1024+,目标小、密集 |
| 目标位置 | 没有 grounding 输出 | 旋转框,任意角度 |
| 领域知识 | ImageNet / COCO 概念 | ”港口""油罐""机库” |
更直白地说:LLaVA-1.5 能告诉你”这张图看起来像机场”,但你问”3 号跑道上的那架飞机”,它就糊了。
2.2 现有方案的折衷#
2023 年下半年有过几个 RS 方向的 VLM 尝试(SatelliteGPT、RSGPT、EarthGPT 等),普遍的做法是:
- 要么从零 pretrain 一个 RS vision encoder(成本极高,数据也不够);
- 要么直接用 CLIP 336×336,接受小目标模糊;
- 要么在 LLaVA 之上加一个”目标检测后处理”分支(双阶段,延迟大)。
GeoChat 的取舍是:不重新 pretrain,不动 CLIP 主干权重,只把位置编码插值到 504×504 + LoRA fine-tune LLM。这一步看起来小,但工程上撬动的杠杆非常大。
💡 小吴笔记:这是”用最少的钱办最大的事”的经典范式。CLIP ViT-L/14 的 pretrain 用了 4 亿图文对,任何团队想从零再训一个 504×504 的 RS vision encoder 都是不现实的。所以 GeoChat 选择”用 CLIP 的知识 + LLaVA-1.5 的对齐 + LoRA 的轻量微调”——三方各贡献自己最擅长的那部分。
三、GeoChat 在 LLaVA-1.5 架构上”动了哪几刀”?#
打开 geochat/model/,你看到的几乎就是 LLaVA-1.5 的翻版。GeoChat 的工程洁癖在于:只改不得不改的地方。
3.1 顶层架构(几乎没动)#
[CLIP ViT-L/14 @ 504] → [2×MLP projector] → [Vicuna 1.5 / 7B]
↑ ↑
vision tower LLM(LoRA-tuned)text跟 LLaVA-1.5 一模一样,只是 vision tower 的输入分辨率从 336 改成 504。
3.2 关键文件改动#
| LLaVA-1.5 文件 | GeoChat 对应文件 | 改动 |
|---|---|---|
llava/model/llava_arch.py | geochat/model/geochat_arch.py(262 行) | 类名重命名,逻辑几乎相同 |
llava/model/language_model/llava_llama.py | geochat/model/language_model/geochat_llama.py(140 行) | 注册为 geochat model_type |
llava/model/language_model/llava_mpt.py | geochat/model/language_model/geochat_mpt.py(113 行) | MPT 备选 backbone |
llava/train/llava_trainer.py | geochat/train/geochat_trainer.py(175 行) | 同名,继承自 transformers Trainer |
llava/train/train.py | geochat/train/train.py(957 行) | 加入 LoRA 支持、group_by_modality_length |
llava/serve/cli.py | geochat/serve/cli.py | 加入旋转框可视化 |
llava/serve/gradio_web_server.py | geochat/serve/gradio_web_server.py | 同 LLaVA,加 RS 任务 token |
docs/Customize_Component.md 把它讲得非常清楚:
“It is quite simple to swap out LLaMA to any other LLMs. You can refer to our implementation of
GeoChat_llama.pyfor an example of how to replace the LLM. Although it may seem that it still needs ~100 lines of code, most of them are copied from the originalllama.pyfrom HF. The only part that is different is to insert some lines for processing the multimodal inputs.”
也就是说,GeoChat 对 LLaVA-1.5 的修改,核心只有两处:
forward()里加一行prepare_inputs_labels_for_multimodal(...);prepare_inputs_for_generation()里把images加进model_inputs。
这两步合起来不到 50 行,剩下的全是 LLaVA-1.5 留下的。
3.3 图像 token 化的三件套#
geochat/constants.py 把多模态对齐用到的特殊 token 都列出来了:
IGNORE_INDEX = -100
IMAGE_TOKEN_INDEX = -200
DEFAULT_IMAGE_TOKEN = "<image>"
DEFAULT_IMAGE_PATCH_TOKEN = "<im_patch>"
DEFAULT_IM_START_TOKEN = "<im_start>"
DEFAULT_IM_END_TOKEN = "<im_end>"pythonprepare_inputs_labels_for_multimodal(...) 在 geochat_arch.py 里(第 90-200 行)做了一件看似简单实则精巧的事:
- 找到
input_ids中所有IMAGE_TOKEN_INDEX的位置; - 把这些位置上的 token 替换成 vision tower 输出的
image_features序列; - 对应的
labels位置填IGNORE_INDEX(-100),让 LLM 不要去”预测图片”。
注意一个 LLaVA 时代的优化:当 batch 内某 sample 不含图像时,把 input_ids 一分为二,中间塞一个空的 image_features 0-length。这避免了 deepspeed zero3 下的特殊处理。
3.4 加载逻辑:LoRA vs Merged#
geochat/model/builder.py:load_pretrained_model(...) 是部署时第一个要调用的函数,它的分支特别值得读:
if 'lora' in model_name.lower() and model_base is not None:
→ 先加载 base model
→ 再 apply LoRA delta
elif 'lora' in model_name.lower() and model_base is None:
→ 警告:没给 base model,会出问题
else:
→ 直接加载 merged full modeltextscripts/merge_lora_weights.py 提供从 LoRA → merged 的能力(读取 non_lora_trainables.bin + LoRA adapter,合并保存)。
💡 小吴笔记:“几乎克隆 LLaVA-1.5”这件事,有人会觉得”没原创性”,但从工程角度是最成熟的选择。LLaVA-1.5 经历过一年多的社区检验,坑几乎被踩完了。GeoChat 在它上面加 504×504 视觉 + 旋转框 + 318K 数据 + LoRA,就把”通用 VLM 跑 RS”这个题目做完了。重写 vision encoder 反而容易踩坑,这是”组合创新”的胜利。
四、318K GeoChat_Instruct:数据流水线是怎么搭的?#
4.1 三阶段数据构造#
docs/Data.md 把数据构造讲得很直接,核心是三阶段:
| 阶段 | 数据来源 | 规模 | 用途 |
|---|---|---|---|
| Pretrain | LAION/CC/SBU BLIP-Caption Concept-balanced 558K | 181 MB | 训练 MLP projector,做 vision-language 对齐 |
| Instruction tuning | GeoChat_Instruct(Vicuna 生成 + RS 任务原始数据) | 263 MB,318K 条 | 训练 LoRA,教模型做 RS 任务 |
| Evaluation | GeoChat-Bench | 7 个 benchmark | 评测 |
4.2 318K 指令怎么来的#
这是论文最精彩的部分之一——数据完全靠”现成检测数据集 + Vicuna 重新生成对话”组合而成。
具体流水线:
1. 拿现成 RS 目标检测数据集(DIOR / DOTA / FAIR1M 等)
→ 每个图像:boxes + class + attribute + relationship
2. 用检测数据集的 annotation 自动生成短描述
"image_id: plane (0.1, 0.2, 0.3, 0.4)"
3. 把短描述 + 元数据喂给 Vicuna-v1.5
→ 生成多轮自然对话:"这张图里有几架飞机?位置在?大小如何?"
4. 加入 VQA / Scene Classification 的原始数据
→ LR / HR BEN、UC Merced、AID
5. 总共 318K image-instruction pairstext这种”用检测数据集当骨架 + LLM 当皮肤”的范式,在 2023-2024 年非常流行(LLaVA-Instruct / ShareGPT4V / LVIS-Instruct4V 都用类似套路),但用在 RS 上是 GeoChat 第一次。
4.3 七种任务 token#
GeoChat 的特别之处是引入任务特定 token,在 prompt 层面区分任务:
[grounding] → 输出自然语言 + 目标框
[refer] → referring expression 定位
[region] → region caption
[detect] → 直接检测
[VQA] → 视觉问答
[scene] → 场景分类
(空) → 普通对话text这一设计在 geochat_demo.py 的 prompt 构造里随处可见。它让同一个模型、同一套参数能做 7 种不同任务,而不需要 7 个 head。这是”prompt-as-routing”的极致体现。
💡 小吴笔记:任务 token 的本质是把”决策”从模型架构搬到 prompt 字符串。这跟 LangChain 的 RouterChain、AutoGPT 的 command dispatch 是同一个思想,但 GeoChat 做得更纯粹——不用加任何 head,不用改任何 loss。代价是模型必须见过这个 token 出现在训练数据里,所以318K 指令里必须把这 7 种 token 都覆盖到。
五、504×504 CLIP 与旋转框:两个关键技术细节#
5.1 怎么把 CLIP 从 336 拉到 504#
CLIP ViT-L/14 默认训练分辨率是 224,ViT-L/14-336 把位置编码扩展到 336。但 336 在 RS 上依然不够——一艘 30 米长的船在 1024×1024 的卫星图上,只有 30 个像素左右。
docs/Customize_Component.md 没明说,但 geochat_demo.py 的 process_images(...) 调用可以看到:
image_tensor_batch = image_processor.preprocess(
image_folder,
crop_size={'height': 504, 'width': 504},
size={'shortest_edge': 504},
return_tensors='pt'
)['pixel_values']python也就是说:
- 位置编码插值:把 336×336 的 sin-cos 位置编码,通过 bicubic 插值到 504×504。CLIP 的
vision_tower.load_model()内部会做这件事; --image_aspect_ratio pad:非正方形图像 pad 到 504×504 而不是 crop。finetune_lora.sh里明确写了这个参数,论文说”能稍微减少幻觉”。
这种”插值位置编码” + “pad 不 crop”的组合,是 CLIP-based VLM 跑高分辨率的标准范式,但GeoChat 是第一个把它系统化用到 RS 上。
5.2 旋转框(rotated bbox)怎么训#
RS 图像里最关键的特性之一是目标任意方向——舰船、桥梁、储油罐常常是斜的。普通水平框(HBB)框不住倾斜目标,IoU 会被严重稀释。
GeoChat 的解决方法是让模型自己输出旋转框:
[grounding] Describe this image in detail with grounded words.
→ "There are 3 airplanes [0.1, 0.2, 0.5, 0.6, 30°], [0.3, 0.4, 0.7, 0.8, 45°]..."text5 个数字 = (x1, y1, x2, y2, angle)。模型直接把这串数字当成普通文本 token 来预测,不需要特殊的 detection head。
geochat/eval/batch_geochat_grounding.py 和 batch_geochat_referring.py 在 inference 时:
- 用正则把
[x1, y1, x2, y2, angle]这种字符串从模型输出里抽出来; - 用
bbox_and_angle_to_polygon(...)把它转成 4 个顶点的 polygon(cli.py:50-66); - 用 matplotlib 或 PIL 画到原图上。
这种”把几何量当字符串回归”的范式叫 “textualized detection”(Kosmos-2 第一个这么做),GeoChat 把这一思想用到旋转框上,比 DINO / YOLO 这类基于 regression head 的检测器更轻——不需要 NMS 后处理,不需要 RoIAlign,模型自己输出 polygon-ready 的坐标。
💡 小吴笔记:“Textualized detection”看起来很 hack,但它有一个非常优雅的好处:detection 跟 VQA、caption、对话共享同一套输出空间(都是自然语言 token)。这意味着一个模型,一份训练,一个 loss,搞定所有任务。代价是数值精度不如 regression head(角度只能精确到 1°),但 RS 任务对精度的容忍度比 COCO 高很多。
六、LoRA + DeepSpeed ZeRO-2 训练实战#
6.1 finetune_lora.sh 完整参数#
scripts/finetune_lora.sh 是 GeoChat 的”标准训练入口”,逐行读:
deepspeed --master_port=$((RANDOM + 10000)) \
--include localhost:gpu_ids \
geochat/train/train_mem.py \
--deepspeed ./scripts/zero2.json \
--lora_enable True \
--model_name_or_path path/to/base/llavav1.5-7b \
--version v1 \
--data_path path/to/GeoChat_Instruct.json \
--image_folder /share/softwares/kartik/final_images_llava \
--vision_tower openai/clip-vit-large-patch14-336 \
--mm_projector_type mlp2x_gelu \
--pretrain_mm_mlp_adapter path/to/llava-v1.5-mlp2x-336px-pretrain-vicuna-7b-v1.5/mm_projector.bin \
--mm_vision_select_layer -2 \
--mm_use_im_start_end False \
--mm_use_im_patch_token False \
--image_aspect_ratio pad \
--bf16 True \
--output_dir path/to/checkpoints_dir \
--num_train_epochs 1 \
--per_device_train_batch_size 32 \
--gradient_accumulation_steps 1 \
--learning_rate 2e-4 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--lr_scheduler_type cosine \
--logging_steps 1 \
--model_max_length 2048 \
--gradient_checkpointing True \
--lazy_preprocess True \
--dataloader_num_workers 16 \
--report_to wandbbash6.2 几个关键参数解释#
| 参数 | 值 | 含义 |
|---|---|---|
--lora_enable True | 启用 LoRA | LoRA rank=64, alpha=16(见 train.py) |
--mm_vision_select_layer -2 | 取 CLIP 倒数第二层特征 | LLaVA-1.5 的默认选择 |
--mm_use_im_start_end False | 不加 <im_start> <im_end> 边界 | 跟 LLaVA-1.5 一致,减少 token 数 |
--image_aspect_ratio pad | 非正方形 pad 不 crop | 减少 RS 边缘目标丢失 |
--bf16 True | bf16 混合精度 | 3×A100 上必备 |
--per_device_train_batch_size 32 | 单卡 batch=32 | 504×504 图像 + bf16,3×A100 跑得动 |
--learning_rate 2e-4 | LoRA lr=2e-4 | 远高于全参数 finetune(2e-5) |
--gradient_checkpointing True | 节省显存 | 7B 模型必备 |
--lazy_preprocess True | 懒预处理图像 | 避免启动时一次性把所有图像 load 进 RAM |
6.3 ZeRO-2 vs ZeRO-3 怎么选#
仓库里同时提供了 zero2.json / zero3.json / zero3_offload.json 三个 DeepSpeed 配置。GeoChat 默认用 zero2.json,原因写在 docs/LoRA.md:
“
zero3.jsonis usually faster thanzero3_offload.jsonbut requires more GPU memory, therefore, we recommend tryingzero3.jsonfirst, and if you run out of GPU memory, tryzero3_offload.json. You can also tweak theper_device_train_batch_sizeandgradient_accumulation_stepsin the config to save memory, and just to make sure thatper_device_train_batch_sizeandgradient_accumulation_stepsremains the same.”
简单说:
- ZeRO-2:参数分片,优化器状态分片,梯度分片,适合 LoRA;
- ZeRO-3:再加参数本身分片,适合全参数 finetune;
- ZeRO-3 offload:把参数 offload 到 CPU,显存极省但慢。
由于 GeoChat 只 LoRA 调 LLM,需要 train 的参数(LoRA + mm_projector)很小,ZeRO-2 就够。
6.4 训练成本#
| 项目 | 数字 |
|---|---|
| GPU | 3×A100 40G |
| 时间 | 25 小时(GeoChat-7B) |
| 数据 | 318K 指令对 |
| 全局 batch size | 32×1×3=96 |
| Epochs | 1 |
| 可训练参数 | LoRA 64-rank + mm_projector ≈ 80M |
💡 小吴笔记:25 小时 3×A100 训完一个领域 VLM,在 2024 年初是非常友好的数字。这意味着一个 6 卡 A100 工作站(¥20-30 万)就能复现论文——这是 GeoChat 能在社区快速铺开的核心原因。如果它要 8×H100 + 72 小时,即使论文再漂亮也难复现。
七、7 个评测基准与 4 个 batch 脚本#
7.1 任务与基准对应#
docs/Evaluation.md 列出 7 个 benchmark,按任务类型分:
| 任务 | Benchmark | 数据来源 | 评测脚本 |
|---|---|---|---|
| Scene Classification | UC Merced / AID | 原始数据集 | batch_geochat_scene.py |
| VQA(LR) | LRBEN | zenodo | batch_geochat_vqa.py |
| VQA(HR) | HRBEN | zenodo | batch_geochat_vqa.py |
| Region Captioning | GeoChat-Bench (region) | GeoChat_Instruct split | batch_geochat_grounding.py |
| Visual Grounding | GeoChat-Bench (grounding) | GeoChat_Instruct split | batch_geochat_grounding.py |
| Referring Expression | GeoChat-Bench (ref) | GeoChat_Instruct split | batch_geochat_referring.py |
| Grounded Description | GeoChat-Bench (mixed) | GeoChat_Instruct split | batch_geochat_grounding.py |
7.2 4 个 batch 脚本的核心套路#
geochat/eval/ 下 4 个 batch 脚本(vqa / scene / grounding / referring)长得几乎一样,核心套路:
# 1. 加载模型
tokenizer, model, image_processor, context_len = load_pretrained_model(...)
# 2. 读 questions jsonl
questions = [json.loads(q) for q in open(args.question_file)]
questions = get_chunk(questions, args.num_chunks, args.chunk_idx)
# 3. 加 task token + 构造 prompt
if questions[j]['type'] == 'ref':
qs = "[refer] Give me the location of <p>" + qs + "</p>"
else:
qs = "[grounding]" + qs
qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_TOKEN + '\n' + qs
# 4. batched inference
output_ids = model.generate(input_ids, images=image_tensor_batch.half().cuda(),
do_sample=False, max_new_tokens=256, ...)
# 5. 解析输出,保存 jsonl
output = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)python注意点:
do_sample=False,全部 greedy decoding——docs/Evaluation.md明确说”不用 beam search,保持与 demo 一致”;image_processor.preprocess(...crop_size={'height':504, 'width':504}, size={'shortest_edge':504})——强制 504;- 输出用
output_ids[:, input_token_len:]切掉 prompt 部分。
7.3 评测的”小坑”#
batch_geochat_grounding.py:34 和 batch_geochat_vqa.py:24 都还残留着:
import pdb; pdb.set_trace()python这一行会让脚本在某些断点处直接进入 pdb(交互式 debugger),非交互式环境会卡住。生产评测时必须手动删掉。
💡 小吴笔记:这是开源项目的”原汁原味”——作者当时是手动 debug 用的,提交时忘了删。但同时也说明 CVPR 论文的官方开源仓,经常不是”production-ready”的,要自己清理小坑才能跑通。复现论文前先
grep -n "pdb" geochat/eval/*.py是个好习惯。
八、怎么把 GeoChat 换成 Qwen / InternVL / 自家 VLM?#
docs/Customize_Component.md 是这篇论文最有”工程复用价值”的一节。它把”换 LLM”和”换 vision encoder”两件事讲得非常直接。
8.1 换 LLM(以 Vicuna → LLaMA-2 / Qwen 为例)#
需要改 3 个地方:
-
新写一个
geochat_<your_llm>.py, 继承 HF 的YourLLMConfig和YourLLMForCausalLM,在forward里插入:
pythoninput_ids, attention_mask, past_key_values, inputs_embeds, labels = \ self.prepare_inputs_labels_for_multimodal(input_ids, attention_mask, past_key_values, labels, images) -
修改
geochat/model/__init__.py,把新类 export 出去; -
在文件末尾注册:
pythonAutoConfig.register("geochat_<your_llm>", GeoChatYourLLMConfig) AutoModelForCausalLM.register(GeoChatYourLLMConfig, GeoChatYourLLMForCausalLM)
总代码量 ~100 行,大部分是从 HF 复制过来改个类名。这意味着迁移到 Qwen-VL / InternVL2 / Yi-VL 这些国产 LLM 几乎是体力活。
8.2 换 vision encoder#
更简单——geochat/model/multimodal_encoder/builder.py 已经支持:
def build_vision_tower(vision_tower_cfg, **kwargs):
vision_tower_cfg = vision_tower_cfg.vision_tower
if 'clip' in vision_tower_cfg.lower():
return CLIPVisionTower(vision_tower_cfg, **kwargs)
# 可以加 eva / siglip / dinov2
raise ValueError(...)python加新 vision encoder,只需要写一个类继承 CLIPVisionTower,改一下 forward,改一下 hidden_size。
8.3 一个隐藏的依赖陷阱#
pyproject.toml 把依赖锁死在:
torch==2.0.1
torchvision==0.15.2
transformers==4.31.0
deepspeed==0.9.5
peft==0.4.0
gradio==3.35.2
bitsandbytes==0.41.0text这套组合在 2024 年初是稳定的,但放到 2026 年已经严重过时。transformers>=4.40 改了 LogitsProcessorList 的内部结构,LLaMATokenizer 的 API 也变了几次。在现代环境里 pip install -e . 几乎一定会报错。
建议的兼容策略:
- 用 conda 创建独立环境,严格锁这些版本;
- 或者升级 transformers 到 4.36+ 之后,自己 patch 一两个文件(
tokenizer_image_token的参数顺序、LlamaFlashAttention 的导入路径); - 最稳的是 fork 一份,起个
geochat-2026名字,直接用transformers>=4.40。
九、局限与未来#
9.1 当前局限#
- 依赖冻结。
pyproject.toml把 torch / transformers / deepspeed 锁到 2024 年版本,2026 年新硬件(Blackwell GPU)无法直接跑; - 单图分辨率天花板 504。
image_processor.preprocess(..., size={'shortest_edge': 504})写死 504,处理 1024+ 的卫星图仍要 tile; - 旋转框精度有限。“Textualized detection”的角度只能精确到 1°,对细长目标(桥梁、跑道)可能不够;
- 任务 token 必须出现在 prompt 里。不写
[grounding]就退化成普通对话,缺少”自动判断任务”能力; - 评测脚本残留 pdb 断点。
batch_geochat_grounding.py:34/batch_geochat_vqa.py:24还留有pdb.set_trace(),非交互式环境会卡; - 数据集无许可证细节。318K 指令背后的检测数据集(DIOR / DOTA / FAIR1M)各有自己的 license,商业用途需要逐一核对;
- 没有开放 zero-shot 评测。论文给的是 supervised + 自家 GeoChat-Bench,跨数据集 zero-shot 能力没系统测。
9.2 未来可能的方向#
- 更高分辨率的 vision encoder。EVA-02 / SigLIP-384 / DINOv2 都是 2024-2026 的备选;
- 把任务 token 换成 LoRA adapter。让”任务路由”变成模块化,不用 prompt 工程;
- 推理时支持 tile + merge。让 2048×2048 的卫星图能直接喂进去;
- 统一 NMS 后处理。“Textualized detection” 的最大问题是重复框,加一个轻量 NMS 收益明显;
- 跨域迁移。把 GeoChat 的范式复用到医学影像、显微镜图、雷达图。
十、复刻流程 5 步走#
# 1. 准备环境
conda create -n geochat python=3.10 -y
conda activate geochat
git clone https://github.com/mbzuai-oryx/GeoChat.git
cd GeoChat
pip install --upgrade pip
pip install -e .
pip install ninja
pip install flash-attn --no-build-isolation
# 2. 下载模型权重(~14GB)
# 从 https://huggingface.co/MBZUAI/geochat-7B 下载 geochat-7B
# 3. 下载数据集
# 从 https://huggingface.co/datasets/MBZUAI/GeoChat_Instruct 下载 images zip + json
cat images_parta* > images.zip
unzip images.zip -d /path/to/final_images_llava
# 4. (可选)微调
# 编辑 scripts/finetune_lora.sh 替换路径
bash scripts/finetune_lora.sh
# 或合并 LoRA 权重
python scripts/merge_lora_weights.py \
--model-path /path/to/lora_model \
--model-base /path/to/base_model \
--save-model-path /path/to/merge_model
# 5. 跑 demo
python geochat_demo.py --model-path /path/to/model
# 跑评测
python geochat/eval/batch_geochat_vqa.py --model-path /path/to/model ...bash十一、总结与启示#
GeoChat 的核心贡献 vs 一般 VLM#
| 维度 | 一般 LLaVA-1.5 | GeoChat |
|---|---|---|
| 输入分辨率 | 336×336 | 504×504(位置编码插值) |
| 任务能力 | 通用对话 | 7 种 RS 任务(scene / VQA / grounding / referring / caption / detection / chat) |
| Grounding | 无 | 支持,旋转框角度直接当 token 输出 |
| 训练数据 | 558K LAION 通用 | + 318K RS 指令对 |
| 训练成本 | 全参数 FT LLaVA | LoRA(80M 可训练),3×A100 25h |
| 评测协议 | 通用 VLM Bench | 7 个 RS 专属 Bench |
给做”领域 VLM”工程的 6 条启示#
- 不要重新发明 vision encoder。CLIP / EVA-02 / SigLIP 的 pretrain 成本极高,直接复用 + 位置编码插值是性价比最高的路线;
- “Textualized detection”是杀手锏。把几何量当 token 输出,一个模型、一个 loss、一份输出空间,搞定 VQA + 检测 + 对话;
- 任务 token 比 multi-head 优雅。7 种任务共享同一个 LLM head,只在 prompt 前面加
[grounding]这种字符串,改起来零成本; - LoRA 足以应付领域化。如果你的数据 < 500K,prompt 风格差异不大,LoRA 几乎一定够用;
- LLaVA-1.5 是”站在巨人肩膀上”。fork 它,加 vision tower、替换数据,几乎不需要碰 LLM 内部。CVPR 2024 很多 RS VLM 都是这个套路;
- 依赖锁定在开源里是”双刃剑”。锁版本=可复现,但锁得太死=几年后跑不动。生产仓库建议加一个
requirements-latest.txt+ CI 测试。
给研究者 / 论文复现者的 4 条建议#
- 必读
docs/Customize_Component.md。它把”换 LLM / 换 vision encoder”讲成体力活,等于送你一份”如何把你的 VLM 接到 GeoChat 数据集”的手册; grep -n "pdb" geochat/eval/*.py先于bash scripts/finetune_lora.sh。开源论文仓的 debug 残留要自己清;- **优先复现 GeoChat-Bench(7 个)**而不是经典 COCO / VQA。
docs/Evaluation.md给了完整的 jsonl 转换流程,这才是论文真正测过的东西; - 用 supplementary 验证数据 pipeline。
docs/geochat_supp.pdf里有更详细的数据生成 prompt 模板、清洗规则、消融实验,论文正文写不下但 reviewer 必看的内容都在那里。
参考资料:
- GeoChat GitHub 仓库 ↗
- GeoChat arXiv 论文 ↗
- GeoChat 官网 ↗
- GeoChat 视频讲解 ↗
- GeoChat-7B 模型权重 ↗
- GeoChat_Instruct 318K 指令数据集 ↗
- GeoChat-Bench 评测集 ↗
- Supplementary Material (PDF) ↗
- docs/LoRA.md(LoRA 训练 + Demo 部署) ↗
- docs/Evaluation.md(7 个 benchmark 评测指南) ↗
- docs/Customize_Component.md(如何换 LLM / vision encoder) ↗
- docs/Data.md(数据集构造) ↗
- docs/MODEL_ZOO.md(模型权重清单) ↗
- MBZUAI IVAL Lab ↗
- Oryx 中心 ↗
- LLaVA-1.5(GeoChat 的基础架构) ↗
- Kosmos-2(textualized detection 的灵感来源) ↗
- DOTA / DIOR / FAIR1M(318K 指令数据的检测骨架来源) ↗