¿Qué es el aprendizaje por transferencia?
Transfer Learning es una técnica de utilizar 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 en 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 el peso de otro modelo de red para reducir el tiempo de entrenamiento porque necesita una gran cantidad de datos para entrenar un modelo de red. Para reducir el tiempo de entrenamiento, utilizas otras redes y su peso y modificas la última capa para solucionar nuestro problema. La ventaja es que puede usar 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 usar Transfer Learning PyTorch, debe comprender el conjunto de datos que va a usar. 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 de Kaggle: Alien vs. Predator.
¿Cómo utilizar el aprendizaje transferido?
A continuación, se muestra un proceso paso a paso sobre cómo utilizar el aprendizaje transferido para el aprendizaje profundo con PyTorch:
Paso 1) Cargue los datos
El primer paso es cargar nuestros datos y hacer alguna transformación a 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, normalizará y finalmente lo convertirá en 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")
Visualicemos nuestro conjunto de datos para PyTorch Transfer Learning. El proceso de visualización obtendrá el siguiente lote de imágenes de los cargadores de datos del tren y las etiquetas y lo mostrará con 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()
Paso 2) Definir modelo
En este proceso de aprendizaje profundo, utilizará ResNet18 del módulo de torchvision.
Utilizará torchvision.models para cargar resnet18 con el peso preentrenado establecido en True. Después de eso, congelará las capas para que estas capas no se puedan entrenar. También modifica la última capa con una capa lineal para que se ajuste a nuestras necesidades, es decir, 2 clases. También usa CrossEntropyLoss para la función de pérdida de múltiples clases y para el optimizador usará SGD con una tasa de aprendizaje de 0.0001 y un impulso de 0.9, como se muestra en el siguiente ejemplo de 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)
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 PyTorch Tutorial 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 = 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, en este ejemplo de Transferir aprendizaje en PyTorch, comencemos nuestro proceso de entrenamiento con el número de épocas establecido en 25 y evaluemos después del proceso de entrenamiento. En cada paso de entrenamiento, el modelo tomará la entrada y predecirá la salida. Después de eso, la salida prevista se pasará al criterio para calcular las pérdidas. Luego de las pérdidas se realizará un cálculo de backprop para calcular la pendiente y finalmente calcular los pesos y optimizar 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.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
Finalmente, la salida de nuestro modelo se visualizará con matplot a continuación:
Resumen
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 nuestro propio módulo de red con facilidad y realizar el proceso de formació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 función de autogrado muy útil para ayudar a los gráficos dinámicos.