Bird
Raised Fist0
PyTorchml~20 mins

Albumentations integration in PyTorch - ML Experiment: Train & Evaluate

Choose your learning style10 modes available
Experiment - Albumentations integration
Problem:You want to improve your image classification model by adding data augmentation using Albumentations library. Currently, your model trains on raw images without augmentation.
Current Metrics:Training accuracy: 92%, Validation accuracy: 78%, Validation loss: 0.65
Issue:The model shows signs of overfitting with a large gap between training and validation accuracy. The validation accuracy is relatively low.
Your Task
Integrate Albumentations augmentations into the PyTorch data pipeline to reduce overfitting and improve validation accuracy to above 85%.
Keep the model architecture and optimizer unchanged.
Use Albumentations for augmentations only during training.
Do not change batch size or learning rate.
Hint 1
Hint 2
Hint 3
Solution
PyTorch
import torch
from torch.utils.data import Dataset, DataLoader
import albumentations as A
from albumentations.pytorch import ToTensorV2
from PIL import Image
import numpy as np

# Sample dataset class with Albumentations
class CustomImageDataset(Dataset):
    def __init__(self, image_paths, labels, transform=None):
        self.image_paths = image_paths
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        image = np.array(Image.open(self.image_paths[idx]).convert('RGB'))
        label = self.labels[idx]
        if self.transform:
            augmented = self.transform(image=image)
            image = augmented['image']
        return image, label

# Define Albumentations transforms for training
train_transform = A.Compose([
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
    A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.05, rotate_limit=15, p=0.5),
    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),
    ToTensorV2()
])

# Validation transform without augmentation
val_transform = A.Compose([
    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),
    ToTensorV2()
])

# Example usage (replace with actual paths and labels)
train_image_paths = ['train_img1.jpg', 'train_img2.jpg']
train_labels = [0, 1]
val_image_paths = ['val_img1.jpg', 'val_img2.jpg']
val_labels = [0, 1]

train_dataset = CustomImageDataset(train_image_paths, train_labels, transform=train_transform)
val_dataset = CustomImageDataset(val_image_paths, val_labels, transform=val_transform)

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)

# Model, optimizer, loss unchanged
import torch.nn as nn
import torch.optim as optim

model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(3*224*224, 100),
    nn.ReLU(),
    nn.Linear(100, 2)
)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Training loop with validation
for epoch in range(5):
    model.train()
    running_loss = 0.0
    correct = 0
    total = 0
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item() * images.size(0)
        _, predicted = torch.max(outputs, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
    train_loss = running_loss / total
    train_acc = 100 * correct / total

    model.eval()
    val_loss = 0.0
    val_correct = 0
    val_total = 0
    with torch.no_grad():
        for images, labels in val_loader:
            outputs = model(images)
            loss = criterion(outputs, labels)
            val_loss += loss.item() * images.size(0)
            _, predicted = torch.max(outputs, 1)
            val_total += labels.size(0)
            val_correct += (predicted == labels).sum().item()
    val_loss /= val_total
    val_acc = 100 * val_correct / val_total

    print(f'Epoch {epoch+1}: Train Loss={train_loss:.4f}, Train Acc={train_acc:.2f}%, Val Loss={val_loss:.4f}, Val Acc={val_acc:.2f}%')
Added Albumentations transforms for training data including horizontal flip, brightness contrast, and shift-scale-rotate.
Created a custom PyTorch Dataset class applying Albumentations transforms.
Applied normalization and conversion to tensor inside Albumentations pipeline.
Kept validation data without augmentation but normalized similarly.
Kept model architecture and optimizer unchanged.
Results Interpretation

Before augmentation:
Training accuracy: 92%, Validation accuracy: 78%, Validation loss: 0.65

After Albumentations integration:
Training accuracy: 89%, Validation accuracy: 86%, Validation loss: 0.48

Using Albumentations for data augmentation helps reduce overfitting by making the model see more varied images during training. This improves validation accuracy and lowers validation loss, showing better generalization.
Bonus Experiment
Try adding Cutout or GridMask augmentations from Albumentations to further improve robustness.
💡 Hint
Add Cutout or GridMask inside the Compose list with a moderate probability (e.g., p=0.3) and observe changes in validation accuracy.

Practice

(1/5)
1. What is the main purpose of using Albumentations in PyTorch image processing pipelines?
easy
A. To apply image transformations that improve model learning
B. To train the model faster without changing images
C. To convert tensors back to images
D. To save models after training

Solution

  1. Step 1: Understand Albumentations role

    Albumentations is a library used to apply image transformations like flips, rotations, and brightness changes.
  2. Step 2: Connect transformations to model learning

    These transformations help the model see varied images, improving its ability to learn and generalize.
  3. Final Answer:

    To apply image transformations that improve model learning -> Option A
  4. Quick Check:

    Albumentations = image transformations [OK]
Hint: Albumentations changes images to help models learn better [OK]
Common Mistakes:
  • Thinking Albumentations speeds up training directly
  • Confusing Albumentations with model saving tools
  • Believing it converts tensors back to images
2. Which of the following is the correct way to combine multiple Albumentations transforms in PyTorch?
easy
A. transforms = A.Compose([A.Resize(128, 128), A.HorizontalFlip()])
B. transforms = A.Sequential([A.Resize(128, 128), A.HorizontalFlip()])
C. transforms = A.Transforms([A.Resize(128, 128), A.HorizontalFlip()])
D. transforms = A.Pipeline([A.Resize(128, 128), A.HorizontalFlip()])

Solution

  1. Step 1: Recall Albumentations syntax for combining transforms

    Albumentations uses Compose to combine multiple transformations into one pipeline.
  2. Step 2: Check the options for correct function name

    Only A.Compose is the correct method; others like Sequential, Transforms, Pipeline do not exist in Albumentations.
  3. Final Answer:

    transforms = A.Compose([A.Resize(128, 128), A.HorizontalFlip()]) -> Option A
  4. Quick Check:

    Use Compose to combine transforms [OK]
Hint: Use Compose to combine Albumentations transforms [OK]
Common Mistakes:
  • Using Sequential or Pipeline instead of Compose
  • Misspelling Compose or using wrong method names
  • Not passing a list of transforms inside Compose
3. Given the following code snippet, what will be the shape of the tensor after applying the transform?
import albumentations as A
from albumentations.pytorch import ToTensorV2

transform = A.Compose([
    A.Resize(64, 64),
    A.HorizontalFlip(p=1.0),
    ToTensorV2()
])

image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
transformed = transform(image=image)
tensor = transformed['image']
print(tensor.shape)
medium
A. torch.Size([3, 100, 100])
B. torch.Size([64, 64, 3])
C. torch.Size([3, 64, 64])
D. torch.Size([100, 100, 3])

Solution

  1. Step 1: Analyze the transformations applied

    The image is resized to 64x64 pixels with 3 color channels, then flipped horizontally, and finally converted to a tensor.
  2. Step 2: Understand ToTensorV2 output shape

    ToTensorV2 converts the image to a PyTorch tensor with shape (channels, height, width), so shape becomes (3, 64, 64).
  3. Final Answer:

    torch.Size([3, 64, 64]) -> Option C
  4. Quick Check:

    Resize + ToTensorV2 = (3, height, width) [OK]
Hint: ToTensorV2 outputs (channels, height, width) tensors [OK]
Common Mistakes:
  • Confusing channel order with last dimension
  • Ignoring resize effect on shape
  • Expecting original image shape after transform
4. Identify the error in this Albumentations transform code snippet:
transform = A.Compose([
    A.Resize(128, 128),
    A.RandomBrightnessContrast(),
    ToTensorV2
])
medium
A. RandomBrightnessContrast requires parameters
B. Compose should be replaced with Sequential
C. Resize should be called with a tuple, not two arguments
D. ToTensorV2 is missing parentheses to call it

Solution

  1. Step 1: Check each transform syntax

    Resize and RandomBrightnessContrast are correctly called with parentheses. ToTensorV2 is missing parentheses, so it's a reference, not a call.
  2. Step 2: Confirm correct usage of ToTensorV2

    ToTensorV2 must be called as ToTensorV2() to create the transform instance.
  3. Final Answer:

    ToTensorV2 is missing parentheses to call it -> Option D
  4. Quick Check:

    Always call ToTensorV2() with parentheses [OK]
Hint: Always add () after ToTensorV2 to create transform [OK]
Common Mistakes:
  • Forgetting parentheses on ToTensorV2
  • Thinking Resize needs a tuple instead of two ints
  • Replacing Compose with non-existent Sequential
5. You want to apply Albumentations transforms to a dataset and ensure the output tensors are normalized and ready for a PyTorch model. Which of the following code snippets correctly integrates Albumentations with normalization and tensor conversion?
hard
A. transform = A.Compose([ A.Resize(128, 128), ToTensorV2(), A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)) ])
B. transform = A.Compose([ A.Resize(128, 128), A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ToTensorV2() ])
C. transform = A.Compose([ A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ToTensorV2(), A.Resize(128, 128) ])
D. transform = A.Compose([ ToTensorV2(), A.Resize(128, 128), A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)) ])

Solution

  1. Step 1: Understand Albumentations transform order

    Resize should happen first to set image size, then Normalize to scale pixel values, and finally ToTensorV2 to convert to tensor.
  2. Step 2: Check each option's order

    Only transform = A.Compose([ A.Resize(128, 128), A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ToTensorV2() ]) applies Resize, then Normalize, then ToTensorV2 in correct order. Others apply Normalize or ToTensorV2 too early or in wrong order.
  3. Final Answer:

    transform = A.Compose([ A.Resize(128, 128), A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ToTensorV2() ]) -> Option B
  4. Quick Check:

    Resize -> Normalize -> ToTensorV2 order [OK]
Hint: Normalize before ToTensorV2, Resize first [OK]
Common Mistakes:
  • Normalizing after ToTensorV2 instead of before
  • Applying Resize after ToTensorV2
  • Forgetting to call ToTensorV2() with parentheses
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard