O que é transferência de aprendizagem?
Transfer Learning é uma técnica de usar um modelo treinado para resolver outra tarefa relacionada. É um método de pesquisa de Aprendizado de Máquina que armazena o conhecimento adquirido ao resolver um problema específico e usa o mesmo conhecimento para resolver outro problema diferente, mas relacionado. Isso melhora a eficiência, reutilizando as informações coletadas na tarefa aprendida anteriormente.
É comum usar outro peso de modelo de rede para reduzir o tempo de treinamento porque você precisa de muitos dados para treinar um modelo de rede. Para reduzir o tempo de treinamento, você usa outras redes e seu peso e modifica a última camada para resolver nosso problema. A vantagem é que você pode usar um pequeno conjunto de dados para treinar a última camada.
A seguir, neste tutorial de aprendizagem do PyTorch Transfer, aprenderemos como usar o Transfer Learning com o PyTorch.
Carregando conjunto de dados
Fonte: Alien vs. Predator Kaggle
Antes de começar a usar o Transfer Learning PyTorch, você precisa entender o conjunto de dados que vai usar. Neste exemplo do Transfer Learning PyTorch, você classificará um Alien e um Predator a partir de cerca de 700 imagens. Para essa técnica, você realmente não precisa de uma grande quantidade de dados para treinar. Você pode baixar o conjunto de dados de Kaggle: Alien vs. Predator.
Como usar a aprendizagem por transferência?
Aqui está um processo passo a passo sobre como usar o Transfer Learning para Deep Learning com PyTorch:
Etapa 1) Carregar os dados
A primeira etapa é carregar nossos dados e fazer alguma transformação nas imagens para que correspondam aos requisitos da rede.
Você carregará os dados de uma pasta com torchvision.dataset. O módulo irá iterar na pasta para dividir os dados para treinamento e validação. O processo de transformação recortará as imagens do centro, realizará uma inversão horizontal, normalizará e, finalmente, converterá em tensor usando 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")
Vamos visualizar nosso conjunto de dados para PyTorch Transfer Learning. O processo de visualização obterá o próximo lote de imagens dos carregadores de dados e rótulos do trem e o exibirá com 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()
Etapa 2) Definir o modelo
Neste processo de aprendizado profundo, você usará o ResNet18 do módulo torchvision.
Você usará torchvision.models para carregar resnet18 com o peso pré-treinado definido como True. Depois disso, você congelará as camadas para que não sejam treináveis. Você também modifica a última camada com uma camada Linear para se ajustar às nossas necessidades, que são 2 classes. Você também usa CrossEntropyLoss para a função de perda de várias classes e para o otimizador, você usará SGD com a taxa de aprendizagem de 0,0001 e um momentum de 0,9, conforme mostrado no exemplo PyTorch Transfer Learning abaixo.
## 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)
A estrutura do modelo de saída
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)))
Etapa 3) Treinar e testar o modelo
Usaremos algumas das funções do Tutorial do Transfer Learning PyTorch para nos ajudar a treinar e avaliar nosso modelo.
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)
Finalmente, neste exemplo de Transfer Learning in PyTorch, vamos começar nosso processo de treinamento com o número de épocas definido como 25 e avaliar após o processo de treinamento. Em cada etapa de treinamento, o modelo pegará a entrada e preverá a saída. Depois disso, a saída prevista será passada para o critério de cálculo das perdas. Em seguida, as perdas realizarão um cálculo de backprop para calcular o gradiente e por fim calcular os pesos e otimizar os parâmetros com autograd.
No modelo de visualização, a rede treinada será testada com um lote de imagens para prever os rótulos. Em seguida, ele será visualizado com a ajuda do matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)visualize_model(vgg_based)plt.show()
Etapa 4) Resultados
O resultado final é que você alcançou uma precisão de 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
No final, a saída do nosso modelo será visualizada com o matplot abaixo:
Resumo
Então, vamos resumir tudo! O primeiro fator é que o PyTorch é uma estrutura de aprendizado profundo em crescimento para iniciantes ou para fins de pesquisa. Oferece alto tempo de computação, gráfico dinâmico, suporte a GPUs e é totalmente escrito em Python. Você é capaz de definir nosso próprio módulo de rede com facilidade e fazer o processo de treinamento com uma iteração fácil. É claro que o PyTorch é ideal para iniciantes para descobrir o aprendizado profundo e para pesquisadores profissionais é muito útil com tempo de computação mais rápido e também a função de autograd muito útil para auxiliar o gráfico dinâmico.