PyTorch Transfer Learning Tutorial med exempel
Vad är Transfer Learning?
Överför lärande är en teknik för att använda en tränad modell för att lösa en annan relaterad uppgift. Det är en forskningsmetod för maskininlärning som lagrar den kunskap som erhållits när man löser ett visst problem och använder samma kunskap för att lösa ett annat annat men relaterat problem. Detta förbättrar effektiviteten genom att återanvända informationen från den tidigare inlärda uppgiften.
Det är populärt att använda andra nätverksmodeller för att minska din träningstid eftersom du behöver mycket data för att träna en nätverksmodell. För att minska träningstiden använder du andra nätverk och dess vikt och modifierar det sista lagret för att lösa vårt problem. Fördelen är att du kan använda en liten datauppsättning för att träna det sista lagret.
Härnäst i denna PyTorch Transfer-inlärningshandledning kommer vi att lära oss hur man använder Transfer Learning med PyTorch.
Laddar datauppsättning
Källa: Alien vs Predator Kaggle
Innan du börjar använda Transfer Learning PyTorch måste du förstå datasetet som du ska använda. I det här Transfer Learning PyTorch-exemplet kommer du att klassificera en Alien och en Predator från nästan 700 bilder. För den här tekniken behöver du egentligen inte en stor mängd data för att träna. Du kan ladda ner datamängden från Kaggle: Alien vs. Predator.
Hur använder man Transfer Learning?
Här är en steg-för-steg-process om hur du använder Transfer Learning för djupinlärning med PyTorch:
Steg 1) Ladda data
Det första steget är att ladda vår data och göra lite omvandling till bilder så att de matchar nätverkskraven.
Du kommer att ladda data från en mapp med torchvision.dataset. Modulen kommer att iterera i mappen för att dela upp data för tåg och validering. Transformationsprocessen kommer att beskära bilderna från mitten, utföra en horisontell vändning, normalisera och slutligen konvertera den till tensor med hjälp av Deep Learning.
from __future__ import print_function, division import os import time import torch import torchvision from torchvision import datasets, models, transforms import torch.optim as optim import numpy as np import matplotlib.pyplot as plt data_dir = "alien_pred" input_shape = 224 mean = [0.5, 0.5, 0.5] std = [0.5, 0.5, 0.5] #data transformation data_transforms = { 'train': transforms.Compose([ transforms.CenterCrop(input_shape), transforms.ToTensor(), transforms.Normalize(mean, std) ]), 'validation': transforms.Compose([ transforms.CenterCrop(input_shape), transforms.ToTensor(), transforms.Normalize(mean, std) ]), } image_datasets = { x: datasets.ImageFolder( os.path.join(data_dir, x), transform=data_transforms[x] ) for x in ['train', 'validation'] } dataloaders = { x: torch.utils.data.DataLoader( image_datasets[x], batch_size=32, shuffle=True, num_workers=4 ) for x in ['train', 'validation'] } dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'validation']} print(dataset_sizes) class_names = image_datasets['train'].classes device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Låt oss visualisera vår datauppsättning för PyTorch Transfer Learning. Visualiseringsprocessen kommer att hämta nästa sats bilder från tågdataladdare och etiketter och visa den med matplot.
images, labels = next(iter(dataloaders['train'])) rows = 4 columns = 4 fig=plt.figure() for i in range(16): fig.add_subplot(rows, columns, i+1) plt.title(class_names[labels[i]]) img = images[i].numpy().transpose((1, 2, 0)) img = std * img + mean plt.imshow(img) plt.show()
Steg 2) Definiera modell
I detta Deep Learning process kommer du att använda ResNet18 från torchvision-modulen.
Du kommer att använda torchvision.models för att ladda resnet18 med den förtränade vikten inställd på True. Efter det kommer du att frysa lagren så att dessa lager inte går att träna. Du modifierar även det sista lagret med ett linjärt lager för att passa våra behov som är 2 klasser. Du använder också CrossEntropyLoss för multi-class förlustfunktion och för optimeraren kommer du att använda SGD med inlärningshastigheten 0.0001 och ett momentum på 0.9 som visas i nedanstående PyTorch Transfer Learning-exempel.
## Load the model based on VGG19 vgg_based = torchvision.models.vgg19(pretrained=True) ## freeze the layers for param in vgg_based.parameters(): param.requires_grad = False # Modify the last layer number_features = vgg_based.classifier[6].in_features features = list(vgg_based.classifier.children())[:-1] # Remove last layer features.extend([torch.nn.Linear(number_features, len(class_names))]) vgg_based.classifier = torch.nn.Sequential(*features) vgg_based = vgg_based.to(device) print(vgg_based) criterion = torch.nn.CrossEntropyLoss() optimizer_ft = optim.SGD(vgg_based.parameters(), lr=0.001, momentum=0.9)
Utgångsmodellens struktur
VGG( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU(inplace) (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (3): ReLU(inplace) (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (6): ReLU(inplace) (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (8): ReLU(inplace) (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU(inplace) (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (13): ReLU(inplace) (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (15): ReLU(inplace) (16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (17): ReLU(inplace) (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (20): ReLU(inplace) (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (22): ReLU(inplace) (23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (24): ReLU(inplace) (25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (26): ReLU(inplace) (27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (29): ReLU(inplace) (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (31): ReLU(inplace) (32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (33): ReLU(inplace) (34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (35): ReLU(inplace) (36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) (classifier): Sequential( (0): Linear(in_features=25088, out_features=4096, bias=True) (1): ReLU(inplace) (2): Dropout(p=0.5) (3): Linear(in_features=4096, out_features=4096, bias=True) (4): ReLU(inplace) (5): Dropout(p=0.5) (6): Linear(in_features=4096, out_features=2, bias=True) ) )
Steg 3) Träna och testa modell
Vi kommer att använda några av funktionerna från Transfer Learning PyTorch handledning för att hjälpa oss att träna och utvärdera vår modell.
def train_model(model, criterion, optimizer, num_epochs=25): since = time.time() for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch, num_epochs - 1)) print('-' * 10) #set model to trainable # model.train() train_loss = 0 # Iterate over data. for i, data in enumerate(dataloaders['train']): inputs , labels = data inputs = inputs.to(device) labels = labels.to(device) optimizer.zero_grad() with torch.set_grad_enabled(True): outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() train_loss += loss.item() * inputs.size(0) print('{} Loss: {:.4f}'.format( 'train', train_loss / dataset_sizes['train'])) time_elapsed = time.time() - since print('Training complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) return model def visualize_model(model, num_images=6): was_training = model.training model.eval() images_so_far = 0 fig = plt.figure() with torch.no_grad(): for i, (inputs, labels) in enumerate(dataloaders['validation']): inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) _, preds = torch.max(outputs, 1) for j in range(inputs.size()[0]): images_so_far += 1 ax = plt.subplot(num_images//2, 2, images_so_far) ax.axis('off') ax.set_title('predicted: {} truth: {}'.format(class_names[preds[j]], class_names[labels[j]])) img = inputs.cpu().data[j].numpy().transpose((1, 2, 0)) img = std * img + mean ax.imshow(img) if images_so_far == num_images: model.train(mode=was_training) return model.train(mode=was_training)
Slutligen i detta Transfer Learning i PyTorch-exemplet, låt oss börja vår träningsprocess med antalet epoker inställt på 25 och utvärdera efter träningsprocessen. Vid varje träningssteg kommer modellen att ta indata och förutsäga resultatet. Efter det kommer den förutsagda uteffekten att överföras till kriteriet för att beräkna förlusterna. Sedan kommer förlusterna att utföra en backprop-beräkning för att beräkna gradienten och slutligen beräkna vikterna och optimera parametrarna med autograd.
Vid visualiseringsmodellen kommer det utbildade nätverket att testas med en grupp bilder för att förutsäga etiketterna. Sedan kommer det att visualiseras med hjälp av matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
Steg 4) Resultat
Slutresultatet är att du uppnådde en noggrannhet på 92%.
Epoch 23/24 ---------- train Loss: 0.0044 train Loss: 0.0078 train Loss: 0.0141 train Loss: 0.0221 train Loss: 0.0306 train Loss: 0.0336 train Loss: 0.0442 train Loss: 0.0482 train Loss: 0.0557 train Loss: 0.0643 train Loss: 0.0763 train Loss: 0.0779 train Loss: 0.0843 train Loss: 0.0910 train Loss: 0.0990 train Loss: 0.1063 train Loss: 0.1133 train Loss: 0.1220 train Loss: 0.1344 train Loss: 0.1382 train Loss: 0.1429 train Loss: 0.1500 Epoch 24/24 ---------- train Loss: 0.0076 train Loss: 0.0115 train Loss: 0.0185 train Loss: 0.0277 train Loss: 0.0345 train Loss: 0.0420 train Loss: 0.0450 train Loss: 0.0490 train Loss: 0.0644 train Loss: 0.0755 train Loss: 0.0813 train Loss: 0.0868 train Loss: 0.0916 train Loss: 0.0980 train Loss: 0.1008 train Loss: 0.1101 train Loss: 0.1176 train Loss: 0.1282 train Loss: 0.1323 train Loss: 0.1397 train Loss: 0.1436 train Loss: 0.1467 Training complete in 2m 47s
Sluta då kommer produktionen av vår modell att visualiseras med matplot nedan:
Sammanfattning
Så låt oss sammanfatta allt! Den första faktorn är PyTorch är ett växande ramverk för djupinlärning för nybörjare eller för forskningsändamål. Den erbjuder hög beräkningstid, Dynamic Graph, GPU-stöd och det är helt inskrivet Python. Du kan enkelt definiera din egen nätverksmodul och göra träningsprocessen med en enkel iteration. Det är tydligt att PyTorch är idealiskt för nybörjare för att ta reda på djup inlärning och för professionella forskare är det mycket användbart med snabbare beräkningstid och även den mycket hjälpsamma autogradfunktionen för att hjälpa dynamisk graf.