Risposta breve:
- In molte impostazioni di big data (diciamo diversi milioni di punti dati), il calcolo del costo o del gradiente richiede molto tempo, perché dobbiamo sommare tutti i punti dati.
- Noi non è necessario aver gradiente esatto per ridurre il costo in una data iterazione. Qualche approssimazione del gradiente funzionerebbe bene.
- Gradiente stocastico decente (SGD) approssima il gradiente usando solo un punto dati. Pertanto, la valutazione del gradiente consente di risparmiare molto tempo rispetto alla somma di tutti i dati.
- Con un numero "ragionevole" di iterazioni (questo numero potrebbe essere un paio di migliaia e molto meno del numero di punti dati, che possono essere milioni), il gradiente stocastico decente può ottenere una buona soluzione ragionevole.
Risposta lunga:
La mia notazione segue il corso Coursera di machine learning di Andrew NG. Se non si ha familiarità con esso, è possibile rivedere la serie di lezioni qui .
Supponiamo che la regressione sulla perdita al quadrato sia la funzione di costo
J( θ ) = 12 mΣi = 1m( hθ( x( i ))- y(i ))2
e il gradiente è
dJ( θ )dθ= 1mΣi = 1m( hθ( x( i )) - y( i )) x( i )
per il gradiente decente (GD), aggiorniamo il parametro di
θn e w= θo l d- α 1mΣi = 1m( 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 )
Ecco perché stiamo risparmiando tempo:
Supponiamo di avere 1 miliardo di punti dati.
In GD, per aggiornare i parametri una volta, dobbiamo avere il gradiente (esatto). Ciò richiede di sommare questi 1 miliardo di punti dati per eseguire 1 aggiornamento.
In SGD, possiamo pensarlo come cercare di ottenere un gradiente approssimativo anziché esatto . L'approssimazione proviene da un punto dati (o da più punti dati chiamati mini batch). Pertanto, in SGD, possiamo aggiornare i parametri molto rapidamente. Inoltre, se "eseguiamo il ciclo" su tutti i dati (chiamati un'epoca), abbiamo effettivamente 1 miliardo di aggiornamenti.
Il trucco è che in SGD non è necessario avere 1 miliardo di iterazioni / aggiornamenti, ma molto meno iterazioni / aggiornamenti, diciamo 1 milione, e avrai un modello "abbastanza buono" da usare.
Sto scrivendo un codice per provare l'idea. Prima risolviamo il sistema lineare con equazione normale, quindi risolviamo con SGD. Quindi confrontiamo i risultati in termini di valori dei parametri e valori della funzione obiettivo finale. Per visualizzarlo in seguito, avremo 2 parametri per la messa a punto.
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)
}
I risultati:
as.vector(res1)
[1] 0.4368427 0.3991028
x
[1] 0.3580121 0.4782659
124.1343123.0355 che sono molto vicini.
Ecco i valori della funzione di costo rispetto alle iterazioni, possiamo vedere che può effettivamente ridurre la perdita, il che illustra l'idea: possiamo usare un sottoinsieme di dati per approssimare il gradiente e ottenere risultati "abbastanza buoni".
Ora controlliamo gli sforzi computazionali tra due approcci. Nell'esperimento, abbiamo1000i punti dati, utilizzando SD, valutano il gradiente una volta che è necessario sommarli. MA in SGD,sq_loss_gr_approx
funzione riassume solo 1 punto dati e, nel complesso, vediamo che l'algoritmo converge meno di300 iterazioni (nota, no 1000 iterazioni). Questo è il risparmio computazionale.