¿Cómo se entrenan las redes neuronales de la computadora?

Daré una versión corta y luego la ampliaré con una respuesta más larga y completa en la sección debajo de la versión corta.

Version corta:

En un nivel alto, una red neuronal toma algunos puntos de datos, cada uno de los cuales tiene algún tipo de clasificación. Los puntos de datos pueden ser imágenes u oraciones, por ejemplo. Las clasificaciones pueden ser qué tipo de objeto muestra la imagen o el sentimiento de una oración.

Cada punto de datos tiene un conjunto de características (piense en el valor de píxeles en un punto o si existe una palabra en una oración) y lo que la red neuronal intenta hacer es encontrar un mapeo entre estas características a la clasificación adecuada.

Cómo aprende a hacer esto con precisión es a través de ver muchos ejemplos. A través de una gran cantidad de datos, prueba y error, la red neuronal está esencialmente calculando cuánto ponderar cada característica en su decisión final.

Por ejemplo, si estaba tratando de clasificar un sistema de reconocimiento de dígitos simple que solo toma imágenes de 0 y 1, la red neuronal aprenderá con el tiempo que la presencia de píxeles fuertes en la imagen central es una característica que probablemente sea más probable que se asigne a una clasificación de 1.

Una vez que ha visto muchos datos, puede usar los pesos que aprendió para hacer predicciones sobre datos que nunca antes había visto. En pocas palabras, cómo funcionan las arquitecturas de redes neuronales más simples.


Versión más larga (con las matemáticas):

Creo que la mejor manera de explicar los detalles de cómo se entrena una red neuronal es con un pequeño ejemplo.

Vayamos con el ejemplo mencionado anteriormente de clasificar 1’s y 0’s de las imágenes de escritura a mano. Ahora, en este ejemplo, nuestros “datos” son cada imagen, etiquetada como 1 o 0. Y recuerde que cada imagen tiene un conjunto de características, y en este ejemplo usaremos sus valores de píxeles como características. Es importante recordar que podemos elegir nuestras funciones para que sean lo que queramos y, en el mundo real, podríamos incluso querer “diseñar” nuevas funciones a partir de los datos que tenemos. Pero para este ejemplo, mantengamos las cosas simples.

Asumamos por simplicidad que las imágenes son 3 x 3 y los valores de píxeles son discretos, con un valor de 1 para blanco y 0 para negro. Una representación intuitiva del conjunto de características para una imagen es una matriz. Aquí hay un ejemplo de cómo podría verse una transformación de una imagen a un conjunto de características (tenga en cuenta que esto podría ser diferente para otra imagen dependiendo de cómo se coloque el 1 o el 0).

[matemática] A = \ begin {bmatrix} 0 & 1 & 0 \\ 0 & 1 & 0 \\ 0 & 1 & 0 \ end {bmatrix} [/ math]

[matemática] B = \ begin {bmatrix} 0 & 1 & 0 \\ 1 & 0 & 1 \\ 0 & 1 & 0 \ end {bmatrix} [/ math]

Entonces, en este ejemplo, tenemos 9 características que representan cada punto de datos. Ahora, en el mundo del aprendizaje automático, nos gusta que cada punto de datos se represente como un vector de características en lugar de una matriz de características (podríamos pasar nuestros datos como una matriz, pero luego entraríamos en el mundo de los tensores – vamos a Mantén las cosas simples). Entonces, un truco simple que se usa todo el tiempo es aplanar (formalmente conocido como vectorización) la matriz.

Así es como se ven nuestras matrices aplanadas:

[math] \ operatorname {vec} (A) = \ begin {bmatrix} 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 \ end {bmatrix} ^ \ top [/ math]

[math] \ operatorname {vec} (B) = \ begin {bmatrix} 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \ end {bmatrix} ^ \ top [/ math]

Hacemos esta operación para cada imagen y al final apilamos nuestros vectores de fila en una matriz de datos de entrenamiento (llamemos a esta matriz [matemáticas] X [/ matemáticas]). Cada fila corresponde a una clasificación (0 o 1) y estas clasificaciones se pueden consolidar en un vector de columna que se pasa junto con los datos de entrenamiento (llamemos a este vector de columna de verdad fundamental [math] y [/ math]). Es por eso que este método de clasificación se llama aprendizaje supervisado: estamos pasando datos junto con etiquetas.

Ahora etiquetemos cada vector de fila de [math] X [/ math] como [math] x_i [/ ​​math], que consiste en las características de cada imagen. Cada elemento de [math] x_i [/ ​​math] corresponde a una neurona en la capa de entrada. Cada una de estas neuronas de la capa de entrada [matemáticas] i [/ matemáticas] está conectada a una neurona oculta [matemáticas] j [/ matemáticas] a través de algo llamado sinapsis, que simplemente tiene un peso [matemáticas] w_ {ij} [/ matemáticas] . Cada neurona en la capa oculta recibe una versión ponderada de cada neurona de la capa de entrada. La capa oculta suma cada una de las entradas ponderadas, esencialmente realizando la operación de un producto de puntos. Formalmente, después de la sumatoria, el resultado es un escalar en la neurona [matemática] j [/ matemática] es [matemática] u_j = \ [/ matemática] [matemática] x_i \ cdot w_j [/ matemática] donde [matemática] w_j [/ matemática ] es el vector de peso de todos los pesos entrantes a la neurona [math] j [/ math]. Podemos generalizar esta operación para todas las neuronas como una simple multiplicación de matriz [matemática] u = Wx_i [/ ​​matemática] con [matemática] W [/ matemática] representando la matriz con todas [matemática] w_ {ij} [/ matemática] como entradas (en otras explicaciones también verá [math] u = Wx_i + b [/ math] donde [math] b [/ math] representa un vector de sesgo que simplemente permite un mejor entrenamiento de las redes en la práctica).

Ahora, después de haber obtenido las sumas ponderadas de las neuronas de entrada, hay un último paso que debemos realizar antes de pasar este vector a la siguiente capa oculta. Esto implica aplicar una función de activación a todos los elementos en el vector [math] u [/ math] que obtuvimos en la sección anterior. Una función de activación común que se usa es la función sigmoidea (también hay otras opciones):

[matemáticas] g (x) = \ frac {1} {1 + e ^ {- x}} [/ matemáticas]

El uso principal de las funciones de activación es que permiten que las redes neuronales modelen relaciones más complejas y no lineales a través de composiciones de tales funciones. En otras palabras, si las funciones de activación no estuvieran presentes, nuestra red neuronal consistiría simplemente en muchas operaciones lineales, que de hecho solo podrían modelar con precisión las relaciones lineales.

Pero una vez que tenemos nuestras funciones de activación para una capa oculta, simplemente aplicamos este elemento de función al vector [math] u [/ math] para obtener la salida de la primera capa oculta [math] h_1 = g (u) [/ matemáticas]. Luego pasamos esta salida a las capas ocultas posteriores y repetimos el mismo proceso.

Cuando finalmente llegamos a la capa de salida, aplicamos la activación una vez más para obtener una salida [matemática] a [/ matemática], que representa la estimación de las redes neuronales de la salida para cada muestra de entrenamiento.

Ahora, aquí es donde entra en juego la optimización. Ya sabemos cuál debería ser el resultado de nuestras muestras de entrenamiento: tenemos en el vector [math] y [/ math] que representa la verdad fundamental. Y en las iteraciones iniciales de entrenamiento de la red neuronal, los pesos se inicializan aleatoriamente y es muy poco probable que obtengamos la salida correcta en el primer intento a través de nuestro conjunto de entrenamiento. Existe alguna noción de error o pérdida y a lo largo del entrenamiento queremos minimizar ese error.

Esta noción de error se representa en las redes neuronales como una función de pérdida y una de las funciones de pérdida más intuitivas es la función de error cuadrático medio:

[matemáticas] MSE \ = \ frac {1} {N} \ sum_ {i = 1} ^ {N} (y_i – a_i) ^ 2 [/ matemáticas]

Esta función literalmente toma el promedio del error al cuadrado entre la estimación de la salida de la red neuronal y la salida correcta. También hay otras funciones de pérdida más sofisticadas, como la función de pérdida de entropía cruzada y la función de pérdida de divergencia KL que se inspiran en las ideas de la teoría de la información.

Ahora, como se mencionó anteriormente, nuestro objetivo aquí es pasar por la fase de entrenamiento y minimizar esta función de pérdida. Idealmente, nos gustaría “ajustar” nuestros pesos para que podamos minimizar esta función de pérdida. ¿Cómo hacemos para hacer eso?

Probablemente recuerde de su curso de cálculo cómo encontrar mínimos locales de una función arbitraria. En dimensiones superiores, esto se expande para encontrar derivadas parciales y específicamente gradientes. En los casos en que nuestras funciones pueden ser increíblemente complejas y no lineales, utilizamos un método fundamental llamado descenso de gradiente. Este método esencialmente encuentra el gradiente en puntos de datos particulares y ajusta los pesos para que la función se mueva en la dirección del descenso más pronunciado, minimizando así la pérdida. Hay una gran cantidad de teoría detrás de esto que te animo a que estudies al leer sobre el algoritmo.

Ahora, una última pieza del rompecabezas es cómo calcular gradientes en redes neuronales. Aquí es donde entra en juego el famoso algoritmo de retropropagación y, al final del día, se reduce a aplicar la regla de la cadena a derivadas parciales. Otras respuestas han hecho un buen trabajo al explicar esta idea, y si quieres ver mi explicación, mira mi respuesta a ¿Cómo entiendo la belleza del algoritmo de retropropagación?

Aquí hay una respuesta breve para eso y le recomiendo que consulte en Internet para encontrar tutoriales en profundidad.

  1. Primero elija la arquitectura NN para ex: (neuronas de entrada = 3 capas ocultas = 1 neuronas ocultas por capa = 4 y neurona de salida = 2)

2. Pase los datos de entrada a salida a través de oculto (Feed Forwarding)

(inicializando los pesos y multiplicando las entradas y calculando salidas)

3.calcule el error (también proporcionamos resultados)

por ejemplo: la entrada de operación XOR es 1,1 la salida es 0

error = salida dada salida predicha (en la capa de salida)

Ej: si la salida pronosticada es 1, entonces error = 0–1 = -1

4.aplicar el algoritmo de propagación hacia atrás (ajustando los pesos según el error)

5. Repita el reenvío de alimentación y repita la propagación hacia atrás durante varias iteraciones (10000) o hasta que el error esté cerca de 0

entonces podemos decir que nuestra red está capacitada y podemos dar una entrada para predecir la salida.

PD: Solo quiero dar una explicación de alto nivel para obtener más detalles. Visite Internet. Hay muchas fuentes disponibles.

Desde pequeñas redes neuronales (NN) a escala de Google, el enfoque de aprendizaje utilizado es el descenso de gradiente básico. Sí, incluso los modelos sofisticados como Inception o redes neuronales residuales (ResNet) están entrenados con métodos de aprendizaje basados ​​en gradientes.

Para que esto funcione, todo el sistema debe ser diferenciable o lo que se llama “soft”. Si hay algunas discontinuidades, entonces podemos usar sub derivadas en su lugar. Es por eso que el cálculo es muy importante si desea comprender los principios de funcionamiento subyacentes de las redes neuronales.

El proceso de aprendizaje actualiza los pesos (parámetros) en la dirección opuesta del campo de gradiente de la siguiente manera:

[matemáticas] \ varphi \ leftarrow \ varphi- \ lambda \ frac {\ partial L} {\ partial \ varphi} [/ math]

Entonces solo necesitamos evaluar:

[matemática] \ frac {\ parcial L} {\ parcial \ varphi} [/ matemática]

Aquí es donde las cosas se ponen un poco complicadas, un NN, especialmente un NN profundo (DNN) tiene muchas capas apiladas que no están directamente vinculadas a la función de pérdida [matemática] L [/ matemática] entonces, ¿cómo evaluamos las derivadas para estructuras tan complejas? ?

Saltemos directamente a las matemáticas.


Suponiendo un grupo básico de funciones anidadas [matemáticas] f_1, f_2, …, f_ {n} [/ matemáticas]

Tal que

[matemáticas] y = f_ {n} (w_ {n}, f_ {n-1} (w_ {n-1}, … f_2 (w_2, f_1 (w_1, x)) …)) [/ matemáticas]

Esto es en realidad un avance N-N en capas porque [matemática] x [/ matemática] es la entrada que se transforma por [matemática] f_1 [/ matemática] luego [matemática] f_2 [/ matemática] y hasta la última transformación [matemáticas] f_ {n} [/ matemáticas]. Cada operación de transformación tiene parámetros denotados por [math] w_ {i} [/ math] para la capa [math] i ^ {th} [/ math] de manera que:

[matemáticas] \ varphi = [w_1, w_2, …, w_ {n}] [/ matemáticas]

Cada [matemática] w [/ matemática] es en realidad una matriz de dimensionalidad igual a [matemática] m × (k + 1) [/ matemática], donde [matemática] m [/ matemática] es el número de nodos y [matemática] k [/ math] = dimensionalidad de entrada y un 1 es un término de sesgo. [math] \ varphi [/ math] es solo un tensor 4D de los parámetros de capa, incluso puede pretender que [math] \ varphi [/ math] es un vector que no afectará su comprensión de lo que estoy tratando de mencionar. De hecho, un tensor es solo un vector visualizado como una construcción matemática de alta dimensión, lo mismo se aplica a una matriz y un vector en sí mismo es solo una lista de variables o números.

Por lo tanto, debemos evaluar las derivadas del peso de cada capa con respecto a la función de pérdida para poder minimizar la pérdida. Antes de comenzar, supongamos que cada función [math] f () [/ math] tiene una transformación lineal intermedia [math] g () [/ math] que envía su salida a través de una operación de activación por elementos tales como:

[matemáticas] f_ {i} (w_ {i}, f_ {i-1}) = \ Phi_ {i} (g_ {i} (w_ {i}, f_ {i-1})) [/ matemáticas]

Donde [math] \ Phi_ {i} [/ math] = función de activación en i, [math] f_ {i-1} [/ math] es la salida de la capa de abajo, entonces [math] f_0 [/ math] es la entrada capa que puede ser una matriz de píxeles para el reconocimiento de imágenes o un espectrograma para el reconocimiento de voz.

Dicho esto, podemos continuar con la expansión de la regla de la cadena de:

[matemáticas] \ frac {\ partial L} {\ partial w_ {i}} = \ frac {\ partial L} {\ partial f_ {i}} \ frac {\ partial f_ {i}} {\ partial w_ {i }}[/matemáticas]

Podemos denotar el error de espalda como:

[matemáticas] \ delta_ {i} = \ frac {\ partial L} {\ partial f_ {i}} [/ math]

Porque solo podemos evaluarlo desde una capa posterior. ¿Ves a lo que estamos llegando? Esto simplifica nuestra expresión a:

[matemáticas] \ frac {\ partial L} {\ partial w_ {i}} = \ delta_ {i} \ frac {\ partial f_ {i}} {\ partial w_ {i}} [/ math]

Entonces podemos centrarnos en:

[matemáticas] \ frac {\ partial f_ {i}} {\ partial w_ {i}} = \ frac {\ partial f_ {i}} {\ partial g_ {i}} \ frac {\ partial g_ {i}} {\ parcial w_ {i}} [/ matemáticas]

Como en cada capa solo estamos haciendo una multiplicación matricial:

[matemáticas] g_ {i} (w_ {i}, f_ {i-1}) = w_ {i} f_ {i-1} [/ matemáticas]

Por lo tanto, podemos mostrar fácilmente que:

[matemática] \ frac {\ parcial g_ {i}} {\ parcial w_ {i}} = f_ {i-1} [/ matemática]

Que es solo la salida de la capa de abajo. Y la derivada de la función de activación viene dada por:

[matemáticas] \ frac {\ partial f_ {i}} {\ partial g_ {i}} = \ frac {\ partial \ Phi_ {i}} {\ partial g_ {i}} [/ math]

Es por eso que necesitamos cosas diferenciables para conectarse a la red.

Entonces

[matemáticas] \ frac {\ partial f_ {i}} {\ partial w_ {i}} = \ frac {\ partial \ Phi_ {i}} {\ partial g_ {i}} f_ {i-1} [/ math ]

Lo que da nuestra forma ahora simplificada como:

[matemáticas] \ frac {\ partial L} {\ partial w_ {i}} = \ delta_ {i} \ frac {\ partial \ Phi_ {i}} {\ partial g_ {i}} f_ {i-1} [ /matemáticas]

Todavía no hemos terminado, aún necesitamos evaluar [math] \ delta_ {i} [/ math] desde la capa posterior i + 1. Es natural comenzar desde la capa [math] i = n [/ math] ya que no hay una capa n + 1 para extraer [math] \ delta [/ math] y podemos evaluar fácilmente cada derivada en la última capa porque Está directamente relacionado con la función de pérdida. Luego podemos movernos iterativamente hasta la primera capa i = 1, un proceso llamado backpropagation of errors o backprop Algorit en resumen.

Entonces, a través de estas matemáticas simples, lo que está a punto de presenciar está en el corazón de los DNN de última generación aplicados en el reconocimiento de imágenes, detección de objetos, comprensión del lenguaje natural (NLU) y sistemas de reconocimiento de voz.

Recuerde que el error de retroceso viene dado por:

[matemáticas] \ frac {\ partial L} {\ partial f_ {i}} = \ frac {\ partial L} {\ partial f_ {i + 1}} \ frac {\ partial f_ {i + 1}} {\ parcial f_ {i}} [/ math]

Podemos denotar aún más

[matemáticas] \ delta_ {i + 1} = \ frac {\ partial L} {\ partial f_ {i + 1}} [/ math]

Ahora puede ver que solo en la última capa podemos evaluar fácilmente [math] \ delta [/ math] directamente:

[matemáticas] \ delta_ {n} = \ frac {\ partial L} {\ partial f_ {n}} [/ math]

La expansión adicional de la regla de la cadena da:

[matemáticas] \ frac {\ partial f_ {i + 1}} {\ partial f_ {i}} = \ frac {\ partial f_ {i + 1}} {\ partial g_ {i + 1}} \ frac {\ parcial g_ {i + 1}} {\ parcial f_ {i}} [/ math]

Y sabemos que:

[matemáticas] g_ {i + 1} (w_ {i + 1}, f_ {i}) = w_ {i + 1} f_ {i} [/ matemáticas]

Entonces

[matemática] \ frac {\ parcial g_ {i + 1}} {\ parcial f_ {i}} = w_ {i + 1} [/ matemática]

Y

[matemáticas] \ frac {\ partial f_ {i + 1}} {\ partial g_ {i + 1}} = \ frac {\ partial \ Phi_ {i + 1}} {\ partial g_ {i + 1}} [ /matemáticas]

Entonces podemos pasar los errores de regreso usando la siguiente expresión:

[matemáticas] \ delta_ {i} = \ delta_ {i + 1} \ frac {\ partial \ Phi_ {i + 1}} {\ partial g_ {i + 1}} w_ {i + 1} [/ math]


El bloque de matemáticas anterior está escrito en forma de vector / matriz, por lo que si desea implementarlo, tenga esto en cuenta. Por lo tanto, las redes neuronales artificiales (ANN) aprenden mediante un enfoque de descenso de gradiente mediante el cual los gradientes se evalúan eficientemente utilizando el algoritmo de backprop.

Espero que esto ayude.

No soy titular de un doctorado en Machine Learning ni investigador académico en Neural Networks, pero he estado leyendo e intentando aprender lo más posible sobre Neural Networks y Machine Learning.

  1. Las redes neuronales están diseñadas para imitar el cerebro humano, el sistema neuronal con la esperanza de lograr un sistema / red que pueda actuar como el cerebro humano y aprender cosas nuevas.
  2. Al igual que los humanos tienen diferentes técnicas de aprendizaje, diferentes técnicas de recuerdo (algunas personas recuerdan por gráficos, algunas personas recuerdan por olor, sonido, algunas personas recuerdan si alguien las piensa, etc.) Las redes neuronales como en diferentes redes con diferentes atributos pueden / tienen diferentes técnicas de aprendizaje
  3. Casi todas las técnicas de aprendizaje (creo) se pueden aplicar a diferentes redes neuronales, pero su éxito en la capacitación depende de los datos, el modelo de la red neuronal.

Si estamos buscando un ejemplo, vale la pena buscar las redes neuronales de retroalimentación y el algoritmo de propagación hacia atrás. También hay un tema de aprendizaje profundo que es casi un área enorme que necesita tiempo para profundizar, aunque recomiendo comenzar con algo más simple.

Quizás quieras leer mi otra respuesta a una pregunta similar

La respuesta de Neelabh Pant a ¿Cuál es la diferencia entre el aprendizaje profundo y el aprendizaje automático? ¿Puedo aprender cualquiera de ellos en casa?