This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Hasta el momento, todo lo que hemos visto sobre redes neuronales en los capítulos anteriores
se ha centrado en entender cómo estas son capaces de modelar información compleja.
Primero estudiamos el funcionamiento de las neuronas y cómo las podíamos usar para resolver
tareas de regresión o clasificación muy simples.
A partir de ahí vimos cómo podíamos juntar muchas de estas neuronas para crear una estructura
más compleja, una red neuronal, con la que podríamos modelar información mucho más
elaborada.
Y no solo nos quedamos ahí, sino que también visualizamos geométricamente lo que esto
significaba e incluso jugamos con una red neuronal para ganar más intuición.
Bueno, ¿y ahora qué?
Pues mira, hemos construido una herramienta con la que, variando sus parámetros, podemos
resolver problemas complejos de clasificación o regresión.
Pero claro, esto va de Inteligencia Artificial, el Machine Learning.
Aquí no queremos ser nosotros quienes tengamos que ajustar los parámetros de la red neuronal,
sino que sea la propia red la que aprenda por sí sola a partir de los datos.
Hoy vamos a ver cómo una red neuronal realiza su aprendizaje automático.
Pero para eso tenemos que movernos hacia atrás.
Bienvenidos a 1986.
Nos encontramos en una época que será recordada por las sombreras, el nacimiento de la MTV
o el Super Mario Bros.
Pero para nosotros, apasionados de la Inteligencia Artificial, 1986 es el año en el que se publicó
el artículo científico que cambiaría el destino de las redes neuronales.
¿Recuerdas en la primera parte cuando solo trabajábamos con una única neurona?
Esta única neurona, por sí misma, puede considerarse como un tipo muy simple de red
neuronal.
Y de hecho, esta unidad lógica era la precursora de las redes neuronales actuales, un tipo
de red que se conocía desde los años 50 con el nombre de Perceptron.
En los primeros años de vida del Perceptron se creyó que este sería el algoritmo que
resolvería una gran variedad de problemas, aunque pronto se hizo evidente alguna de sus
importantes limitaciones.
Como ya hemos visto anteriormente, esta arquitectura de una única neurona solo es capaz de resolver
problemas lineales, siendo necesario juntar más neuronas para poder abarcar problemas
no lineales más complejos.
Y aquí está el problema.
Y es que el algoritmo de aprendizaje automático que se venía utilizando para entrenar al
Perceptron no era extensible a otros tipos de redes más complejas, es decir, queríamos
redes neuronales, pero no sabíamos cómo entrenarlas.
Fue tal la repercusión de este problema que tras publicarse el libro Perceptrons, de Minsky
y Papert, donde se mostraba matemáticamente las importantes limitaciones del Perceptron,
hubo un corte repentino en la financiación de proyectos de Inteligencia Artificial y
más específicamente en aquellos relacionados con los sistemas de redes neuronales, un periodo
de más de 15 años conocido como el invierno de la Inteligencia Artificial.
Por suerte después de un duro invierno siempre viene la primavera, y en este caso veríamos
florecer de nuevo la investigación en Inteligencia Artificial con la publicación de un trabajo
que volvería a dar popularidad a las redes neuronales.
El trabajo, firmado por Ramel Hart, Hilton y Williams y basado en otros avances en diferenciación
automática, mostraría experimentalmente cómo usando un nuevo algoritmo de aprendizaje
se podría conseguir que una red neuronal autoajustara sus parámetros para así aprender
una representación interna de la información que estaba procesando, vamos, justamente lo
que estamos buscando.
El nombre de este algoritmo?
Backpropagation.
La importancia de este algoritmo es clave dentro de la arquitectura de una red neuronal,
y por eso hoy nos vamos a centrar en entender exactamente cómo funciona, posiblemente
más de uno que ya conozca este algoritmo esté pensando, uff, ya estamos de nuevo con
esa parte en la que la teoría se vuelve engorrosa y llena de fórmulas.
Tranquilo, en el vídeo de hoy solo nos centraremos en entender cuál es la intuición detrás
de este algoritmo, y ya después en la siguiente parte veremos cómo las fórmulas no esconden
ningún misterio.
No solo eso, la buena noticia, ya tenemos parte del trabajo hecho.
¿Recuerdas el vídeo del descenso del gradiente?
Si no lo has visto aún, es parado obligatorio.
Como recordatorio, con el descenso del gradiente conseguíamos una estrategia perfecta para
ajustar los parámetros de, bueno, en su momento una regresión lineal.
El truco que usábamos era el de evaluar el error del modelo en el punto en el que nos
encontrábamos, y calcular las derivadas parciales en dicho punto.
Con esto obteníamos un vector de direcciones que nos indicaba la pendiente de la función,
hacia donde el error se incrementaba, lo que se llama el gradiente, y con eso nos movíamos
en la dirección contraria, así teníamos una forma por la cual iterativamente podríamos
ir reduciendo el error del modelo como si la altura de una montaña se tratase.
¿Te acuerdas?
Vale, el descenso del gradiente es la leche, pero ¿y por qué no lo usamos directamente
en nuestra red neuronal?
Spoiler, lo vamos a utilizar, pero no es tan sencillo.
Fíjate, para aplicar el descenso del gradiente necesitamos, bueno, eso, el gradiente, ¿no?
Cuando trabajamos por ejemplo con regresión lineal, calcular el vector gradiente era muy
sencillo.
Para la regresión simple teníamos solo dos parámetros, estos de aquí, que afectaban
directamente al resultado del modelo, con lo cual calcular el gradiente para cada uno
de los parámetros era simplemente responder a la pregunta ¿cómo varía el coste ante
un cambio del parámetro W?
Pregunta que matemáticamente se responde con las derivadas parciales, derivada parcial
de la función de coste con respecto a cada uno de los parámetros.
Simple.
Sin embargo, cuando trabajamos con redes neuronales la cosa es un poco más compleja, aquí el
gradiente viene a ser el mismo concepto de antes, como varía el coste cuando variamos
un parámetro.
Pero claro, aquí la forma en la que variar un parámetro puede afectar al resultado
final y por tanto al coste de la red neuronal es más complejo.
El parámetro de esta conexión de aquí puede influir al resultado final por la información
que fluye por esta conexión, o por esta otra conexión, o cualquiera de estas otras.
Y no solo eso, sino que el efecto de este parámetro se ve también controlado por el
valor del resto de parámetros de las capas posteriores.
Vamos, una cadena de responsabilidades que hace que esta derivada de aquí, de nuevo,
como varía el coste cuando variamos alguno de los parámetros, sea más compleja de calcular.
¿Y quién es la que nos va a dar ese valor?
Efectivamente, el algoritmo de backpropagation.
Es decir, al igual que hacíamos antes, utilizaremos el descenso del gradiente para optimizar nuestra
función de coste, haciendo uso de la técnica de backpropagation para calcular el vector
de gradientes dentro de la complejidad de la arquitectura de la red neuronal.
¿Lo entiendes?
Perfecto.
Coffee Break.
Un agricultor en Colombia cosecha grano de café siguiendo un proceso que él ha elegido.
Esos granos son enviados a una de las muchas fábricas en la que se tuesta, muele ni envasan
el café.
Después, los paquetes de café de la compañía X viajarán a diferentes puntos de venta,
que se encargarán de desplegar una estrategia de marketing para hacer que el cliente, yo,
me decida comprar justamente esa marca.
En casa me prepararé una taza de café que me dará el chute de energía necesario para
inspirarme en producir exactamente este trozo de vídeo, un vídeo que finalmente será consumido
por ti, con la esperanza de que entiendas su contenido y lo que te quiero enseñar.
Para que así tú, en tu satisfacción de sentirte autor realizado por haber aprendido
un nuevo concepto de machine learning, me premietándole a like a este vídeo.
¿Pero qué coj-?
¿Un dislike?
¿En serio?
¿Pero qué ha pasado aquí?
Vale, calmémonos.
Lo que acaba de suceder es que tú, al dar dislike, has generado una fuerte señal de
error.
Vamos, has penalizado el trabajo que yo he hecho.
¿Y de quién es la culpa?
¿Tuya por no haberlo entendido bien o mía por haber hecho el vídeo mal?
¿O quizás ha sido la taza de café que no me ha dado la energía suficiente?
Quizás me equivoque a comprar ese café y no otro, y de ser así, ¿quién tiene la
culpa?
¿El que ha hecho el café, la distribución, la fábrica?
Bueno, como ves aquí, lo que hemos dibujado es una cadena de responsabilidades que se
puede asemejar a una red neuronal, donde cada nodo es una neurona especializada en una tarea
determinada.
El vídeo lo podríamos ver como el resultado de salida de nuestra red y la evaluación
que tú das como nuestra función de coste.
Si al yo ver que has generado dicha señal de error tan fuerte, quisiera intentar que
no se volviera a producir, una estrategia inteligente a seguir sería la de analizar
toda la cadena de responsabilidades que ha afectado al resultado.
Si de repente encontramos una neurona que haya tenido influencia en el error obtenido,
entonces deberemos de responsabilizar a dicha neurona con parte de ese error.
Y aquí está la clave.
Esta análisis de cuánta responsabilidad tiene cada neurona tiene sentido hacerlo hacia atrás,
desde la señal de error hacia las primeras capas.
Esto tiene sentido hacerlo porque en una red neuronal, el error de las capas anteriores
depende directamente del error de las capas posteriores, es decir, si por ejemplo vemos
que en el mal resultado del vídeo no depende mucho si la calidad del café es buena o mala,
entonces el error de las fases previas a esta, por ejemplo los efectos de cosechar mal el
café, también deberán de afectar poco al error final.
Si por el contrario el café sí es responsable del error, entonces sí que habría que analizar
las responsabilidades que las fases previas tienen en la posterior calidad del café.
Con esto vemos cómo existe una lógica que podemos explotar para determinar qué parte
de culpa tiene cada neurona en el resultado final, mediante la retro propagación de errores.
Lo bueno es que siguiendo esta estrategia de ir hacia atrás, también estamos trabajando
de forma eficiente.
Fíjate, si comenzamos a analizar la cadena de responsabilidades hacia atrás, desde
la señal de error, nuestra primera parada sería la última capa.
Como hemos dicho, en función de cuánto se haya implicado cada neurona en general el
resultado final, podremos responsabilizar a cada una de estas neuronas de un porcentaje
del error.
En este caso, si asumimos que durante toda la fase de creación del video tomado principalmente
del café X, entonces la mayor responsabilidad de ese error recaerá en el café X, así
que de esta manera podemos hacer un reparto de dichos errores.
Ese será el error de la neurona, y será lo que utilizaremos principalmente para calcular
cuánto hay que modificar cada parámetro en dicha neurona.
Lo interesante es que una vez hemos imputado los errores a las neuronas de dicha capa,
podemos proceder a repetir el mismo proceso de antes como si este fuera el error final
de nuestra red, es decir, asumiendo que esta es nuestra nueva última capa.
Así aplicar backpropagation es operar siempre de forma recursiva capa tras capa moviendo
el error hacia atrás.
Gracias a esto, cuando lleguemos a la primera capa, habremos obtenido cuál es el error
para cada neurona y para cada uno en sus parámetros, solamente propagando una única vez el error
hacia atrás, lo cual hace de este algoritmo una estrategia muy muy eficiente.
¿En serio?
No es pareja trivial, pero antes de existir backpropagation, el cálculo de la responsabilidad
de cada neurona en el resultado se hacía siguiendo una estrategia de fuerza bruta,
preguntándose para cada neurona cómo variaba el coste cuando se introducía algún pequeño
cambio.
En la práctica, esto requería computar muchas veces pases hacia adelante en nuestra red,
siendo así muy ineficiente de entrenar.
Por el contrario, lo propuesto al algoritmo de backpropagation permite obtener todos esos
errores con un único pase hacia atrás.
Estos errores son los que usaremos para calcular las derivadas parciales de cada parámetro
de la red, conformando así el vector gradiente, que como ya sabemos es lo que necesita el
algoritmo del descenso del gradiente para minimizar el error y por tanto entrenar a
la red.
Interesante, ¿verdad?
Y todo esto ¿cómo se traduce a las matemáticas?
Tranquilo, eso lo veremos en el siguiente video, pero ya verás que si entiendes los
fundamentos de lo que hemos hablado no te costará entenderlo.
Si he conseguido que entiendas esto, me doy por satisfecho, y en ese caso, no podríamos
considerar este como un buen video.
¡Suscríbete al canal!