Wat is Transfer Learning?
Transfer Learning is een techniek waarbij een getraind model wordt gebruikt om een andere gerelateerde taak op te lossen. Het is een Machine Learning-onderzoeksmethode die de opgedane kennis tijdens het oplossen van een bepaald probleem opslaat en dezelfde kennis gebruikt om een ander, maar gerelateerd probleem op te lossen. Dit verbetert de efficiëntie door de informatie die is verzameld uit de eerder geleerde taak opnieuw te gebruiken.
Het is populair om het gewicht van een ander netwerkmodel te gebruiken om uw trainingstijd te verkorten, omdat u veel gegevens nodig heeft om een netwerkmodel te trainen. Om de trainingstijd te verminderen, gebruikt u andere netwerken en het gewicht ervan en past u de laatste laag aan om ons probleem op te lossen. Het voordeel is dat je een kleine dataset kunt gebruiken om de laatste laag te trainen.
Vervolgens zullen we in deze PyTorch Transfer Learning-tutorial leren hoe we Transfer Learning met PyTorch kunnen gebruiken.
Dataset laden
Bron: Alien vs. Predator Kaggle
Voordat u Transfer Learning PyTorch gaat gebruiken, moet u de dataset begrijpen die u gaat gebruiken. In dit Transfer Learning PyTorch-voorbeeld classificeer je een Alien en een Predator uit bijna 700 afbeeldingen. Voor deze techniek heb je niet echt veel data nodig om te trainen. U kunt de dataset downloaden van Kaggle: Alien vs. Predator.
Hoe Transfer Learning te gebruiken?
Hier is een stapsgewijs proces voor het gebruik van Transfer Learning voor Deep Learning met PyTorch:
Stap 1) Laad de gegevens
De eerste stap is om onze gegevens te laden en wat transformatie naar afbeeldingen uit te voeren, zodat deze overeenkomen met de netwerkvereisten.
U laadt de gegevens uit een map met torchvision.dataset. De module herhaalt in de map om de gegevens te splitsen voor trein en validatie. Het transformatieproces zal de afbeeldingen vanuit het midden bijsnijden, een horizontale flip uitvoeren, normaliseren en uiteindelijk converteren naar tensor met behulp van 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")
Laten we onze dataset voor PyTorch Transfer Learning visualiseren. Het visualisatieproces haalt de volgende batch afbeeldingen van de treindata-laders en labels en geeft deze weer met 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()
Stap 2) Definieer het model
In dit Deep Learning-proces gebruik je ResNet18 van de torchvision-module.
U zult torchvision.models gebruiken om resnet18 te laden met het vooraf getrainde gewicht ingesteld op True. Daarna bevries je de lagen zodat deze niet trainbaar zijn. Je past ook de laatste laag aan met een lineaire laag om aan onze behoeften te voldoen, namelijk 2 klassen. U gebruikt CrossEntropyLoss ook voor de verliesfunctie van meerdere klassen en voor de optimizer gebruikt u SGD met een leersnelheid van 0,0001 en een momentum van 0,9, zoals weergegeven in het onderstaande PyTorch Transfer Learning-voorbeeld.
## 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)
De output model structuur
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)))
Stap 3) Model trainen en testen
We zullen een deel van de functie van Transfer Learning PyTorch Tutorial gebruiken om ons te helpen bij het trainen en evalueren van ons model.
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)
Laten we tot slot in dit Transfer Learning in PyTorch-voorbeeld ons trainingsproces starten met het aantal tijdperken ingesteld op 25 en evalueren na het trainingsproces. Bij elke trainingsstap neemt het model de input en voorspelt de output. Daarna wordt de voorspelde output doorgegeven aan het criterium om de verliezen te berekenen. Vervolgens zullen de verliezen een backprop-berekening uitvoeren om de helling te berekenen en uiteindelijk de gewichten berekenen en de parameters optimaliseren met autograd.
Bij het visualisatiemodel wordt het getrainde netwerk getest met een batch afbeeldingen om de labels te voorspellen. Vervolgens wordt het gevisualiseerd met behulp van matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Stap 4) Resultaten
Het uiteindelijke resultaat is dat je een nauwkeurigheid van 92% hebt behaald.
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
Einde dan wordt de output van ons model gevisualiseerd met onderstaande matplot:
Overzicht
Dus laten we alles samenvatten! De eerste factor is dat PyTorch een groeiend diepgaand leerkader is voor beginners of voor onderzoeksdoeleinden. Het biedt een hoge rekentijd, Dynamic Graph, GPU's-ondersteuning en het is volledig geschreven in Python. U bent in staat om met gemak onze eigen netwerkmodule te definiëren en het trainingsproces uit te voeren met een gemakkelijke iteratie. Het is duidelijk dat PyTorch ideaal is voor beginners om diep leren te ontdekken en voor professionele onderzoekers is het erg handig met snellere rekentijd en ook de zeer nuttige autograd-functie om dynamische grafieken te ondersteunen.