¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.dev
Juan Iglesias 18/03/2019 Cargando comentarios…
El aprendizaje profundo (Deep Learning en inglés) con redes neuronales es actualmente una de las ramas de la inteligencia artificial más prometedora. Esta innovadora tecnología se usa comúnmente en aplicaciones como reconocimiento de imágenes, de voz, sistemas de traducción automática, entre otras.
Existen varias opciones en cuanto a tecnologías y librerías se refiere, siendo Tensorflow, desarrollada por Google, la más extendida actualmente.
Sin embargo, nos vamos a centrar en PyTorch, una alternativa emergente que está ganando tracción rápidamente gracias a su facilidad de uso y otras ventajas como su capacidad nativa para ejecutar en la GPU o tarjeta gráfica, lo que permite acelerar procesos tradicionalmente lentos como el entrenamiento de modelos. Es la librería principal de Facebook para aplicaciones de aprendizaje profundo.
Sus elementos fundamentales son los tensores, que se pueden equiparar con vectores de una o varias dimensiones.
Una Red Neuronal Artificial es un sistema de nodos interconectados de forma ordenada, distribuido en capas, a través del cual una señal de entrada se propaga para producir una salida. Se conocen así porque pretenden emular de forma sencilla el funcionamiento de las redes neuronales biológicas que se encuentran en el cerebro animal.
Constan de una capa de entrada, una o varias capas ocultas y una capa de salida y se las puede entrenar para que “aprendan” a reconocer ciertos patrones. Esta característica es la que las incluye dentro del ecosistema de tecnologías conocidas como inteligencia artificial.
Las RNAs tienen varias décadas de historia, pero han cobrado gran relevancia recientemente debido a la disponibilidad de las grandes cantidades de datos y de la potencia de computación necesarias para su utilización en problemas complejos.
Han supuesto un hito histórico en aplicaciones tradicionalmente esquivas a la programación clásica, basada en reglas como el reconocimiento de imágenes o de voz.
Si tenemos instalado el entorno de Anaconda, la instalación se realiza con el comando:
console
conda install pytorch torchvision -c pytorch
En caso contrario podemos usar pip de la siguiente forma:
console
pip3 install torch torchvision
Vamos a ver un ejemplo sencillo de clasificación de imágenes mediante aprendizaje profundo, utilizando el conocido conjunto de datos MNIST, que contiene imágenes de números manuscritos del 0-9.
import torch, torchvision
Para poder usar el dataset con PyTorch, se debe transformar a tensor. Para ello, definimos una transformación T que usaremos en el proceso de carga. Definimos también un DataLoader, un objeto generador de Python cuyo cometido es proporcionar las imágenes en grupos de batch_size imágenes a la vez.
% block:blockquote
% items:
% text:Nota: es común, en el entrenamiento de redes neuronales, actualizar los parámetros cada N entradas en vez de cada entrada individual. Sin embargo, incrementar demasiado el tamaño del grupo podría ocupar demasiada memoria RAM en el sistema.
% endblock
T = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
images = torchvision.datasets.MNIST('mnist_data', transform=T,download=True)
image_loader = torch.utils.data.DataLoader(images,batch_size=128)
A continuación hemos de definir cómo va a ser la topología de nuestra red. Una RNA se compone de una capa de entrada, una o varias capas intermedias u ocultas, como se las suele conocer y una capa de salida.
El número de capas ocultas, así como la cantidad de neuronas en ellas, depende de la complejidad y el tipo de problema. En este caso sencillo vamos a implementar dos capas ocultas, con 100 y 50 neuronas respectivamente.
La clase que debemos crear hereda de la clase nn.Module y también necesitaremos inicializar los métodos de la superclase.
import torch.nn as nn
#definimos la red neuronal
class Classifier(nn.Module):
def __init__(self):
super(Classifier,self).__init__()
self.input_layer = nn.Linear(28*28,100)
self.hidden_layer = nn.Linear(100,50)
self.output_layer = nn.Linear(50,10)
self.activation = nn.ReLU()
def forward(self, input_image):
input_image = input_image.view(-1,28*28) #convertimos la imagen a vector
output = self.activation(self.input_layer(input_image)) #pasada por la capa entrada
output = self.activation(self.hidden_layer(output)) #pasada por la capa oculta
output = self.output_layer(output) #pasada por la capa de salida
return output
Tiene tantas neuronas como datos contienen nuestras muestras. En este caso, las entradas son imágenes de 28x28 píxeles mostrando los números manuscritos. Por tanto, nuestra capa de entrada consta de 28x28 neuronas.
Tiene tantas posibles salidas como clases hay en nuestros datos, 10 en este caso (dígitos del 0 al 9). A cada entrada, los nodos de salida producirán un valor, el mayor de los cuales se identifica con la clase de salida detectada.
Es la función que define la salida de un nodo en función de una entrada o un conjunto de entradas. En este caso utilizamos la función sencilla ReLU (Rectified Linear Unit):
Define cómo se van realizando los cálculos desde los datos de entrada, que pasan por las distintas capas, hasta la salida. Comienza aplanando la entrada desde un Tensor bidimensional de 28x28 píxeles a uno unidimensional de 784 valores que se le pasan a la capa de entrada, con la función view.
A continuación, estos valores se propagan a las capas ocultas mediante la función de activación y finalmente a la capa de salida, que devuelve el resultado.
Para entrenar nuestra red satisfactoriamente, necesitamos definir algunos parámetros.
from torch import optim
import numpy as np
classifier = Classifier() #instanciamos la RN
loss_function = nn.CrossEntropyLoss() #función de pérdidas
parameters = classifier.parameters()
optimizer = optim.Adam(params=parameters, lr=0.001) #algoritmo usado para optimizar los parámetros
epochs = 3 #número de veces que pasamos cada muestra a la RN durante el entrenamiento
iterations = 0 #número total de iterations para mostrar el error
losses = np.array([]) #array que guarda la pérdida en cada iteración
Lo primero instanciamos un objeto de la clase anteriormente definida, que llamamos clasificador. Además necesitaremos:
Nos valdremos de esta función para la optimización de los parámetros, minimizando su valor durante la fase de entrenamiento de la red. Hay muchas funciones de pérdida disponibles para PyTorch. En este caso, utilizaremos la pérdida de entropía cruzada, que se recomienda en situaciones de clasificación multiclase como la que tratamos en este post.
Este objeto recibe los parámetros del modelo y la tasa de aprendizaje (learning rate) y se encarga de actualizar dichos parámetros en función del gradiente de la función de pérdida de forma iterativa durante el entrenamiento de la red. Se ha utilizado un algoritmo Adam para este caso, aunque hay otras posibilidades.
Epoch define el número de veces que se pasará el conjunto de datos por la RNA para entrenamiento. Esta práctica es una convención frecuente en el entrenamiento de sistemas de aprendizaje profundo. El resto de parámetros se usará para almacenar y mostrar resultados posteriormente.
from torch.autograd import Variable #necesario para calcular gradientes
for e in range(epochs):
for i, (images, tags) in enumerate(image_loader):
images, tags = Variable(images), Variable(tags) #Convertir a variable para derivación
output = classifier(images) #calcular la salida para una imagen
classifier.zero_grad() #poner los gradientes a cero en cada iteración
error = loss_function(output, tags) #calcular el error
error.backward() #obtener los gradientes y propagar
optimizer.step() #actualizar los pesos con los gradientes
iterations += 1
losses = np.append(losses,error.item())
El entrenamiento se realiza el número de veces que se ha definido en la variable epochs, que se refleja en el bucle exterior. Seguidamente se van realizando los siguientes pasos:
¡Ya estamos listos para ver los resultados de nuestro entrenamiento! Usaremos la librería matplotlib. Como hemos guardado las iteraciones y la pérdida, simplemente tenemos que mostrarlos en una gráfica que nos dará una idea de cómo ha ido progresando nuestra RNA.
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
#vemos las pérdidas en cada iteración de forma gráfica
plt.plot(np.arange(iterations),losses)
Se puede apreciar cómo va disminuyendo el error de clasificación a medida que se ha ido entrenando la RNA.
Existen diversas opciones disponibles para la programación de RNAs, tanto libres como propietarias. Aunque TensorFlow, de Google, sigue siendo líder indiscutible del mercado, poco a poco van apareciendo alternativas interesantes que pueden aportar valor al ecosistema por medio de compatibilidades nativas, facilidad de uso, etc.
PyTorch está ganando popularidad rápidamente y puede ser una opción muy interesante, ya seas un experto o estés pensando iniciarte en el mundo del aprendizaje profundo.
Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.