Mikä on siirto-oppiminen?
Transfer Learning on tekniikka, jolla koulutettua mallia käytetään toisen siihen liittyvän tehtävän ratkaisemiseen. Se on koneoppimisen tutkimusmenetelmä, joka tallentaa tietyn ongelman ratkaisemisessa saadun tiedon ja käyttää samaa tietoa toisen erilaisen, mutta siihen liittyvän ongelman ratkaisemiseksi. Tämä parantaa tehokkuutta hyödyntämällä aiemmin opitusta tehtävästä kerättyä tietoa.
On suositeltavaa käyttää muuta verkkomallin painoa harjoitteluaikasi lyhentämiseen, koska tarvitset paljon tietoa verkkomallin kouluttamiseen. Harjoitteluajan lyhentämiseksi käytät muita verkkoja ja niiden painoa ja muokkaat viimeistä kerrosta ongelmamme ratkaisemiseksi. Etuna on, että voit käyttää pientä tietoaineistoa viimeisen kerroksen kouluttamiseen.
Seuraavaksi tässä PyTorch Transfer -opetusoppaassa opit käyttämään Transfer Learning -ohjelmaa PyTorchin kanssa.
Ladataan tietoaineistoa
Lähde: Alien vs.Predator Kaggle
Ennen kuin aloitat Transfer Learning PyTorchin käytön, sinun on ymmärrettävä tietojoukko, jota aiot käyttää. Tässä Transfer Learning PyTorch -esimerkissä luokitellaan ulkomaalainen ja saalistaja lähes 700 kuvasta. Tätä tekniikkaa varten et todellakaan tarvitse suurta määrää tietoa harjoittelua varten. Voit ladata tietojoukon Kaggle: Alien vs. Predator -sivulta.
Kuinka käyttää siirto-oppimista?
Tässä on askel askeleelta prosessi siitä, miten siirto-oppimista käytetään syvälliseen oppimiseen PyTorchin kanssa:
Vaihe 1) Lataa tiedot
Ensimmäinen vaihe on ladata tietomme ja tehdä muutos kuviksi siten, että se vastaa verkon vaatimuksia.
Ladaat tiedot kansiosta, jossa on torchvision.dataset. Moduuli toistaa kansion jakamaan tiedot junaa ja validointia varten. Muunnosprosessi rajaa kuvat keskeltä, suorittaa vaakasuoran käännön, normalisoi ja lopulta muuntaa sen tensoriksi Deep Learning -toiminnon avulla.
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")
Visualisoidaan PyTorch Transfer Learning -tietojoukkomme. Visualisointiprosessi saa seuraavan erän junan datakuormaajista ja tarroista ja näyttää sen matplotilla.
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()
Vaihe 2) Määritä malli
Tässä syvällisessä oppimisprosessissa käytetään ResNet18 from torchvision -moduulia.
Ladat resnet18: n käyttämällä torchvision.models-mallia, kun ennalta koulutettu paino on tosi. Sen jälkeen jäädytät kerrokset niin, että nämä kerrokset eivät ole treenattavissa. Voit myös muokata viimeistä kerrosta lineaarisella kerroksella tarpeidemme mukaiseksi eli 2 luokkaa. Käytät myös CrossEntropyLossia moniluokkaisiin tappiotoimintoihin ja optimoijaan SGD: tä, jonka oppimisnopeus on 0,0001 ja liikemäärä 0,9, kuten alla olevassa PyTorch Transfer Learning -esimerkissä näkyy.
## 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)
Tuotosmallin rakenne
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)))
Vaihe 3) Juna- ja testimalli
Käytämme joitain Transfer Learning PyTorch Tutorial -toiminnon toimintoja auttaaksemme meitä kouluttamaan ja arvioimaan malliamme.
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)
Lopuksi tässä esimerkissä PyTorch Transfer Learning, aloitetaan harjoitusprosessimme asettamalla aikakausien lukumääräksi 25 ja arvioimalla harjoitusprosessin jälkeen. Kussakin harjoitteluvaiheessa malli ottaa panoksen ja ennustaa tuotoksen. Sen jälkeen ennustettu tuotos välitetään kriteerille tappioiden laskemiseksi. Sitten tappiot suorittavat backprop-laskelman gradientin laskemiseksi ja lopuksi painojen laskemiseksi ja parametrien optimoimiseksi autogradilla.
Visualisointimallissa koulutettu verkko testataan kuvaryhmällä tarrojen ennustamiseksi. Sitten se visualisoidaan matplotlibin avulla.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Vaihe 4) Tulokset
Lopputulos on, että saavutit 92 prosentin tarkkuuden.
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
Loppu sitten mallimme tuotos visualisoidaan alla olevan matplotin avulla:
Yhteenveto
Joten tiivistetään kaikki! Ensimmäinen tekijä on, että PyTorch on kasvava syvällinen oppimiskehys aloittelijoille tai tutkimustarkoituksiin. Se tarjoaa korkean laskenta-ajan, dynaamisen kaavion, grafiikkasuoritinten tuen ja se on kirjoitettu täysin Pythonissa. Pystyt määrittelemään oman verkkomoduulimme helposti ja tekemään harjoitusprosessin helposti iteroimalla. On selvää, että PyTorch on ihanteellinen aloittelijoille syvällisen oppimisen oppimiseksi, ja ammattimaisille tutkijoille se on erittäin hyödyllinen nopeammalla laskenta-ajalla ja erittäin hyödyllisellä autograd-toiminnolla, joka auttaa dynaamista kuvaajaa.