Processing math: 100%

Herramientas de usuario

Herramientas del sitio


clase:iabd:pia:2eval:tema07.backpropagation_descenso_gradiente

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
clase:iabd:pia:2eval:tema07.backpropagation_descenso_gradiente [2024/02/22 11:51]
admin [Ejercicios]
clase:iabd:pia:2eval:tema07.backpropagation_descenso_gradiente [2025/01/22 18:28] (actual)
admin [Ejercicios]
Línea 1: Línea 1:
-====== 7. Entrenamiento de redes neuronales bDescenso de gradiente ======+====== 7.b Descenso de gradiente ======
  
 El Descenso de gradiente es el algoritmo que usamos para entrenar la red neuronal.  El Descenso de gradiente es el algoritmo que usamos para entrenar la red neuronal. 
Línea 26: Línea 26:
 $$ $$
 \large loss(x,y,parametros)=\frac{1}{N} \sum_{i=1}^{N}|y_i-\frac{1}{1 + e^{-(  w_{5,2}\frac{1}{1 + e^{-( w_{2}x_i+b_{2}  )}}+w_{5,3}\frac{1}{1 + e^{-( w_{3}x_i+b_{3}  )}}+w_{5,4}\frac{1}{1 + e^{-( w_{4}x_i+b_{4}  )}}+b_5 )}}|     \large loss(x,y,parametros)=\frac{1}{N} \sum_{i=1}^{N}|y_i-\frac{1}{1 + e^{-(  w_{5,2}\frac{1}{1 + e^{-( w_{2}x_i+b_{2}  )}}+w_{5,3}\frac{1}{1 + e^{-( w_{3}x_i+b_{3}  )}}+w_{5,4}\frac{1}{1 + e^{-( w_{4}x_i+b_{4}  )}}+b_5 )}}|    
 +$$
 +
 +$$
 +loss(x,y,parametros)=loss(x,y,w_{2} , w_{3} , w_{4} , w_{5,2} , w_{5,3} , w_{5,4} , b_{4} , b_{2} , b_{3} , b_5)
 $$ $$
  
Línea 126: Línea 130:
 La siguiente imagen ilustra la idea. La siguiente imagen ilustra la idea.
 {{ :clase:iabd:pia:2eval:descenso_gradiente.png?direct |}} {{ :clase:iabd:pia:2eval:descenso_gradiente.png?direct |}}
 +
 +Y podemos jugar con un simulador de descenso de gradiente en [[https://losslandscape.com/explorer|Loss Landscape Explorer]]
 +
 +[[https://losslandscape.com/explorer|{{:clase:iabd:pia:2eval:descenso_gradiente_1.png?400|}}]]
 +
 +Y ver un video de como funciona en [[https://www.youtube.com/watch?v=QeViLO0pU1I|LR COASTER | learning rate in machine learning | Loss Landscape visualization | Deep Learning]]
 +
 +[[https://www.youtube.com/watch?v=QeViLO0pU1I|{{:clase:iabd:pia:2eval:descenso_gradiente_2.png?400|}}]]
 +
  
 ¿Como hacemos eso matemáticamente? Pues lo primero es pensar que cuando se inicializa la red neuronal, a los parámetros (w0 y w1) se les da un valor aleatorio, por lo que estamos en un punto cualquiera de esa //montaña//. ¿Como sabemos en que dirección debemos movernos? Pues muy fácil, incrementamos un poquito el valor del parámetro (a ese incremento lo llamaremos h o Δx) y vemos como se incrementa con respecto del valor original, (a ese incremento de la función lo llamamos Δf) . Es decir los restamos (aunque también lo dividimos entre el valor del incremento).  ¿Como hacemos eso matemáticamente? Pues lo primero es pensar que cuando se inicializa la red neuronal, a los parámetros (w0 y w1) se les da un valor aleatorio, por lo que estamos en un punto cualquiera de esa //montaña//. ¿Como sabemos en que dirección debemos movernos? Pues muy fácil, incrementamos un poquito el valor del parámetro (a ese incremento lo llamaremos h o Δx) y vemos como se incrementa con respecto del valor original, (a ese incremento de la función lo llamamos Δf) . Es decir los restamos (aunque también lo dividimos entre el valor del incremento). 
Línea 147: Línea 160:
  
 <note tip>En el contexto del descenso de gradiente no se suele hablar que el resultado de la fórmula es la derivada sino el gradiente. Ya que para eso estamos en el //descenso de gradente//</note> <note tip>En el contexto del descenso de gradiente no se suele hablar que el resultado de la fórmula es la derivada sino el gradiente. Ya que para eso estamos en el //descenso de gradente//</note>
 +
 +Para entender la derivada podemos usar estos 2 recursos de Gecebra:
 +  * [[https://www.geogebra.org/classic/kspgbec4|Pendiente de una recta]]: La pendiente es el valor de las derivada.
 +  * [[https://www.geogebra.org/m/zfg8nxt6|Cálculo gráfico de derivadas]]: Se puede ver la derivada (pendiente) en cada punto de una curva
  
  
Línea 454: Línea 471:
 Que genera la siguiente gráfica Que genera la siguiente gráfica
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_1.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_1.png?direct&500 |}}
  
  
Línea 464: Línea 481:
 </note> </note>
  
 +==== Optimizadores de Keras ====
 + Podemos mejorar nuestro código en Python haciendo que podamos usar directamente los [[https://keras.io/api/optimizers/|Optimizers]] de Keras y de esa forma ver como funciona cada uno de ellos. Para poder usarlos directamente vamos a creas las nuevas funciones ''loss_tf'' y ''get_puntos_descenso_gradiente_optimizer'' adecuadas a TensorFlow y Keras.
  
 +
 +<sxh python>
 +def loss_tf(w_0,w_1):
 +    return  3*(1 - w_0)**2 * tf.exp(-w_0**2 - (w_1 + 1)**2)  - 10*(w_0/5 - w_0**3 - w_1**5)*tf.exp(-w_0**2 - w_1**2) - 1./3*tf.exp(-(w_0 + 1)**2 - w_1**2) 
 +
 +def get_puntos_descenso_gradiente_optimizer(epochs,optimizer_function,w_0_init,w_1_init):
 +
 +    puntos_descenso_gradiente=np.array([[w_0_init,w_1_init]])
 +
 +    w_0=w_0_init
 +    w_1=w_1_init
 +    for epoch in range(epochs): 
 +        var_w_0=tf.Variable(w_0)
 +        var_w_1=tf.Variable(w_1)
 +
 +        optimizer_function.minimize(lambda: loss_tf(var_w_0,w_1),  var_list=[var_w_0])
 +        optimizer_function.minimize(lambda: loss_tf(w_0,var_w_1),  var_list=[var_w_1])
 +
 +        w_0=var_w_0.numpy()
 +        w_1=var_w_1.numpy()      
 +
 +        puntos_descenso_gradiente=np.append(puntos_descenso_gradiente,[[w_0,w_1]], axis=0)           
 +
 +    return puntos_descenso_gradiente
 +</sxh>
 +
 +Lo que ha cambiado principalmente es la función ''get_puntos_descenso_gradiente_optimizer''  no hace cálculo  del gradiente (derivada) ni actualiza los parámetros, sino que llama a la función de Keras de optimización.
 +
 +
 +Si usamos ''get_puntos_descenso_gradiente_optimizer'' ahora con ''tf.keras.optimizers.SGD''
 +<sxh python>
 +get_puntos_descenso_gradiente_optimizer(5,tf.keras.optimizers.SGD(learning_rate=0.03),-0.35,-0.67)
 +</sxh>
 +<sxh base>
 +array([[-0.35      , -0.67      ],
 +       [-0.269319  , -0.72470832],
 +       [-0.13292952, -0.83883744],
 +       [ 0.06544246, -1.06462073],
 +       [ 0.24086528, -1.40752137],
 +       [ 0.26578248, -1.59573841]])
 +</sxh>
 +Vamos que el resultado es prácticamente el mismo que cuando lo hicimos manualmente.
 +
 +Y podemos generar de la misma forma el gráfico:
 +<sxh python>
 +figure=plt.figure(figsize=(16,15))
 +axes = figure.add_subplot()
 +plot_loss_function(axes)
 +
 +plot_descenso_gradiente(axes,get_puntos_descenso_gradiente_optimizer(5,tf.keras.optimizers.SGD(learning_rate=0.03),-0.35,-0.67))
 +</sxh>
 +
 +
 +{{ :clase:iabd:pia:2eval:optimizer_sgd.png?direct&500 |}}
 +
 +Y obviamente el resultado es el mismo
  
 ==== Learning rate y epochs ==== ==== Learning rate y epochs ====
Línea 476: Línea 551:
  
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_2.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_2.png?direct&500 |}}
  
  
Línea 488: Línea 563:
  
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_4.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_4.png?direct&500 |}}
  
 El valor de ''learning_rate'' es mayor aun , siendo de ''0.1'' por lo que damos //pasos// tan grandes que nos salimos de mínimo de la función y eso que hemos pasado de 5 épocas a 11 épocas.  El valor de ''learning_rate'' es mayor aun , siendo de ''0.1'' por lo que damos //pasos// tan grandes que nos salimos de mínimo de la función y eso que hemos pasado de 5 épocas a 11 épocas. 
Línea 500: Línea 575:
 </sxh> </sxh>
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_5.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_5.png?direct&500 |}}
  
 Vemos que al dar //pasos// tan pequeños nos quedamos a mitad de camino y eso que también hemos puesto 11 épocas. En este caso para solucionarlo solo habría que aumentar el número de épocas. Vemos que al dar //pasos// tan pequeños nos quedamos a mitad de camino y eso que también hemos puesto 11 épocas. En este caso para solucionarlo solo habría que aumentar el número de épocas.
Línea 510: Línea 585:
 </sxh> </sxh>
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_6.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_6.png?direct&500 |}}
  
 Y ahora ya ha llegado hasta el mínimo. Y ahora ya ha llegado hasta el mínimo.
Línea 530: Línea 605:
  
  
-{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_3.png?direct&700 |}}+{{ :clase:iabd:pia:2eval:descenso_gradiente_algoritmo_vanilla_3.png?direct&500 |}}
  
 Esta última gráfica es muy interesante. No hay que perder de vista que las **estrellas rojas** es el valor inicial de los pesos que tenemos en nuestra red neuronal.  Esta última gráfica es muy interesante. No hay que perder de vista que las **estrellas rojas** es el valor inicial de los pesos que tenemos en nuestra red neuronal. 
Línea 547: Línea 622:
 Para intentar solventar los problemas del algoritmo del descenso de gradiente existen diversas variaciones del mismo que vamos a ver en el siguiente apartado. Para intentar solventar los problemas del algoritmo del descenso de gradiente existen diversas variaciones del mismo que vamos a ver en el siguiente apartado.
  
 +==== Punto de silla ====
 +Al entrenar redes neuronales, existe el concepto de "Punto de silla"
 +Es un punto en el que para cada parámetro estaría en un mínimo o máximo local. 
 +Su nombre viene de que parece una silla de montar a caballo.
 +
 +{{:clase:iabd:pia:2eval:punto_de_silla.png?500|}}
 +
 +No debe preocuparnos los puntos de silla ya que al actualizar los parámetros, la "forma" de la función de coste cambiará y lo fácil es que se salga del punto de silla.
  
 ===== Usando optimizadores en Keras  ===== ===== Usando optimizadores en Keras  =====
Línea 777: Línea 860:
   * [[https://vineetrawat9121996.medium.com/rmsprop-saviour-of-adagrad-de4e705427b4|RMSprop saviour of Adagrad]]: Lo que intenta mejorar RMSprop de Adagrad   * [[https://vineetrawat9121996.medium.com/rmsprop-saviour-of-adagrad-de4e705427b4|RMSprop saviour of Adagrad]]: Lo que intenta mejorar RMSprop de Adagrad
   * [[https://visharma1.medium.com/adagrad-and-adadelta-optimizer-in-depth-explanation-6d0ad2fdf22|Adagrad and Adadelta Optimizer: In-Depth Explanation]]   * [[https://visharma1.medium.com/adagrad-and-adadelta-optimizer-in-depth-explanation-6d0ad2fdf22|Adagrad and Adadelta Optimizer: In-Depth Explanation]]
-  * [[https://medium.com/geekculture/a-2021-guide-to-improving-cnns-optimizers-adam-vs-sgd-495848ac6008|A 2021 Guide to improving CNNs-Optimizers: Adam vs SGD]]+  * [[https://medium.com/geekculture/a-2021-guide-to-improving-cnns-optimizers-adam-vs-sgd-495848ac6008|A 2021 Guide to improving CNNs-Optimizers: Adam vs SGD]]: Las fórmulas de los optimizadores 
 + 
 +===== Backpropagation ===== 
 +El Backpropagation es el algoritmo que optimiza el entrenamiento de la red. Calcular el gradiente (o derivada) de toda la red es muy costoso. Se basa en la idea de que los parámetros de una capa no dependen de la capa anterior. 
 + 
 + 
 +Si volvemos a ver nuestra red neuronal de ejemplo, podemos calcular los pesos de la neurona 5 sin que influya en como van a ser los pesos de las neuronas 2, 3 y 4. Es decir que empezamos con las neuronas de las capas más hacía la salida y una vez calculados sus pesos , calculamos los parámetros de las capa anterior (más hacia la entrada) , y eso significa ir hacia atrás o //backpropagation//
 + 
 +{{ :clase:iabd:pia:2eval:backpropagation_1.gif?direct |}} 
 + 
 +{{ :clase:iabd:pia:2eval:backpropagation_2.gif?direct |}} 
 + 
 +{{ :clase:iabd:pia:2eval:backpropagation_3.mp4?700 |}} 
 + 
 +Con backpropagation acabamos de ver el orden en el que se calculan los parámetros de cada neurona y a continuación vamos a ver con el descenso de gradiente como calculamos los parámetros de una neurona. 
 + 
 +Junto con el backpropagation  aparece otro concepto llamado //regla de la cadena// o //chain rule// que se usa para junto al backpropagation para hacer menos cálculos. Está relacionado con el cálculo de derivadas. 
 + 
 +En los siguientes videos está explicado perfectamente el backpropagation y la //chain rule//: 
 +  * [[https://www.youtube.com/watch?v=eNIqz_noix8|¿Qué es una Red Neuronal? Parte 3 : Backpropagation | DotCSV]]: Video 
 +  * [[https://www.youtube.com/watch?v=M5QHwkkHgAA|¿Qué es una Red Neuronal? Parte 3.5 : Las Matemáticas de Backpropagation | DotCSV]]: Video 
 + 
  
 ===== Hardware entrenamiento ===== ===== Hardware entrenamiento =====
Línea 994: Línea 1099:
 x=iris.data[0:99,2] x=iris.data[0:99,2]
 y_true=iris.target[0:99] y_true=iris.target[0:99]
 +</sxh>
  
-parametros=[(-0.3,0.1)]+<sxh python> 
 +parametros=[(-0.3,0),(0.1,-0.2),(0.4,-0.4),(0.8,-2)]
 plot_parametros(x,y_true,parametros) plot_parametros(x,y_true,parametros)
 </sxh> </sxh>
  
-Que muestra la siguiente gráfica:+Que muestra la siguiente figura:
  
 {{:clase:iabd:pia:2eval:tema_7_ejer_3_salida.png|}} {{:clase:iabd:pia:2eval:tema_7_ejer_3_salida.png|}}
  
-Esta gráfica muestra en rojo que con los valores de ''w=-0.3'' y ''b=0.1'' el valor de la pérdida de la red es 0.59. ''loss=0.59''.  +Cada par de valores del array ''parametros'' son los parámetros en cada una de las épocas. 
-Mientras que en verde se muestra los valores que harían mínima cada ua de las funciones ''w=0.55'' y ''b=-4''.+ 
 +En las 2 primeras gráficas se muestra en rojo que con los valores de ''w=-0.3'' y ''b=0'' el valor de la pérdida de la red es 0.58. ''loss=0.50''.  
 +Mientras que en verde se muestra los valores que harían mínima cada una de las funciones ''w=0.56'' y ''b=-5''.  
 +Y así sucesivamente con el resto de parámetros 
 + 
 +En las últimas gráficas se muestra a la izquierda cada uno de los "loss" que ha habido en cada "época" y a la derecha como han evolucionado los parámetros en cada "época".
  
 Modifica el array ''parametros'' añadiendo mas pares de valores de ''w'' y ''b'' para ver si consigues obtener un valor de ''loss'' lo más cercano a 0 que sea posible. Deberás ir modificando poco a poco los valores de ''w'' y ''b''. Modifica el array ''parametros'' añadiendo mas pares de valores de ''w'' y ''b'' para ver si consigues obtener un valor de ''loss'' lo más cercano a 0 que sea posible. Deberás ir modificando poco a poco los valores de ''w'' y ''b''.
clase/iabd/pia/2eval/tema07.backpropagation_descenso_gradiente.1708599105.txt.gz · Última modificación: 2024/02/22 11:51 por admin