¿Cómo podría el descenso de gradiente estocástico ahorrar tiempo en comparación con el descenso de gradiente estándar?

15

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í .

Alina
fuente
1
En el segundo caso, tomaría un pequeño lote para aproximar todo el conjunto de datos. Esto generalmente funciona bastante bien. Entonces, la parte confusa es que parece que el número de épocas es el mismo en ambos casos, pero no necesitaría tantas épocas en el caso 2. Los "hiperparámetros" serían diferentes para esos dos métodos: GD nb_epochs! = SGD nb_epochs. Digamos para el propósito del argumento: GD nb_epochs = ejemplos de SGD * nb_epochs, de modo que el número total de bucles es el mismo, pero el cálculo del gradiente es mucho más rápido en SGD.
Nima Mousavi
Esta respuesta en CV es buena y relacionada.
Zhubarb

Respuestas:

23

Respuesta corta:

  • En muchos entornos de big data (digamos varios millones de puntos de datos), calcular el costo o el gradiente lleva mucho tiempo, porque necesitamos sumar todos los puntos de datos.
  • Nosotros no necesita tener gradiente exacta para reducir el costo en una iteración dada. Alguna aproximación de gradiente funcionaría bien.
  • El gradiente estocástico decente (SGD) aproxima el gradiente usando solo un punto de datos. Por lo tanto, evaluar el gradiente ahorra mucho tiempo en comparación con la suma de todos los datos.
  • Con un número "razonable" de iteraciones (este número podría ser un par de miles, y mucho menos que el número de puntos de datos, que pueden ser millones), el gradiente estocástico decente puede obtener una buena solución razonable.

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

J(θ)=12metroyo=1metro(hθ(X(yo))-y(yo))2

y el gradiente es

reJ(θ)reθ=1metroyo=1metro(hθ(X(yo))-y(yo))X(yo)

para gradiente decente (GD), actualizamos el parámetro por

θnortemiw=θolre-α1metroyo=1metro(hθ(X(yo))-y(yo))X(yo)

1/ /metroX(yo),y(yo)

θnortemiw=θolre-α(hθ(X(yo))-y(yo))X(yo)

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.

set.seed(0);n_data=1e3;n_feature=2;
A=matrix(runif(n_data*n_feature),ncol=n_feature)
b=runif(n_data)
res1=solve(t(A) %*% A, t(A) %*% b)

sq_loss<-function(A,b,x){
  e=A %*% x -b
  v=crossprod(e)
  return(v[1])
}

sq_loss_gr_approx<-function(A,b,x){
  # note, in GD, we need to sum over all data
  # here i is just one random index sample
  i=sample(1:n_data, 1)
  gr=2*(crossprod(A[i,],x)-b[i])*A[i,]
  return(gr)
}

x=runif(n_feature)
alpha=0.01
N_iter=300
loss=rep(0,N_iter)

for (i in 1:N_iter){
  x=x-alpha*sq_loss_gr_approx(A,b,x)
  loss[i]=sq_loss(A,b,x)
}

Los resultados:

as.vector(res1)
[1] 0.4368427 0.3991028
x
[1] 0.3580121 0.4782659

124.1343123.0355

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".

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

1000sq_loss_gr_approx3001000

Haitao Du
fuente
Pensé que el argumento sobre "velocidad" es más sobre cuántas operaciones / iteraciones se necesitan para converger a un óptimo local. (Y también que el descenso de gradiente estocástico tiende a converger a mejor óptimas.)
GeoMatt22
Según tengo entendido, en el código de Python que proporcioné la variable "datos" es la misma. El código decente del gradiente de mini lotes es diferente del SDG (y exactamente allí usa solo una pequeña fracción de los datos). Además, en la explicación que proporcionó, aunque eliminamos la suma en SDG, todavía calculamos la actualización para cada punto de datos. Todavía no entiendo cómo actualizar un parámetro al recorrer cada punto de datos es más rápido que simplemente tomar una suma sobre todos los puntos de datos a la vez.
Alina
@ GeoMatt22 En el enlace que proporcioné dice: "Por otro lado, esto en última instancia complica la convergencia al mínimo exacto, ya que SGD seguirá superando". Lo que significa que no converge a mejores óptimas. ¿O me equivoqué?
Alina
@Tonja No soy un experto, pero, por ejemplo, este artículo altamente influyente en el aprendizaje profundo ofrece el argumento de "entrenamiento más rápido y confiable" para el descenso de gradiente estocástico. Tenga en cuenta que no utiliza la versión "en bruto", sino que utiliza varias estimaciones de curvatura para establecer la tasa de aprendizaje (dependiente de coordenadas).
GeoMatt22
1
@Tonja, sí. cualquier aproximación "débil" del gradiente funcionaría. Puede marcar "aumento de gradiente", que es una idea similar. Por otro lado, estoy escribiendo un código para demostrar la idea. Lo publicaré cuando esté listo.
Haitao Du