How Finely Can Vision–Language Models See Biology?
Bio-VQA: A Benchmark for Taxonomic, Morphological, Spatial and Individual Reasoning
S M Rayeed · Qian Ma · Charles V. Stewart · Yao Ma
🌐 Project page | 🤗 HF Dataset | 💻 Github Repo | 📄 Paper: WACV 2027 (link will be added here)
- 2026-11 — Camera-ready version for WACV 2027. This README, the numbers in every component README and the environment notes are updated to match the camera-ready paper.
- 2026-11 — The full benchmark, Bio-VQA-Lite (500 questions per task, 12,000 in total), and the per-item answers of
all 18 models are public on Hugging Face:
imageomics/Bio-VQA.
In biodiversity monitoring, a single image raises several questions: which taxon, how many, which trait, and whether this individual has been seen before. In practice each is answered by its own specialist model, or by a field expert. Bio-VQA asks whether one generalist vision–language model (VLM) can answer all four.
Bio-VQA holds 1,861,608 questions over 216,715 images from 11 public datasets, organized into four components and 24 tasks. Every question is generated only where an existing annotation supplies the ground truth, so every answer can be checked against its source. Every task is bounded by an image-blind floor and, where one exists, by a domain-specialist ceiling. Scoring is graded, so a near miss counts for more than a distant one, and each graded score is reported next to the exact match it modifies.
| Component | What it asks | Tasks | Images | Questions | Source | Code | |
|---|---|---|---|---|---|---|---|
| C1 | Hierarchical taxonomic reasoning | Which taxon, at eight ranks? | 9 | 100,000 | 890,000 | TreeOfLife-200M | 1.Hierarchical_taxonomic_reasoning/ |
| C2 | Fine-grained attribute grounding | Which trait, on which part, on which side? | 4 | 23,576 | 824,104 | CUB-200-2011 | 2.Fine-grained_attribute_grounding/ |
| C3 | Quantitative spatial reasoning | How many, how far, where, facing where? | 8 | 78,139 | 132,504 | 8 datasets | 3.Quantitative_spatial_reasoning/ |
| C4 | Individual re-identification | Is this the same animal? | 3 | 15,000 | 15,000 | 5 wildlife catalogs | 4.Individual_reidentification/ |
| Total | 24 | 216,715 | 1,861,608 | 11 datasets |
C3 draws on WAID, Boxes on Bees, 2018-NEON-Beetles and DePondFi, and also on four of the C4 catalogs (WhaleSharkID, HyenaID, LeopardID, GZCD) for localization and viewpoint. That is why the component sources add up to more than 11.
Where to find what
| You want to… | Go to |
|---|---|
| See figures, examples and the leaderboard | 🌐 Project page |
| Download the questions, images, Lite subset or model answers | 🤗 Hugging Face dataset card |
| Regenerate the questions, run a model, or score a model | 💻 This repository (Pipeline, Quick start) |
| Read the method and full analysis | 📄 The paper (Citation) |
- Quick start
- The data at a glance
- Repository layout
- Pipeline
- Environment
- Evaluation protocol
- Metrics
- Results
- Reproducibility
- Limitations
- License
- Citation
- References
Bio-VQA-Lite is a stratified sample of 500 questions per task, 12,000 in total. It is drawn with a fixed seed and is meant for cheap evaluation and for development. Details are on the dataset card.
from datasets import load_dataset
lite = load_dataset("imageomics/Bio-VQA", "lite") # C1.csv, C2.csv, C3.csv, C4.csv
print(lite)# Read one image that is stored inside a zip shard (C2 marker renders, C3, C4)
import io, zipfile
from huggingface_hub import hf_hub_download
from PIL import Image
def load_image(component, image_zip, image_in_zip):
path = hf_hub_download("imageomics/Bio-VQA", f"{component}/{image_zip}", repo_type="dataset")
with zipfile.ZipFile(path) as z:
return Image.open(io.BytesIO(z.read(image_in_zip))).convert("RGB")C1 images come from TreeOfLife-200M and C2 photographs come from CUB-200-2011. Neither is re-hosted. See
Images on the dataset card, and
Release/fetch_c1_images.py for C1.
Every scorer in this repository reads a question file that has one extra column named <model>_answer. That column
holds your model's raw, unparsed reply. Parsing and normalization happen inside the scorer, and they are the same for
every model.
# 1) append a column <mymodel>_answer to the component question file(s)
# 2) run that component's scorer
python 1.Hierarchical_taxonomic_reasoning/Evaluation/Evaluate_build_synonyms.py ... # once, before C1 scoring
python 1.Hierarchical_taxonomic_reasoning/Evaluation/Evaluate_run.py --base_dir <dir with C1 csvs> --parquet <ToL catalog> --synonyms <synonym map>
python 2.Fine-grained_attribute_grounding/Evaluation/evaluate.py --base_dir <dir with C2 csvs>
python 3.Quantitative_spatial_reasoning/Reasoning_Tasks/<Task>/3.Evaluate/evaluate.py --results_dir <dir>
python 4.Individual_reidentification/Evaluation/Evaluate.py --base_dir <C4 root>Each Evaluation/ or 3.Evaluate/ folder has a README with every flag spelled out. C1 note: build the synonym map
first. Without it, soft match silently falls back to hard match and no error is raised.
Each component has one runner script per model (Runs/, Experiment-Runs/, 2.Experiment_Runs/, Experiment_Runs/).
The launch commands are written out in each runner folder's README. See Pipeline and
Environment.
The predictions/ folder on Hugging Face holds the per-item answers of all 18 models and both specialists, exactly as
scored in the paper. Point a scorer at those files to regenerate any table.
This is a short summary. The dataset card has the full description, file layout, column reference and licensing.
| Component | Task | Format | Questions | Ground truth from |
|---|---|---|---|---|
| C1 | phylum · class · order · family · genus · species epithet · scientific name · common name | open-ended | 790,000 | TreeOfLife-200M lineage (GBIF Backbone) |
| C1 | common name, 4-way multiple choice | MCQ | 100,000 | same image and target as the open-ended common name |
| C2 | morphological attributes (attr_bare_value) |
MCQ | 280,433 | CUB-200-2011 attributes |
| C2 | relative salience (attr_group_value) |
MCQ | 321,073 | CUB-200-2011 attributes |
| C2 | anatomical localization (marker_localization, visibility_partset, visibility_side) |
MCQ | 165,032 | CUB part locations, rendered markers |
| C2 | naming (category_mcq, open_common_name, open_scientific_name, open_genus, open_kind_of) |
MCQ + open | 57,566 | CUB class labels |
| C3 | counting | integer | 53,498 | instance annotations, all ten subsets |
| C3 | relative counting | 1 of 4 panels | 42,412 | instance annotations, all ten subsets |
| C3 | absolute distance | number (cm) | 14,108 | NEON beetle trait + scalebar measurements |
| C3 | relative distance | 1 of 4 specimens | 3,976 | NEON beetle trait measurements |
| C3 | localization | 4 integers (box) | 3,988 | wildlife-catalog bounding boxes |
| C3 | relative position | direction | 1,000 | NEON beetle tray layout |
| C3 | viewpoint | 1 of 10 orientations | 13,000 | wildlife-catalog viewpoint labels |
| C3 | OCR (negative control) | string | 522 | NEON barcode labels |
| C4 | easy · random · hard pairing, 5 species | Yes / No | 15,000 | catalog individual IDs |
C1 asks the reptiles group seven rank questions, not eight, because GBIF has no order rank for Squamata. So that group contributes 8 question types instead of 9.
Bio-VQA/
├── README.md ← you are here
├── requirements.txt ← shared environment (see "Environment")
├── LICENSE ← MIT, code only
│
├── 1.Hierarchical_taxonomic_reasoning/ ← C1
│ ├── README.md
│ ├── Tree-of-Life-200M/ ← data: download.py · verify.py · generateQA.py · stat.py
│ │ └── Resolve_common_names/ ← non-English common names → English (iNaturalist, Wikidata)
│ ├── Runs/ ← 18 runners: run_<model>.py
│ ├── Post-run/ ← Merge_csv_chunks.py · Fix_Llama_Answers.py · Assign_difficulty/
│ └── Evaluation/ ← Evaluate_build_synonyms.py · Evaluate_check_synonyms.py · Evaluate_run.py
│ run_pyBioCLIP.py · prefetch_pybioclip.py (BioCLIP-2 ceiling)
│
├── 2.Fine-grained_attribute_grounding/ ← C2
│ ├── README.md
│ ├── Data-Preparation/ ← 1.preprocess.py · 2.prepareQA.py · 3.stat.py · taxon_name_mapping.json
│ ├── Experiment-Runs/ ← per-family runners: run_qwen.py · run_InternVL.py · run_gemma.py · …
│ └── Evaluation/ ← evaluate.py (CAGS) · evaluate_soft.py · sensitivity_sweep.py
│ └── Human Study/ ← 306-item, 3-annotator validation of CAGS
│
├── 3.Quantitative_spatial_reasoning/ ← C3
│ ├── README.md
│ ├── Datasets/ ← Aerial/ (WAID) · Bees/ · Beetles/ · Fish/ (DePondFi) · Zebra/ (GZCD)
│ └── Reasoning_Tasks/
│ ├── Counting/ ├── Counting_Relative/ ├── Distance_Absolute/ ├── Distance_Relative/
│ ├── Localization/ ├── Relative_Position/ ├── Viewpoint/ └── OCR/
│ └── <task>/ 1.Generate_QA/ → 2.Experiment_Runs/ (Preprocess/ + 18 runners) → 3.Evaluate/
│
├── 4.Individual_reidentification/ ← C4
│ ├── README.md
│ ├── Data_Preparation/ ← download.py · extract_embeddings.py (DINOv2) · generate_QA.py
│ ├── Experiment_Runs/ ← 18 VLM runners + megadescriptor.py (specialist)
│ └── Evaluation/ ← Evaluate.py (accuracy, d′, c, bootstrap CIs)
│
└── Release/ ← how the Hugging Face release was built
├── README.md
├── make_lite.py ← Bio-VQA-Lite (500 per task, seeded, stratified)
├── pack_images.py ← images → zip shards + image_zip / image_in_zip columns
└── fetch_c1_images.py ← fetch C1 images from TreeOfLife-200M source URLs
Each component folder and most subfolders have their own README with construction details, every command, and results. No shell scripts are committed; every launch command is written out in a README.
public dataset ──► 1. acquire & filter ──► 2. generate QA ──► 3. preprocess / shard ──► 4. inference (18 VLMs + specialist)
(annotations) (download, verify, (seeded; only (manifest, row_id, (greedy, one attempt,
resolve names) where GT exists) pre-run audit) raw string stored)
│
6. tables & figures ◄── 5. score (one scorer per component; floors, graded metrics, CIs) ◄┘
Every component follows these six stages. The folder names differ a little between components (shown below), but what each stage does is the same.
| Stage | C1 | C2 | C3 (per task) | C4 |
|---|---|---|---|---|
| 1 Acquire | Tree-of-Life-200M/download.py, verify.py, Resolve_common_names/ |
CUB-200-2011 official release | Datasets/<corpus>/download.py, preprocess.py |
Data_Preparation/download.py |
| 2 Generate QA | Tree-of-Life-200M/generateQA.py |
Data-Preparation/1.preprocess.py → 2.prepareQA.py |
1.Generate_QA/generateQA*.py |
extract_embeddings.py → generate_QA.py |
| 3 Preprocess | chunked manifests | — | 2.Experiment_Runs/Preprocess/split_qa.py, stats.py |
— |
| 4 Inference | Runs/run_<model>.py |
Experiment-Runs/run_<family>.py |
2.Experiment_Runs/<model>.py |
Experiment_Runs/<model>.py, megadescriptor.py |
| 4b Specialist | Evaluation/run_pyBioCLIP.py (BioCLIP-2: tol · kingdom · group) |
3-annotator human study | image-blind floors (in the scorer) | Experiment_Runs/megadescriptor.py |
| 5 Post-run | Post-run/Merge_csv_chunks.py, Fix_Llama_Answers.py, Assign_difficulty/ |
run_llama3.2_fix_answers.py |
3.Evaluate/merge_results.py |
— |
| 6 Score | Evaluation/Evaluate_build_synonyms.py → Evaluate_run.py |
Evaluation/evaluate.py, sensitivity_sweep.py |
3.Evaluate/evaluate.py |
Evaluation/Evaluate.py |
📁 1.Hierarchical_taxonomic_reasoning/ · 🤗 config C1_taxonomy
- Sample.
download.pyruns DuckDB queries over the TreeOfLife-200M catalog. It takes 10,000 images from each of 10 organismal groups (amphibians, angiosperms, arachnids, birds, bryophytes, fish, gymnosperms, insects, mammals, reptiles). Three constraints apply: (a) the lineage must be complete from phylum to species, with a common name; (b) the image must meet a minimum resolution (--min_size_kb); (c) there is a per-species cap (--images_per_species), so abundant species do not take over a group. The sample spans 626 families, 2,311 genera and 3,403 species — 6× VLM4Bio's genus coverage and 4× its species coverage. - Verify.
verify.pychecks that a manifest row exists if and only if its image is on disk and every rank the generator needs is non-null. - Resolve names. GBIF vernacular names are not filtered by language. They include Swedish, Danish and
Norwegian names.
Resolve_common_names/resolves every non-English common name to English against iNaturalist and Wikidata. - Generate QA.
generateQA.pyasks each image for its phylum, class, order, family, genus, species epithet, scientific name and common name. It also asks the common name a second time as 4-way multiple choice, with distractors drawn uniformly from taxa in the same class as the target. - Run. There are 18 runners in
Runs/. The BioCLIP-2 ceiling isEvaluation/run_pyBioCLIP.py, in three label-set configurations:tol(the full TreeOfLife-200M label set, used in the paper's main table),kingdomandgroup. - Post-run. Merge chunks, repair Llama-3.2 answer formatting, and assign Easy / Medium / Hard tiers by how common the target taxon is in TreeOfLife-200M (top third, middle third and bottom third by image count at each rank).
- Score. Exact match, soft exact match (any GBIF Backbone synonym of the target counts as correct, so Felis concolor = Puma concolor), Wu–Palmer, Lin similarity, and error severity.
📁 2.Fine-grained_attribute_grounding/ · 🤗 config C2_attributes
- Invert the attributes. CUB-200-2011 stores 312 binary attributes per image as part · property · value
(
has_wing_color::brown). Asking 312 sparse yes/no questions per image would be uninformative, since a constant no scores well. So1.preprocess.pyand2.prepareQA.pymerge each part and property into one question (What is the wing color?) and take the marked value as the answer. Annotator certainty is used to select and filter candidate traits. - Distractors. These are other values attested for the same part and property. Any value that is also true of the image is excluded, so exactly one option is correct.
- Marker localization. A marker is rendered onto each of the 11,788 images, and the question asks which body part it marks. Two controlled distractors are added: one shares the marker's color but not its shape, the other shares its shape but not its color. The model has to bind both cues to answer. The renders double the image count to 23,576.
- Ten question families in four categories. See the data at a glance.
- Score. CAGS (chance-adjusted graded score), using CIEDE2000 color distance for colors and annotation
co-occurrence for parts. It is 0 at chance and 1 at perfect for any number of options.
sensitivity_sweep.pyreruns the ranking under 11 kernel and hyperparameter settings.Human Study/holds the 306-item, 3-annotator validation.
📁 3.Quantitative_spatial_reasoning/ · 🤗 config C3_spatial
The tasks follow AVA-Bench's decomposition of spatial reasoning into atomic skills, so a failure can be traced to a specific ability. The source datasets are aggregated into ten 500-image subsets. These are count-stratified, so sparse and dense scenes are balanced, and images whose annotation completeness cannot be verified are dropped. Each task runs only where its ground truth exists:
| Task | Folder | Runs on | Answer form | Metric | Floor (image-blind) |
|---|---|---|---|---|---|
| Counting | Reasoning_Tasks/Counting/ |
all ten subsets; Easy / Medium / Hard canvas tiers | integer | CAS, macro-averaged over subsets | modal count |
| Relative counting | Reasoning_Tasks/Counting_Relative/ |
all ten subsets; same- and different-dataset panels | 1 of 4 | balanced accuracy | chance |
| Absolute distance | Reasoning_Tasks/Distance_Absolute/ |
NEON beetles (scalebar) | cm | share within 20% | one constant per measurement type |
| Relative distance | Reasoning_Tasks/Distance_Relative/ |
NEON beetles | 1 of 4 | balanced accuracy | chance |
| Localization | Reasoning_Tasks/Localization/ |
wildlife catalogs (Easy tier) | box | mean IoU (unparsed = 0) | mean gold box |
| Relative position | Reasoning_Tasks/Relative_Position/ |
NEON beetle trays | direction | balanced accuracy | chance (.250) |
| Viewpoint | Reasoning_Tasks/Viewpoint/ |
wildlife catalogs | 1 of 10 | agreement over gold labels | majority class |
| OCR (control) | Reasoning_Tasks/OCR/ |
NEON barcode labels | string | exact match | — |
Every task folder has the same three stages: 1.Generate_QA/ → 2.Experiment_Runs/ (with Preprocess/split_qa.py
and the 18 runners) → 3.Evaluate/ (merge_results.py, evaluate.py). Within each task, the block marked
# HARNESS is byte-identical across the 18 runners. You can check this:
cd 3.Quantitative_spatial_reasoning/Reasoning_Tasks/Counting/2.Experiment_Runs
for f in *.py; do sed -n '/^# HARNESS/,$p' "$f" | md5sum; done | sort -u | wc -l # prints 1Counting tiers. Every counting canvas has the same pixel budget. Easy fills the canvas with one image. Medium splits it into two panels from different datasets. Hard splits it into two panels from the same dataset. OCR is a designed negative control: locating the label is spatial, but the answer depends on transcription.
📁 4.Individual_reidentification/ · 🤗 config C4_reidentification
- Catalogs. WhaleSharkID (spot pattern), BelugaID (scarring, dorsal ridge), HyenaID (spot pattern), LeopardID (rosettes) and GZCD Grevy's zebra (stripes).
- Embed.
extract_embeddings.pycomputes DINOv2 embeddings. Retrieval runs within viewpoint groups, because viewpoint dominates the embedding space. - Pair (
generate_QA.py, seeded). Each catalog gives 1,000 balanced pairs per condition (500 same and 500 different), and same-individual pairs are drawn first because they are scarce.- Easy: a same pair is an animal with its nearest match; a different pair is two animals that look nothing alike. Appearance and identity agree.
- Random: both pairs are drawn without using appearance, so appearance carries no signal.
- Hard (adversarial): a different pair is two nearest neighbors; a same pair is an animal with its furthest sighting. Appearance and identity disagree.
- Ask. The two photographs are placed side by side on one canvas, and the question is: "This image shows two images placed side by side. Is the main subject in the left image the very same individual animal as the main subject in the right image?" The runner adds "Answer with one word: Yes or No. Do not explain." The prompt never reveals that the set is balanced.
- Specialist.
megadescriptor.pyruns MegaDescriptor on Grevy's zebra. - Score.
Evaluate.pyreports accuracy and d′ / criterion c from signal detection theory, with a log-linear correction, plus 95% bootstrap CIs (2,000 resamples per cell), balanced accuracy, MCC and Cohen's κ.
📁 Release/ — the scripts that built the Hugging Face release:
| Script | What it does |
|---|---|
make_lite.py |
Builds Bio-VQA-Lite: 500 questions per task (24 tasks, 12,000 total). Strata: organismal group (C1), question family (C2), source dataset × tier × subset (C3), species × answer (C4). Seeded; model-answer columns are dropped. |
pack_images.py |
Packs the images a question file refers to into zip shards, and adds image_zip / image_in_zip columns. With --rename, C4 images get neutral names (img_000001.png, …), because the original names encode the label. |
fetch_c1_images.py |
Downloads the C1 images from the TreeOfLife-200M source_url of each row and saves them as <uuid>.<ext>. |
All 18 models run in one shared Python 3.12 environment (requirements.txt). The one exception
is Molmo2-8B: AI2 ships Molmo2 as custom code pinned to transformers==4.57.1, so it has its own environment.
# shared environment (17 models, data preparation, scoring)
python3.12 -m venv bio-vqa && source bio-vqa/bin/activate
pip install -r requirements.txt
# Molmo2-8B only
python3.12 -m venv bio-vqa-molmo2 && source bio-vqa-molmo2/bin/activate
pip install -r requirements.txt "transformers==4.57.1"Hardware. C1 image download is network- and I/O-bound, so use CPU nodes. Inference needs one H100-class GPU per
job; the 30B–38B models need two. Some runner READMEs show SLURM launch lines that build a per-job virtual environment
in $TMPDIR. That is a scheduling convenience; it installs the same packages.
The exact checkpoint of each model is listed in the supplementary material (Table S2) and in each runner's
MODEL BLOCK. Examples: Qwen/Qwen3-VL-32B-Instruct, OpenGVLab/InternVL3-38B-Instruct, google/gemma-3-12b-it,
allenai/Molmo2-8B, mistral-community/pixtral-12b, microsoft/Phi-3.5-vision-instruct,
meta-llama/Llama-3.2-11B-Vision-Instruct, llava-hf/llava-v1.6-vicuna-7b-hf, llava-hf/llava-v1.6-mistral-7b-hf.
| Setting | Value |
|---|---|
| Decoding | greedy (do_sample=False) |
| Attempts per item | one |
| Chain-of-thought / reasoning mode | none |
| Few-shot demonstrations | none |
| Question and answer-format instruction | the same for every model within a question family |
| Example answer in the format instruction | yes for C1 and for six of the eight C3 tasks (counting, absolute distance, localization, relative position, viewpoint, OCR) — e.g. "e.g., Arthropoda", "If you count seven, respond: 7". The exact strings are in the supplement, §S10. |
| Model-specific wrapping | each model's own chat template; Gemma receives the instruction as a system message; InternVL adds an English-answer prefix |
| Scoring | one scorer per component, the same for every model |
| Reported alongside | parse rate and letter–text mismatch rate, so a formatting failure is never read as a knowledge error |
The 18 models span 3.75B–38.4B parameters across eleven families: Qwen2.5-VL (3B, 7B), Qwen3-VL (8B, 30B-A3B MoE, 32B), InternVL3 (8B, 38B), InternVL3.5 (8B, 30B-A3B MoE, 38B), Gemma-3-12B, Gemma-4-12B, Molmo2-8B, Pixtral-12B, Phi-3.5-Vision, Llama-3.2-11B-Vision, and LLaVA-NeXT (Vicuna-7B, Mistral-7B).
Specialists. BioCLIP-2 for C1, which is trained on TreeOfLife-200M and ranks a closed label set, so treat it as an optimistic upper bound. MegaDescriptor for C4, on Grevy's zebra.
Exact match is reported for every task. Every graded metric is reported next to the exact match it modifies, so no claim rests on the graded score alone.
| Component | Graded metric | What it fixes |
|---|---|---|
| C1 | Wu–Palmer, Lin, soft EM (synonyms), severity | On a warbler, Turdidae is a near miss and Fungi is wrong by far; exact match scores them the same. |
| C2 |
CAGS: |
Answer spaces have structure (red is closer to brown than green is) and uneven size (3 options for bill length, 15 for color). |
| C3 |
CAS: |
14 beetles for 15 beats 20 for 15; and a score means nothing without knowing what a blind guess gets. |
| C4 |
d′ |
A model answering yes to everything scores 50% accuracy. |
A lift of 0 means the model does no better than an image-blind rule; negative lift means it does worse. Two C3 tasks (localization and absolute distance) have field means below their floors.
18 models × 24 tasks (Table 2 of the paper). Bold marks the best of the 18 models in each column.
| # | Model | phy | cls | ord | fam | gen | spc | sci | com | sal | mrp | loc | nam | cnt | rcnt | adst | rdst | lcl | rpos | view | ocr | d′ | acc |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| BioCLIP-2 (tol) ¹ | .925 | .874 | .821 | .775 | .691 | .545 | .544 | .500 | — | — | — | — | — | — | — | — | — | — | — | — | — | — | |
| MegaDescriptor ² | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | .733 | .683 | |
| 1 | Qwen3-VL-32B | .831 | .615 | .712 | .612 | .444 | .066 | .244 | .078 | .584 | .644 | .475 | .731 | .789 | .555 | .622 | .443 | .866 | .550 | .427 | .900 | .696 | .636 |
| 2 | Qwen3-VL-30B-A3B | .864 | .731 | .757 | .612 | .417 | .072 | .221 | .107 | .558 | .631 | .453 | .658 | .795 | .483 | .528 | .423 | .861 | .355 | .391 | .979 | .518 | .602 |
| 3 | InternVL3-38B | .911 | .683 | .638 | .484 | .355 | .054 | .189 | .044 | .562 | .645 | .413 | .669 | .799 | .567 | .367 | .363 | .744 | .205 | .373 | .105 | .463 | .581 |
| 4 | Gemma-4-12B | .880 | .686 | .578 | .363 | .183 | .021 | .065 | .043 | .592 | .621 | .431 | .374 | .753 | .563 | .385 | .443 | .589 | .495 | .331 | .345 | .351 | .567 |
| 5 | Qwen3-VL-8B | .887 | .680 | .720 | .589 | .406 | .046 | .202 | .065 | .531 | .624 | .441 | .643 | .739 | .414 | .303 | .345 | .862 | .421 | .373 | .711 | .492 | .572 |
| 6 | InternVL3.5-38B | .746 | .636 | .624 | .363 | .271 | .038 | .128 | .025 | .559 | .638 | .375 | .536 | .765 | .504 | .503 | .360 | .412 | .219 | .340 | .192 | .258 | .542 |
| 7 | Molmo2-8B | .823 | .563 | .469 | .286 | .137 | .021 | .038 | .016 | .503 | .643 | .474 | .330 | .623 | .416 | .290 | .358 | .055 | .457 | .483 | .692 | .491 | .578 |
| 8 | Qwen2.5-VL-7B | .763 | .504 | .673 | .541 | .420 | .047 | .269 | .062 | .541 | .580 | .356 | .713 | .724 | .410 | .334 | .337 | .308 | .213 | .395 | .916 | .442 | .541 |
| 9 | InternVL3.5-30B-A3B | .486 | .469 | .545 | .310 | .240 | .034 | .118 | .024 | .537 | .609 | .350 | .539 | .727 | .489 | .378 | .333 | .289 | .252 | .309 | .188 | .568 | .612 |
| 10 | InternVL3-8B | .827 | .497 | .478 | .322 | .262 | .032 | .124 | .020 | .508 | .584 | .346 | .581 | .738 | .320 | .297 | .304 | .246 | .203 | .335 | .314 | .684 | .601 |
| 11 | InternVL3.5-8B | .819 | .531 | .421 | .266 | .191 | .023 | .077 | .015 | .495 | .603 | .372 | .457 | .747 | .408 | .263 | .299 | .236 | .224 | .264 | .460 | .236 | .544 |
| 12 | Gemma-3-12B | .790 | .688 | .626 | .429 | .225 | .048 | .093 | .047 | .466 | .551 | .410 | .511 | .606 | .415 | .352 | .280 | .329 | .145 | .235 | .352 | .120 | .505 |
| 13 | Qwen2.5-VL-3B | .416 | .457 | .477 | .454 | .358 | .040 | .206 | .064 | .427 | .500 | .389 | .661 | .640 | .321 | .194 | .300 | .307 | .110 | .230 | .904 | .655 | .559 |
| 14 | Pixtral-12B | .688 | .501 | .530 | .349 | .187 | .029 | .079 | .027 | .447 | .495 | .320 | .465 | .599 | .352 | .307 | .304 | .229 | .266 | .246 | .065 | .119 | .519 |
| 15 | LLaVA-NeXT-Vicuna | .662 | .343 | .290 | .100 | .028 | .003 | .015 | .003 | .457 | .454 | .364 | .198 | .510 | .250 | .217 | .250 | .701 | .125 | .187 | .000 | .000 | .500 |
| 16 | Phi-3.5-Vision | .748 | .359 | .267 | .191 | .066 | .013 | .023 | .009 | .454 | .533 | .154 | .217 | .613 | .316 | .198 | .256 | .030 | .160 | .221 | .044 | .562 | .576 |
| 17 | Llama-3.2-Vision | .545 | .482 | .518 | .434 | .234 | .031 | .104 | .054 | .317 | .483 | .286 | .520 | .724 | .286 | .260 | .317 | .061 | .125 | .250 | .722 | .000 | .500 |
| 18 | LLaVA-NeXT-Mistral | .364 | .392 | .408 | .162 | .029 | .005 | .015 | .004 | .372 | .484 | .259 | .238 | .616 | .259 | .332 | .250 | .089 | .131 | .173 | .000 | .476 | .508 |
| Mean | .725 | .545 | .541 | .382 | .247 | .035 | .123 | .039 | .495 | .574 | .370 | .502 | .695 | .407 | .341 | .331 | .401 | .259 | .309 | .438 | .396 | .558 | |
| Floor | .500 | .100 | .111 | .060 | .035 | .005 | .001 | .011 | .000 | .000 | .000 | .000 | .501 | .250 | .410 | .250 | .415 | .250 | .170 | .000 | .000 | .500 |
Columns. C1 (exact match): phylum, class, order, family, genus, species epithet, scientific name, common name (open-ended). C2 (CAGS): relative salience, morphological attributes, anatomical localization, naming. C3: counting (CAS), relative counting, absolute distance (share within 20%), relative distance, localization (mean IoU), relative position, viewpoint, ocr (exact match). C4: d′ and accuracy under random pairing. Floor is the score an image-blind rule reaches; for C1 it is the most frequent taxon at each rank. CAGS and d′ are chance-corrected, so their floors are zero. ¹ Domain specialist for taxonomy, full TreeOfLife-200M label set. ² Domain specialist for re-identification, on Grevy's zebra only.
Per-item answers for every cell are in predictions/ on
Hugging Face. Leaderboards with confidence intervals, per-group,
per-tier and per-dataset breakdowns are in each component README and in the supplement.
General visual capabilities do not transfer to biological organisms, and scale does not close the gap. The failures below hold across a tenfold range of model size (3.75B → 38.4B).
| Finding | Number |
|---|---|
| Exact match, mean of 18 models: phylum → class → family → genus → scientific name | .725 → .545 → .382 → .247 → .123 (falls to one sixth) |
| Best model vs BioCLIP-2 (tol), class | .731 vs .874 (1.2×) |
| Best model vs BioCLIP-2 (tol), scientific name | .269 vs .544 (2.0×) |
| Common name, open-ended vs 4-way MCQ, same images and targets | .039 vs .645 (16.4×): models recognize names they cannot recall |
| InternVL3 8B → 38B gain, class vs scientific name | +18.7 vs +6.5 points (InternVL3.5: +10.5 vs +5.0) |
| Exception to the scaling pattern | Qwen3-VL 8B → 32B: class .680 → .615, scientific name .202 → .244 |
| Models below the image-blind floor at phylum (Chordata for everything = .500) | 3 (InternVL3.5-30B .486, Qwen2.5-VL-3B .416, LLaVA-NeXT-Mistral .364) |
| Finding | Number |
|---|---|
| Mean CAGS: morphological · naming · relative salience · anatomical localization | .574 · .502 · .495 · .370 |
| Hardest families | part-set visibility .341, laterality .411 |
| Laterality, given the correct part | 17 of 18 models at or below chance; 9 significantly below |
| Mirror confusion | 21.8% – 54.0% vs a 20% baseline; rises with model strength (ρ = .75) |
| The one exception | Molmo2-8B (pointing-supervised): laterality .746, +.220 over the next model |
| CAGS robustness | ρ ≥ .996 across the base grid of 11 settings; human agreement .908 of the inter-annotator rate; AUC .676 on EM = 0 items |
| Finding | Number |
|---|---|
| Localization: mean IoU vs mean-gold-box floor | .401 vs .415; 12 of 18 below the floor; only Qwen3-VL-32B / 8B / 30B (.866 / .862 / .861) find the animal reliably |
| Absolute distance: models below a one-constant-per-type floor (.410) | 15 of 18; only Qwen3-VL-32B (.622), Qwen3-VL-30B (.528), InternVL3.5-38B (.503) beat it |
| Counting: CAS mean vs floor | .695 vs .501 (best InternVL3-38B .799); exact match never exceeds .242 |
| Counting, everyday vs biological, same 2–10 range | Qwen3-VL-32B 94.9% exact on CountBench vs 41.7% on single-image Bio-VQA items (2.3× lower) |
| Relative tasks vs floor | relative counting .407 vs .250; relative distance .331 vs .250; relative position .259 vs .250 (chance) |
| OCR as negative control | the 7 spatial tasks inter-correlate at mean ρ = +.703; none correlates with OCR |
| Finding | Number |
|---|---|
| MegaDescriptor vs VLM mean, Grevy's zebra, random pairing | d′ .733 vs .391 (1.9×); easy pairing 2.055 vs 1.346 (1.5×). The two strongest VLMs, Qwen3-VL-30B (1.088) and Qwen3-VL-32B (.931), exceed it on this dataset. |
| Hard (adversarial) pairing | 17 of 18 models have negative d′ (−.932 to −.091); MegaDescriptor −.969 |
| Difficulty ordering easy ≥ random ≥ hard | holds in 77 of 90 model × dataset cells (chance of a monotone order: 1/6) |
| Response bias | criterion c < 0 for 17 of 18 models, and it grows more negative as pairs get harder: models say yes more as the task gets harder |
| Spearman ρ (18 models) | C1 | C2 | C3 | C4 |
|---|---|---|---|---|
| C1 (α .981) | — | .689 | .787 | .433† |
| C2 (α .901) | — | .927 | .514† | |
| C3 (α .925) | — | .610 | ||
| C4 (α .889) | — |
† not significant after Holm correction. At n = 18 the confidence intervals are wide (median width .66).
- Tasks agree more within a component than across components: mean ρ .749 vs .534 (label permutation, p = .0005). Internal agreement is .841 for C1, .662 for C3, .645 for C2 and .617 for C4.
- C4 stands alone. Knowing how well a model names an organism says nothing about whether it can tell two individuals of that organism apart.
- C2 and C3 overlap (ρ = .927). Both ask a model to find something fine-grained. They are reported separately because they diagnose different failures, but they should not be treated as independent evidence.
- A strong model is strong everywhere; below the top, rankings reorder. One factor explains 62.2% of the variance. InternVL3-38B, Qwen3-VL-30B and Qwen3-VL-32B are top five in every component. The median model moves 5.5 of 18 places between components (Phi-3.5-Vision: 8th percentile on C1, 64th on C4).
| Stage | Deterministic? | Mechanism |
|---|---|---|
| C1 image download | ❌ | Thread interleaving decides which concurrent downloads fill the per-group budget. The released manifests (TreeOfLife-200M uuid per row) are the artifact of record. |
| QA generation | ✅ | Seeded per component |
| Manifest sharding | ✅ | --seed 42, applied after row_id assignment |
| Inference | ✅ | Greedy decoding, one attempt per item |
| Difficulty tiers | ✅ | Deterministic; ties broken by taxon name |
| Scoring | ✅ | A pure function of the merged prediction files; bootstraps use fixed seeds |
| Bio-VQA-Lite | ✅ | Release/make_lite.py --seed 0 |
Given a manifest, everything downstream reproduces exactly. Use the released question files rather than expecting to regenerate the C1 image set byte for byte.
- Open-weight models only; we cannot say whether proprietary models (e.g. GPT-5) behave the same way.
- One decoding protocol (zero-shot, greedy, no chain-of-thought). Reasoning modes may score higher.
- Images come from public datasets that a model may have seen in pretraining, including BioCLIP-2's training corpus for C1.
- No human performance reference. Human raters validate C2 scoring only; C1, C3 and C4 ground truth have no human audit.
- Floors are rule-based; a text-only VLM may set a higher one.
- Two models (Molmo2-8B, Phi-3.5-Vision) mostly copy the example box on localization.
- Species-epithet answers are truncated in the released runs, so species results are analyzed using the scientific name.
- The CAGS anatomy kernel over-credits laterality confusions.
- Localization is evaluated on the Easy tier (3,988 items).
- Code in this repository: MIT.
- Benchmark annotations (questions, answers, Lite, predictions) on Hugging Face: CC BY-NC 4.0.
- Images keep the license of their source dataset. See the dataset card for per-source terms. Check them before redistributing any image.
If you use Bio-VQA, please cite:
@inproceedings{rayeed2027biovqa,
title = {How Finely Can Vision--Language Models See Biology? {Bio-VQA}: A Benchmark for Taxonomic, Morphological, Spatial and Individual Reasoning},
author = {Rayeed, S M and Ma, Qian and Stewart, Charles V. and Ma, Yao},
booktitle = {Proceedings of the IEEE/CVF Winter Conference on Applications of Computer Vision (WACV)},
year = {2027}
}Links: 🌐 Project page · 🤗 Dataset · 💻 Code
Every source dataset, baseline, model, metric and benchmark referenced by
Bio-VQA or by any component README. The key column is the BibTeX key used in
the paper, so entries can be cross-referenced against the manuscript's .bib
directly.
All source imagery retains its original license. This repository distributes code only; the benchmark data are on Hugging Face. Verify licensing before redistributing any downloaded imagery.
Eleven public datasets supply every image and every ground-truth annotation. A question is generated only where an existing annotation supplies the answer.
| Dataset | Key | Used by |
|---|---|---|
| TreeOfLife-200M | stevens2025bioclip2 |
C1 — 100K image subset, 10 organismal groups |
| CUB-200-2011 | wah2011caltech |
C2 — 11,788 images, 312 binary attributes |
| WAID | waid2023 |
C3 — aerial wildlife: camel, cattle, kiang, seal, sheep, zebra |
| Boxes on Bees and Pollen | boxesonbees |
C3 — dense hive frames |
| 2018-NEON-beetles | neonbeetles |
C3 — specimen trays with scalebars |
| DePondFi | depondfi |
C3 — pond fish |
| GZCD | gzcd |
C3 + C4 — Grevy's zebra |
| WhaleSharkID | whalesharkid |
C3 + C4 — spot pattern |
| BelugaID | belugaid |
C4 — scarring, dorsal ridge |
| HyenaID | hyenaid |
C3 + C4 — spot pattern |
| LeopardID | leopardid |
C3 + C4 — rosette pattern |
BioCLIP-2 and MegaDescriptor are the measured ceilings for C1 and C4. DINOv2 is used for C4 pair mining, not as a baseline. The remaining entries are the re-identification literature the component situates itself against.
| Model | Key | Role |
|---|---|---|
| BioCLIP-2 | stevens2025bioclip2 |
C1 taxonomic ceiling |
| BioCLIP | stevens2024bioclip |
predecessor; tree-of-life scale contrastive |
| BioTrove-CLIP | biotrove2024 |
alternative biological encoder |
| MegaDescriptor | cermak2024wildlifedatasets |
C4 specialist baseline |
| DINOv2 | oquab2024dinov2 |
C4 pair mining by embedding similarity |
| MiewID | otarashvili2024miewid |
multi-species re-ID descriptor |
| HotSpotter | crall2013hotspotter |
hand-crafted local features for re-ID |
| PIE | moskvyak2019pie |
learned re-ID embeddings |
| ALFReID | nepovinnykh2024alfreid |
learned re-ID embeddings |
| TransReID | he2021transreid |
transformer re-ID |
Eighteen open-weight models from 3.75B to 38.4B parameters. Two of the 30B models are mixture-of-experts activating 3B parameters per token.
| Family | Key | Sizes evaluated |
|---|---|---|
| Qwen2.5-VL | qwen25vl |
3.75B, 8.3B |
| Qwen3-VL | qwen3vl |
8.8B, 30.5B MoE, 32.8B |
| InternVL3 | internvl3 |
8.1B, 38.4B |
| InternVL3.5 | internvl35 |
8.1B, 30.5B MoE, 38.4B |
| Gemma-3 | gemma3 |
12.2B |
| Gemma-4 | gemma4 |
12.2B |
| Molmo 2 | molmo2 |
8.0B, pointing-supervised |
| Pixtral | pixtral |
12.4B |
| Phi-3.5-Vision | phi35 |
4.2B |
| Llama-3.2-Vision | llama32 |
10.7B |
| LLaVA-NeXT | llavanext |
7.1B Vicuna, 7.6B Mistral |
Every graded metric is reported alongside the exact match it modifies.
| Method | Key | Used for |
|---|---|---|
| Wu–Palmer similarity | wu1994verb |
C1 — depth of the lowest common ancestor |
| Lin similarity | lin1998information |
C1 — information-content weighted |
| Open-ended taxonomic evaluation | ging2024openended |
C1 — hierarchical scoring precedent |
| Cohen's kappa | cohen1960coefficient |
C2/C3 — chance correction |
| Signal detection theory | green1966signal |
C4 — d-prime and criterion |
| Detection theory | macmillan2004detection |
C4 — d-prime and criterion |
| Log-linear correction | hautus1995 |
C4 — required when H or F reaches 0 or 1 |
| Labeled Faces in the Wild | lfw2007 |
C4 — the verification protocol |
| Element | Key | Setting |
|---|---|---|
| Greedy decoding | holtzman2020 |
no sampling |
| Prompt sensitivity | sclar2024 |
same question and format instruction for every model within a family |
| Chain-of-thought | wei2022cot |
explicitly NOT used |
| Few-shot prompting | brown2020few |
explicitly NOT used |
| Benchmark | Key | Relevance |
|---|---|---|
| VLM4Bio | vlm4bio2024 |
closest prior biological VQA |
| PlantExpertVQA | plantexpertvqa2025 |
crop diseases |
| J-EDI QA | jediqa2024 |
100 deep-sea images |
| AgroCoT | agrocot2025 |
agricultural chain-of-thought |
| AVA-Bench | avabench2026 |
atomic visual skills — the decomposition precedent |
| MMBench | liu2024mmbench |
general multi-task |
| SEED-Bench | li2023seedbench |
general multi-task |
| BLINK | fu2024blink |
general perception |
| MMVP | tong2024eyes |
visual patterns |
| CV-Bench / Cambrian | tong2024cambrian |
counting comparison |
| MM-Spatial | mmspatial2025 |
spatial reasoning; blind-baseline result |
| ScienceQA | lu2022scienceqa |
expert-domain VQA |
| MMMU | yue2024mmmu |
expert ceilings |
| MicroVQA | burgess2025microvqa |
microscopy |
| TallyQA | tallyqa2019 |
counting |
| CountBench | paiss2023countbench |
counting |
| VSR | liu2023vsr |
spatial relations |
| SpatialVLM | chen2024spatialvlm |
spatial reasoning |
| INQUIRE | vendrow2024inquire |
biodiversity retrieval |
| IUCN LLM evaluation | iucnllm2026 |
biodiversity, no imagery |
| Animal re-ID survey | animalreid2026 |
no VLMs reported |
| Resource | Key | Used for |
|---|---|---|
| GBIF Backbone | gbif2024 |
versioned snapshot; synonym map, accepted names |
| iNaturalist | inaturalist2024 |
common-name resolution to English |
| Wikidata | wikidata |
common-name resolution to English |
Bio-VQA · project page · dataset · images retain their original licenses