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( θ ) = 12 m∑i = 1metro( hθ( x( i )) - y( i ))2
y el gradiente es
reJ( θ )reθ= 1metro∑i = 1metro( hθ( x( i )) - y( i )) x( i )
para gradiente decente (GD), actualizamos el parámetro por
θn e w= θo l d- α 1metro∑i = 1metro( hθ( x( i )) - y( i )) x( i )
1 / mX( i ), y( i )
θn e w= θo l d- α ⋅ ( hθ( x( i )) - y( i )) x( i )
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".
1000sq_loss_gr_approx
3001000