Co to jest transfer uczenia się?
Transfer Learning to technika wykorzystania wytrenowanego modelu do rozwiązania innego powiązanego zadania. Jest to metoda badawcza uczenia maszynowego, która przechowuje wiedzę zdobytą podczas rozwiązywania konkretnego problemu i wykorzystuje tę samą wiedzę do rozwiązania innego, ale powiązanego problemu. Poprawia to wydajność poprzez ponowne wykorzystanie informacji zebranych z wcześniej wyuczonego zadania.
Popularne jest używanie innej wagi modelu sieci, aby skrócić czas uczenia, ponieważ do trenowania modelu sieci potrzeba dużej ilości danych. Aby skrócić czas szkolenia, wykorzystujesz inne sieci i jego wagę i modyfikujesz ostatnią warstwę, aby rozwiązać nasz problem. Zaletą jest to, że możesz użyć małego zbioru danych do trenowania ostatniej warstwy.
Następnie w tym samouczku szkoleniowym dotyczącym narzędzia PyTorch Transfer dowiemy się, jak korzystać z nauki transferu w programie PyTorch.
Ładowanie zbioru danych
Źródło: Alien vs. Predator Kaggle
Zanim zaczniesz korzystać z narzędzia Transfer Learning PyTorch, musisz zapoznać się z zestawem danych, którego będziesz używać. W tym przykładzie Transfer Learning PyTorch sklasyfikujesz Obcego i Predatora z prawie 700 obrazów. W przypadku tej techniki naprawdę nie potrzebujesz dużej ilości danych do trenowania. Możesz pobrać zestaw danych z Kaggle: Alien vs. Predator.
Jak korzystać z transferu uczenia się?
Oto proces krok po kroku, jak korzystać z uczenia transferowego w uczeniu głębokim z PyTorch:
Krok 1) Załaduj dane
Pierwszym krokiem jest załadowanie naszych danych i dokonanie transformacji do obrazów, tak aby pasowały do wymagań sieci.
Dane zostaną załadowane z folderu zawierającego torchvision.dataset. Moduł dokona iteracji w folderze, aby podzielić dane do pociągu i walidacji. Proces transformacji obetnie obrazy od środka, wykona odwrócenie w poziomie, znormalizuje i ostatecznie przekształci je w tensor za pomocą głębokiego uczenia.
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")
Zwizualizujmy nasz zbiór danych dla PyTorch Transfer Learning. Proces wizualizacji pobierze kolejną partię obrazów z modułów ładujących dane pociągu i etykiet i wyświetli ją za pomocą 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()
Krok 2) Zdefiniuj model
W tym procesie Deep Learning użyjesz ResNet18 z modułu torchvision.
Użyjesz torchvision.models do załadowania resnet18 z wstępnie wytrenowaną wagą ustawioną na True. Następnie zamrozisz warstwy, aby nie można ich było trenować. Zmodyfikujesz również ostatnią warstwę warstwą Linear, aby dopasować ją do naszych potrzeb, czyli 2 klasy. Używasz również CrossEntropyLoss dla funkcji strat z wieloma klasami, a dla optymalizatora użyjesz SGD z szybkością uczenia się 0,0001 i momentum 0,9, jak pokazano w poniższym przykładzie nauki transferu PyTorch.
## 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 modelu wyjściowego
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)))
Krok 3) Wytrenuj i przetestuj model
Użyjemy niektórych funkcji z samouczka Transfer Learning PyTorch, aby pomóc nam trenować i oceniać nasz 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)
Na koniec, w tym przykładzie Transfer Learning w PyTorch, zacznijmy nasz proces szkolenia od liczby epok ustawionej na 25 i dokonajmy oceny po zakończeniu procesu szkolenia. Na każdym etapie szkolenia model będzie uwzględniał dane wejściowe i przewidywał wyniki. Następnie przewidywana produkcja zostanie przekazana do kryterium obliczania strat. Następnie straty wykonają obliczenia backprop, aby obliczyć gradient i ostatecznie obliczyć wagi i zoptymalizować parametry za pomocą autogradu.
W modelu wizualizacji przeszkolona sieć zostanie przetestowana przy użyciu partii obrazów, aby przewidzieć etykiety. Następnie zostanie zwizualizowany za pomocą matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Krok 4) Wyniki
Ostateczny wynik jest taki, że osiągnąłeś dokładność na poziomie 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 koniec dane wyjściowe naszego modelu zostaną zwizualizowane za pomocą poniższego wykresu matowego:
Podsumowanie
Podsumujmy więc wszystko! Pierwszym czynnikiem jest to, że PyTorch to rozwijająca się platforma uczenia głębokiego dla początkujących lub do celów badawczych. Oferuje wysoki czas obliczeń, dynamiczny wykres, obsługę procesorów graficznych i jest całkowicie napisany w języku Python. Jesteś w stanie z łatwością zdefiniować nasz własny moduł sieciowy i przeprowadzić proces szkolenia z prostą iteracją. Oczywiste jest, że PyTorch jest idealny dla początkujących, aby odkryć głębokie uczenie, a dla profesjonalnych badaczy jest bardzo przydatny dzięki szybszemu czasowi obliczeń, a także bardzo pomocnej funkcji autograd, która wspomaga dynamiczny wykres.