Tutorial de aprendizaje de transferencia de PyTorch con ejemplos
¿Qué es el aprendizaje por transferencia?
Transferir aprendizaje es una técnica que utiliza un modelo entrenado para resolver otra tarea relacionada. Es un método de investigación de aprendizaje automático que almacena el conocimiento adquirido al resolver un problema particular y utiliza el mismo conocimiento para resolver otro problema diferente pero relacionado. Esto mejora la eficiencia al reutilizar la información recopilada de la tarea aprendida previamente.
Es popular utilizar otros pesos de modelo de red para reducir el tiempo de entrenamiento porque se necesitan muchos datos para entrenar un modelo de red. Para reducir el tiempo de entrenamiento, utiliza otras redes y su peso y modifica la última capa para resolver nuestro problema. La ventaja es que puedes utilizar un pequeño conjunto de datos para entrenar la última capa.
A continuación, en este tutorial de aprendizaje de PyTorch Transfer, aprenderemos cómo usar Transfer Learning con PyTorch.
Cargando conjunto de datos
Fuente: Alien vs Predator Kaggle
Antes de comenzar a utilizar Transfer Learning PyTorch, debe comprender el conjunto de datos que va a utilizar. En este ejemplo de Transfer Learning PyTorch, clasificará un Alien y un Predator a partir de casi 700 imágenes. Para esta técnica, realmente no necesitas una gran cantidad de datos para entrenar. Puede descargar el conjunto de datos desde Kaggle: Alien contra depredador.
¿Cómo utilizar el aprendizaje por transferencia?
Aquí hay un proceso paso a paso sobre cómo usar Transfer Learning para Deep Learning con PyTorch:
Paso 1) Cargar los datos
El primer paso es cargar nuestros datos y realizar algunas transformaciones en imágenes para que coincidan con los requisitos de la red.
Cargará los datos desde una carpeta con torchvision.dataset. El módulo iterará en la carpeta para dividir los datos para el entrenamiento y la validación. El proceso de transformación recortará las imágenes desde el centro, realizará un giro horizontal, las normalizará y finalmente las convertirá a tensor utilizando Deep Learning.
from __future__ import print_function, division import os import time import torch import torchvision from torchvision import datasets, models, transforms import torch.optim as optim import numpy as np import matplotlib.pyplot as plt data_dir = "alien_pred" input_shape = 224 mean = [0.5, 0.5, 0.5] std = [0.5, 0.5, 0.5] #data transformation data_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'].classes device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Visualicemos nuestro conjunto de datos para PyTorch Transfer Learning. El proceso de visualización obtendrá el siguiente lote de imágenes de las etiquetas y cargadores de datos del tren y lo mostrará con matplot.
images, labels = next(iter(dataloaders['train'])) rows = 4 columns = 4 fig=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 + mean plt.imshow(img) plt.show()
Paso 2) Definir modelo
En este Aprendizaje profundo En el proceso, utilizará ResNet18 del módulo torchvision.
Usarás Torchvision.models para cargar resnet18 con el peso entrenado previamente establecido como Verdadero. Después de eso, congelarás las capas para que no se puedan entrenar. También modificarás la última capa con una capa lineal para que se ajuste a nuestras necesidades, es decir, 2 clases. También usarás CrossEntropyLoss para la función de pérdida de múltiples clases y para el optimizador usarás SGD con una tasa de aprendizaje de 0.0001 y un momento de 0.9, como se muestra en el siguiente ejemplo de aprendizaje por transferencia de PyTorch.
## Load the model based on VGG19 vgg_based = torchvision.models.vgg19(pretrained=True) ## freeze the layers for param in vgg_based.parameters(): param.requires_grad = False # Modify the last layer number_features = vgg_based.classifier[6].in_features features = list(vgg_based.classifier.children())[:-1] # Remove last layer features.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)
La estructura del modelo de salida.
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) ) )
Paso 3) Entrenar y probar el modelo
Usaremos algunas de las funciones de Transfer Learning Tutorial de PyTorch para ayudarnos a entrenar y evaluar nuestro 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 = data inputs = 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() - since print('Training complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) return model def visualize_model(model, num_images=6): was_training = model.training model.eval() images_so_far = 0 fig = 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 += 1 ax = 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 + mean ax.imshow(img) if images_so_far == num_images: model.train(mode=was_training) return model.train(mode=was_training)
Finalmente, en este ejemplo de Transferencia de aprendizaje en PyTorch, comencemos nuestro proceso de capacitación con el número de épocas establecidas en 25 y evalúelos después del proceso de capacitación. En cada paso de entrenamiento, el modelo tomará la entrada y predecirá la salida. Después de eso, la producción prevista se pasará al criterio para calcular las pérdidas. Luego, las pérdidas realizarán un cálculo de backprop para calcular el gradiente y finalmente calcularán los pesos y optimizarán los parámetros con autograd.
En el modelo de visualización, la red entrenada se probará con un lote de imágenes para predecir las etiquetas. Luego se visualizará con la ayuda de matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
Paso 4) Resultados
El resultado final es que logró una precisión del 92%.
Epoch 23/24 ---------- train Loss: 0.0044 train Loss: 0.0078 train Loss: 0.0141 train Loss: 0.0221 train Loss: 0.0306 train Loss: 0.0336 train Loss: 0.0442 train Loss: 0.0482 train Loss: 0.0557 train Loss: 0.0643 train Loss: 0.0763 train Loss: 0.0779 train Loss: 0.0843 train Loss: 0.0910 train Loss: 0.0990 train Loss: 0.1063 train Loss: 0.1133 train Loss: 0.1220 train Loss: 0.1344 train Loss: 0.1382 train Loss: 0.1429 train Loss: 0.1500 Epoch 24/24 ---------- train Loss: 0.0076 train Loss: 0.0115 train Loss: 0.0185 train Loss: 0.0277 train Loss: 0.0345 train Loss: 0.0420 train Loss: 0.0450 train Loss: 0.0490 train Loss: 0.0644 train Loss: 0.0755 train Loss: 0.0813 train Loss: 0.0868 train Loss: 0.0916 train Loss: 0.0980 train Loss: 0.1008 train Loss: 0.1101 train Loss: 0.1176 train Loss: 0.1282 train Loss: 0.1323 train Loss: 0.1397 train Loss: 0.1436 train Loss: 0.1467 Training complete in 2m 47s
Finalice, el resultado de nuestro modelo se visualizará con el siguiente diagrama matplo:
Resum
Entonces, ¡resumamos todo! El primer factor es que PyTorch es un marco de aprendizaje profundo en crecimiento para principiantes o con fines de investigación. Ofrece un alto tiempo de cálculo, gráficos dinámicos, compatibilidad con GPU y está totalmente escrito en Python. Puede definir su propio módulo de red con facilidad y realizar el proceso de capacitación con una iteración sencilla. Está claro que PyTorch es ideal para que los principiantes descubran el aprendizaje profundo y para los investigadores profesionales es muy útil con un tiempo de cálculo más rápido y también la muy útil función de autograduación para ayudar a los gráficos dinámicos.