En los artículos anteriores, aprendimos cómo las redes neuronales realizan estimaciones: se realiza una suma ponderada entre las entradas de la red y sus pesos. Hasta ahora, los valores de esos pesos nos fueron dados por una fuerza externa misteriosa. Dimos por sentado que esos son los valores que producen las mejores estimaciones.
Encontrar el valor correcto para cada peso es un paso crucial en el deep learning: es el proceso por el cual la red aprende. A un nivel muy abstracto, puedes ver la red como una colección de pesos que trabajan juntos para producir predicciones. Entrenamos la red ajustando sus pesos hasta que prediga con precisión.
En este capítulo, aprenderemos una forma básica de aprendizaje: el aprendizaje caliente/frío. La idea es extremadamente simple, pero es un buen primer paso para entender formas más elaboradas de aprendizaje.
Antes de proceder, echemos otro vistazo al proceso utilizado por las redes neuronales para realizar predicciones.
Predecir, comparar, aprender
Es útil imaginar el proceso de entrenar una red neuronal como 3 etapas: estimación, comparación y aprendizaje.
Al principio, tenemos una colección de valores de entrada y salida. Puede ser, por ejemplo, una hoja de cálculo que relaciona el número de minutos que una persona corre con el número de calorías que quema. Este es nuestro conjunto de entrenamiento, el que usaremos para entrenar la red neuronal.
El primer paso, estimación, es algo con lo que ya estamos familiarizados: se da una entrada a la red neuronal, que se multiplica por los pesos de la red y se suma para producir una salida.
El segundo paso, comparación, evalúa qué tan buena es nuestra predicción. Supongamos que sabemos por nuestra hoja de cálculo que correr 20 minutos quema alrededor de 180 kcal. Damos 20 como entrada a nuestra red neuronal y predice que quemaremos 140 kcal. 180 es nuestro valor esperado, el que observamos en la vida real y sabemos que es verdadero, mientras que 140 es el valor predicho que nuestra red devolvió. Estas 2 piezas de información son suficientes para calcular el error. Una forma de hacerlo es restar el valor esperado del predicho, y luego calcular el valor absoluto del resultado:
|140-180| = |-40| = 40
En este ejemplo, nuestro error es igual a 40. Este es un ejemplo de error absoluto medio, y hay otras formas de calcular el error en una predicción.
El tercer paso, aprendizaje, es donde actualizamos los pesos de nuestra red neuronal para mejorar las predicciones. Usamos el error calculado en el paso anterior para decidir cuánto necesitamos ajustar los pesos. Es importante notar que si el error es 0 (o un número muy cerca de 0) podemos concluir que nuestra predicción es lo suficientemente buena y declarar completo el proceso de aprendizaje.
Este es un proceso iterativo: después de ajustar los pesos en el paso de aprendizaje, empezamos el ciclo otra vez. Con los nuevos pesos, producimos una nueva predicción, calculamos el error y si es necesario actualizamos los pesos otra vez, hasta que nuestro error se vuelva lo suficientemente pequeño.
Los pesos pueden ser ajustados de muchas maneras diferentes, de hecho, la mayoría de la investigación en deep learning se enfoca en proporcionar formas más efectivas de ajustar sus valores. Por ahora, trataremos con una de las formas más simples: el aprendizaje caliente y frío.
Calculando el error cuadrático medio
Como se mencionó antes, necesitamos una forma de calcular qué tan lejos de los valores esperados están nuestras predicciones. Hay diferentes formas de calcular este valor: substracciones simples, diferencias con valores absolutos, la distancia entre puntos en un plano, diferencias al cuadrado.
Todas estas formas de calcular error priorizan diferentes cosas. El error cuadrático medio (aprenderemos sobre esto más tarde), por ejemplo, pone más atención a errores más grandes e ignora los pequeños, mientras también ignora el signo (positivo o negativo) del error. Seleccionar la forma correcta de calcular el error es importante, ya que determina cómo evalúas la calidad de las predicciones de tu red.
El error cuadrático medio (MSE) es una forma muy popular de calcular el error en diferentes sistemas de machine learning. La definición es bastante simple, supón que tienes una colección de entradas con su respectivo valor esperado, y ejecutas la red neuronal para predecir un valor estimado para cada una de las entradas.
Luego resta el valor esperado a su respectivo valor estimado, eleva al cuadrado el resultado, y al final súmalos todos. Como último paso, divide el resultado de la suma por el número de pares.
La fórmula para MSE es:
Calculémoslo a mano una vez. Supongamos que realizamos una serie de estimaciones y tabulamos los resultados:
Entrada | Valor esperado | Valor estimado |
---|---|---|
2.1 | 11 | 13 |
4.0 | 23 | 19 |
22 | 45 | 52 |
Luego calculamos el MSE como:
¿Fácil, verdad?
Podrías haber notado que los resultados de las substracciones se elevan al cuadrado, esto tiene las siguientes propiedades interesantes:
- Todos los errores son positivos: Porque elevar al cuadrado un número real siempre da un número positivo como resultado, los errores en MSE siempre son positivos. Esto significa que la información sobre la dirección del error (¿es menor de lo esperado o mayor de lo esperado?) se pierde. Esto está bien, debido a la siguiente propiedad.
- Los errores no se cancelan entre sí: Si tomamos en consideración la dirección de los números y hacemos un agregado de todos ellos, podríamos cancelar algunos errores con otros de signo opuesto. Si una estimación se desvía por -10000000 y la otra se desvía por +10000000, nuestro error medio sería 0, a pesar de predicciones horribles en ambas instancias. Un valor positivo para cada error asegura que todos contribuyan al valor agregado.
- Los errores grandes se enfatizan sobre los pequeños: Podrías recordar de la preparatoria que si el valor está entre 0 y 1, elevarlo al cuadrado lo hace más pequeño. Esto resulta en que errores pequeños (0 < errores < 1) se vuelvan aún menos significativos y los más grandes (errores > 1) contribuyan más pesadamente. Esto es bueno, ya que después podemos concentrarnos en minimizar los errores más grandes.
Aprendizaje caliente y frío
Ahora que entendemos los cálculos de error, regresemos al aprendizaje.
En el aprendizaje caliente y frío, simplemente ajustas los pesos hacia arriba y hacia abajo y ves cómo cambia el error. Esencialmente sigues aumentando/disminuyendo el valor de tus pesos hasta que el error desaparece o se vuelve muy pequeño.
Implementémoslo etapa por etapa. Al principio, necesitamos una red neuronal que realice una estimación, también es importante tener un valor esperado para medir el error.
def neural_network(input, weight):
predicted_value = input * weight
return predicted_value
minutes_running = 20
actual_calories_burned = 180
# Realizamos esta asignación extra solo para mantener consistencia con los nombres
input = minutes_running
expected_value = actual_calories_burned
weight = 7
predicted_value = neural_network(input, weight)
print("Según mi red neuronal, quemé {} calorías".format(predicted_value))
Si ejecutamos este código, me dice que quemé 140 calorías. Calculemos el error.
error = (predicted_value - expected_value)**2
print("El error en la predicción es {} ".format(error))
Esto nos dice que el error en la estimación tiene un valor de 1600 (MSE).
Ahora es tiempo de hacer pequeños ajustes al valor de nuestro peso y ver cómo reacciona el error. Usaremos un valor pequeño para nuestra tasa de aprendizaje: un número que sumamos y restamos de nuestro peso para ver cómo cambia el error.
Con una tasa de 0.1, calculamos errores para los pesos 7.1 y 6.9. El que produce el error menor se convertirá en nuestro nuevo peso. Este proceso se repite hasta que nuestro error se vuelve 0 o se acerca mucho a él.
learning_rate = 0.1
prediction_upwards = neural_network(input, weight + learning_rate)
error_upwards = (prediction_upwards - expected_value)**2
print("La predicción con un peso actualizado de {} tiene un error de {}".format(weight+learning_rate, error_upwards))
prediction_downwards = neural_network(input, weight - learning_rate)
error_downwards = (prediction_downwards - expected_value)**2
print("La predicción con un peso actualizado de {} tiene un error de {}".format(weight-learning_rate, error_downwards))
Nuestra primera ejecución imprime los siguientes resultados:
La predicción con un peso actualizado de 7.1 tiene un error de 1444.0
La predicción con un peso actualizado de 6.9 tiene un error de 1764.0
Como puedes ver, un peso con un valor de 7.1 produce un valor de error menor, así que actualizamos nuestro peso para tener ese valor.
Demo completamente iterativo
El aprendizaje caliente y frío es un proceso iterativo: continuaremos actualizando pesos hasta que nuestro error se vuelva muy pequeño. Esta demo completamente iterativa hace exactamente eso:
def neural_network(input, weight):
predicted_value = input * weight
return predicted_value
minutes_running = 20
actual_calories_burned = 180
# Realizamos esta asignación extra solo para mantener consistencia con los nombres
input = minutes_running
expected_value = actual_calories_burned
weight = 7
while True:
predicted_value = neural_network(input, weight)
print("Según mi red neuronal, quemé {} calorías".format(predicted_value))
error = (predicted_value - expected_value)**2
print("El error en la predicción es {} ".format(error))
learning_rate = 0.4
prediction_upwards = neural_network(input, weight + learning_rate)
error_upwards = (prediction_upwards - expected_value)**2
print("La predicción con un peso actualizado de {} tiene un error de {}".format(weight+learning_rate, error_upwards))
prediction_downwards = neural_network(input, weight - learning_rate)
error_downwards = (prediction_downwards - expected_value)**2
print("La predicción con un peso actualizado de {} tiene un error de {}".format(weight-learning_rate, error_downwards))
if(error_upwards < error_downwards):
weight = round(weight + learning_rate, 2)
else:
weight = round(weight - learning_rate, 2)
print("\n")
if(error == 0):
break
Cuando lo ejecutas, esto es lo que imprime:
Según mi red neuronal, quemé 140 calorías
El error en la predicción es 1600
La predicción con un peso actualizado de 7.4 tiene un error de 1024.0
La predicción con un peso actualizado de 6.6 tiene un error de 2304.0
Según mi red neuronal, quemé 148.0 calorías
El error en la predicción es 1024.0
La predicción con un peso actualizado de 7.800000000000001 tiene un error de 576.0
La predicción con un peso actualizado de 7.0 tiene un error de 1600.0
Según mi red neuronal, quemé 156.0 calorías
El error en la predicción es 576.0
La predicción con un peso actualizado de 8.2 tiene un error de 256.0
La predicción con un peso actualizado de 7.3999999999999995 tiene un error de 1024.0
Según mi red neuronal, quemé 164.0 calorías
El error en la predicción es 256.0
La predicción con un peso actualizado de 8.6 tiene un error de 64.0
La predicción con un peso actualizado de 7.799999999999999 tiene un error de 576.0000000000014
Según mi red neuronal, quemé 172.0 calorías
El error en la predicción es 64.0
La predicción con un peso actualizado de 9.0 tiene un error de 0.0
La predicción con un peso actualizado de 8.2 tiene un error de 256.0
Según mi red neuronal, quemé 180.0 calorías
El error en la predicción es 0.0
La predicción con un peso actualizado de 9.4 tiene un error de 64.0
La predicción con un peso actualizado de 8.6 tiene un error de 64.0
Como puedes ver en las últimas 3 líneas, cualquier cambio al peso de 9 resultará en valores de error más altos.
Ten cuidado con la tasa de aprendizaje
Una tasa de aprendizaje de 0.4 es mucho más rápida que una tasa de 0.1 para encontrar una solución. Si aumentamos la tasa de aprendizaje a 1, podemos alcanzar un error de 0 aún más rápido:
Según mi red neuronal, quemé 140 calorías
El error en la predicción es 1600
La predicción con un peso actualizado de 8 tiene un error de 400
La predicción con un peso actualizado de 6 tiene un error de 3600
Según mi red neuronal, quemé 160 calorías
El error en la predicción es 400
La predicción con un peso actualizado de 9 tiene un error de 0
La predicción con un peso actualizado de 7 tiene un error de 1600
Según mi red neuronal, quemé 180 calorías
El error en la predicción es 0
La predicción con un peso actualizado de 10 tiene un error de 400
La predicción con un peso actualizado de 8 tiene un error de 400
¿Eso significa que un valor más alto será aún más rápido? bueno, sí, un valor de 2 será el más rápido. Pero si vas por encima de eso, el aprendizaje caliente y frío nunca producirá una solución apropiada. El problema es que empezará a oscilar entre valores que están lejos de 9, y podría nunca detenerse. Inténtalo tú mismo y establece la tasa de aprendizaje en 8, ejecuta el código y ve cómo eternamente imprime estas líneas:
...
Según mi red neuronal, quemé 300 calorías
El error en la predicción es 14400
La predicción con un peso actualizado de 23 tiene un error de 78400
La predicción con un peso actualizado de 7 tiene un error de 1600
Según mi red neuronal, quemé 140 calorías
El error en la predicción es 1600
La predicción con un peso actualizado de 15 tiene un error de 14400
La predicción con un peso actualizado de -1 tiene un error de 40000
Según mi red neuronal, quemé 300 calorías
El error en la predicción es 14400
La predicción con un peso actualizado de 23 tiene un error de 78400
La predicción con un peso actualizado de 7 tiene un error de 1600
Según mi red neuronal, quemé 140 calorías
El error en la predicción es 1600
La predicción con un peso actualizado de 15 tiene un error de 14400
La predicción con un peso actualizado de -1 tiene un error de 40000
...
Un valor muy bajo para nuestra tasa de aprendizaje hará nuestra red lenta pero uno que sea demasiado alto la haría inutilizable. Esto, y el hecho de que el aprendizaje caliente y frío usualmente es muy lento, es la razón por la que esto nunca se usa en producción.
Aún así, es una muy buena forma de entender los fundamentos del proceso de aprendizaje de una red neuronal, algo que espero esté mucho más claro para ti después de leer este artículo. En el siguiente artículo, aprenderemos sobre una forma más poderosa de aprendizaje: el descenso de gradiente.
¡Gracias por leer!
Qué hacer después
- Comparte este artículo con amigos y colegas. Gracias por ayudarme a llegar a personas que podrían encontrar útil esta información.
- Puedes encontrar el código fuente para esta serie aquí
- Este artículo está basado en el libro: Grokking Deep Learning y en Deep Learning (Goodfellow, Bengio, Courville).
- Envíame un email con preguntas, comentarios o sugerencias (está en la página Autor)