MOBILECLIP2 · IMAGE CLASSIFICATION
MobileCLIP2: choose a model and classify an image
Compare S0, S2 and the larger variants, then run image–text matching with your own labels. MobileCLIP2 produces embeddings for classification and retrieval; use FastVLM when you need a written answer.
Which MobileCLIP2 model?
Start with S0 for the smallest image encoder. S2 raises published ImageNet accuracy from 71.5% to 77.2%. Evaluate the larger models on your actual images before accepting their extra memory and compute costs.
| Model | Image encoder (M) | Text encoder (M) | ImageNet top-1 (%) |
|---|---|---|---|
| S0 ↗ | 11.4 | 63.4 | 71.5 |
| S2 ↗ | 35.7 | 63.4 | 77.2 |
| B ↗ | 86.3 | 63.4 | 79.4 |
| S3 ↗ | 125.1 | 123.6 | 80.7 |
| L-14 ↗ | 304.3 | 123.6 | 81.9 |
| S4 ↗ | 321.6 | 123.6 | 81.9 |
Apple-published model-card values, checked September 12, 2026. Parameter counts are in millions; ImageNet zero-shot top-1 is accuracy on that benchmark, not a prediction for your images. Apple model card
Run your own image classification
- Create a Python environment and install the packages below.
- Download mobileclip2.py and save it next to your image.
- Run the command with at least two candidate labels. The first run downloads model weights.
- Inspect the JSON ranking. Change the labels to test whether the distinction is useful for your task.
python -m venv .venv
source .venv/bin/activate
python -m pip install "open_clip_torch==3.3.0" "timm==1.0.29" torch pillow
curl -fLO https://fastvlm.net/examples/mobileclip2.py
python mobileclip2.py image.png --model S0 --labels "a receipt" "a chart" "a photograph" """Classify a local image against candidate labels with MobileCLIP2.
Install: python -m pip install "open_clip_torch==3.3.0" "timm==1.0.29" torch pillow
Run: python mobileclip2.py image.png --labels 'a receipt' 'a chart' 'a photograph'
Uses the timm/OpenCLIP adaptation of Apple's weights, downloaded on first run.
Source: https://huggingface.co/timm/MobileCLIP2-S0-OpenCLIP
"""
import argparse
import json
from pathlib import Path
import open_clip
import torch
from PIL import Image
from timm.utils import reparameterize_model
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('image', type=Path)
parser.add_argument('--model', choices=['S0', 'S2', 'B', 'S3', 'L-14', 'S4'], default='S0')
parser.add_argument('--labels', nargs='+', required=True)
args = parser.parse_args()
if not args.image.is_file():
parser.error('The image file does not exist.')
if len(args.labels) < 2:
parser.error('Provide at least two candidate labels.')
name = 'MobileCLIP2-' + args.model
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model, _, preprocess = open_clip.create_model_and_transforms(name, pretrained='dfndr2b')
model = reparameterize_model(model.eval()).to(device)
tokenizer = open_clip.get_tokenizer(name)
image = preprocess(Image.open(args.image).convert('RGB')).unsqueeze(0).to(device)
text = tokenizer(args.labels).to(device)
with torch.inference_mode():
image_features = model.encode_image(image)
text_features = model.encode_text(text)
image_features /= image_features.norm(dim=-1, keepdim=True)
text_features /= text_features.norm(dim=-1, keepdim=True)
scores = (100.0 * image_features @ text_features.T).softmax(dim=-1)[0].cpu().tolist()
results = sorted(zip(args.labels, scores), key=lambda item: item[1], reverse=True)
print(json.dumps({'model': name, 'scores': [{'label': label, 'score': score} for label, score in results],
'note': 'Relative scores within the supplied labels, not calibrated probabilities.'}, indent=2))
if __name__ == '__main__':
main()
Expected output: a JSON object with the model and labels sorted by score. Scores are relative to your candidate set; they are not calibrated probabilities. Try both relevant and unrelated labels.
This example uses the timm/OpenCLIP adaptation of Apple’s model. The original Apple checkpoint and the OpenCLIP-compatible files use different naming and loading paths.
MobileCLIP, MobileCLIP2, CLIP or FastVLM?
- MobileCLIP → MobileCLIP2: compare the same size and preprocessing on your own labeled images. Version 2 changes the training recipe; do not apply first-generation speed claims to every v2 model.
- CLIP / SigLIP alternatives: use the same image set, candidate labels and device. Compare accuracy, latency and memory together.
- FastVLM: choose generative image question answering when a ranked list of labels cannot answer the question.
Troubleshooting
- Unknown model: update open_clip_torch and timm; check that open_clip.list_models() includes MobileCLIP2-S0.
- Incorrect results: keep the model in eval mode and use its own preprocess and tokenizer.
- Download fails: check your connection to Hugging Face and available disk space.