Ce este Transfer Learning?
Învățarea prin transfer este o tehnică de utilizare a unui model instruit pentru a rezolva o altă sarcină conexă. Este o metodă de cercetare de învățare automată care stochează cunoștințele acumulate în timp ce rezolvă o anumită problemă și folosește aceleași cunoștințe pentru a rezolva o altă problemă diferită, dar conexă. Acest lucru îmbunătățește eficiența prin reutilizarea informațiilor colectate din sarcina învățată anterior.
Este popular să utilizați greutatea altor modele de rețea pentru a vă reduce timpul de antrenament, deoarece aveți nevoie de multe date pentru a instrui un model de rețea. Pentru a reduce timpul de antrenament, utilizați alte rețele și greutatea acesteia și modificați ultimul strat pentru a rezolva problema noastră. Avantajul este că puteți utiliza un mic set de date pentru a antrena ultimul strat.
În continuare, în acest tutorial de învățare PyTorch Transfer, vom învăța cum să folosim Transfer Learning cu PyTorch.
Se încarcă setul de date
Sursa: Alien vs. Predator Kaggle
Înainte de a începe să utilizați Transfer Learning PyTorch, trebuie să înțelegeți setul de date pe care urmează să îl utilizați. În acest exemplu de învățare de transfer PyTorch, veți clasifica un extraterestru și un prădător din aproape 700 de imagini. Pentru această tehnică, nu aveți nevoie de o cantitate mare de date pentru a vă antrena. Puteți descărca setul de date din Kaggle: Alien vs. Predator.
Cum se folosește Transfer Learning?
Iată un proces pas cu pas despre cum să utilizați Transfer Learning pentru Deep Learning cu PyTorch:
Pasul 1) Încărcați datele
Primul pas este să ne încărcăm datele și să facem o transformare în imagini, astfel încât să corespundă cerințelor rețelei.
Veți încărca datele dintr-un folder cu torchvision.dataset. Modulul va itera în folder pentru a împărți datele pentru tren și validare. Procesul de transformare va decupa imaginile din centru, va efectua un flip orizontal, se va normaliza și, în cele din urmă, le va converti în tensor folosind Deep Learning.
from __future__ import print_function, divisionimport osimport timeimport torchimport torchvisionfrom torchvision import datasets, models, transformsimport torch.optim as optimimport numpy as npimport matplotlib.pyplot as pltdata_dir = "alien_pred"input_shape = 224mean = [0.5, 0.5, 0.5]std = [0.5, 0.5, 0.5]#data transformationdata_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'].classesdevice = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Să ne vizualizăm setul de date pentru PyTorch Transfer Learning. Procesul de vizualizare va obține următorul lot de imagini de pe încărcătoarele de date și etichete ale trenului și îl va afișa cu matplot.
images, labels = next(iter(dataloaders['train']))rows = 4columns = 4fig=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 + meanplt.imshow(img)plt.show()
Pasul 2) Definiți modelul
În acest proces de învățare profundă, veți utiliza ResNet18 din modulul torchvision.
Veți utiliza torchvision.models pentru a încărca resnet18 cu greutatea pre-antrenată setată ca fiind True. După aceea, veți îngheța straturile, astfel încât aceste straturi să nu fie antrenabile. De asemenea, modificați ultimul strat cu un strat liniar pentru a se potrivi cu nevoile noastre, care este de 2 clase. De asemenea, utilizați CrossEntropyLoss pentru funcția de pierdere în mai multe clase, iar pentru optimizator veți utiliza SGD cu o rată de învățare de 0.0001 și un impuls de 0.9 așa cum se arată în exemplul de învățare de transfer PyTorch de mai jos.
## Load the model based on VGG19vgg_based = torchvision.models.vgg19(pretrained=True)## freeze the layersfor param in vgg_based.parameters():param.requires_grad = False# Modify the last layernumber_features = vgg_based.classifier[6].in_featuresfeatures = list(vgg_based.classifier.children())[:-1] # Remove last layerfeatures.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)
Structura modelului de ieșire
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)))
Pasul 3) Antrenează și testează modelul
Vom folosi o parte din funcția din Transfer Learning PyTorch Tutorial pentru a ne ajuta să ne instruim și să ne evaluăm modelul.
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 = datainputs = 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() - sinceprint('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))return modeldef visualize_model(model, num_images=6):was_training = model.trainingmodel.eval()images_so_far = 0fig = 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 += 1ax = 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 + meanax.imshow(img)if images_so_far == num_images:model.train(mode=was_training)returnmodel.train(mode=was_training)
În sfârșit, în acest exemplu de învățare prin transfer în PyTorch, să începem procesul de formare cu numărul de epoci setat la 25 și să evaluăm după procesul de formare. La fiecare pas de antrenament, modelul va prelua intrarea și va prezice rezultatul. După aceea, rezultatul previzionat va fi trecut la criteriul de calcul al pierderilor. Apoi pierderile vor efectua un calcul backprop pentru a calcula gradientul și în cele din urmă pentru a calcula greutățile și pentru a optimiza parametrii cu autograd.
La modelul de vizualizare, rețeaua instruită va fi testată cu un lot de imagini pentru a prezice etichetele. Apoi va fi vizualizat cu ajutorul matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Pasul 4) Rezultate
Rezultatul final este că ați obținut o precizie de 92%.
Epoch 23/24----------train Loss: 0.0044train Loss: 0.0078train Loss: 0.0141train Loss: 0.0221train Loss: 0.0306train Loss: 0.0336train Loss: 0.0442train Loss: 0.0482train Loss: 0.0557train Loss: 0.0643train Loss: 0.0763train Loss: 0.0779train Loss: 0.0843train Loss: 0.0910train Loss: 0.0990train Loss: 0.1063train Loss: 0.1133train Loss: 0.1220train Loss: 0.1344train Loss: 0.1382train Loss: 0.1429train Loss: 0.1500Epoch 24/24----------train Loss: 0.0076train Loss: 0.0115train Loss: 0.0185train Loss: 0.0277train Loss: 0.0345train Loss: 0.0420train Loss: 0.0450train Loss: 0.0490train Loss: 0.0644train Loss: 0.0755train Loss: 0.0813train Loss: 0.0868train Loss: 0.0916train Loss: 0.0980train Loss: 0.1008train Loss: 0.1101train Loss: 0.1176train Loss: 0.1282train Loss: 0.1323train Loss: 0.1397train Loss: 0.1436train Loss: 0.1467Training complete in 2m 47s
Încheiați, apoi rezultatul modelului nostru va fi vizualizat cu matplot mai jos:
rezumat
Deci, să rezumăm totul! Primul factor este că PyTorch este un cadru de învățare profundă în creștere pentru începători sau în scopuri de cercetare. Oferă timp de calcul ridicat, grafic dinamic, suport pentru GPU-uri și este complet scris în Python. Puteți defini cu ușurință propriul nostru modul de rețea și puteți efectua procesul de instruire cu o iterație ușoară. Este clar că PyTorch este ideal pentru începători să afle învățarea profundă, iar pentru cercetătorii profesioniști este foarte util cu timp de calcul mai rapid și, de asemenea, funcția foarte utilă de autograd pentru a ajuta graficul dinamic.