This repository contains a Vision-Language Model (VLM) for image captioning based on CLIP prefixes with an emphasis on practical explainability using a custom Grad-CAM over CLIP's visual transformer layers. The system pairs CLIP as the vision backbone and OPT-125M as the language model, bridged by a transformer mapper that projects CLIP image features into a sequence of prefix tokens consumed by the language model, using the Prexif Tuning, A PEFT (Parameter Efficient Tuning) technique.
Explainability visualizations highlight where the model focused when preferring one caption over another. A core contribution of this work is an automatic dataset labeling pipeline driven by CLIP: the model synthesizes training captions from top-k prompt probabilities and uses them to train the captioner end-to-end without manual labels.
This project is part of a research fellowship on the theme of "Digital Twin and Fintech services for sustainable supply chain" and part of my Master Thesis. The core objective is to find, identify, and explain—both visually and textually—defective items within a supply chain environment.

https://github.com/user-attachments/assets/96688854-460b-42a4-88fb-7694de15c909
Visual understanding with CLIP (frozen)
utils/knowledge.py) is tokenized once and cached.Mapping image features to language tokens (TransformerMapper)
TransformerMapper into a sequence of prefix_length vectors, each with dimensionality matching OPT-125M’s token embeddings.prefix_text). This is the ClipCap intuition: inject vision information as a learned prefix so the LM continues in natural language space without modifying the LM itself.Language generation with OPT-125M (decoder-only)
prefix_text]. It then autoregressively generates tokens using temperature/top-k/top-p sampling, with early-EOS avoidance until a desired min_length is reached.prefix_text so only the caption content remains.Auto-labeling with CLIP (dataset creation)
utils/summarizer.py).*.pt) and (b) the synthesized caption into a training corpus (caption_mapping.csv). This step eliminates manual labeling and scales cheaply.Training on generated labels (teacher forcing)
Explainability with Grad-CAM over CLIP’s ViT
The application is run via a Gradio interface launched by launch.py. After training and having a checkpoint available, users can upload images, generate captions, and view explanation maps directly in the browser.
Benefits
Considerations
CLIPCap-XAI/
models/
clip.py # CLIP wrapper: preprocessing, inference, Grad-CAM, preprocessing pipeline
mapper.py # TransformerMapper projecting CLIP features to LM embedding space
vlm.py # ClipCaptioner: OPT-125M + CLIP wrapper + training/inference logic
utils/
data.py # Training dataset built from preprocessed embeddings/captions
knowledge.py # Prompt set (domain knowledge) for CLIP text side
plot.py # Helpers to render individual and combined Grad-CAM overlays
summarizer.py # Synthesize a natural caption from top caption-probability pairs
launch.py # Gradio app for interactive captioning + Grad-CAM visualization on Web Interfaces
visualize.py # File in which the entire Pipeline is tested and processed (basically, the what launch does but iterative)
vlm_train.py # Train Script: preprocess dataset and train the VLM
vlm_predict.py # Test script: load VLM checkpoint and run captioning + visualizations
clip_predict.py # Test script: CLIP-only demo (after training, for quick checks)
launch.py
MODEL_PATH) into ClipCaptioner.model.generate, and returns combined + individual Grad-CAM overlays, top-5 probabilities, and the final caption.visualize.py
vlm_train.py
ClipCaptioner.preprocess_dataset: explore a class-structured folder, computes CLIP embeddings from images and their synthesized captions, writes *.pt and caption_mapping.csv files ready to be used in the train process.ClipCaptioner.train_model: trains the OPT-125M + TransformerMapper using teacher-forced captions; logs loss and saves periodic checkpoints.root_dir, processed_dir, output_dir before running.vlm_predict.py
ClipCaptioner.generate(image=...).clip_predict.py
CLIPW.utils/knowledge.py), extracts top-k predictions, and synthesizes a caption via utils/summarizer.synthesize.models/vlm.py (class ClipCaptioner)
TransformerMapper to project CLIP image features to a prefix_length × embedding_dim prefix sequence.CLIPW wrapper instance for image processing, top-k prompt probabilities, and Grad-CAM maps.forward(tokens, prefix, mask=None, labels=None): concatenates prefix projections with token embeddings and forwards through OPT.preprocess_dataset(root_dir, output_dir, batch_size): delegates to CLIPW to build a training dataset from raw images.get_visual_explanation(image, ...): returns Grad-CAM outputs via CLIPW.visualize.generate(image, ..., k, plot_individual, combined_threshold, combined_alpha, normalize_alpha_scaling): full inference path returning probabilities dict, final caption, combined and individual overlays.train_model(dataset_path, output_dir, epochs, ...): training loop with logging, scheduler, and checkpointing.from_pretrained(model_path): load a previously saved checkpoint.models/clip.py (class CLIPW, Wrapper for the CLIP model)
top_k extraction.*.pt) + synthesized captions (caption_mapping.csv).individual_map) and a probability-aware combined overlay (combined_map).models/mapper.py (class TransformerMapper)
prefix_length tokens to be concatenated with LM token embeddings.utils/data.py (class Dataset)
caption_mapping.csv and *.pt embeddings.(embedding_tensor, caption_string) pairs for training.utils/knowledge.py
captions["fruits"] covering diseases, texture, damage, and aging cues.utils/plot.py
individual_map(original_img, cam_map, caption, probability): returns a two-panel PIL image (original + overlay) with optional probability in title.combined_map(original_img, captions, cam_maps, probabilities_for_alpha, original_probabilities, k, threshold, alpha, normalize_alpha_scaling): returns a PIL image overlay with a legend and probability-aware alpha scaling.utils/summarizer.py
synthesize(captions_with_probabilities): converts top-k (caption, probability) into a natural sentence using a severity hierarchy.Vision encoder (CLIP, frozen)
models/clip.py) handles preprocessing, batching, top-k selection, Grad-CAM generation, and dataset preprocessing.Transformer mapper (learned)
models/mapper.py lifts CLIP embeddings into a sequence of prefix_length vectors in LM embedding space via Linear → TransformerEncoder (N layers) → Linear → LayerNorm.Language model (OPT-125M, learned)
Data pipeline
CLIPW.preprocess_dataset → .pt embeddings + caption_mapping.csv with synthesized captions → utils/data.Dataset → DataLoader.Training and checkpoints
ClipCaptioner.train_model handles loop, logging, scheduler; save_pretrained persists model/optimizer/epoch/loss.Inference + XAI
ClipCaptioner.generate returns (probs_dict, caption, combined_plot_PIL, [individual_plot_PILs]) with configurable sampling and Grad-CAM controls.Prerequisites:
openai-clip (clip), transformers, gradio, tqdm, pandas, matplotlib, opencv-python, Pillow, numpyExample setup (conda or venv is recommended):
# 1. Create a CONDA or VENV environment.
# Venv:
python -m venv .venv
source .venv/bin/activate
# Conda
conda create -n supplychain python=3.9
# 2. Update PIP
pip install --upgrade pip
# 3. Pytorch installation (use your CUDA version)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 4. Install CLIP directly from the OPENAI repo
pip install git+https://github.com/openai/CLIP.git
# 5. Install other dependencies
pip install transformers gradio tqdm pandas matplotlib opencv-python Pillow numpy
scikit-learn ftfy regex tqdm
# 6. Pydantic compatible with gradio
pip install pydantic==2.10.6
Before starting to understand how this tool works, let's quickly talks about the output of the model itself so if you want to test it out, having a better understanding might be beneficial for test purposes.
There are mainly two usable model in this project: The CLIP wrapper and the actual CLIP-Captioner.
CLIPW.visualize(image, ...):
probs (dict[str, float]): caption → softmax probability (sorted desc).image_features (torch.Tensor): CLIP image embedding (e.g., [1, 512]), Used for training purposes or saving .pt file for training.combined_plot_image (PIL.Image | None): combined Grad-CAM overlay for top-k (None if k==1).individual_plot_images (list[PIL.Image]): per-caption Grad-CAM overlays (one per top-k when enabled).ClipCaptioner.generate(image, ...):
probs (dict[str, float]): caption → probability over the prompt set.caption (str): final generated caption.combined_plot (PIL.Image): combined overlay for the selected top-k.individual_plots (list[PIL.Image]): per-caption overlays.As you can see, the difference between CLIPW (the wrapper) and the Captioner are subtle: Since ClipCaptioner Embed CLIPWrapper, it will have some output shared with it! But you can obviously use them distinctly, for various usage (maybe you want to auto label a dataset? Or just trying the wrapper out?). The main difference is obviously that, the ClipCaptioner returns the caption generated by the model instead the image features.
Notes:
combined_plot_image from visualize is None and individual_plot_images has a single item.plot_individual=False, only the combined overlay is produced for k>1.The entire pipeline is extremeley easy to just train and run. After you gathered your dataset, all you have to do is:
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset"
output_dir = "/path/to/checkpoints"
model = ClipCaptioner()
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
model.train_model(dataset_path=processed_dir, output_dir=output_dir, epochs=10, batch_size=32)
Note that, even with a small amount of epoch (circa ~10) the model performs EXTREMELY well!
python launch.py
Edit MODEL_PATH at the top of launch.py (e.g., train/checkpoints/clipcap_epoch_X.pt). Upload an image in the WEB-UI to generate a caption and view Grad-CAM overlays.
Your raw dataset should be class-structured (any labels you have), e.g.:
root_dir/
ClassA/
img1.jpg
img2.png
ClassB/
img3.jpg
...
Use the CLIP wrapper’s preprocessing to build an embedding+caption dataset:
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset" # will contain *.pt + caption_mapping.csv
model = ClipCaptioner()
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
Artifacts in processed_dir:
emb_XXXXXXXX.pt files for each image (CLIP image features)caption_mapping.csv mapping embedding IDs to synthesized captionsfailed_images.txt (optional) with any images that failed preprocessingQuick-start via vlm_train.py (edit paths in the file):
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset"
output_dir = "/path/to/checkpoints"
model = ClipCaptioner(prefix_length=10, clip_length=512, hidden_size=768, num_layers=8, num_heads=8)
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
model.train_model(dataset_path=processed_dir, output_dir=output_dir, epochs=10, batch_size=32)
Adjusts value as you please.
Training log and checkpoints are saved under output_dir/ (e.g., clipcap_epoch_9.pt). Checkpoints store model and optimizer state.
After you have trained the model and produced a checkpoint, you can use the test scripts to validate components individually:
vlm_predict.py: loads a VLM checkpoint and generates a caption plus Grad-CAM visualizations for a single image.clip_predict.py: runs CLIP-only scoring and synthesized captioning from prompts (useful for quick checks of the CLIP side).Example (vlm_predict.py):
from models.vlm import ClipCaptioner
model_path = "train/checkpoints/clipcap_epoch_9.pt" # update path
model = ClipCaptioner().from_pretrained(model_path)
img_path = "test_img.jpg"
probs, caption, combined_plot, individual_plots = model.generate(
image=img_path,
combined_alpha=0.4,
)
# Save visuals
import os
os.makedirs("results/vlm_predict", exist_ok=True)
combined_plot.save("results/vlm_predict/combined_plot.png")
for i, plot in enumerate(individual_plots):
plot.save(f"results/vlm_predict/individual_plot_{i}.png")
print("Caption:", caption)
print("All probabilities:", probs)
The interactive demo is the heart of the entire application since it allows the user to play in real time with the tool.
Launch the Gradio UI in launch.py (this is the main application entry point). Edit the MODEL_PATH at the top if needed:
python launch.py
UI features:
By default, the demo attempts to load a checkpoint train/checkpoints/clipcap_epoch_X.pt and enables share=True to expose a temporary public Gradio URL.
The CLIPW.visualize API (used by ClipCaptioner.generate) supports:
Returned objects from generate(image=...):
probs: dict mapping candidate captions to probabilitiescaption: generated caption (prefix text removed)combined_plot: a PIL image with the combined overlayindividual_plots: list of PIL images for per-caption overlaysThe CLIP text prompts live in utils/knowledge.py under the captions["fruits"] list (diseases, damage, aging cues, texture, etc.). You can extend or change these prompts to adapt to different domains. The wrapper caches tokenized prompts for efficiency.
train/checkpoints/clipcap_epoch_X.pt). Update paths to your environment..pt embeddings and caption_mapping.csv generated by the preprocessing step; make sure paths align.Images below are examples generated by the model. Replace or extend with your own results.
Media folder: FINAL_TESI/media/
- source_img.jpg
- combined_plot.png
- individual_plot_0.png
- individual_plot_1.png
- individual_plot_2.png
- individual_plot_3.png
- individual_plot_4.png
Preview of the output of the model:
| Source image | Combined Grad-CAM overlay |
|---|---|
![]() | ![]() |
| Individual 0 | Individual 1 | Individual 2 | Individual 3 | Individual 4 |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
BibTeX for ClipCap:
@misc{mokady2021clipcapclipprefiximage,
title={ClipCap: CLIP Prefix for Image Captioning},
author={Ron Mokady and Amir Hertz and Amit H. Bermano},
year={2021},
eprint={2111.09734},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2111.09734},
}
If you use this repository, please cite the original works above and acknowledge this implementation:
@software{clip_captioner_gradcam_thesis,
title = {CLIP-Captioner with Grad-CAM Explainability},
author = {Asynchronousx},
year = {2025},
url = {https://github.com/<your-username>/<your-repo>](https://github.com/Asynchronousx/CLIPCap-XAI}
}
34 commits
Python
100.0%
This repository contains a Vision-Language Model (VLM) for image captioning based on CLIP prefixes with an emphasis on practical explainability using a custom Grad-CAM over CLIP's visual transformer layers. The system pairs CLIP as the vision backbone and OPT-125M as the language model, bridged by a transformer mapper that projects CLIP image features into a sequence of prefix tokens consumed by the language model, using the Prexif Tuning, A PEFT (Parameter Efficient Tuning) technique.
Explainability visualizations highlight where the model focused when preferring one caption over another. A core contribution of this work is an automatic dataset labeling pipeline driven by CLIP: the model synthesizes training captions from top-k prompt probabilities and uses them to train the captioner end-to-end without manual labels.
This project is part of a research fellowship on the theme of "Digital Twin and Fintech services for sustainable supply chain" and part of my Master Thesis. The core objective is to find, identify, and explain—both visually and textually—defective items within a supply chain environment.

https://github.com/user-attachments/assets/96688854-460b-42a4-88fb-7694de15c909
Visual understanding with CLIP (frozen)
utils/knowledge.py) is tokenized once and cached.Mapping image features to language tokens (TransformerMapper)
TransformerMapper into a sequence of prefix_length vectors, each with dimensionality matching OPT-125M’s token embeddings.prefix_text). This is the ClipCap intuition: inject vision information as a learned prefix so the LM continues in natural language space without modifying the LM itself.Language generation with OPT-125M (decoder-only)
prefix_text]. It then autoregressively generates tokens using temperature/top-k/top-p sampling, with early-EOS avoidance until a desired min_length is reached.prefix_text so only the caption content remains.Auto-labeling with CLIP (dataset creation)
utils/summarizer.py).*.pt) and (b) the synthesized caption into a training corpus (caption_mapping.csv). This step eliminates manual labeling and scales cheaply.Training on generated labels (teacher forcing)
Explainability with Grad-CAM over CLIP’s ViT
The application is run via a Gradio interface launched by launch.py. After training and having a checkpoint available, users can upload images, generate captions, and view explanation maps directly in the browser.
Benefits
Considerations
CLIPCap-XAI/
models/
clip.py # CLIP wrapper: preprocessing, inference, Grad-CAM, preprocessing pipeline
mapper.py # TransformerMapper projecting CLIP features to LM embedding space
vlm.py # ClipCaptioner: OPT-125M + CLIP wrapper + training/inference logic
utils/
data.py # Training dataset built from preprocessed embeddings/captions
knowledge.py # Prompt set (domain knowledge) for CLIP text side
plot.py # Helpers to render individual and combined Grad-CAM overlays
summarizer.py # Synthesize a natural caption from top caption-probability pairs
launch.py # Gradio app for interactive captioning + Grad-CAM visualization on Web Interfaces
visualize.py # File in which the entire Pipeline is tested and processed (basically, the what launch does but iterative)
vlm_train.py # Train Script: preprocess dataset and train the VLM
vlm_predict.py # Test script: load VLM checkpoint and run captioning + visualizations
clip_predict.py # Test script: CLIP-only demo (after training, for quick checks)
launch.py
MODEL_PATH) into ClipCaptioner.model.generate, and returns combined + individual Grad-CAM overlays, top-5 probabilities, and the final caption.visualize.py
vlm_train.py
ClipCaptioner.preprocess_dataset: explore a class-structured folder, computes CLIP embeddings from images and their synthesized captions, writes *.pt and caption_mapping.csv files ready to be used in the train process.ClipCaptioner.train_model: trains the OPT-125M + TransformerMapper using teacher-forced captions; logs loss and saves periodic checkpoints.root_dir, processed_dir, output_dir before running.vlm_predict.py
ClipCaptioner.generate(image=...).clip_predict.py
CLIPW.utils/knowledge.py), extracts top-k predictions, and synthesizes a caption via utils/summarizer.synthesize.models/vlm.py (class ClipCaptioner)
TransformerMapper to project CLIP image features to a prefix_length × embedding_dim prefix sequence.CLIPW wrapper instance for image processing, top-k prompt probabilities, and Grad-CAM maps.forward(tokens, prefix, mask=None, labels=None): concatenates prefix projections with token embeddings and forwards through OPT.preprocess_dataset(root_dir, output_dir, batch_size): delegates to CLIPW to build a training dataset from raw images.get_visual_explanation(image, ...): returns Grad-CAM outputs via CLIPW.visualize.generate(image, ..., k, plot_individual, combined_threshold, combined_alpha, normalize_alpha_scaling): full inference path returning probabilities dict, final caption, combined and individual overlays.train_model(dataset_path, output_dir, epochs, ...): training loop with logging, scheduler, and checkpointing.from_pretrained(model_path): load a previously saved checkpoint.models/clip.py (class CLIPW, Wrapper for the CLIP model)
top_k extraction.*.pt) + synthesized captions (caption_mapping.csv).individual_map) and a probability-aware combined overlay (combined_map).models/mapper.py (class TransformerMapper)
prefix_length tokens to be concatenated with LM token embeddings.utils/data.py (class Dataset)
caption_mapping.csv and *.pt embeddings.(embedding_tensor, caption_string) pairs for training.utils/knowledge.py
captions["fruits"] covering diseases, texture, damage, and aging cues.utils/plot.py
individual_map(original_img, cam_map, caption, probability): returns a two-panel PIL image (original + overlay) with optional probability in title.combined_map(original_img, captions, cam_maps, probabilities_for_alpha, original_probabilities, k, threshold, alpha, normalize_alpha_scaling): returns a PIL image overlay with a legend and probability-aware alpha scaling.utils/summarizer.py
synthesize(captions_with_probabilities): converts top-k (caption, probability) into a natural sentence using a severity hierarchy.Vision encoder (CLIP, frozen)
models/clip.py) handles preprocessing, batching, top-k selection, Grad-CAM generation, and dataset preprocessing.Transformer mapper (learned)
models/mapper.py lifts CLIP embeddings into a sequence of prefix_length vectors in LM embedding space via Linear → TransformerEncoder (N layers) → Linear → LayerNorm.Language model (OPT-125M, learned)
Data pipeline
CLIPW.preprocess_dataset → .pt embeddings + caption_mapping.csv with synthesized captions → utils/data.Dataset → DataLoader.Training and checkpoints
ClipCaptioner.train_model handles loop, logging, scheduler; save_pretrained persists model/optimizer/epoch/loss.Inference + XAI
ClipCaptioner.generate returns (probs_dict, caption, combined_plot_PIL, [individual_plot_PILs]) with configurable sampling and Grad-CAM controls.Prerequisites:
openai-clip (clip), transformers, gradio, tqdm, pandas, matplotlib, opencv-python, Pillow, numpyExample setup (conda or venv is recommended):
# 1. Create a CONDA or VENV environment.
# Venv:
python -m venv .venv
source .venv/bin/activate
# Conda
conda create -n supplychain python=3.9
# 2. Update PIP
pip install --upgrade pip
# 3. Pytorch installation (use your CUDA version)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 4. Install CLIP directly from the OPENAI repo
pip install git+https://github.com/openai/CLIP.git
# 5. Install other dependencies
pip install transformers gradio tqdm pandas matplotlib opencv-python Pillow numpy
scikit-learn ftfy regex tqdm
# 6. Pydantic compatible with gradio
pip install pydantic==2.10.6
Before starting to understand how this tool works, let's quickly talks about the output of the model itself so if you want to test it out, having a better understanding might be beneficial for test purposes.
There are mainly two usable model in this project: The CLIP wrapper and the actual CLIP-Captioner.
CLIPW.visualize(image, ...):
probs (dict[str, float]): caption → softmax probability (sorted desc).image_features (torch.Tensor): CLIP image embedding (e.g., [1, 512]), Used for training purposes or saving .pt file for training.combined_plot_image (PIL.Image | None): combined Grad-CAM overlay for top-k (None if k==1).individual_plot_images (list[PIL.Image]): per-caption Grad-CAM overlays (one per top-k when enabled).ClipCaptioner.generate(image, ...):
probs (dict[str, float]): caption → probability over the prompt set.caption (str): final generated caption.combined_plot (PIL.Image): combined overlay for the selected top-k.individual_plots (list[PIL.Image]): per-caption overlays.As you can see, the difference between CLIPW (the wrapper) and the Captioner are subtle: Since ClipCaptioner Embed CLIPWrapper, it will have some output shared with it! But you can obviously use them distinctly, for various usage (maybe you want to auto label a dataset? Or just trying the wrapper out?). The main difference is obviously that, the ClipCaptioner returns the caption generated by the model instead the image features.
Notes:
combined_plot_image from visualize is None and individual_plot_images has a single item.plot_individual=False, only the combined overlay is produced for k>1.The entire pipeline is extremeley easy to just train and run. After you gathered your dataset, all you have to do is:
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset"
output_dir = "/path/to/checkpoints"
model = ClipCaptioner()
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
model.train_model(dataset_path=processed_dir, output_dir=output_dir, epochs=10, batch_size=32)
Note that, even with a small amount of epoch (circa ~10) the model performs EXTREMELY well!
python launch.py
Edit MODEL_PATH at the top of launch.py (e.g., train/checkpoints/clipcap_epoch_X.pt). Upload an image in the WEB-UI to generate a caption and view Grad-CAM overlays.
Your raw dataset should be class-structured (any labels you have), e.g.:
root_dir/
ClassA/
img1.jpg
img2.png
ClassB/
img3.jpg
...
Use the CLIP wrapper’s preprocessing to build an embedding+caption dataset:
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset" # will contain *.pt + caption_mapping.csv
model = ClipCaptioner()
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
Artifacts in processed_dir:
emb_XXXXXXXX.pt files for each image (CLIP image features)caption_mapping.csv mapping embedding IDs to synthesized captionsfailed_images.txt (optional) with any images that failed preprocessingQuick-start via vlm_train.py (edit paths in the file):
from models.vlm import ClipCaptioner
root_dir = "/path/to/raw_dataset"
processed_dir = "/path/to/processed_dataset"
output_dir = "/path/to/checkpoints"
model = ClipCaptioner(prefix_length=10, clip_length=512, hidden_size=768, num_layers=8, num_heads=8)
model.preprocess_dataset(root_dir=root_dir, output_dir=processed_dir, batch_size=32)
model.train_model(dataset_path=processed_dir, output_dir=output_dir, epochs=10, batch_size=32)
Adjusts value as you please.
Training log and checkpoints are saved under output_dir/ (e.g., clipcap_epoch_9.pt). Checkpoints store model and optimizer state.
After you have trained the model and produced a checkpoint, you can use the test scripts to validate components individually:
vlm_predict.py: loads a VLM checkpoint and generates a caption plus Grad-CAM visualizations for a single image.clip_predict.py: runs CLIP-only scoring and synthesized captioning from prompts (useful for quick checks of the CLIP side).Example (vlm_predict.py):
from models.vlm import ClipCaptioner
model_path = "train/checkpoints/clipcap_epoch_9.pt" # update path
model = ClipCaptioner().from_pretrained(model_path)
img_path = "test_img.jpg"
probs, caption, combined_plot, individual_plots = model.generate(
image=img_path,
combined_alpha=0.4,
)
# Save visuals
import os
os.makedirs("results/vlm_predict", exist_ok=True)
combined_plot.save("results/vlm_predict/combined_plot.png")
for i, plot in enumerate(individual_plots):
plot.save(f"results/vlm_predict/individual_plot_{i}.png")
print("Caption:", caption)
print("All probabilities:", probs)
The interactive demo is the heart of the entire application since it allows the user to play in real time with the tool.
Launch the Gradio UI in launch.py (this is the main application entry point). Edit the MODEL_PATH at the top if needed:
python launch.py
UI features:
By default, the demo attempts to load a checkpoint train/checkpoints/clipcap_epoch_X.pt and enables share=True to expose a temporary public Gradio URL.
The CLIPW.visualize API (used by ClipCaptioner.generate) supports:
Returned objects from generate(image=...):
probs: dict mapping candidate captions to probabilitiescaption: generated caption (prefix text removed)combined_plot: a PIL image with the combined overlayindividual_plots: list of PIL images for per-caption overlaysThe CLIP text prompts live in utils/knowledge.py under the captions["fruits"] list (diseases, damage, aging cues, texture, etc.). You can extend or change these prompts to adapt to different domains. The wrapper caches tokenized prompts for efficiency.
train/checkpoints/clipcap_epoch_X.pt). Update paths to your environment..pt embeddings and caption_mapping.csv generated by the preprocessing step; make sure paths align.Images below are examples generated by the model. Replace or extend with your own results.
Media folder: FINAL_TESI/media/
- source_img.jpg
- combined_plot.png
- individual_plot_0.png
- individual_plot_1.png
- individual_plot_2.png
- individual_plot_3.png
- individual_plot_4.png
Preview of the output of the model:
| Source image | Combined Grad-CAM overlay |
|---|---|
![]() | ![]() |
| Individual 0 | Individual 1 | Individual 2 | Individual 3 | Individual 4 |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
BibTeX for ClipCap:
@misc{mokady2021clipcapclipprefiximage,
title={ClipCap: CLIP Prefix for Image Captioning},
author={Ron Mokady and Amir Hertz and Amit H. Bermano},
year={2021},
eprint={2111.09734},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2111.09734},
}
If you use this repository, please cite the original works above and acknowledge this implementation:
@software{clip_captioner_gradcam_thesis,
title = {CLIP-Captioner with Grad-CAM Explainability},
author = {Asynchronousx},
year = {2025},
url = {https://github.com/<your-username>/<your-repo>](https://github.com/Asynchronousx/CLIPCap-XAI}
}
34 commits
Python
100.0%