Cuesta abajo: Gradient Descent y los dos pasos que todo el mundo se salta
Calcula el techo exacto de una tasa de aprendizaje y observa cómo una búsqueda de fuerza bruta en 3600 direcciones redescubre el gradiente.
En esta página
El capítulo anterior terminó con un valle.
No uno metafórico: una curva real, la pérdida representada frente a un único parámetro, bajando y volviendo a subir. Y la pérdida bajo ella no se escogió porque quedara limpia: se derivó a partir de una afirmación sobre el ruido en las mediciones, y el error cuadrático apareció al final como una consecuencia, no como una convención.
Así que tenemos un paisaje con un fondo, y una razón para creer que el fondo es el lugar correcto. Lo que no tenemos es una forma de llegar hasta él.
Este capítulo construye una, y es el algoritmo que entrena todos los modelos del resto de este curso: todos, sin excepción, hasta incluir los que tienen cientos de miles de millones de parámetros. Cabe en unas veinte líneas. Las dos partes difíciles no están en esas veinte líneas, y son las dos cosas que casi todas las explicaciones se saltan:
- Por qué el signo menos. La actualización resta el gradiente. Todos los tutoriales lo escriben; muy pocos dicen por qué el gradiente es la dirección que va hacia arriba, que es el único hecho que convierte el signo menos en algo distinto de un acto de fe.
- Qué tamaño de paso. «Demasiado grande diverge, demasiado pequeño es lento» es verdad e inútil. Hay un número exacto, se puede calcular a partir de la pérdida, y este capítulo lo calcula dos veces: una para una parábola de juguete y otra para los datos reales.
El planteamiento, y por qué no puedes limitarte a buscar
Enlace a la sección: El planteamiento, y por qué no puedes limitarte a buscarReplanteado para que este capítulo se sostenga por sí solo: las ocho piezas de la cinta transportadora del Capítulo 1, pero con otra pregunta. No aceptar o rechazar —eso volverá más adelante—, sino predecir el peso de una pieza a partir de su anchura.
import numpy as np
WIDTH = np.array([18.0, 19.5, 20.2, 21.0, 24.0, 25.5, 23.0, 26.0])
WEIGHT = np.array([47.0, 52.0, 49.0, 55.0, 61.0, 66.0, 70.0, 58.0])
x = WIDTH - WIDTH.mean() # 22.15 mm
y = WEIGHT - WEIGHT.mean() # 57.25 gLas mediciones están centradas, exactamente igual que en el Capítulo 1 y por una razón que volverá con intereses antes de que termine este capítulo. El modelo es una recta, , y la pérdida es el error cuadrático medio que derivó el capítulo anterior:
Dos parámetros. ¿Por qué no probar simplemente muchos valores? Hagámoslo de verdad: una cuadrícula de a y de a , con pasos de :
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.592450Medio millón de evaluaciones para fijar dos números con dos decimales; y ese segundo es tiempo de reloj en una máquina, así que al repetirlo puede caer entre tres y seis. El recuento de evaluaciones y el mínimo son la parte que se reproduce. Gradient descent, al final de este capítulo, obtiene cuatro decimales en ocho pasos y la respuesta float64 completa en treinta y seis.
Pero la velocidad no es el argumento, y este es el punto que decide todo el curso. La búsqueda en cuadrícula cuesta evaluaciones para parámetros con valores cada uno. Con mil valores por eje:
| modelo | parámetros | evaluaciones en cuadrícula |
|---|---|---|
| esta recta | 2 | |
| la red XOR del Capítulo 5 | 9 | |
| una red multicapa pequeña | 20.000 |
La tercera fila no es un número grande, es un número sin sentido: hay aproximadamente átomos en el universo observable. La búsqueda no se vuelve más lenta cuando los modelos crecen; deja de existir. Todo lo que sigue existe por esa tabla.
Una derivada es una medición que puedes tomar
Enlace a la sección: Una derivada es una medición que puedes tomarFija por un momento para que haya un parámetro y una curva, que es la imagen con la que te dejó el capítulo anterior. Toma un punto sobre ella, , y pregunta: si empujo una pequeña cantidad , ¿cuánto se mueve la pérdida, por unidad de empuje?
Esa razón es una subida sobre avance: la pendiente de la recta que pasa por dos puntos de la curva. A medida que se encoge, los dos puntos se deslizan hasta juntarse y la recta se convierte en la tangente. Su pendiente es la derivada : la tasa a la que cambia la pérdida por unidad de cambio en . No es una aproximación de nada, ni una cantidad infinitamente pequeña. Es un límite de razones ordinarias.
Merece la pena ejecutarlo, porque los números dicen algo que la definición no dice:
def loss1(a):
return np.mean((a * x - y) ** 2)
for h in [1.0, 1e-2, 1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-14]:
q = (loss1(1.0 + h) - loss1(1.0)) / h
print(f"h = {h:<8.0e} slope estimate = {q:.10f} error = {abs(q + 16.385):.3e}")h = 1e+00 slope estimate = -8.9400000000 error = 7.445e+00
h = 1e-02 slope estimate = -16.3105500000 error = 7.445e-02
h = 1e-04 slope estimate = -16.3842555001 error = 7.445e-04
h = 1e-06 slope estimate = -16.3849925556 error = 7.444e-06
h = 1e-08 slope estimate = -16.3850003787 error = 3.787e-07
h = 1e-10 slope estimate = -16.3850444324 error = 4.443e-05
h = 1e-12 slope estimate = -16.3851154866 error = 1.155e-04
h = 1e-14 slope estimate = -17.0530256582 error = 6.680e-01Aquí pasan dos cosas, y ambas sostienen el edificio.
El error no es vagamente proporcional a : es exactamente . Divide entre cien y el error se divide entre cien, con cuatro cifras significativas cada vez. Esa constante no es decoración: es la mitad de la segunda derivada de la pérdida, y es la primera aparición de una idea que llegará dentro de dos secciones: que una curva cerca de un punto se parece a una recta más una corrección proporcional a .
Y entonces el patrón se rompe. Por debajo de la estimación empeora, y en ya se equivoca en el segundo dígito. No ha ocurrido nada matemático; ha ocurrido la caja de coma flotante del capítulo anterior. y coinciden en sus diez primeros dígitos, restarlos destruye esos dígitos, y dividir los restos por un número diminuto amplifica lo que queda. Hay un mejor : aquí alrededor de , aproximadamente la raíz cuadrada del épsilon de la máquina. Ir a un valor más pequeño no es tener más cuidado, es tener menos. Recuérdalo; una función al final de este capítulo depende de ello.
La pendiente exacta, por cálculo y no por medición, es . Así que podemos dejar de medir y empezar a derivar.
Composición, y la regla de la cadena
Enlace a la sección: Composición, y la regla de la cadenaEsta es la idea sobre la que se construye el resto del curso, expresada una vez y de forma clara.
Componer dos funciones es alimentar una con la otra: . Nada más.
Una red profunda no es como una composición. Es una composición. Una capa es una función; apilar capas es componerlas; la «profundidad» es el número de funciones en la cadena. Cuando el Capítulo 5 construya una red, estará construyendo y nada más. Lo que significa que la regla de cálculo más importante para nuestros fines es la que diferencia una composición:
Las tasas se multiplican. Si cambia tres veces más rápido que , y cambia el doble de rápido que , entonces cambia seis veces más rápido que . Ese es todo el contenido, y es la razón por la que una señal que vuelve atravesando diez capas se multiplica por diez números; por eso el Capítulo 6 dedica una sección a lo que ocurre cuando todos esos números son ligeramente menores que uno.
Úsala sobre nuestra pérdida. Escribe el residual , de modo que . Cada depende de a través de la función interna , cuya derivada es . Regla de la cadena, término a término:
Esos símbolos curvos marcan una derivada parcial: diferencias respecto a una variable y tratas todas las demás como constantes. No pasa nada nuevo: es el mismo límite de antes, tomado a lo largo de un eje. Junta las parciales en un vector y tienes el gradiente:
En el punto , ese vector es . Dos números. La pregunta es qué significan, y este es el primer paso que todo el mundo se salta.
Por qué el gradiente apunta cuesta arriba
Enlace a la sección: Por qué el gradiente apunta cuesta arribaEl gradiente es un vector de pendientes a lo largo de los ejes. Eso es todo lo que hemos demostrado. No es obvio —no debería serlo— que ensamblarlas en un vector produzca algo que apunte a algún sitio en particular.
Así que definamos lo que realmente queremos. Elige un vector unitario , una dirección. La derivada direccional es la tasa a la que cambia la pérdida cuando caminas en esa dirección:
La regla de la cadena convierte esto en algo calculable. Caminar a lo largo de cambia a una tasa y a una tasa , y las contribuciones se suman:
La tasa de cambio en cualquier dirección es el producto escalar del gradiente con esa dirección. Y ahora el remate, que es una línea de geometría. Escribiendo el producto escalar con el ángulo entre los vectores,
puesto que tiene longitud 1. Lo único que controlas es , que es máximo en y mínimo a media vuelta, grados. Así que:
- El ascenso más empinado es a lo largo de , y la pendiente ahí es exactamente .
- El descenso más empinado es a lo largo de , y la pendiente ahí es .
- Perpendicular al gradiente, la pérdida no cambia en absoluto. Por eso las líneas de un mapa de contorno cruzan el gradiente en ángulo recto.
Ese es el signo menos. No es una convención, ni un cambio de signo que alguien eligió: la dirección de descenso más rápido es el gradiente negativo porque se minimiza a media vuelta, y por ninguna otra razón.
Como es una afirmación sobre todas las direcciones, pruébala contra todas las direcciones. Muestrea 3.600, una por cada décima de grado, y mide cada una con un pequeño empujón:
theta = np.array([1.0, 4.0])
g = grad(theta)
print("gradient ", g)
print("its length ", np.linalg.norm(g))
print("its angle ", np.degrees(np.arctan2(g[1], g[0])) % 360, "degrees")
best = max(
((loss(theta + 1e-6 * u) - loss(theta - 1e-6 * u)) / 2e-6, np.degrees(ang))
for ang, u in (
(a, np.array([np.cos(a), np.sin(a)])) for a in np.arange(3600) * 2 * np.pi / 3600
)
)
print("steepest slope", best[0], "at", best[1], "degrees")gradient [-16.385 8. ]
its length 18.23371122399386
its angle 153.97598928042032 degrees
steepest slope 18.233709624837502 at 154.0 degreesUna búsqueda que no sabe nada de gradientes, sobre 3.600 direcciones, encuentra su subida más empinada en 154,0 grados: la propia dirección del gradiente, dentro de la resolución de 0,1 grados de la búsqueda. Y la pendiente que encuentra ahí, 18,2337, es la longitud del gradiente con seis cifras. El teorema no es una historia sobre lo que significan los gradientes; es un hecho medible, y esa es la medición.
Por qué un pequeño paso cuesta abajo ayuda de verdad
Enlace a la sección: Por qué un pequeño paso cuesta abajo ayuda de verdadAhora el segundo paso que se suele saltar. Sabemos qué dirección es hacia abajo. De ahí no se deduce que caminar en esa dirección reduzca la pérdida, porque «hacia abajo» es una afirmación sobre un empujón infinitesimal y un paso no es infinitesimal.
El puente es la linealización. Cerca de un punto, una función suave es su tangente más una corrección:
Esa es la expansión de Taylor de primer orden. El descartado es la curvatura: el mismo término que hacía que la estimación de la tabla de pendientes fallara exactamente por . Introduce el paso que pretendemos dar, :
La pérdida baja en . Cada parte de eso es no negativa, así que la promesa es real: para un lo bastante pequeño, porque el término ignorado crece como y al final se lo come. Esa es toda la teoría. Aquí está la promesa cumpliéndose, y después rompiéndose:
eta = 0.2 promised 66.49364500 delivered -16.01619240 ratio -0.240868
eta = 0.1 promised 33.24682250 delivered 12.61936315 ratio 0.379566
eta = 0.01 promised 3.32468225 delivered 3.11840766 ratio 0.937957
eta = 0.001 promised 0.33246822 delivered 0.33040548 ratio 0.993796
eta = 0.0001 promised 0.03324682 delivered 0.03322620 ratio 0.999380
eta = 1e-05 promised 0.00332468 delivered 0.00332448 ratio 0.999938Léelo desde abajo. A medida que se encoge, la bajada entregada converge a la prometida —ratio 0,99938, luego 0,99994—, que es el teorema de Taylor acertando. Léelo desde arriba y en la «bajada» entregada es menos dieciséis. El paso fue cuesta abajo y la pérdida subió.
Así que la regla de actualización es
y viene con una condición que nadie enuncia: que sea lo bastante pequeño. Lo bastante pequeño comparado con qué, exactamente, es la siguiente sección.
La tasa de aprendizaje tiene un techo, y se puede calcular
Enlace a la sección: La tasa de aprendizaje tiene un techo, y se puede calcularEmpieza con el valle más simple que existe, , donde . Un paso de gradient descent es
La posición se multiplica por en cada paso. Eso es una sucesión geométrica, y las sucesiones geométricas tienen exactamente una regla: se encogen cuando el multiplicador es menor que 1 en valor absoluto y crecen en caso contrario. Así que , que es .
La frontera está exactamente en . No «alrededor de 1», ni «1 suele ser demasiado grande». En el multiplicador es y el punto rebota entre y para siempre, sin acercarse ni escapar. Por debajo, converge; por encima, diverge. El intervalo vuelve a dividirse en , donde el multiplicador cambia de signo: por debajo de eso la aproximación es monótona, por encima el punto se pasa y alterna lados, y exactamente en el multiplicador es 0 y un único paso aterriza en el mínimo.
Cuatro regímenes, a partir de cuatro líneas de álgebra. Ve y cruza tú mismo las fronteras:
Y ahora el caso interesante:
Ahora la regla general, que sale del mismo argumento. El multiplicador era en realidad , y cerca de un mínimo una pérdida con varios parámetros tiene uno de esos números por dirección: los autovalores de la matriz de segundas derivadas. Todas las direcciones tienen que ser estables a la vez, así que el techo lo fija la mayor:
Para , , techo 1, que es lo que acabamos de derivar. Para nuestra cinta, la matriz de segundas derivadas es con como matriz de entradas de dos columnas, y sus autovalores son 2 y 14,89, así que el techo es . Es una predicción con cinco cifras significativas. Pruébala:
lr=0.1343 -> L = 24.5924
lr=0.13431 -> L = 24.5924
lr=0.13432 -> L = 4707.8 BLEW UP
lr=0.13433 -> L = 4.00452e+16 BLEW UP
lr=0.1344 -> L = 1.18229e+107 BLEW UPCinco decimales de acuerdo entre una línea de álgebra lineal y cien mil iteraciones de un bucle for.
Y aquí es donde vuelve el Capítulo 1. Todo lo anterior usó las mediciones centradas. Ejecuta el mismo código sobre milímetros y gramos sin procesar y los autovalores son 0,0298 y 998,1 en lugar de 2 y 14,89. El techo se desploma de 0,134 a 0,002004: con la misma exactitud, convergiendo en lr=0.002003 y explotando en lr=0.002004.
Peor que el techo es la razón entre los autovalores. El número de condición mide lo lejos que está el valle de ser redondo: una zanja larga y estrecha obliga a usar una tasa lo bastante pequeña para las paredes empinadas, y entonces el suelo de la zanja se recorre con ese mismo paso de tortuga. El nuestro pasa de 7,44 centrado a 33.452 sin centrar. Con la mejor tasa que puede usar cada versión:
| variables | número de condición | mejor tasa | pasos hasta estar a un 1% del óptimo |
|---|---|---|---|
| centradas | 7,44 | 0,1184 | 10 |
| milímetros y gramos sin centrar | 33.452 | 0,0020037 | 79.513 |
Mismos datos, mismo código, misma respuesta al final; y ocho mil veces más trabajo, porque nadie restó una media. En el Capítulo 1, la misma omisión le costó al perceptrón un factor de seis mil en épocas, y el diagnóstico allí era geométrico: los datos flotaban lejos del origen. Es la misma geometría aquí con disfraz de optimización, y por eso la normalización de entradas no es un consejo de higiene, sino aritmética.1
Veinte líneas
Enlace a la sección: Veinte líneasNada de lo anterior necesitaba una librería. Aquí está el optimizador entero.
def loss(theta):
a, b = theta
return np.mean((a * x + b - y) ** 2)
def grad(theta):
a, b = theta
residual = a * x + b - y
return np.array([np.mean(2 * residual * x), np.mean(2 * residual)])
def descend(theta, lr, steps):
theta = np.array(theta, dtype=float)
for _ in range(steps):
theta = theta - lr * grad(theta)
return theta
theta = descend([0.0, 0.0], lr=0.05, steps=60)
print(theta, loss(theta))[ 2.10040296e+00 -2.76445533e-15] 24.592448791134984La respuesta de mínimos cuadrados en forma cerrada para estos ocho puntos es , , con una pérdida de . El bucle la encontró con ocho cifras significativas sin saber que existe una forma cerrada; y eso importa, porque desde el Capítulo 5 en adelante no habrá una.
La trayectoria, porque verla es el punto:
0 a=0.000000 b=0.000000 L=57.437500
1 a=1.563750 b=0.000000 L=26.736582
2 a=1.963288 b=-0.000000 L=24.732418
5 a=2.098116 b=-0.000000 L=24.592488
10 a=2.100400 b=-0.000000 L=24.592449
60 a=2.100403 b=-0.000000 L=24.592449La mayor parte de la distancia se recorre en los dos primeros pasos, porque el gradiente es mayor cuando estás más lejos del fondo y se encoge al acercarte. Gradient descent se ralentiza automáticamente cerca de un mínimo. Eso es una ventaja y también, en el Capítulo 6, un problema.
Dónde más la pendiente es cero
Enlace a la sección: Dónde más la pendiente es ceroEl argumento hasta ahora tiene un agujero. El paso se detiene cuando , y hemos estado llamando a eso «el mínimo». Un punto con gradiente cero es un punto crítico, y ser un mínimo es solo una de las formas de serlo:
- un mínimo local: subida en todas las direcciones, aunque quizá no sea el punto de ese tipo más bajo en ninguna parte;
- un máximo local: bajada en todas las direcciones;
- un punto de silla: subida en algunas direcciones y bajada en otras. La superficie tiene , que es cero en el origen, donde la función es un mínimo a lo largo del eje y un máximo a lo largo del eje al mismo tiempo.
Gradient descent no puede distinguirlos, porque solo mira el gradiente, y el gradiente es cero en los tres.
Nuestra recta tiene un único punto crítico y es la respuesta: una pérdida de error cuadrático sobre un modelo lineal es convexa, un único cuenco, y el descenso sobre ella no puede fallar al encontrar el mínimo global. Esa propiedad no sobrevive al contacto con este curso. La pérdida de una red neuronal no es convexa, y desde el Capítulo 5 en adelante «el mínimo» no es una cosa que exista: hay muchos, de distintas profundidades, y el que obtengas depende de dónde empezaste. Eso es una frase y se queda en una frase, porque la teoría es grande y la consecuencia práctica es pequeña.
Puedes ver toda la consecuencia en una sola curva. Toma , que tiene dos valles de distintas profundidades:
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimumCaer en el valle somero es un 56,7% peor en pérdida, y el algoritmo no tiene forma de saberlo, porque desde dentro de un valle todas las direcciones son cuesta arriba. No hay reparación para esto en gradient descent y no va a llegar ninguna. Lo que hay, en la práctica, es el hallazgo de que importa mucho menos de lo que sugiere esta imagen: en las altísimas dimensiones de una red real, la mayoría de los puntos críticos resultan ser sillas y no trampas,2 y el Capítulo 5 mide con qué frecuencia una red pequeña se queda realmente atascada.
Pasos más baratos: estocástico, minibatch, momentum
Enlace a la sección: Pasos más baratos: estocástico, minibatch, momentumHay algo en grad arriba que debería molestarte: suma todo el dataset para cada paso. Ocho piezas no son nada. Un millón son un millón de cálculos de gradiente para mover los parámetros una vez.
La vía de escape es que el gradiente es una media, y una media puede estimarse a partir de una muestra. Calcúlalo sobre un puñado aleatorio —un minibatch— y da el paso con eso. La estimación tiene ruido; también es insesgada, y cientos de pasos ruidosos y baratos vencen a uno exacto y caro. Sobre cien mil piezas sintéticas, contando gradientes por ejemplo en vez de pasos:
| método | pasos hasta estar a un 0,1% del óptimo | gradientes por ejemplo |
|---|---|---|
| batch completo | 7 | 700.000 |
| minibatch de 32 | 100 | 3.200 |
| un ejemplo cada vez | 17.580 | 17.580 |
Doscientas diecinueve veces menos aritmética para llegar al mismo sitio. Y el extremo —un ejemplo cada vez, la aproximación estocástica original de Robbins y Monro3— no es el ganador: es cinco veces peor que batches de 32, porque 32 ejemplos no cuestan casi nada más que uno en hardware que multiplica matrices, mientras que el ruido cae con la raíz cuadrada del tamaño del batch. Ese intercambio es la razón por la que todo script de entrenamiento que leas tendrá un batch_size dentro.
Momentum es el otro arreglo barato, y apunta directamente a la zanja. En un valle mal condicionado, los pasos zigzaguean a través de la dirección estrecha mientras avanzan a rastras por la larga. Momentum mantiene una media móvil de gradientes pasados, de modo que los componentes oscilantes se cancelan y el componente consistente se acumula:4
Dos líneas extra. Sobre la cinta sin centrar —número de condición 33.452, el peor caso que tenemos—, con la mejor tasa que puede usar el descenso simple:
momentum beta=0.0 -> 79,513 steps to 1%
momentum beta=0.9 -> 1,609 steps to 1%
momentum beta=0.99 -> 461 steps to 1%Un factor de 172 por dos líneas de código. El Capítulo 6 convierte esto en Adam; el mecanismo ya está aquí.
La comprobación que necesitarás en el Capítulo 5
Enlace a la sección: La comprobación que necesitarás en el Capítulo 5Todos los gradientes de este capítulo se derivaron a mano y, por tanto, podían estar mal. La solución es la tabla de pendientes del principio: medir la derivada numéricamente y comparar. Usa la diferencia central, , que cancela el término de error principal y es muchísimo más precisa para el mismo .
def numeric_grad(f, theta, h=1e-5):
theta = np.asarray(theta, dtype=float)
out = np.zeros_like(theta)
for i in range(theta.size):
bump = np.zeros_like(theta)
bump[i] = h
out[i] = (f(theta + bump) - f(theta - bump)) / (2 * h)
return out
def gradcheck(f, df, theta, h=1e-5):
analytic = np.asarray(df(theta), dtype=float)
numeric = numeric_grad(f, theta, h)
return np.max(np.abs(analytic - numeric) / np.maximum(1e-8, np.abs(analytic) + np.abs(numeric)))La forma relativa de la comparación importa: una diferencia absoluta de es un desastre en un gradiente de tamaño e irrelevante en uno de tamaño .
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744La primera línea es el gradiente derivado a mano de arriba. La segunda es la misma función con el factor 2 omitido en un componente —una errata de un solo carácter—, y la comprobación la detecta de inmediato. Todo lo que esté por debajo de aproximadamente es acuerdo; todo lo que esté por encima de es un bug. Guarda esta función: el Capítulo 5 la usa para depurar un motor de diferenciación automática, y es la única razón por la que un gradiente incorrecto puede encontrarse.
Hacia dónde va esto
Enlace a la sección: Hacia dónde va estoTodo este capítulo descansaba sobre una suposición que nunca se enunció: que puedes escribir .
Para una recta con dos parámetros, eso era una línea de álgebra. Deja de serlo casi de inmediato. Pídele a un sistema de álgebra simbólica la derivada de la pérdida de una red respecto a un único peso de la primera capa, para un único ejemplo, y cuenta la aritmética de la respuesta:
| red | operaciones en una derivada parcial |
|---|---|
| cuatro unidades ocultas, una capa | 40 |
| cuatro unidades ocultas, dos capas | 301 |
| cuatro unidades ocultas, tres capas | 1.717 |
La tercera fila es una red con 57 parámetros —una red tan pequeña que sería una nota al pie en el Capítulo 6—, y escribir su gradiente a mano implica unas 97.869 operaciones para un ejemplo de entrenamiento. No hay notación que rescate esto. Lo rescata la observación de que la regla de la cadena aplicada a una composición tiene una estructura enorme, que las mismas cantidades intermedias aparecen una y otra vez, y que calcularlas en el orden correcto obtiene todas las derivadas por más o menos el precio de una pasada hacia delante. Eso es el Capítulo 5.
Pero antes hay un problema más pequeño, y está esperando justo delante.
Ahora tenemos una máquina que rodará cuesta abajo sobre cualquier pérdida diferenciable. Apúntala a la pregunta original de la cinta —aceptar o rechazar, un objetivo que es 1 o 0—, pon una sigmoide en la salida para que prediga una probabilidad, y minimiza el error cuadrático. Funcionará. También apenas se moverá cuando más equivocada esté, y el gradiente explica por qué:
| salida | predicción | verdad | gradiente con error cuadrático | gradiente con entropía cruzada |
|---|---|---|---|---|
| 0.5000 | 1 | |||
| 0.1192 | 1 | |||
| 0.0025 | 1 | |||
| 1 |
Un modelo confiada y catastróficamente equivocado —prediciendo 0,0000454 cuando la respuesta es 1— produce un gradiente de error cuadrático de . No tiene ni idea de que está en problemas. La otra columna, de una pérdida que aún no hemos derivado, informa de 1,0: urgencia máxima, exactamente donde corresponde.
Lo que plantea la pregunta con la que abre el siguiente capítulo. El capítulo anterior dijo que una pérdida es una suposición sobre el ruido, y el error cuadrático asume ruido gaussiano. ¿Qué modelo de ruido tiene una respuesta de sí o no, y qué pérdida sale cuando aplicas la misma derivación sobre él?
Fuentes y método
Enlace a la sección: Fuentes y métodoEl método es más antiguo que todos estos: Cauchy lo describió en una nota a la Académie des Sciences en 1847, como una forma de resolver sistemas de ecuaciones caminando cuesta abajo sobre la suma de sus residuales al cuadrado. También merece la pena leer junto a este capítulo: An overview of gradient descent optimization algorithms, de Sebastian Ruder (arXiv:1609.04747), que cubre momentum hasta Adam en catorce páginas legibles; el capítulo 3 de Numerical Optimization, de Nocedal y Wright (2.ª ed., Springer, 2006), cuyo teorema 3.3 da la tasa de convergencia del descenso más empinado sobre una cuadrática en términos del número de condición —es la teoría que hay detrás de por qué el condicionamiento decide el recuento de pasos, aunque trata la búsqueda de línea en lugar del techo de con paso fijo medido arriba—, o §5.8 y §7.1 de Mathematics for Machine Learning, de Deisenroth, Faisal y Ong, para el mismo terreno con menos maquinaria; §6.1 de Understanding Deep Learning, de Prince, y §4.3 de Deep Learning, de Goodfellow, Bengio y Courville; Dive into Deep Learning §12.1–12.3, que tiene el análisis de minibatch con más mediciones de las que caben aquí; y el capítulo 4 de Hands-On Machine Learning, de Géron (3.ª ed.), el tratamiento más práctico de la tasa de aprendizaje como algo que ajustas en vez de derivar. Las notas de MIT 6.390 ponen gradient descent antes de la clasificación, como hace este curso y por la misma razón.
Referencias
Enlace a la sección: Referencias-
LeCun, Y., Bottou, L., Orr, G. B. y Müller, K.-R. Efficient BackProp, en Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. La sección 4.3 da la recomendación y la sección 5.1 el argumento usado en el recuadro de detalle de arriba: centrar y escalar las entradas cambia los autovalores de la matriz de segundas derivadas y, por tanto, el número de pasos, no solo la comodidad numérica. ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. y Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). El argumento de que en dimensiones altas los puntos críticos son abrumadoramente sillas y no mínimos locales, porque un mínimo exige que todas y cada una de miles de direcciones se curven hacia arriba a la vez. ↩
-
Robbins, H. y Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). El artículo que estableció que una estimación ruidosa de un gradiente basta, siempre que el tamaño de paso se reduzca de la forma correcta. ↩
-
Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), pp. 1–17 (1964). El método heavy-ball, que es la actualización con momentum de arriba, veintidós años antes de que backpropagation llegara a este campo. ↩