Što je prijenosno učenje?
Transfer učenje je tehnika korištenja obučenog modela za rješavanje drugog povezanog zadatka. To je metoda istraživanja 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 ponovnom upotrebom podataka prikupljenih iz prethodno naučenog zadatka.
Popularno je koristiti drugu težinu mrežnog modela kako biste smanjili vrijeme treninga, jer vam je potrebno puno podataka da biste trenirali mrežni model. Da biste smanjili vrijeme treninga, koristite druge mreže i njihovu težinu i izmijenite posljednji sloj da biste riješili naš problem. Prednost je što možete koristiti mali skup podataka za treniranje posljednjeg sloja.
Sljedeće u ovom vodiču za učenje PyTorch Transfera naučit ćemo kako se koristi Transfer Learning s PyTorchom.
Učitavanje skupa podataka
Izvor: Alien vs. Predator Kaggle
Prije nego što počnete koristiti Transfer Learning PyTorch, morate razumjeti skup podataka koji ćete koristiti. U ovom primjeru PyTorch za prijenos učenja klasificirat ćete vanzemaljca i grabežljivca iz gotovo 700 slika. Za ovu tehniku vam zapravo nije potrebna velika količina podataka za trening. Skup podataka možete preuzeti s Kaggle: Alien vs. Predator.
Kako se koristi učenje transfera?
Slijedi korak po korak kako koristiti prijenos učenja za dubinsko učenje s PyTorchom:
Korak 1) Učitajte podatke
Prvi je korak učitati naše podatke i napraviti neku transformaciju slika tako da odgovaraju mrežnim zahtjevima.
Učitat ćete podatke iz mape s torchvision.dataset. Modul će se ponoviti u mapi kako bi podijelio podatke za vlak i provjeru valjanosti. Proces transformacije obrezati će slike iz središta, izvesti vodoravno okretanje, normalizirati i na kraju pretvoriti u tenzor pomoću dubokog učenja.
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")
Vizualizirajmo naš skup podataka za PyTorch Transfer Learning. Postupak vizualizacije dobit će sljedeću seriju slika iz uređaja za učitavanje vlakova i naljepnica i prikazati ih matplotom.
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()
Korak 2) Definirajte model
U ovom procesu dubokog učenja koristit ćete ResNet18 iz modula torchvision.
Upotrijebit ćete Torchvision.models za učitavanje resnet18 s unaprijed obučenom težinom postavljenom na True. Nakon toga zamrznut ćete slojeve tako da se ti slojevi ne mogu obučiti. Također posljednji sloj modificirate Linearnim slojem kako bi odgovarao našim potrebama, a to su 2 klase. Također koristite CrossEntropyLoss za višerazrednu funkciju gubitka, a za optimizator ćete koristiti SGD sa stopom učenja 0,0001 i impulsom 0,9, kao što je prikazano u donjem primjeru PyTorch Transfer Learning.
## 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)
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) Model treninga i testa
Koristit ćemo neke od funkcija iz Transfer Learning PyTorch Tutorial-a kako bi nam pomogli u treningu 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 = 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)
Napokon, u ovom primjeru Prijenosa učenja u PyTorchu, započnimo svoj proces treninga s brojem epoha postavljenih na 25 i procijenimo nakon procesa treninga. U svakom koraku treninga model će uzimati ulaz i predviđati izlaz. Nakon toga, predviđeni izlaz proslijedit će se na kriterij za izračunavanje gubitaka. Tada će gubici izvršiti izračun povratnog sloja za izračunavanje gradijenta i konačno izračunavanje težina i optimizaciju parametara pomoću autogradnje.
Na vizualiziranom modelu obučena mreža testirat će se sa nizom slika kako bi se predvidjele oznake. Tada ć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.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
Na kraju će se izlaz našeg modela vizualizirati matplotom ispod:
Sažetak
Dakle, sažejmo sve! Prvi je čimbenik PyTorch rastući okvir za duboko učenje za početnike ili u istraživačke svrhe. Nudi dugo računanje, dinamički graf, podršku za grafičke procesore i u potpunosti je napisan na Pythonu. Možete s lakoćom definirati naš vlastiti mrežni modul i odraditi proces obuke s laganom iteracijom. Jasno je da je PyTorch idealan za početnike kako bi otkrili duboko učenje, a za profesionalne istraživače vrlo je koristan s bržim vremenom izračunavanja i vrlo korisnom funkcijom autograda za pomoć dinamičkom grafu.