Download inference.py from jressler/cactus-classifier: direct link, hf CLI and curl.
- Browser
- Download file 2.09 kB
-
https://huggingface.co/jressler/cactus-classifier/resolve/main/inference.py
- Command line
-
hf download hf://jressler/cactus-classifier/inference.py
-
curl -L -o inference.py https://huggingface.co/jressler/cactus-classifier/resolve/main/inference.py
2.09 kB
| """Load and run the exported ConvNeXt Small model with PyTorch and Torchvision.""" | |
| from __future__ import annotations | |
| import json | |
| from pathlib import Path | |
| import torch | |
| from PIL import Image | |
| from torchvision import models, transforms | |
| def load_model(model_dir: str | Path, device: str = "auto"): | |
| """Load model weights and the preprocessing parameters from an export folder.""" | |
| model_dir = Path(model_dir) | |
| config = json.loads((model_dir / "config.json").read_text(encoding="utf-8")) | |
| if config["model_name"] != "convnext_small": | |
| raise ValueError(f"Unsupported model architecture: {config['model_name']}") | |
| if device == "auto": | |
| if torch.cuda.is_available(): | |
| device = "cuda" | |
| elif torch.backends.mps.is_available(): | |
| device = "mps" | |
| else: | |
| device = "cpu" | |
| target = torch.device(device) | |
| model = models.convnext_small(weights=None) | |
| model.classifier[-1] = torch.nn.Linear( | |
| model.classifier[-1].in_features, config["num_labels"], | |
| ) | |
| state_dict = torch.load( | |
| model_dir / config["weights_file"], map_location="cpu", weights_only=True, | |
| ) | |
| model.load_state_dict(state_dict) | |
| model.to(target).eval() | |
| preprocess = transforms.Compose([ | |
| transforms.Resize(config["resize_size"]), | |
| transforms.CenterCrop(config["image_size"]), | |
| transforms.ToTensor(), | |
| transforms.Normalize(mean=config["image_mean"], std=config["image_std"]), | |
| ]) | |
| return model, preprocess, config["class_names"], target | |
| def predict(image: Image.Image, model, preprocess, class_names: list[str], device) -> list[dict]: | |
| """Return all class scores, ordered from highest to lowest.""" | |
| tensor = preprocess(image.convert("RGB")).unsqueeze(0).to(device) | |
| probabilities = torch.softmax(model(tensor), dim=1)[0].cpu().tolist() | |
| return sorted( | |
| ({"class_name": name, "probability": float(probabilities[index])} | |
| for index, name in enumerate(class_names)), | |
| key=lambda score: score["probability"], reverse=True, | |
| ) | |