""" Shows a small example of how to load a pretrain model (VGG16) from PyTorch, and modifies this to train on the CIFAR10 dataset. The same method generalizes well to other datasets, but the modifications to the network may need to be changed. Programmed by Aladdin Persson * 2020-04-08 Initial coding * 2022-12-19 Updated comments, minor code changes, made sure it works with latest PyTorch """ # Imports import torch import torchvision import torch.nn as nn # All neural network modules, nn.Linear, nn.Conv2d, BatchNorm, Loss functions import torch.optim as optim # For all Optimization algorithms, SGD, Adam, etc. import torch.nn.functional as F # All functions that don't have any parameters from torch.utils.data import ( DataLoader, ) # Gives easier dataset managment and creates mini batches import torchvision.datasets as datasets # Has standard datasets we can import in a nice way import torchvision.transforms as transforms # Transformations we can perform on our dataset from tqdm import tqdm device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # Hyperparameters num_classes = 10 learning_rate = 1e-3 batch_size = 1024 num_epochs = 5 # Load pretrain model & modify it model = torchvision.models.vgg16(weights="DEFAULT") # If you want to do finetuning then set requires_grad = False # Remove these two lines if you want to train entire model, # and only want to load the pretrain weights. for param in model.parameters(): param.requires_grad = False model.avgpool = nn.Identity() model.classifier = nn.Sequential( nn.Linear(512, 100), nn.ReLU(), nn.Linear(100, num_classes) ) model.to(device) # Load Data train_dataset = datasets.CIFAR10( root="dataset/", train=True, transform=transforms.ToTensor(), download=True ) train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) # Loss and optimizer criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=learning_rate) # Train Network for epoch in range(num_epochs): losses = [] for batch_idx, (data, targets) in enumerate(tqdm(train_loader)): # Get data to cuda if possible data = data.to(device=device) targets = targets.to(device=device) # forward scores = model(data) loss = criterion(scores, targets) losses.append(loss.item()) # backward optimizer.zero_grad() loss.backward() # gradient descent or adam step optimizer.step() print(f"Cost at epoch {epoch} is {sum(losses)/len(losses):.5f}") # Check accuracy on training & test to see how good our model def check_accuracy(loader, model): if loader.dataset.train: print("Checking accuracy on training data") else: print("Checking accuracy on test data") num_correct = 0 num_samples = 0 model.eval() with torch.no_grad(): for x, y in loader: x = x.to(device=device) y = y.to(device=device) scores = model(x) _, predictions = scores.max(1) num_correct += (predictions == y).sum() num_samples += predictions.size(0) print( f"Got {num_correct} / {num_samples} with accuracy {float(num_correct)/float(num_samples)*100:.2f}" ) model.train() check_accuracy(train_loader, model)