Identificación de dígitos escritos a mano mediante regresión logística en PyTorch

La regresión logística es un método estadístico muy utilizado que nos permite predecir una salida binaria a partir de un conjunto de variables independientes. Las diversas propiedades de la regresión logística y su implementación en Python se han cubierto en este artículo anteriormente. Ahora, descubriremos cómo implementar esto en PyTorch, una biblioteca de aprendizaje profundo muy popular que está siendo desarrollada por Facebook.
Ahora, veremos cómo clasificar los dígitos escritos a mano del conjunto de datos MNIST utilizando la regresión logística en PyTorch. En primer lugar, deberá instalar PyTorch en su entorno de Python. La forma más fácil de hacer esto es usar la herramienta pip o conda. Visite pytorch.org e instale la versión de su intérprete de Python y el administrador de paquetes que le gustaría usar.
Con PyTorch instalado, ahora echemos un vistazo al código. Escriba las tres líneas que se indican a continuación para importar las funciones y los objetos de biblioteca requeridos.

Python3

import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable

Aquí, el módulo torch.nn contiene el código requerido para el modelo, torchvision.datasets contiene el conjunto de datos MNIST. Contiene el conjunto de datos de dígitos escritos a mano que usaremos aquí. El módulo torchvision.transforms contiene varios métodos para transformar objetos en otros. Aquí, lo usaremos para transformar imágenes a tensores PyTorch. Además, el módulo torch.autograd contiene la clase Variable, entre otras, que usaremos al definir nuestros tensores.
A continuación, descargaremos y cargaremos el conjunto de datos en la memoria.

Python3

# MNIST Dataset (Images and Labels)
train_dataset = dsets.MNIST(root ='./data', 
                            train = True, 
                            transform = transforms.ToTensor(),
                            download = True)
  
test_dataset = dsets.MNIST(root ='./data', 
                           train = False, 
                           transform = transforms.ToTensor())
  
# Dataset Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, 
                                           batch_size = batch_size, 
                                           shuffle = True)
  
test_loader = torch.utils.data.DataLoader(dataset = test_dataset, 
                                          batch_size = batch_size, 
                                          shuffle = False)

Ahora, definiremos nuestros hiperparámetros.

Python3

# Hyper Parameters 
input_size = 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001

En nuestro conjunto de datos, el tamaño de la imagen es 28*28. Por lo tanto, nuestro tamaño de entrada es 784. Además, hay 10 dígitos presentes en esto y, por lo tanto, podemos tener 10 salidas diferentes. Por lo tanto, establecemos num_classes en 10. Además, entrenaremos cinco veces en todo el conjunto de datos. Finalmente, entrenaremos en pequeños lotes de 100 imágenes cada uno para evitar que el programa se cuelgue debido a un desbordamiento de memoria.
Después de esto, definiremos nuestro modelo de la siguiente manera. Aquí, inicializaremos nuestro modelo como una subclase de torch.nn.Module y luego definiremos el paso hacia adelante. En el código que estamos escribiendo, el softmax se calcula internamente durante cada avance y, por lo tanto, no necesitamos especificarlo dentro de la función forward().

Python3

class LogisticRegression(nn.Module):
    def __init__(self, input_size, num_classes):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(input_size, num_classes)
  
    def forward(self, x):
        out = self.linear(x)
        return out

Habiendo definido nuestra clase, ahora instanciamos un objeto para la misma.

Python3

model = LogisticRegression(input_size, num_classes)

A continuación, configuramos nuestra función de pérdida y el optimizador. Aquí, usaremos la pérdida de entropía cruzada y para el optimizador, usaremos el algoritmo de descenso de gradiente estocástico con una tasa de aprendizaje de 0.001 como se define en el hiperparámetro anterior.

Python3

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)

Ahora, vamos a empezar el entrenamiento. Aquí, realizaremos las siguientes tareas:

  1. Restablece todos los degradados a 0.
  2. Haz un pase hacia adelante.
  3. Calcular la pérdida.
  4. Realizar retropropagación.
  5. Actualizar todos los pesos.

Python3

# Training the Model
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
  
        # Forward + Backward + Optimize
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
  
        if (i + 1) % 100 == 0:
            print('Epoch: [% d/% d], Step: [% d/% d], Loss: %.4f'
                  % (epoch + 1, num_epochs, i + 1,
                     len(train_dataset) // batch_size, loss.data[0]))

Finalmente, probaremos el modelo usando el siguiente código.

Python3

# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
    images = Variable(images.view(-1, 28 * 28))
    outputs = model(images)
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()
  
print('Accuracy of the model on the 10000 test images: % d %%' % (
            100 * correct / total))

Suponiendo que haya realizado todos los pasos correctamente, obtendrá una precisión del 82 %, lo que está muy lejos del modelo de última generación actual, que utiliza un tipo especial de arquitectura de red neuronal. Para su referencia, puede encontrar el código completo de este artículo a continuación:

Python3

import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
  
  
# MNIST Dataset (Images and Labels)
train_dataset = dsets.MNIST(root ='./data',
                            train = True,
                            transform = transforms.ToTensor(),
                            download = True)
  
test_dataset = dsets.MNIST(root ='./data',
                           train = False,
                           transform = transforms.ToTensor())
  
# Dataset Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
                                           batch_size = batch_size,
                                           shuffle = True)
  
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = batch_size,
                                          shuffle = False)
  
# Hyper Parameters
input_size = 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001
  
# Model
class LogisticRegression(nn.Module):
    def __init__(self, input_size, num_classes):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(input_size, num_classes)
  
    def forward(self, x):
        out = self.linear(x)
        return out
  
  
model = LogisticRegression(input_size, num_classes)
  
# Loss and Optimizer
# Softmax is internally computed.
# Set parameters to be updated.
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)
  
# Training the Model
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
  
        # Forward + Backward + Optimize
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
  
        if (i + 1) % 100 == 0:
            print('Epoch: [% d/% d], Step: [% d/% d], Loss: %.4f'
                  % (epoch + 1, num_epochs, i + 1,
                     len(train_dataset) // batch_size, loss.data[0]))
  
# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
    images = Variable(images.view(-1, 28 * 28))
    outputs = model(images)
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()
  
print('Accuracy of the model on the 10000 test images: % d %%' % (
            100 * correct / total))

Referencias :

Publicación traducida automáticamente

Artículo escrito por somnath y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *