import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms, models
from torch.utils.data import DataLoader
# --------------------------------------------------
# 1. Device
# --------------------------------------------------
device = torch.device(
"cuda" if torch.cuda.is_available() else "cpu"
)
print("Using:", device)
# --------------------------------------------------
# 2. Transform
# --------------------------------------------------
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(
[0.485, 0.456, 0.406],
[0.229, 0.224, 0.225]
)
])
# --------------------------------------------------
# 3. Dataset
# --------------------------------------------------
train_data = datasets.CIFAR10(
"./data",
train=True,
download=True,
transform=transform
)
test_data = datasets.CIFAR10(
"./data",
train=False,
download=True,
transform=transform
)
# --------------------------------------------------
# 4. DataLoader
# --------------------------------------------------
train_loader = DataLoader(
train_data,
batch_size=64,
shuffle=True
)
test_loader = DataLoader(
test_data,
batch_size=64
)
print("Train:", len(train_data))
print("Test:", len(test_data))
# --------------------------------------------------
# 5. Pretrained ResNet-18
# --------------------------------------------------
model = models.resnet18(weights="DEFAULT")
# --------------------------------------------------
# 6. Replace classifier
# --------------------------------------------------
model.fc = nn.Linear(
model.fc.in_features,
10
)
model = model.to(device)
# --------------------------------------------------
# 7. Freeze pretrained layers
# --------------------------------------------------
for param in model.parameters():
param.requires_grad = False
for param in model.fc.parameters():
param.requires_grad = True
# --------------------------------------------------
# 8. Loss and optimizer
# --------------------------------------------------
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(
model.fc.parameters(),
lr=0.001
)
# --------------------------------------------------
# 9. Train classifier
# --------------------------------------------------
for epoch in range(3):
model.train()
correct = 0
total = 0
for images, labels in train_loader:
images = images.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
predictions = outputs.argmax(1)
total += labels.size(0)
correct += (
predictions == labels
).sum().item()
accuracy = 100 * correct / total
print(
f"Epoch {epoch + 1}: "
f"Loss = {loss.item():.4f}, "
f"Accuracy = {accuracy:.2f}%"
)
# --------------------------------------------------
# 10. Fine-tune layer4
# --------------------------------------------------
for param in model.layer4.parameters():
param.requires_grad = True
# --------------------------------------------------
# 11. Smaller learning rate
# --------------------------------------------------
optimizer = optim.Adam(
filter(
lambda p: p.requires_grad,
model.parameters()
),
lr=0.0001
)
# --------------------------------------------------
# 12. Fine-tuning
# --------------------------------------------------
for epoch in range(2):
model.train()
for images, labels in train_loader:
images = images.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
print(
f"Fine-tuning Epoch {epoch + 1}: "
f"Loss = {loss.item():.4f}"
)
# --------------------------------------------------
# 13. Evaluation
# --------------------------------------------------
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
predictions = outputs.argmax(1)
total += labels.size(0)
correct += (
predictions == labels
).sum().item()
accuracy = 100 * correct / total
print(f"Test Accuracy: {accuracy:.2f}%")
# --------------------------------------------------
# 14. Predictions
# --------------------------------------------------
classes = [
"airplane",
"automobile",
"bird",
"cat",
"deer",
"dog",
"frog",
"horse",
"ship",
"truck"
]
images, labels = next(iter(test_loader))
images = images.to(device)
with torch.no_grad():
outputs = model(images)
predictions = outputs.argmax(1)
for i in range(10):
print(
f"Actual: {classes[labels[i]]:10s} "
f"Predicted: {classes[predictions[i].item()]}"
)