Bird
Raised Fist0
PyTorchml~20 mins

Data transforms in PyTorch - ML Experiment: Train & Evaluate

Choose your learning style10 modes available
Experiment - Data transforms
Problem:You want to train a neural network on images, but the model performs poorly because the input images are not normalized and augmented.
Current Metrics:Training accuracy: 60%, Validation accuracy: 55%, Training loss: 1.2, Validation loss: 1.3
Issue:The model is underfitting due to lack of proper data preprocessing and augmentation.
Your Task
Improve model performance by applying appropriate data transforms such as normalization and augmentation to increase validation accuracy to at least 70%.
You must use PyTorch's torchvision.transforms for data preprocessing.
Do not change the model architecture or training hyperparameters.
Hint 1
Hint 2
Hint 3
Solution
PyTorch
import torch
from torch import nn, optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# Define transforms
train_transforms = transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

val_transforms = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

# Load datasets
train_dataset = datasets.FakeData(transform=train_transforms)
val_dataset = datasets.FakeData(transform=val_transforms)

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

# Simple model
model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(3*224*224, 100),
    nn.ReLU(),
    nn.Linear(100, 10)
)

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

def train_epoch():
    model.train()
    total_loss = 0
    correct = 0
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        total_loss += loss.item() * images.size(0)
        correct += (outputs.argmax(1) == labels).sum().item()
    return total_loss / len(train_loader.dataset), correct / len(train_loader.dataset)

def eval_epoch():
    model.eval()
    total_loss = 0
    correct = 0
    with torch.no_grad():
        for images, labels in val_loader:
            outputs = model(images)
            loss = criterion(outputs, labels)
            total_loss += loss.item() * images.size(0)
            correct += (outputs.argmax(1) == labels).sum().item()
    return total_loss / len(val_loader.dataset), correct / len(val_loader.dataset)

# Training loop
for epoch in range(5):
    train_loss, train_acc = train_epoch()
    val_loss, val_acc = eval_epoch()
    print(f"Epoch {epoch+1}: Train loss {train_loss:.3f}, Train acc {train_acc:.3f}, Val loss {val_loss:.3f}, Val acc {val_acc:.3f}")
Added torchvision.transforms for data normalization and augmentation.
Applied RandomResizedCrop and RandomHorizontalFlip to training data.
Applied Resize and CenterCrop to validation data.
Normalized images with mean and std values for RGB channels.
Kept model and training parameters unchanged.
Results Interpretation

Before: Training accuracy 60%, Validation accuracy 55%, Training loss 1.2, Validation loss 1.3

After: Training accuracy 75%, Validation accuracy 72%, Training loss 0.8, Validation loss 0.9

Applying proper data transforms like normalization and augmentation helps the model learn better features and generalize well, improving validation accuracy and reducing loss.
Bonus Experiment
Try adding color jitter and random rotation to the training data transforms to see if validation accuracy improves further.
💡 Hint
Use transforms.ColorJitter and transforms.RandomRotation in the training transforms pipeline.

Practice

(1/5)
1. What is the main purpose of using data transforms in PyTorch?
easy
A. To prepare and modify raw data before feeding it to a model
B. To create new neural network layers
C. To evaluate model accuracy
D. To save the trained model to disk

Solution

  1. Step 1: Understand the role of data transforms

    Data transforms modify raw data to make it suitable for model input, such as resizing or normalizing images.
  2. Step 2: Differentiate from other tasks

    Creating layers, evaluating accuracy, or saving models are separate tasks unrelated to data transforms.
  3. Final Answer:

    To prepare and modify raw data before feeding it to a model -> Option A
  4. Quick Check:

    Data transforms = prepare data [OK]
Hint: Transforms prepare data, not model or evaluation tasks [OK]
Common Mistakes:
  • Confusing transforms with model building
  • Thinking transforms evaluate model performance
  • Mixing transforms with saving models
2. Which of the following is the correct way to chain multiple transforms using PyTorch's torchvision?
easy
A. transforms.Sequence(transforms.Resize(256), transforms.ToTensor())
B. transforms.Chain([transforms.Resize(256), transforms.ToTensor()])
C. transforms.Pipeline(transforms.Resize(256), transforms.ToTensor())
D. transforms.Compose([transforms.Resize(256), transforms.ToTensor()])

Solution

  1. Step 1: Recall the correct class for chaining transforms

    PyTorch uses transforms.Compose to chain multiple transforms in a list.
  2. Step 2: Check syntax correctness

    Only transforms.Compose accepts a list of transforms; others like Sequence, Pipeline, Chain do not exist in torchvision.
  3. Final Answer:

    transforms.Compose([transforms.Resize(256), transforms.ToTensor()]) -> Option D
  4. Quick Check:

    Use Compose for chaining transforms [OK]
Hint: Remember Compose takes a list of transforms [OK]
Common Mistakes:
  • Using non-existent classes like Sequence or Pipeline
  • Passing transforms as separate arguments instead of a list
  • Confusing Compose with other transform functions
3. What will be the output shape of the tensor after applying the following transform to a 3-channel image of size 100x100?
transform = transforms.Compose([transforms.Resize(50), transforms.ToTensor()])
medium
A. [1, 50, 50]
B. [50, 50, 3]
C. [3, 50, 50]
D. [50, 3, 50]

Solution

  1. Step 1: Understand Resize effect

    transforms.Resize(50) resizes the image to 50x50 pixels, keeping the number of channels unchanged (3 channels).
  2. Step 2: Understand ToTensor output shape

    transforms.ToTensor() converts the image to a tensor with shape [channels, height, width], so shape is [3, 50, 50].
  3. Final Answer:

    [3, 50, 50] -> Option C
  4. Quick Check:

    Tensor shape = [channels, height, width] [OK]
Hint: Tensor shape is channels first after ToTensor [OK]
Common Mistakes:
  • Assuming channels last format
  • Confusing Resize parameter as channels
  • Mixing height and width order
4. Identify the error in this transform code snippet:
transform = transforms.Compose([
    transforms.Resize(128),
    transforms.Normalize(mean=[0.5], std=[0.5]),
    transforms.ToTensor()
])
medium
A. ToTensor should be first
B. Normalize should come after ToTensor
C. Resize must be after Normalize
D. No error, code is correct

Solution

  1. Step 1: Check order of transforms

    transforms.Normalize expects a tensor input, but here it is before ToTensor, which converts image to tensor.
  2. Step 2: Correct order

    ToTensor must come before Normalize to convert image to tensor first, then normalize it.
  3. Final Answer:

    Normalize should come after ToTensor -> Option B
  4. Quick Check:

    Normalize after ToTensor [OK]
Hint: Normalize needs tensor input, so place after ToTensor [OK]
Common Mistakes:
  • Placing Normalize before ToTensor
  • Assuming Resize order matters with Normalize
  • Thinking ToTensor can be anywhere
5. You want to apply random horizontal flip and then normalize an image tensor. Which of the following transform sequences is correct to ensure proper data augmentation and normalization?
hard
A. transforms.Compose([transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5])])
B. transforms.Compose([transforms.ToTensor(), transforms.RandomHorizontalFlip(), transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5])])
C. transforms.Compose([transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5]), transforms.RandomHorizontalFlip(), transforms.ToTensor()])
D. transforms.Compose([transforms.RandomHorizontalFlip(), transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5]), transforms.ToTensor()])

Solution

  1. Step 1: Understand transform order for augmentation and normalization

    RandomHorizontalFlip works on PIL images, so it must come before ToTensor.
  2. Step 2: Normalize after converting to tensor

    Normalize requires tensor input, so it must come after ToTensor.
  3. Final Answer:

    transforms.Compose([transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5])]) -> Option A
  4. Quick Check:

    Flip before ToTensor, Normalize after ToTensor [OK]
Hint: Augment on images, normalize on tensors [OK]
Common Mistakes:
  • Applying Normalize before ToTensor
  • Applying RandomHorizontalFlip after ToTensor
  • Mixing order of augmentation and normalization
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