Krótka odpowiedź:
- W wielu ustawieniach dużych danych (powiedzmy kilka milionów punktów danych) obliczenie kosztu lub gradientu zajmuje bardzo dużo czasu, ponieważ musimy zsumować wszystkie punkty danych.
- Mamy nie muszą mieć dokładnie gradientu w celu zmniejszenia kosztów w danej iteracji. Pewne przybliżenie gradientu działałoby OK.
- Stochastyczny gradient przyzwoity (SGD) aproksymuje gradient przy użyciu tylko jednego punktu danych. Tak więc ocena gradientu oszczędza dużo czasu w porównaniu do sumowania wszystkich danych.
- Przy „rozsądnej” liczbie iteracji (liczba ta może wynosić kilka tysięcy, a znacznie mniej niż liczba punktów danych, które mogą być milionami), przyzwoity gradient stochastyczny może uzyskać rozsądne dobre rozwiązanie.
Długa odpowiedź:
Moja notacja jest zgodna z kursem Coursera do uczenia maszynowego Andrew NG. Jeśli nie znasz go, możesz przejrzeć serię wykładów tutaj .
Załóżmy regresję straty kwadratowej, funkcją kosztu jest
jot( θ ) = 12 m∑i = 1m( hθ( x( i )) - y( i ))2)
a gradient wynosi
rejot( θ )reθ= 1m∑i = 1m( hθ( x( i )) - y( i )) x( i )
dla gradientu przyzwoitego (GD) aktualizujemy parametr o
θ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 )
Oto dlaczego oszczędzamy czas:
Załóżmy, że mamy 1 miliard punktów danych.
W GD, aby raz zaktualizować parametry, musimy mieć (dokładny) gradient. Wymaga to zsumowania tych 1 miliarda punktów danych, aby wykonać 1 aktualizację.
W SGD możemy myśleć o tym jako o próbie uzyskania przybliżonego gradientu zamiast gradientu dokładnego . Przybliżenie pochodzi z jednego punktu danych (lub kilku punktów danych zwanych mini wsadami). Dlatego w SGD możemy bardzo szybko zaktualizować parametry. Ponadto, jeśli „zapętlimy” wszystkie dane (zwane jedną epoką), faktycznie mamy 1 miliard aktualizacji.
Sztuka polega na tym, że w SGD nie musisz mieć 1 miliarda iteracji / aktualizacji, ale znacznie mniej iteracji / aktualizacji, powiedzmy 1 milion, i będziesz miał model „wystarczająco dobry” do użycia.
Piszę kod, aby zilustrować ten pomysł. Najpierw rozwiązujemy układ liniowy za pomocą równania normalnego, a następnie rozwiązujemy go za pomocą SGD. Następnie porównujemy wyniki pod względem wartości parametrów i wartości funkcji celu końcowego. W celu późniejszej wizualizacji będziemy musieli dostroić 2 parametry.
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)
}
Wyniki:
as.vector(res1)
[1] 0.4368427 0.3991028
x
[1] 0.3580121 0.4782659
124,1343123,0355
Oto wartości funkcji kosztu nad iteracjami, widzimy, że może skutecznie zmniejszyć stratę, co ilustruje pomysł: możemy użyć podzbioru danych do przybliżenia gradientu i uzyskania „wystarczająco dobrych” wyników.
1000sq_loss_gr_approx
3001000