Vodič za učenje prijenosa PyTorcha s primjerima
Što je transferno učenje?
Prijenos učenja je tehnika korištenja uvježbanog modela za rješavanje drugog srodnog zadatka. To je istraživačka metoda strojnog učenja koja pohranjuje znanje stečeno tijekom rješavanja određenog problema i koristi isto znanje za rješavanje drugog različitog, ali povezanog problema. To poboljšava učinkovitost ponovnim korištenjem informacija prikupljenih iz prethodno naučenog zadatka.
Popularno je koristiti drugu težinu mrežnog modela kako biste smanjili vrijeme vježbanja jer vam je potrebno mnogo podataka za treniranje mrežnog modela. Da biste smanjili vrijeme treninga, koristite druge mreže i njihovu težinu i modificirajte posljednji sloj kako biste riješili naš problem. Prednost je što možete koristiti mali skup podataka za obuku posljednjeg sloja.
Zatim ćemo u ovom vodiču za učenje prijenosa PyTorch naučiti kako koristiti učenje prijenosa s PyTorchom.
Učitavanje skupa podataka
Izvor: Alien vs. Predator Kaggle
Prije nego počnete koristiti Transfer Learning PyTorch, morate razumjeti skup podataka koji ćete koristiti. U ovom primjeru Transfer Learning PyTorch klasificirati ćete izvanzemaljca i predatora iz gotovo 700 slika. Za ovu tehniku zapravo vam nije potrebna velika količina podataka za treniranje. Skup podataka možete preuzeti s Kaggle: Alien protiv Predatora.
Kako koristiti prijenos učenja?
Ovdje je korak po korak postupak kako koristiti Transfer Learning za duboko učenje s PyTorchom:
Korak 1) Učitajte podatke
Prvi korak je učitavanje naših podataka i neka transformacija slika tako da odgovaraju zahtjevima mreže.
Učitat ćete podatke iz mape s torchvision.dataset. Modul će ponavljati u mapi kako bi podijelio podatke za obuku i provjeru valjanosti. Proces transformacije izrezat će slike iz središta, izvršiti horizontalno okretanje, normalizirati i konačno pretvoriti u tenzor koristeći 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")
Idemo vizualizirati naš skup podataka za PyTorch Transfer Learning. Proces vizualizacije će dobiti sljedeću skupinu slika iz učitavača podataka o vlaku i naljepnica i prikazati ih s matplotom.
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()
Korak 2) Definirajte model
U ovom Duboko učenje procesu, koristit ćete ResNet18 iz torchvision modula.
Koristit ćete torchvision.models za učitavanje resnet18 s prethodno uvježbanom težinom postavljenom na True. Nakon toga ćete zamrznuti slojeve tako da se ti slojevi ne mogu trenirati. Također mijenjate posljednji sloj s linearnim slojem kako bi odgovarao našim potrebama, a to su 2 klase. Također koristite CrossEntropyLoss za funkciju gubitka više klasa, a za optimizator ćete koristiti SGD sa stopom učenja od 0.0001 i momentom od 0.9 kao što je prikazano u donjem primjeru učenja PyTorch Transfera.
## 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)
Struktura izlaznog modela
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) ) )
Korak 3) Obuka i testiranje modela
Koristit ćemo neke od funkcija iz Transfer Learninga Vodič za PyTorch da nam pomognu u obuci i procjeni našeg modela.
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)
Konačno, u ovom primjeru prijenosa učenja u PyTorchu, započnimo naš proces obuke s brojem epoha postavljenim na 25 i procijenimo nakon procesa obuke. U svakom koraku obuke, model će uzeti ulaz i predvidjeti izlaz. Nakon toga, predviđeni izlaz će se proslijediti kriteriju za izračun gubitaka. Zatim će gubici izvršiti izračun pozadinske potpore za izračun gradijenta i na kraju izračunati težine i optimizirati parametre s autogradom.
Na modelu vizualizacije, obučena mreža će se testirati sa serijom slika za predviđanje oznaka. Zatim će se vizualizirati uz pomoć matplotliba.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
Korak 4) Rezultati
Konačni rezultat je da ste postigli točnost od 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
Kraj, tada će se izlaz našeg modela vizualizirati s matplotom ispod:
rezime
Dakle, rezimirajmo sve! Prvi faktor je da je PyTorch rastući okvir dubokog učenja za početnike ili u istraživačke svrhe. Nudi dugo vrijeme računanja, Dynamic Graph, podršku za GPU i potpuno je upisan Python. U mogućnosti ste s lakoćom definirati vlastiti mrežni modul i obaviti proces obuke s jednostavnom iteracijom. Jasno je da je PyTorch idealan za početnike kako bi saznali dubinsko učenje, a za profesionalne istraživače vrlo je koristan s bržim vremenom računanja i također vrlo korisnom funkcijom autograd za pomoć dinamičkom grafikonu.