""" 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. Video explanation: https://youtu.be/U4bHxEhMGNk Got any questions leave a comment on youtube :) Programmed by Aladdin Persson * 2020-04-08 Initial coding """ # 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 # Set device 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 # Simple Identity class that let's input pass without changes class Identity(nn.Module): def __init__(self): super(Identity, self).__init__() def forward(self, x): return x # Load pretrain model & modify it model = torchvision.models.vgg16(pretrained=True) # 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 = 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(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)