Download examples/tutorials/attention_chefer.py from gexinh/vlm-probe: direct link, hf CLI and curl.
- Browser
- Download file 3.15 kB
-
https://huggingface.co/spaces/gexinh/vlm-probe/resolve/main/examples/tutorials/attention_chefer.py
- Command line
-
hf download hf://spaces/gexinh/vlm-probe/examples/tutorials/attention_chefer.py
-
curl -L -o attention_chefer.py https://huggingface.co/spaces/gexinh/vlm-probe/resolve/main/examples/tutorials/attention_chefer.py
3.15 kB
| from pathlib import Path | |
| import os | |
| from io import BytesIO | |
| from urllib.request import urlopen | |
| import numpy as np | |
| import torch | |
| from PIL import Image | |
| from transformers import AutoImageProcessor, ViTForImageClassification | |
| from vlmprobe import Prober, ClassScore | |
| from vlmprobe import visualization as viz | |
| import matplotlib.pyplot as plt | |
| # Install: pip install "vlmprobe[transformers,visualization]" | |
| # Set VLM_PROBING_MODEL to a local directory to avoid downloading this checkpoint. | |
| model_id = os.environ.get("VLM_PROBING_MODEL", "google/vit-base-patch16-224") | |
| device = os.environ.get("VLM_PROBING_DEVICE", "cuda:0" if torch.cuda.is_available() else "cpu") | |
| model = ViTForImageClassification.from_pretrained(model_id, attn_implementation="eager").to(device).eval() | |
| processor = AutoImageProcessor.from_pretrained(os.environ.get("VLM_PROBING_PROCESSOR", model_id)) | |
| probe = Prober(model, processor) | |
| # A raw COCO image, not a saved attention map or a previous model result. | |
| image_path = os.environ.get("VLM_PROBING_IMAGE") | |
| image = (Image.open(image_path) if image_path else Image.open(BytesIO(urlopen( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/coco_sample.png" | |
| ).read()))).convert("RGB") | |
| inputs = {k: v.to(device) for k, v in processor(images=image, return_tensors="pt").items()} | |
| with torch.no_grad(): | |
| logits = model(**inputs).logits | |
| target_id = int(logits[0].argmax()) # Choose once; keep fixed during attribution. | |
| metric = ClassScore(target_id, kind="logit") | |
| print("Fixed target:", target_id, model.config.id2label.get(target_id)) | |
| # Plot the actual processed image; its crop/resize aligns with the patch tokens. | |
| mean = torch.tensor(processor.image_mean)[:, None, None] | |
| std = torch.tensor(processor.image_std)[:, None, None] | |
| rgb = (inputs["pixel_values"][0].detach().cpu() * std + mean).clamp(0, 1) | |
| processed_image = Image.fromarray((rgb.permute(1, 2, 0).numpy() * 255).astype("uint8")) | |
| patch = model.config.patch_size | |
| grid_shape = tuple(int(n // patch) for n in inputs["pixel_values"].shape[-2:]) | |
| visual_positions = list(range(1, 1 + grid_shape[0] * grid_shape[1])) # CLS is 0. | |
| last = probe.describe()["methods"]["attention.profile"]["sites"][-1] | |
| output_dir = Path(os.environ.get("VLM_PROBING_OUTPUT", "outputs/attention-tutorial")) | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| method = probe.attention.dtd_lrp(method="transformer_attribution", start_layer=0, device=device) | |
| result = method.run(inputs["pixel_values"], target=target_id) | |
| print("Patch map:", result.tensors["patch_relevance"].shape) | |
| # The converted author-rule backend must keep the native classifier predictions. | |
| with torch.no_grad(): | |
| native_logits = model(**inputs).logits.cpu() | |
| torch.testing.assert_close(result.tensors["logits"], native_logits, rtol=1e-4, atol=1e-4) | |
| ax = viz.plot_attention_overlay( | |
| processed_image, result, tensor="patch_relevance", image_alpha=0.25, | |
| signed=bool((result.tensors["patch_relevance"] < 0).any()), | |
| title="Chefer CVPR 2021 Transformer Attribution", | |
| ) | |
| ax.figure.savefig(output_dir / "attention-chefer.png", dpi=160, bbox_inches="tight") | |
| result.save(output_dir / "attention-chefer") | |
| plt.show() | |