import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, random_split
import matplotlib.pyplot as plt
# Define simple neural network
class SimpleNN(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.linear = nn.Linear(28*28, 10)
def forward(self, x):
x = self.flatten(x)
return self.linear(x)
# Prepare dataset and dataloaders
transform = transforms.ToTensor()
full_dataset = datasets.MNIST(root='.', train=True, download=True, transform=transform)
train_size = int(0.8 * len(full_dataset))
val_size = len(full_dataset) - train_size
train_dataset, val_dataset = random_split(full_dataset, [train_size, val_size])
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=64)
# Initialize model, loss, optimizer
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)
train_losses = []
val_losses = []
for epoch in range(5):
model.train()
running_train_loss = 0.0
for images, labels in train_loader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_train_loss += loss.item() * images.size(0)
avg_train_loss = running_train_loss / len(train_loader.dataset)
train_losses.append(avg_train_loss)
model.eval()
running_val_loss = 0.0
with torch.no_grad():
for images, labels in val_loader:
outputs = model(images)
loss = criterion(outputs, labels)
running_val_loss += loss.item() * images.size(0)
avg_val_loss = running_val_loss / len(val_loader.dataset)
val_losses.append(avg_val_loss)
print(f"Epoch {epoch+1}: Train Loss = {avg_train_loss:.4f}, Val Loss = {avg_val_loss:.4f}")
# Plot losses
plt.plot(range(1,6), train_losses, label='Training Loss')
plt.plot(range(1,6), val_losses, label='Validation Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training and Validation Loss over Epochs')
plt.legend()
plt.show()