Spaces:
Sleeping
Sleeping
File size: 1,853 Bytes
67fffca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import json
from pathlib import Path
import torch
from safetensors.torch import load_file
from torchvision import transforms
from torchvision.models import ResNet18_Weights, resnet18
MEAN = [0.485, 0.456, 0.406]
STD = [0.229, 0.224, 0.225]
def build_model(num_classes: int, pretrained: bool = False):
model = resnet18(weights=ResNet18_Weights.DEFAULT if pretrained else None)
model.fc = torch.nn.Linear(model.fc.in_features, num_classes)
return model
def preprocessing(config: dict, training: bool = False):
size = config["image_size"]
operations = (
[transforms.RandomResizedCrop(size, scale=(.8, 1.0)), transforms.RandomHorizontalFlip()]
if training else
[transforms.Resize(round(size * 256 / 224)), transforms.CenterCrop(size)]
)
return transforms.Compose(operations + [
transforms.ToTensor(),
transforms.Normalize(config["mean"], config["std"]),
])
def load_classifier(directory: str | Path):
directory = Path(directory)
config = json.loads((directory / "config.json").read_text())
model = build_model(len(config["labels"]))
model.load_state_dict(load_file(str(directory / "model.safetensors")))
model.eval()
return model, config
@torch.inference_mode()
def classify(model, config: dict, image, top_k: int):
if image is None:
raise ValueError("Choose an image")
if not 1 <= top_k <= len(config["labels"]):
raise ValueError("Invalid top_k")
tensor = preprocessing(config)(image.convert("RGB")).unsqueeze(0)
tensor = tensor.to(next(model.parameters()).device)
probabilities = model(tensor).softmax(dim=1)[0]
scores, indices = probabilities.topk(top_k)
return [
{"label": config["labels"][index], "score": float(score)}
for score, index in zip(scores.tolist(), indices.tolist())
]
|