PyTorch Data Transforms

Transforms prepare raw data into a format that neural networks can process effectively. They convert images from disk into tensors, normalize pixel values, resize images to a standard dimension, and augment training data to help models generalize. TorchVision's transforms module provides a large collection of ready-to-use transforms.

Why Transforms Matter

Raw image from disk:
  → Format: JPEG / PNG
  → Type: PIL Image
  → Pixel range: 0 to 255 (uint8)
  → Size: varies (e.g. 640×480, 1920×1080)

What the model needs:
  → Format: PyTorch tensor
  → Type: float32
  → Value range: 0.0 to 1.0 (or normalized with mean/std)
  → Size: fixed (e.g. 224×224 for ResNet)

Transforms bridge this gap.

The Most Common Transforms

from torchvision import transforms

# Chain multiple transforms with Compose
transform = transforms.Compose([
    transforms.Resize((224, 224)),       # resize to 224×224
    transforms.ToTensor(),               # PIL → tensor, scales to [0, 1]
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],      # ImageNet mean per channel
        std=[0.229, 0.224, 0.225]        # ImageNet std per channel
    )
])

Applying Transforms to a Dataset

from torchvision import datasets, transforms

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

train_data = datasets.MNIST(
    root='./data',
    train=True,
    download=True,
    transform=transform
)

img, label = train_data[0]
print(img.shape)   # torch.Size([1, 28, 28])
print(img.min(), img.max())   # approximately -1.0 and 1.0 after normalization

Data Augmentation Transforms

Augmentation artificially increases the variety of training data by randomly modifying samples. A model trained on augmented data learns to recognize objects regardless of orientation, lighting, or crop position — it generalizes better to real-world data it has never seen.

train_transform = transforms.Compose([
    transforms.RandomHorizontalFlip(p=0.5),    # flip left-right 50% of the time
    transforms.RandomRotation(degrees=15),      # rotate up to 15 degrees
    transforms.ColorJitter(
        brightness=0.2, contrast=0.2,
        saturation=0.2, hue=0.1
    ),
    transforms.RandomCrop(224, padding=4),      # random crop with padding
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])
])

Augmentation Diagram

Original image of a dog:
  [🐕 facing right, bright lighting]

After augmentation (random each epoch):
  Epoch 1:  [🐕 flipped left, slightly rotated]
  Epoch 2:  [🐕 darker, slightly cropped]
  Epoch 3:  [🐕 original orientation, different crop]

The model sees a "different" image every epoch —
  it can't memorize positions or lighting.

Separate Transforms for Train vs Validation

Apply augmentation only to training data. Validation and test data should always use the same deterministic transforms so the evaluation metric is consistent across runs.

train_transform = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(10),
    transforms.ToTensor(),
    transforms.Normalize([0.5], [0.5])
])

val_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize([0.5], [0.5])
    # No random augmentation here!
])

Common Individual Transforms

Transform                    What it does
─────────────────────────────────────────────────────────
ToTensor()                   PIL Image → float32 tensor, /255
Resize((h, w))               Resize to fixed height × width
CenterCrop(size)             Crop from the center
RandomCrop(size)             Crop at a random position
RandomHorizontalFlip()       Flip left-right with p=0.5
RandomVerticalFlip()         Flip upside-down with p=0.5
RandomRotation(degrees)      Rotate by random angle
ColorJitter(...)             Randomly change brightness/contrast
Grayscale()                  Convert RGB image to grayscale
Normalize(mean, std)         Standardize channel values
RandomErasing()              Randomly erase a rectangle (cutout)
GaussianBlur(kernel_size)    Apply blur to the image

Transforms for Non-Image Data

Transforms are not exclusive to images. For tabular data, you typically apply transforms as preprocessing steps before creating a Dataset — normalizing columns, encoding categories, or filling missing values using pandas or scikit-learn, then converting to tensors.

import torch
import pandas as pd
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data.csv')
X = df.drop('target', axis=1).values
y = df['target'].values

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

X_tensor = torch.tensor(X_scaled, dtype=torch.float32)
y_tensor  = torch.tensor(y,       dtype=torch.long)

Custom Transform Class

You can write your own transform as a callable class. It must implement __call__.

class AddGaussianNoise:
    def __init__(self, std=0.1):
        self.std = std

    def __call__(self, tensor):
        noise = torch.randn_like(tensor) * self.std
        return tensor + noise

transform = transforms.Compose([
    transforms.ToTensor(),
    AddGaussianNoise(std=0.05)    # add small noise to the tensor
])

Summary

Transforms convert raw data into the format a model expects and optionally augment training samples to improve generalization. Use transforms.Compose to chain multiple transforms in sequence. Always include ToTensor() and Normalize() for images. Apply random augmentation transforms only to training data — not to validation or test sets. Write custom transforms as callable classes when built-in transforms don't cover your needs. Augmentation is one of the most cost-effective ways to improve model accuracy without collecting more data.

Leave a Comment

Your email address will not be published. Required fields are marked *