thedatasense/medicalvlm_attention_without_grounding

0

stars

1

commits

Python

primary language

Jun 13, 2026

updated

README

Attention Without Grounding: Causal Evaluation of Visual Explanations in Medical VLMs

Anonymized code release accompanying the submission. This repository reproduces the explanation-faithfulness audit: whether attention and saliency heatmaps from medical Vision-Language Models (VLMs) point to the image evidence a model actually uses, tested against radiologist annotations and causal perturbation.

All author-, institution-, and account-identifying information has been removed for double-blind review. Absolute paths appear as /path/to/... or read from environment variables.

What is here

scripts/cxr/        # evaluation pipeline
  run_counterfactuals.py        # 16x16 patch occlusion -> causal-importance maps; ROI-delete; mild-contrast
  run_method_vs_occlusion.py    # per-method saliency-vs-causal Spearman (raw attn, rollout, grad x attn, Winsor-CAM, integrated_gradients)
  run_rise_attribution.py       # RISE (model-agnostic perturbation saliency), grid-aligned to the causal map
  run_chexagent_roi_grounding.py# CheXagent ROI causal-grounding probe (separate conda env, see below)
  run_chexlocalize_eval.py      # pixel-mask attribution metrics (pointing-game, AMiM, pixel-AP)
  run_densenet_baseline.py      # DenseNet121-CXR Grad-CAM positive control
  run_resnet_baseline.py        # ResNet50-CXR Grad-CAM positive control
  run_qwen3_*.py                # Qwen3-VL cross-family probe
  run_llavarad_*.py             # LLaVA-RAD cross-family probe
  saliency.py                   # attribution methods incl. integrated_gradients
  data_loaders.py               # PadChest, CheXlocalize, VinDr-CXR loaders
  constants.py, metrics.py, model_loader.py, roi_masking.py
vlm_explain/           # Winsor-CAM and activation-capture helpers
results/cxr/        # cached outputs that back the paper's numbers (see "Results map")

Setup

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
  • Python >= 3.10, one A100-class GPU for the VLM runs.
  • The main pipeline uses transformers==4.57.
  • CheXagent only requires a separate environment pinned to transformers==4.40.0 (its modeling code asserts that version). Create it and point the runner at it:
    conda create -n chexagent python=3.10 && conda activate chexagent
    pip install "transformers==4.40.0" torch albumentations pillow tqdm numpy
    CUDA_VISIBLE_DEVICES=0 /path/to/conda/envs/chexagent/bin/python \
        scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill gray
    

Data

Set DATA_ROOT to the directory holding the datasets (default fallbacks point to ${DATA_ROOT}/...). Datasets are obtained from their original sources under their own licenses:

DatasetAccessUse
MIMIC-CXRcredentialed (PhysioNet)in-distribution sanity check
PadChestpublicbounding-box overlap, causal grounding
CheXlocalizepublicpixel-mask attribution
VinDr-CXRpublicsecond annotated grounding dataset
export DATA_ROOT=/your/datasets

Reproduce the paper's results

# 1) Patch-occlusion causal maps (PadChest; add --dataset vindr for VinDr-CXR)
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model base
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model targeted_lora
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model full_lora

# 2) Per-method saliency vs causal importance (adds integrated gradients)
python scripts/cxr/run_method_vs_occlusion.py --model base --methods integrated_gradients

# 3) RISE (model-agnostic perturbation saliency)
python scripts/cxr/run_rise_attribution.py --model base --max-samples 200 --n-masks 320

# 4) CheXagent ROI causal-grounding 2x2 (run in the chexagent env, see Setup)
python scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill gray --max-samples 500
python scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill blur --max-samples 300
python scripts/cxr/run_chexagent_roi_grounding.py --dataset vindr   --fill gray --max-samples 300
python scripts/cxr/run_chexagent_roi_grounding.py --dataset vindr   --fill blur --max-samples 300

# 5) Positive-control classifier baselines (Grad-CAM)
python scripts/cxr/run_densenet_baseline.py
python scripts/cxr/run_resnet_baseline.py

Results map (cached outputs in results/cxr/)

Paper claimFile
Integrated-gradients Spearman rho (per MedGemma variant)method_vs_occlusion_ig/<model>/summary.json
RISE near-uniform saliencyrise/<model>/summary.json
Patch-occlusion causal grounding (PadChest, VinDr)counterfactuals/<model>[ _vindr]/patch_occlusion/{per_case.jsonl,summary.json}
CheXagent ROI grounding 2x2 (dataset x fill)chexagent_roi_<dataset>[_<fill>]/summary.json

Per-patch causal-map .npy files are omitted for size; regenerate them with step 1.

Notes

  • results/.../summary.json carries bootstrap 95% confidence intervals (2000 resamples).
  • This is a research artifact for review. It is not a clinical tool.
  • Reproducibility provenance: if you regenerate result files, scrub any run-provenance metadata (e.g. embedded git commit hash) before re-hosting, since it can link back to a public repository.

Contributors

thedatasense

1 commits

thedatasense/medicalvlm_attention_without_grounding

0

stars

1

commits

Python

primary language

Jun 13, 2026

updated

README

Attention Without Grounding: Causal Evaluation of Visual Explanations in Medical VLMs

Anonymized code release accompanying the submission. This repository reproduces the explanation-faithfulness audit: whether attention and saliency heatmaps from medical Vision-Language Models (VLMs) point to the image evidence a model actually uses, tested against radiologist annotations and causal perturbation.

All author-, institution-, and account-identifying information has been removed for double-blind review. Absolute paths appear as /path/to/... or read from environment variables.

What is here

scripts/cxr/        # evaluation pipeline
  run_counterfactuals.py        # 16x16 patch occlusion -> causal-importance maps; ROI-delete; mild-contrast
  run_method_vs_occlusion.py    # per-method saliency-vs-causal Spearman (raw attn, rollout, grad x attn, Winsor-CAM, integrated_gradients)
  run_rise_attribution.py       # RISE (model-agnostic perturbation saliency), grid-aligned to the causal map
  run_chexagent_roi_grounding.py# CheXagent ROI causal-grounding probe (separate conda env, see below)
  run_chexlocalize_eval.py      # pixel-mask attribution metrics (pointing-game, AMiM, pixel-AP)
  run_densenet_baseline.py      # DenseNet121-CXR Grad-CAM positive control
  run_resnet_baseline.py        # ResNet50-CXR Grad-CAM positive control
  run_qwen3_*.py                # Qwen3-VL cross-family probe
  run_llavarad_*.py             # LLaVA-RAD cross-family probe
  saliency.py                   # attribution methods incl. integrated_gradients
  data_loaders.py               # PadChest, CheXlocalize, VinDr-CXR loaders
  constants.py, metrics.py, model_loader.py, roi_masking.py
vlm_explain/           # Winsor-CAM and activation-capture helpers
results/cxr/        # cached outputs that back the paper's numbers (see "Results map")

Setup

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
  • Python >= 3.10, one A100-class GPU for the VLM runs.
  • The main pipeline uses transformers==4.57.
  • CheXagent only requires a separate environment pinned to transformers==4.40.0 (its modeling code asserts that version). Create it and point the runner at it:
    conda create -n chexagent python=3.10 && conda activate chexagent
    pip install "transformers==4.40.0" torch albumentations pillow tqdm numpy
    CUDA_VISIBLE_DEVICES=0 /path/to/conda/envs/chexagent/bin/python \
        scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill gray
    

Data

Set DATA_ROOT to the directory holding the datasets (default fallbacks point to ${DATA_ROOT}/...). Datasets are obtained from their original sources under their own licenses:

DatasetAccessUse
MIMIC-CXRcredentialed (PhysioNet)in-distribution sanity check
PadChestpublicbounding-box overlap, causal grounding
CheXlocalizepublicpixel-mask attribution
VinDr-CXRpublicsecond annotated grounding dataset
export DATA_ROOT=/your/datasets

Reproduce the paper's results

# 1) Patch-occlusion causal maps (PadChest; add --dataset vindr for VinDr-CXR)
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model base
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model targeted_lora
python scripts/cxr/run_counterfactuals.py --mode patch_occlusion --model full_lora

# 2) Per-method saliency vs causal importance (adds integrated gradients)
python scripts/cxr/run_method_vs_occlusion.py --model base --methods integrated_gradients

# 3) RISE (model-agnostic perturbation saliency)
python scripts/cxr/run_rise_attribution.py --model base --max-samples 200 --n-masks 320

# 4) CheXagent ROI causal-grounding 2x2 (run in the chexagent env, see Setup)
python scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill gray --max-samples 500
python scripts/cxr/run_chexagent_roi_grounding.py --dataset padchest --fill blur --max-samples 300
python scripts/cxr/run_chexagent_roi_grounding.py --dataset vindr   --fill gray --max-samples 300
python scripts/cxr/run_chexagent_roi_grounding.py --dataset vindr   --fill blur --max-samples 300

# 5) Positive-control classifier baselines (Grad-CAM)
python scripts/cxr/run_densenet_baseline.py
python scripts/cxr/run_resnet_baseline.py

Results map (cached outputs in results/cxr/)

Paper claimFile
Integrated-gradients Spearman rho (per MedGemma variant)method_vs_occlusion_ig/<model>/summary.json
RISE near-uniform saliencyrise/<model>/summary.json
Patch-occlusion causal grounding (PadChest, VinDr)counterfactuals/<model>[ _vindr]/patch_occlusion/{per_case.jsonl,summary.json}
CheXagent ROI grounding 2x2 (dataset x fill)chexagent_roi_<dataset>[_<fill>]/summary.json

Per-patch causal-map .npy files are omitted for size; regenerate them with step 1.

Notes

  • results/.../summary.json carries bootstrap 95% confidence intervals (2000 resamples).
  • This is a research artifact for review. It is not a clinical tool.
  • Reproducibility provenance: if you regenerate result files, scrub any run-provenance metadata (e.g. embedded git commit hash) before re-hosting, since it can link back to a public repository.

Contributors

thedatasense

1 commits

Languages

Python

99.4%