PyTorch
image testing
machine learning
neural networks
computer vision

How to test one single image in pytorch

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Running inference on one image in PyTorch is mostly about reproducing the same preprocessing and model state used during training. The model has to be loaded, switched to evaluation mode, fed a tensor with a batch dimension, and run inside a no-gradient context. If any of those pieces are missing, the prediction may fail or produce misleading results.

Load the Model and Switch to Evaluation Mode

For a trained classifier, start by recreating the model architecture, loading the saved weights, and setting the model to evaluation mode.

python
1import torch
2from torchvision import models
3
4device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
5
6model = models.resnet18(num_classes=3)
7model.load_state_dict(torch.load("model_weights.pth", map_location=device))
8model.to(device)
9model.eval()

model.eval() matters because it changes how layers such as dropout and batch normalization behave. Without it, inference can be inconsistent.

Apply the Same Transforms Used During Training

Single-image inference often goes wrong because the test image is preprocessed differently than the training data. Resize, crop, convert to tensor, and normalize exactly as the model expects.

python
1from PIL import Image
2from torchvision import transforms
3
4transform = transforms.Compose([
5    transforms.Resize((224, 224)),
6    transforms.ToTensor(),
7    transforms.Normalize(
8        mean=[0.485, 0.456, 0.406],
9        std=[0.229, 0.224, 0.225],
10    ),
11])
12
13image = Image.open("example.jpg").convert("RGB")
14image_tensor = transform(image)

If training used different size or normalization values, reuse those exact settings here.

Add a Batch Dimension

PyTorch image models expect input shaped like (batch, channels, height, width). A single transformed image has shape (channels, height, width), so you need to add one batch dimension.

python
image_tensor = image_tensor.unsqueeze(0).to(device)
print(image_tensor.shape)

Without this step, many models raise a shape error because they still expect a batch axis even for one example.

Run Inference Without Gradient Tracking

For inference, disable gradient calculation. That reduces memory use and makes intent explicit.

python
1with torch.no_grad():
2    logits = model(image_tensor)
3    predicted_index = logits.argmax(dim=1).item()
4
5print(predicted_index)

This gives the predicted class index. If you want human-readable labels, map the index through a label list.

python
class_names = ["cat", "dog", "rabbit"]
print(class_names[predicted_index])

Get Confidence Scores

If the model outputs classification logits, convert them to probabilities with softmax.

python
1with torch.no_grad():
2    logits = model(image_tensor)
3    probabilities = torch.softmax(logits, dim=1)
4    confidence, predicted_index = torch.max(probabilities, dim=1)
5
6print(class_names[predicted_index.item()])
7print(confidence.item())

This is useful for debugging and for showing results in an application UI.

Keep Device Placement Consistent

The model and the input tensor must be on the same device. If the model is on GPU and the image tensor is on CPU, PyTorch raises a device mismatch error.

That is why the common pattern is:

  • choose a device once
  • move the model to that device
  • move the input tensor to that same device

Keeping device logic explicit prevents many small inference bugs.

Wrap It in a Helper Function

If you plan to run several images, put the steps into a reusable helper.

python
1def predict_image(image_path, model, transform, class_names, device):
2    image = Image.open(image_path).convert("RGB")
3    tensor = transform(image).unsqueeze(0).to(device)
4
5    with torch.no_grad():
6        logits = model(tensor)
7        probabilities = torch.softmax(logits, dim=1)
8        confidence, predicted_index = torch.max(probabilities, dim=1)
9
10    return class_names[predicted_index.item()], confidence.item()

This keeps the serving code short and reduces the chance of forgetting a preprocessing step.

Common Pitfalls

  • Forgetting model.eval() and getting unstable inference behavior.
  • Using different preprocessing at inference time than during training.
  • Omitting the batch dimension and hitting a shape mismatch.
  • Running inference without torch.no_grad() and wasting memory.
  • Putting the model and input tensor on different devices.

Summary

  • Load the trained weights and call model.eval() before inference.
  • Apply the same transforms used during training.
  • Add a batch dimension with unsqueeze(0).
  • Use torch.no_grad() for efficient prediction.
  • Keep the model and the input tensor on the same device.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.