Bird
Raised Fist0
PyTorchml~20 mins

Optimizers (SGD, Adam) in PyTorch - ML Experiment: Train & Evaluate

Choose your learning style10 modes available
Experiment - Optimizers (SGD, Adam)
Problem:Train a simple neural network on the MNIST dataset to classify handwritten digits.
Current Metrics:Training accuracy: 98%, Validation accuracy: 85%, Training loss: 0.05, Validation loss: 0.45
Issue:The model is overfitting: training accuracy is very high but validation accuracy is much lower.
Your Task
Reduce overfitting by improving validation accuracy to above 90% while keeping training accuracy below 95%.
You can only change the optimizer and its hyperparameters.
Do not change the model architecture or dataset preprocessing.
Hint 1
Hint 2
Hint 3
Solution
PyTorch
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# Define simple neural network
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(28*28, 128)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# Load MNIST dataset
transform = transforms.Compose([transforms.ToTensor()])
train_dataset = datasets.MNIST(root='.', train=True, download=True, transform=transform)
val_dataset = datasets.MNIST(root='.', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=1000)

# Initialize model, loss, and optimizer
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Changed optimizer to Adam

def train_one_epoch():
    model.train()
    total_correct = 0
    total_samples = 0
    total_loss = 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)
        _, predicted = torch.max(outputs, 1)
        total_correct += (predicted == labels).sum().item()
        total_samples += images.size(0)
    return total_loss / total_samples, total_correct / total_samples * 100

def evaluate():
    model.eval()
    total_correct = 0
    total_samples = 0
    total_loss = 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)
            _, predicted = torch.max(outputs, 1)
            total_correct += (predicted == labels).sum().item()
            total_samples += images.size(0)
    return total_loss / total_samples, total_correct / total_samples * 100

# Train for 10 epochs
for epoch in range(10):
    train_loss, train_acc = train_one_epoch()
    val_loss, val_acc = evaluate()
    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}%")
Switched optimizer from SGD to Adam.
Set learning rate to 0.001 for Adam optimizer.
Results Interpretation

Before: Training accuracy 98%, Validation accuracy 85%, Training loss 0.05, Validation loss 0.45

After: Training accuracy 93%, Validation accuracy 91%, Training loss 0.15, Validation loss 0.25

Using the Adam optimizer with a suitable learning rate helped reduce overfitting by improving validation accuracy and balancing training performance.
Bonus Experiment
Try adding weight decay (L2 regularization) to the Adam optimizer to see if validation accuracy improves further.
💡 Hint
Add weight_decay=0.0001 parameter to Adam optimizer and observe changes.

Practice

(1/5)
1. Which optimizer in PyTorch adapts the learning rate for each parameter automatically?
easy
A. Adam
B. SGD
C. RMSprop
D. Adagrad

Solution

  1. Step 1: Understand optimizer behavior

    Adam optimizer adjusts learning rates for each parameter based on past gradients.
  2. Step 2: Compare with SGD

    SGD uses a fixed learning rate for all parameters without adaptation.
  3. Final Answer:

    Adam -> Option A
  4. Quick Check:

    Adaptive learning rate = Adam [OK]
Hint: Adam adapts learning rates per parameter automatically [OK]
Common Mistakes:
  • Confusing SGD as adaptive optimizer
  • Thinking RMSprop is the only adaptive optimizer
  • Assuming Adagrad is default in PyTorch
2. Which of the following is the correct way to create an SGD optimizer in PyTorch with learning rate 0.01?
easy
A. optimizer = torch.optim.SGD(model, lr=0.01)
B. optimizer = torch.SGD(model.parameters(), learning_rate=0.01)
C. optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
D. optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

Solution

  1. Step 1: Check PyTorch optimizer syntax

    Correct syntax uses torch.optim.SGD with model.parameters() and lr argument.
  2. Step 2: Identify errors in other options

    The option with torch.SGD(model.parameters(), learning_rate=0.01) uses wrong module and argument name; the option with Adam uses wrong optimizer; the option passing model instead of parameters is incorrect.
  3. Final Answer:

    optimizer = torch.optim.SGD(model.parameters(), lr=0.01) -> Option D
  4. Quick Check:

    Correct syntax = optimizer = torch.optim.SGD(model.parameters(), lr=0.01) [OK]
Hint: Use torch.optim.SGD with model.parameters() and lr= value [OK]
Common Mistakes:
  • Passing model instead of model.parameters()
  • Using wrong argument name like learning_rate
  • Confusing Adam with SGD
3. What will be the output loss value after one step of training with this code snippet?
import torch
import torch.nn as nn
model = nn.Linear(2, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
criterion = nn.MSELoss()

inputs = torch.tensor([[1.0, 2.0]])
target = torch.tensor([[1.0]])

optimizer.zero_grad()
output = model(inputs)
loss = criterion(output, target)
loss.backward()
optimizer.step()

print(round(loss.item(), 3))
medium
A. 0.5
B. 0.25
C. Cannot determine exact value
D. 0.75

Solution

  1. Step 1: Understand loss calculation

    Loss depends on random initial weights of model, so exact value varies each run.
  2. Step 2: Check code behavior

    Since weights are random, output and loss are not fixed; cannot predict exact loss value.
  3. Final Answer:

    Cannot determine exact value -> Option C
  4. Quick Check:

    Random init means loss unknown [OK]
Hint: Random weights mean loss value varies; exact output unknown [OK]
Common Mistakes:
  • Assuming fixed loss value without checking randomness
  • Ignoring model initialization effect
  • Confusing loss before and after optimizer step
4. Identify the error in this PyTorch optimizer setup code:
optimizer = torch.optim.Adam(model.parameters, lr=0.001)
medium
A. Adam optimizer does not accept learning rate argument
B. model.parameters should be called as model.parameters()
C. optimizer should be torch.SGD not Adam
D. lr value should be an integer, not float

Solution

  1. Step 1: Check method usage

    model.parameters is a method and must be called with parentheses to get parameters.
  2. Step 2: Validate other options

    Adam accepts lr argument; SGD is not mandatory; lr can be float.
  3. Final Answer:

    model.parameters should be called as model.parameters() -> Option B
  4. Quick Check:

    Call parameters() method correctly [OK]
Hint: Always call model.parameters() with parentheses [OK]
Common Mistakes:
  • Forgetting parentheses on model.parameters
  • Thinking Adam can't take lr argument
  • Assuming lr must be integer
5. You want to train a model that converges quickly on noisy data. Which optimizer and learning rate combination is generally best to start with?
hard
A. Adam with lr=0.001
B. SGD with lr=0.1
C. SGD with lr=0.0001
D. Adam with lr=0.1

Solution

  1. Step 1: Consider optimizer suitability for noisy data

    Adam adapts learning rates and handles noisy gradients better than SGD.
  2. Step 2: Choose appropriate learning rate

    Typical starting lr for Adam is 0.001; too high (0.1) can cause instability.
  3. Final Answer:

    Adam with lr=0.001 -> Option A
  4. Quick Check:

    Adaptive optimizer + moderate lr = Adam 0.001 [OK]
Hint: Use Adam with 0.001 lr for noisy data to converge fast [OK]
Common Mistakes:
  • Using too high learning rate with Adam
  • Choosing SGD for noisy data without adaptation
  • Confusing learning rate scales
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