Descenso de gradiente estándar calcularía el gradiente para todo el conjunto de datos de entrenamiento.
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
Para un número predefinido de épocas, primero calculamos el vector de gradiente weights_grad de la función de pérdida para todo el conjunto de datos con nuestros parámetros de vector de parámetros.
El Descenso de gradiente estocástico, por el contrario, realiza una actualización de parámetros para cada ejemplo de entrenamiento x (i) y etiqueta y (i).
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
Se dice que SGD es mucho más rápido. Sin embargo, no entiendo cómo puede ser mucho más rápido si todavía tenemos un bucle sobre todos los puntos de datos. ¿El cálculo del gradiente en GD es mucho más lento que el cálculo de GD para cada punto de datos por separado?
El código viene de aquí .
Respuestas:
Respuesta corta:
Respuesta larga:
Mi notación sigue el curso Coursera de aprendizaje automático de Andrew NG. Si no está familiarizado con él, puede revisar la serie de conferencias aquí .
Supongamos una regresión sobre la pérdida al cuadrado, la función de costo es
y el gradiente es
para gradiente decente (GD), actualizamos el parámetro por
Aquí es por qué estamos ahorrando tiempo:
Supongamos que tenemos mil millones de puntos de datos.
En GD, para actualizar los parámetros una vez, necesitamos tener el gradiente (exacto). Esto requiere resumir estos mil millones de puntos de datos para realizar 1 actualización.
En SGD, podemos pensar que trata de obtener un gradiente aproximado en lugar de un gradiente exacto . La aproximación proviene de un punto de datos (o varios puntos de datos llamados mini lotes). Por lo tanto, en SGD, podemos actualizar los parámetros muy rápidamente. Además, si "recorremos" todos los datos (llamados una época), en realidad tenemos mil millones de actualizaciones.
El truco es que, en SGD, no necesita tener mil millones de iteraciones / actualizaciones, pero mucho menos iteraciones / actualizaciones, digamos 1 millón, y tendrá un modelo "suficientemente bueno" para usar.
Estoy escribiendo un código para demostrar la idea. Primero resolvemos el sistema lineal por ecuación normal, luego lo resolvemos con SGD. Luego comparamos los resultados en términos de valores de parámetros y valores de función objetivo final. Para visualizarlo más tarde, tendremos 2 parámetros para ajustar.
Los resultados:
Aquí están los valores de la función de costo sobre las iteraciones, podemos ver que puede disminuir efectivamente la pérdida, lo que ilustra la idea: podemos usar un subconjunto de datos para aproximar el gradiente y obtener resultados "suficientemente buenos".
sq_loss_gr_approx
fuente