Guía Visual e Interactiva de Conceptos Básicos de Redes Neuronales

Discusiones: Hacker News (63 points, 8 comments), Reddit r/programming (312 points, 37 comments)

Nota

Este post no es de mi autoría, es una traducción al español de la siguiente entrada en el blog de Jay Alammar:

A Visual and Interactive Guide to the Basics of Neural Networks

Update: Parte 2 está disponible en: A Visual And Interactive Look at Basic Neural Network Math

Motivación

No soy un experto en machine learning. Soy un ingeniero de software y he tenido poca interacción con inteligencia artificial. Siempre quise ahondar en machine learning, pero nunca encontré una forma de entrar al área. Por eso cuando Google convirtió TensorFlow en un proyecto de código abierto en Noviembre de 2015, me emocioné y sentí que era el momento de comenzar el camino de aprendizaje. No quiero sonar dramático, pero para mí se sintió como Prometeo entregando el fuego del Monte Olimpo de machine learning a la humanidad. En el fondo de mi mente estaba la idea de que el desarrollo del campo entero de Big Data y tecnologías como Hadoop se aceleró cuando investigadores de Google liberaron su paper de Map Reduce. Esta vez no es un paper – es el software que han usado internamente luego de años y años de evolución.

Asi qué empecé a aprender lo que pude acerca de los conceptos básicos del tema, y ví la necesidad de que existan recursos más amables para gente sin experiencia en el campo. Este es mi intento de lograr eso.

Comienza aquí

Empecemos con un ejemplo simple. Digamos que estás ayudando a una amiga que quiere comprar una casa. Le cotizaron $400,000 por una casa de 2000 pies cuadrados (185 metros). ¿Es un buen precio o no?

nota del traductor: Conservo las unidades de medida del original ya que los gráficos animados las utilizan, y por el momento no dispongo del tiempo de generar nuevos GIFs con los valores en metros cuadrados (si alguien se ofrece sería de gran ayuda)

No es fácil determinarlo sin un marco de referencia. Así que le preguntás a tus amigos que han comprado casa en los mismos barrios y obtenés 3 ejemplos.

Area (sq ft) (x) Price (y)
2,104 399,900
1,600 329,900
2,400 369,000

Personalmente, mi primer instinto sería obtener el precio promedio por pie cuadrado. En este caso sería de $180 por pie cuadrado.

¡Bienvenido a tu primera red neuronal! No está al nivel de Siri aún, pero ya conocés el bloque de construcción fundamental. Se parece a esto:

Diagramas como este te muestran la estructura de una red y como calcula una predicción. El cálculo comienza desde el nodo de entrada (input) a la derecha. El valor de entrada fluye hacia la derecha. Es multiplicado por el peso y el resultado se convierte en nuestra salida (output).

Multiplicar 2.000 pies cuadrados por 180 nos da $360.000. En este punto, es todo lo que hay. Calcular la predicción es una simple multiplicación. Pero antes de eso, debemos pensar acerca del peso con el que realizaremos la multiplicación. Aquí empezamos con un promedio, pero más adelante veremos algoritmos mejores que pueden escalar cuando agreguemos más entradas y modelos más complciados. Encontrar el peso es nuestra etapa de “entrenamiento”. Así que cuando escuchés que alguien está “entrenando” una red neuronal, simplemente significa encontrando los pesos adecuados que usamos para calcular una predicción.

Esta es una forma de predicción. Es un modelo predictivo simple que toma una entrada, hace un cálculo, y entrega una salida (dado que la salida es de valores continuos, el nombre técnico para lo que tenemos acá sería un “modelo de regresión”).

Visualicemos este proceso (para simplificar, cambiemos el precio por unidad de $1 a $1000. Ahora nuestros peso es 0.180 en vez de 180):

1. Visualicemos: Tamaño (X) vs Precio (Y)
2. Acá están nuestros 3 data points
3. Esta es nuestra línea de predicción
4. Para hacer una predicción, buscamos el valor de entrada en el eje X
5. La línea nos da el valor de Y

Más difícil, mejor, más rapido, más resistente

¿Podemos lograr algo mejor que estimar el precio basado en el promedio de nuestros data points? Lo intentemos. Primero definiremos qué significa hacerlo mejor en este escenario. Si aplicamos nuestro modelo a los tres data point que tenemos, ¿qué tan buen trabajo haría?

1. Visualicemos: Tamaño (X) vs Precio (Y) 2. Acá están nuestros 3 data points 3. Esta es nuestra línea de predicción 4. Para hacer una predicción, buscamos el valor de entrada en el eje X 5. La línea nos da el valor de Y

Eso tiene mucho amarillo. Amarillo es malo. Amarillo es error. Queremos minimizar el amarillo lo más que podamos.

Área (x) Precio ($1000) (y_) Predicción (y) y_-y (y_-y
2,104 399.9 379 21 449
1,600 329.9 288 42 1756
2,400 369 432 -63 3969
Promedio: 2,058

Acá podemos ver el precio verdadero, el precio predicho, y the la diferencia entre ellos. Luego tomaremos el promedio de estas diferencias para tener un número que nos diga cuánto error hay en éste modelo predictivo. Pero tenemos un problema, la tercera fila tiene el valor -63. Tenemos que lidiar con el valor negativo si queremos usar la diferencia entre predicción y precio como nuestra vara para medir el error. Esa es una de las razones por la que introducimos una columna adicional que muestra el error cuadrado, que elimina el valor negativo.

Esta es nuestra definición de hacerlo mejor – un mejor modelo es uno que tiene un error menor. El error es medido como el promedio de los errores de cada punto en nuestro conjunto de datos. Por cada punto, el error es medido como la diferencia enter el valor verdadero y el valor predicho, elevado al cuadrado. Esto se llama Error Cuadrático Medio. Al usarlo como la guía para entrenar nuestro modelo, se convierte en nuestra función de pérdida (también llamada función de costo)

Ahora que hemos definido la vara con la que mediremos un mejor modelo, experimentemos con un par de valores de los pesos, y comparemos con nuestra selección del promedio:

1. Linea de predicción Y = 0.180 X, tiene un valor de error de 2.058. Intentemos con otras líneas 2. Y = 0.190 X Error: 2.746 peor que 2.058 3. Y = 0.160 X Error: 3.229 peor que 2.058 4. Cambiando sólo la pendiente no estamos mejorando sobre el promedio. Agreguemos la ordenada al origen en nuestra fórmula: Y = wX + b 5. Y = 0.100 X + 150 error: 799 ¡mejor que 2.058! Ahora sí estamos avanzando No podemos mejorar el modelo mucho más sólo variando el peso. Pero si agregamos la ordenada al origen podemos encontrar valores que mejoran el modelo.

Las líneas pueden aproximar mejor nuestros valores ahora que hemos agregado este componente b en la fórmula de la línea. En este contexto lo llamamos “sesgo”. Esto hace que nuestra red neuronal se vea así:

Podemos generalizar diciendo que una red neuronal con una entrada y una salida (alerta de spoiler: y sin capas ocultas) se ve así:

Entrada - Peso - Sesgo - Salida

En este gráfico, W y b son valores que encontramos durante el proceso de entrenamiento. X es la entrada que insertamos en la fórmula (área en pies cuadrados en nuestro ejemplo). Y es el precio predicho.

El cálculo de la predicción ahora usa ésta fórmula:

Entonces, nuestro modelo calcula sus predicciones ingresando el área de la casa como x en ésta fórmula:

Entrena a tu dragón

¿Y si intentamos entrenar nuestra red neuronal de juguete? Minimizá la función de costo moviendo los controles de peso y sesgo. ¿Podés obtener un valor de error menor a 799?

Error
 
Peso 0
Sesgo 0

Automatización

¡Felicitaciones por entrenar tu primera red neuronal manualmente! Ahora veamos como automatizar el proceso de entrenamiento. Abajo hay otro ejemplo con una funcionalidad adicional tipo piloto automático. Estos son los botones de pasos GD. Usan un algoritmo llamado “Descenso por gradiente” para intentar ir hacia los valores correctos de peso y sesgo que minimizan la función de costo.

Error
 
Weight 0
Bias 0

Los dos nuevos gráficos son para ayudarte a seguir los valores de error a medida que jugás con los parámetros (peso y sesgo) del modelo. Es importante seguir los valores de error ya que el proceso de entrenamiento es básicamente la reducción de este error lo más posible.

¿Cómo sabe el descenso por gradiente cuál debería ser su próximo paso? Cálculo diferencial. Sabiendo la función que estamos minimizando (nuestra función de costo, el promedio de (y_ -y)² para todos nuestros ejemplos), las derivadas de la función nos dicen hacia qué dirección empujar W y b para minimizar el error.

Podés aprender más acerca de descenso por gradiente y como usarlo para calcular pesos y sesgos en las primeras clases del curso Machine Learning de Coursera.

Y entonces fueron dos

¿Es el tamaño de la casa la única variable que importa al calcular cuánto cuesta una casa? Obviamente hay muchos otros factores. Agreguemos otra variable y veamos como ajustar nuestra red neuronal.

Supongamos que tu amiga investiga un poco más y encuentra varios ejemplos más. También encuentra cuántos baños tiene cada casa:

Area (sq ft) (x1) Baños (x2) Precio (y)
2,104 3 399,900
1,600 3 329,900
2,400 3 369,000
1,416 2 232,000
3,000 4 539,900
1,985 4 299,900
1,534 3 314,900
1,427 3 198,999
1,380 3 212,000
1,494 3 242,500

Nuestra red neuronal con dos variables se ve así:

Ahora tenemos que encontrar dos pesos (uno por cada entrada) y un sesgo para crear nuestro modelo.

El cálculo de Y ahora se ve así

¿Pero cómo encontramos w1 y w2? Esto es un poco más complicado que cuando teníamos sólo un peso para preocuparnos. ¿Cuánto cambia el tener un baño extra la forma en que predecimos el valor de una casa?

Intentá encontrar los parámetros. Vas a comenzar a notar la complejidad en la que entramos cuando el número de entradas se incrementa. Empezamos a perder la habilidad de crear formas simples en dos dimensiones que nos permiten visualizar el modelo de un vistazo. En cambio, tenemos que confiar principalmente en como va evolucionando el error a medida que tocamos los parámetros del modelo.

Error
 
Peso #1 0
Peso #2 0
Sesgo 0

Nuestro confiable descenso por gradiente está otra vez aquí para ayudarnos. Todavía es valioso para ayudarnos a encontrar los correctos pesos y sesgo.

Atributos (Features)

Ahora que viste una red neuronal con uno o dos atributos, podés descifrar como agregar atributos adicionales y usarlos para calcular tus predicciones. El número de pesos continuará creciendo, y nuestra implementación de descenso por gradiente tendrá que ser retocada por cada atributo que agreguemos, a fin de que pueda actualizar los pesos asociados con cada uno de ellos.

Es importante mencionar que no alimentamos a la red con todos los datos que poseemos de cada ejemplo sin analizarlos. Tenemos que ser selectivos acerca de qué atributos queremos usar para alimentar el modelo. La selección y procesamiento de atributos (feature selection/processing) es una entera disciplina con su conjunto de buenas prácticas y consideraciones. Si querés ver un ejemplo del proceso de examinar un dataset y elegir que atributos usar en un modelo predictivo, dale una mirada a A Journey Through Titanic. Es un notebook donde Omar EL Gabry narra su proceso para resolver el desafío del Titanic de Kaggle. Kaggle deja disponible el manifiesto de pasajeros del Titanic, incluyendo datos como el nombre, sexo, edad, cabina y si la persona sobrevivió o no. El desafío consiste en construir un modelo que predice si una persona particular sobrevivió o no dados los otros datos.

Clasificación

Continuemos jugando con nuestro ejemplo. Asumamos que tu amiga te da una lista de casas. Esta vez, ella etiquetó cuáles son los que ella piensa que tienen una buena relación de tamaño y cantidad de baños:

Area (sq ft) (x1) Baños (x2) Etiqueta (y)
2,104 3 Good
1,600 3 Good
2,400 3 Good
1,416 2 Bad
3,000 4 Bad
1,985 4 Good
1,534 3 Bad
1,427 3 Good
1,380 3 Good
1,494 3 Good

Ella necesita que uses esto para crear un modelo que prediga si le gustaría una casa o no, dependiendo de su tamaño y los baños que tiene. Vos vas a usar esta lista para construir el modelo, luego ella usará el modelo para clasificar muchas otras casas. Un desafío adicional en el proceso es que ella tiene una lista adicional de 10 casas que etiquetó, pero que no te la va a mostrar. Esa lista será usada para evaluar to modelo después de que lo hayas entrenado – para de esta forma asegurarse que tu modelo comprende las condiciones que realmente hacen que a ella le gusten los atributos de la casa.

Las redes neuronales con las que hemos estado jugando hasta ahora han estado haciendo “regresión” – calculan como salida una variable “continua” (la salida puede ser 4, o 100,6 o 2134,342343). En la práctica, las redes neuronales son usadas con mayor frecuencia en problemas de “clasificación”. En estos problemas, la salida de la red tiene que pertenecer a un conjunto discreto de valores (o “clases”) como “Buena” o “Mala”. La forma en que esto funciona es que tendremos un modelo que va a decirnos que está 75% seguro de que la casa es “Buena” en vez de directamente decir “buena” o “mala”.

La aplicación de TensorFlow que discuto en mi post previo es un buen ejemplo de un modelo de clasificación.

Una forma en la que podemos transformar la red que vimos en una red de clasificación es hacer que emita dos valores – uno por cada clase (nuestras clases son “buena” y “mala”). Luego pasamos estos valores a través de una operación llamada “softmax”. La salida de softmax es la probabilidad de cada clase. Por ejemplo, supongamos que la capa emite 2 para “buena” y 4 para “mala”, si alimentamos la función softmax con [2, 4], devolverá [0.11, 0.88] como la salida. Que traduce los valores para decir que la red está 88% segura que la casa de ejemplo es “mala” y a nuestra amiga no le gustaría.

Softmax toma como entrada un vector y emite un vector del mismo largo. Tené en cuenta que los componentes del vector de salida son todos positivos y suman 1 – lo que es muy útil cuando estamos emitiendo un valor de probabilidad. También notá que aún cuando 4 es el doble de 2, su probabilidad no es el doble, si no ocho veces la de 2. Esta es una propiedad conveniente que exagera la diferencia en las salidas, mejorando nuestro proceso de entrenamiento.

  salida
softmax([ 1 ]) [ 1 ]
softmax([ 1, 1 ]) [ 0.5, 0.5 ]
softmax([ 0, 1 ]) [ 0.26, 0.73 ]
softmax([ 2, 4 ]) [ 0.11, 0.88 ]
softmax([ 5, 10 ]) [ 0.007, 0.993 ]
softmax([ -1, 0, 1 ]) [ 0.09, 0.24, 0.66 ]
softmax([ 1, 2, 4 ]) [ 0.04, 0.11, 0.84 ]

Como podés ver en las últimas dos filas, softmax puede tomar cualquier número de entradas. Entonces si tu amiga agrega una tercera etiqueta (algo como “Buena, pero costosa”), softmax escala para acomodar ese cambio.

Tomá un minuto para explorar la forma de la red cuando variás la cantidad de atributos (x1, x2, x3… etc) (que pueden ser área, número de baños, precio, cercanía a una escuela… etc) y cuando cambiás el número de clases (y1, y2, y3… etc)(que pueden ser “muy cara”, “buen negocio”, “muy pequeña”… etc):

Atributos (x):
Clases (y):

Podés ver un ejemplo de cómo crear y entrenar esta red usando TensofFlow en este notebook que creé para acompañar este post.

Motivación Verdadera

Si llegaste tan lejos, tengo que revelarte otro de mis motivos para escribir este post. Está pensado como una introducción más amable a los tutoriales de TensorFlow. Si ahora empezás a trabajar sobre MNIST Para principiantes de ML y te encontrás con este gráfico:

Escribí este post para preparar a gente sin experiencia en machine learning para este gŕafico en el tutorial introductorio de TensorFlow. Es por eso que simulé su estilo visual.

Espero que te sientas preparado y que comprendas este sistema y cómo funciona. Si querés empezar a jugar con el código, sentite libre de empezar desde el tutorial introductorio y enseñale a una red neuronal como detectar dígitos manuscritos.

También deberías continuar tu educación leyendo las bases teóricas y matemáticas de los conceptos discutidos acá. Algunas buenas preguntas para hacerse incluyen:

  • ¿Qué otras clases de funciones de costo existen?¿Cuáles son mejores para qué aplicaciones?
  • ¿Cuál es el algoritmo que realmente calcula los nuevos pesos usando descenso por gradiente?
  • ¿Cuáles son los casos de uso para machine learning en el campo en el cuál ya tenés conocimiento? ¿Qué nueva magia podés crear mezclando estos conjuros con otros en tu libro de hechizos?

Excelentes recursos de aprendizaje incluyen:

Agradecimientos

Gracias a Yasmine Alfouzan, Ammar Alammar, Khalid Alnuaim, Fahad Alhazmi, Mazen Melibari, y Hadeel Al-Negheimish por su ayuda revisando versiones previas de este post.

Por favor contactenme en Twitter por cualquier corrección o feedback.

Written on August 14, 2019