Standardowe zejście gradientu obliczałoby gradient dla całego zestawu danych treningowych.
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
Dla wstępnie zdefiniowanej liczby epok najpierw obliczamy wektor gradientu wagi_grad funkcji straty dla całego zestawu danych w stosunku do naszych parametrów wektora parametru.
Natomiast Stochastyczne zejście gradientu wykonuje aktualizację parametru dla każdego przykładu treningowego x (i) i etykiety 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
Mówi się, że SGD jest znacznie szybszy. Nie rozumiem jednak, jak może być znacznie szybciej, jeśli nadal mamy pętlę nad wszystkimi punktami danych. Czy obliczanie gradientu w GD jest znacznie wolniejsze niż obliczanie GD dla każdego punktu danych osobno?
Kod pochodzi stąd .
Odpowiedzi:
Krótka odpowiedź:
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
a gradient wynosi
dla gradientu przyzwoitego (GD) aktualizujemy parametr o
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.
Wyniki:
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.
sq_loss_gr_approx
źródło