Какво е трансферното обучение?
Трансферното обучение е техника за използване на обучен модел за решаване на друга свързана задача. Това е метод за машинно обучение, който съхранява знанията, получени по време на решаването на определен проблем и използва същите знания, за да реши друг различен, но все още свързан проблем. Това подобрява ефективността чрез повторно използване на информацията, събрана от предварително научената задача.
Популярно е да се използва тежест на други мрежови модели, за да се намали времето за обучение, защото се нуждаете от много данни, за да обучите мрежов модел. За да намалите времето за обучение, вие използвате други мрежи и тежестта им и модифицирате последния слой, за да разрешите нашия проблем. Предимството е, че можете да използвате малък набор от данни, за да тренирате последния слой.
След това в този урок за обучение на PyTorch Transfer ще научим как да използваме Learning Transfer с PyTorch.
Зареждане на набор от данни
Източник: Alien срещу Predator Kaggle
Преди да започнете да използвате Transfer Learning PyTorch, трябва да разберете набора от данни, който ще използвате. В този пример за трансфер на обучение за PyTorch ще класифицирате извънземен и хищник от близо 700 изображения. За тази техника всъщност нямате нужда от голямо количество данни, за да тренирате. Можете да изтеглите набора от данни от Kaggle: Alien vs. Predator.
Как да използвам трансферното обучение?
Ето стъпка по стъпка как да използвате Transfer Learning за дълбоко обучение с PyTorch:
Стъпка 1) Заредете данните
Първата стъпка е да заредим данните си и да извършим някаква трансформация на изображения, така че да съответстват на мрежовите изисквания.
Ще заредите данните от папка с torchvision.dataset. Модулът ще повтори в папката, за да раздели данните за влак и проверка. Процесът на трансформация ще изреже изображенията от центъра, ще извърши хоризонтално обръщане, ще се нормализира и накрая ще го преобразува в тензор с помощта на 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")
Нека да визуализираме нашия набор от данни за PyTorch Transfer Learning. Процесът на визуализация ще получи следващата партида изображения от устройствата за зареждане на данни и етикетите на влака и ще ги покаже с 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()
Стъпка 2) Определете модела
В този процес на задълбочено обучение ще използвате ResNet18 от Torchvision модул.
Ще използвате Torchvision.models, за да заредите resnet18 с предварително обученото тегло, зададено на True. След това ще замразите слоевете, така че тези слоеве да не могат да бъдат обучени. Можете също така да модифицирате последния слой с линеен слой, за да отговаря на нашите нужди, който е 2 класа. Също така използвате CrossEntropyLoss за мултикласова функция за загуба, а за оптимизатора ще използвате SGD със скорост на обучение 0,0001 и инерция 0,9, както е показано в примера по-долу на 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)
Структура на изходния модел
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)))
Стъпка 3) Модел за обучение и тест
Ще използваме част от функцията от Преподаване на обучение за PyTorch, за да ни помогне да обучим и оценим нашия модел.
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)
И накрая, в този пример за трансфер на обучение в PyTorch, нека започнем процеса на обучение с броя на епохите, зададени на 25 и да оценим след процеса на обучение. На всяка тренировъчна стъпка моделът взема входа и прогнозира изхода. След това прогнозираната продукция ще бъде предадена на критерия за изчисляване на загубите. Тогава загубите ще извършат обратно изчисление за изчисляване на градиента и накрая изчисляване на теглата и оптимизиране на параметрите с автограда.
При визуализирания модел обучената мрежа ще бъде тествана с партида изображения, за да предскаже етикетите. След това ще се визуализира с помощта на matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Стъпка 4) Резултати
Крайният резултат е, че сте постигнали точност от 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
В края на изхода на нашия модел ще се визуализира с matplot по-долу:
Обобщение
И така, нека обобщим всичко! Първият фактор е PyTorch е нарастваща дълбока рамка за обучение за начинаещи или с изследователска цел. Той предлага дълго време за изчисления, динамична графика, поддръжка на графични процесори и е изцяло написан на Python. Можете да дефинирате нашия собствен мрежов модул с лекота и да извършите процеса на обучение с лесна итерация. Ясно е, че PyTorch е идеален за начинаещи, за да разберат задълбоченото обучение, а за професионални изследователи е много полезен с по-бързо изчислително време, а също и много полезната функция autograd за подпомагане на динамична графика.