File size: 4,959 Bytes
48a89ad ea3b5c8 b504556 ea3b5c8 48a89ad 67d0363 ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad b504556 48a89ad ea3b5c8 48a89ad b504556 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 67d0363 b504556 ea3b5c8 48a89ad ea3b5c8 b504556 ea3b5c8 48a89ad ea3b5c8 48a89ad ea3b5c8 | 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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | """Minimal inference example for DeiT-Tiny INT8 using ExecuTorch.
Loads a quantized .pte model and runs inference on a single image,
printing the top-5 ImageNet class predictions with probabilities.
"""
import json
from pathlib import Path
import torch
from executorch.runtime import Runtime
from PIL import Image
from torchvision import transforms
from torchvision.models import GoogLeNet_Weights
# ββ Configuration ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
MODEL_PATH = "deit_raspberry_executorch_optimized.pte"
IMAGE_PATH = "sample_input.jpg"
INPUT_SIZE = (224, 224)
RESIZE_SIZE = 256 # resize shorter edge before center crop
MEAN = [0.485, 0.456, 0.406]
STD = [0.229, 0.224, 0.225]
TOP_K = 5
# ββ Model Loading ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def load_model(pte_path: str):
"""Load ExecuTorch .pte model and return the forward method."""
runtime = Runtime.get()
program = runtime.load_program(pte_path)
return program.load_method("forward")
# ββ Preprocessing ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def preprocess(image_path: str) -> torch.Tensor:
"""Load and preprocess image for model input.
Pipeline:
1. Resize shortest edge to 256 px (bicubic)
2. Center-crop to 224x224
3. Convert to float32 tensor in [0, 1]
4. Normalize with ImageNet mean/std
"""
transform = transforms.Compose(
[
transforms.Resize(
RESIZE_SIZE, interpolation=transforms.InterpolationMode.BICUBIC
),
transforms.CenterCrop(INPUT_SIZE),
transforms.ToTensor(),
transforms.Normalize(mean=MEAN, std=STD),
]
)
image = Image.open(image_path).convert("RGB")
tensor = transform(image)
return tensor.unsqueeze(0) # [1, 3, 224, 224]
# ββ Inference ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def run_inference(method, input_tensor: torch.Tensor) -> torch.Tensor:
"""Run forward pass and return the raw logits tensor."""
outputs = method.execute([input_tensor])
return outputs[0]
# ββ Postprocessing βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def postprocess(raw_output: torch.Tensor, labels: list) -> list[dict]:
"""Convert raw logits to top-k class predictions.
Applies softmax over the 1000-class logit vector, then returns the
top-k (class name, probability) pairs sorted by descending probability.
"""
logits = raw_output.squeeze(0) # [1000]
probabilities = torch.softmax(logits, dim=-1)
top_probs, top_indices = torch.topk(probabilities, TOP_K)
return [
{"class": labels[idx.item()], "probability": round(prob.item(), 6)}
for prob, idx in zip(top_probs, top_indices, strict=False)
]
# ββ Save Results βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def save_results(results: list[dict], script_dir: Path) -> None:
"""Save top-k predictions to predictions.json in the script's directory."""
output_path = script_dir / "predictions.json"
with open(output_path, "w") as f:
json.dump(results, f, indent=2)
print(f"Saved predictions to {output_path}")
# ββ Main βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def main() -> None:
script_dir = Path(__file__).parent
# ImageNet class labels (1000 classes)
WEIGHTS = GoogLeNet_Weights.IMAGENET1K_V1
IMAGENET_CLASSES = WEIGHTS.meta["categories"]
# Load model, run inference, decode results
method = load_model(str(script_dir / MODEL_PATH))
input_tensor = preprocess(str(script_dir / IMAGE_PATH))
raw_output = run_inference(method, input_tensor)
results = postprocess(raw_output, IMAGENET_CLASSES)
# Print top-k predictions
print(f"Top-{TOP_K} predictions:")
for i, r in enumerate(results, 1):
print(f" {i}. {r['class']} ({r['probability'] * 100:.2f}%)")
save_results(results, script_dir)
if __name__ == "__main__":
main()
|