ML Atlas

Kurs: sieci neuronowe od środka · Lekcja 6 z 12 · 14 min

Krok, paczka i optymalizator

W skrócie

Gradient mówi, w którą stronę iść. Jak daleko, na ilu przykładach go liczyć i jak łączyć kolejne kroki, decydują krok uczenia, paczka i optymalizator.

Rozgrzewka Dwa pytania z kursu ML, na których ta lekcja się opiera. Minuta, a lekcji nie blokuje.
Z kursu ML, lekcja 1.6: Spadek gradientu: nauka małymi krokami Strata rośnie z każdym krokiem. Jaka jest najbardziej prawdopodobna przyczyna?

Pokaż odpowiedź

Poprawna odpowiedź: Za duży współczynnik uczenia, przez który kroki przeskakują minimum

Przy zbyt długim kroku parametry za każdym razem przeskakują dolinę do wyższego punktu i błąd rośnie.

Z kursu ML, lekcja 1.6: Spadek gradientu: nauka małymi krokami Dlaczego w sieciach neuronowych używa się spadku gradientu zamiast dokładnego wzoru?

Pokaż odpowiedź

Poprawna odpowiedź: Bo wzoru na najlepsze parametry zwykle nie ma, a gradient da się policzyć

Spadek gradientu potrzebuje tylko nachylenia straty w bieżącym punkcie, a to jest dostępne nawet przy miliardach parametrów.

Propagacja wsteczna z lekcji 5 daje gradient: dla każdej wagi kierunek, w którym strata rośnie. Zostają trzy decyzje. Krok uczenia η mówi, jak daleko pójść w przeciwną stronę. Paczka mówi, na ilu przykładach liczyć gradient przed jednym krokiem. Optymalizator mówi, jak z gradientów zrobić krok: wprost, z rozpędem albo z osobną skalą dla każdej wagi. Epoka to jedno przejście przez wszystkie przykłady treningowe.

Przewidź, potem sprawdź Ta sama mała sieć uczy się 5 epok na tych samych 499 cyfrach. Raz paczka ma 1 przykład, raz cały zbiór naraz. Obie widzą każdą cyfrę 5 razy. Która kończy z niższą stratą treningową?
Jak bardzo jesteś pewny(-a)?

Eksperyment

Ten interaktywny eksperyment działa w przeglądarce z włączonym JavaScriptem. Tekst wokół opisuje, co w nim widać. W eksperymencie: Na tej samej sieci do cyfr (10 epok) Adam przekracza 90% przy współczynnikach 0,001, 0,01 i 0,1, zwykły SGD tylko przy 0,1 i 0,5, a SGD z momentem przy 0,01 i 0,1; najlepsze wyniki są podobne: 96,1%, 98,1% i 96,4%.

Pokaż odpowiedź

Poprawna odpowiedź: Paczka po 1 przykładzie

Paczka po 1 przykładzie robi 2495 kroków i kończy ze stratą 0,10. Cały zbiór robi 5 kroków i kończy ze stratą 2,29, prawie tam, gdzie zaczął (2,42).

Spróbuj

  • Lab startuje z Adamem i krokiem 0,001: po 10 epokach 93,6% cyfr testowych.
  • Wybierz SGD i znajdź krok, przy którym trafność przekracza 90%. To cel labu.
  • Porównaj SGD z momentem przy kroku 0,01 i zwykły SGD przy 0,1: 93,6% i 94,2%.
  • Wybierz Adama i krok 0,5. Zobacz, co się dzieje z krzywą trafności.

Pomysł w prostych słowach

Gradient z jednego przykładu jest tani, ale chwiejny: jedna cyfra ciągnie wagi w swoją stronę. Gradient z całego zbioru jest dokładny, ale drogi, i daje jeden krok na epokę. Paczka jest pośrodku: w labie 32 cyfry, czyli 45 kroków na epokę, 450 kroków w 10 epok. Na karcie graficznej przykłady z jednej paczki liczą się równolegle.

Krok uczenia to długość kroku. Za mały i wagi prawie stoją: zwykły SGD przy kroku 0,01 kończy z 73,8%. Za duży i wagi przeskakują dolinę straty, zamiast do niej zejść.

Moment dodaje rozpęd: krok to suma bieżącego gradientu i 0,9 poprzedniego kroku. Gdy kolejne gradienty wskazują podobnie, krok rośnie. Adam idzie dalej: każdą wagę przesuwa o krok podzielony przez typową wielkość jej gradientu, więc wagi z małym gradientem też się ruszają.

Dlaczego to działa

W przewidywaniu wygrała liczba kroków, nie dokładność gradientu. Przy równych 200 krokach paczka 16 kończy ze stratą 0,72, a cały zbiór 0,71, choć przeliczył ok. 32 razy więcej przykładów. Paczka po 1 przykładzie po 200 krokach ma 0,99, bo widziała tylko 200 cyfr. Mała paczka daje więc dużo tanich kroków, a duża dokładne i drogie.

Moment 0,9 sumuje mniej więcej 10 ostatnich gradientów. Dlatego SGD z momentem przy kroku 0,01 daje prawie to samo co zwykły SGD przy kroku 10 razy większym.

Adam dzieli krok przez wielkość gradientu, więc rusza wagę o ułamek η, prawie niezależnie od skali gradientu. W labie w 1. epoce przy kroku 0,001 waga przesuwała się średnio o 0,42·η na krok, a przy SGD o 0,012·η. Dlatego SGD potrzebuje kroku co najmniej 0,1, a Adam działa już przy 0,001.

Częsty błąd

Prawda czy fałsz: „Adam działa zawsze, więc krok nie ma znaczenia.” Fałsz. W labie Adam przekracza 90% przy krokach 0,001, 0,01 i 0,1, ale przy 0,5 wagi wybijają się z doliny i trafność spada poniżej 25%, blisko zgadywania (10 cyfr, czyli 10%). Na pięciu startach wag Adam przy 0,5 nie przekroczył 25% ani razu. Najlepsze wyniki trzech optymalizatorów różnią się za to najwyżej o 2 pkt proc.: SGD 96,1%, SGD z momentem 98,1%, Adam 96,4%. To trafność przy kroku, który wypadł najlepiej na teście, więc trochę za optymistyczna; uczciwie krok wybiera się na walidacji. Adam nie jest lepszy, tylko wybacza więcej przy wyborze kroku.

Quiz

Trzy pytania na sprawdzenie się. Wybierz odpowiedź albo rozwiń odpowiedź pod pytaniem. Z klawiatury: strzałki wybierają, Enter albo spacja zatwierdza.

1. Dlaczego w 5 epokach paczka po 1 przykładzie zeszła niżej niż cały zbiór naraz?
Pokaż odpowiedź

Poprawna odpowiedź: Bo zrobiła 2495 kroków, a cały zbiór tylko 5

Obie widziały te same cyfry; przy równej liczbie kroków przewaga małej paczki znika.

2. SGD przy kroku 0,01 kończy z 73,8%, przy 0,1 z 94,2%. Co to mówi o kroku uczenia?
Pokaż odpowiedź

Poprawna odpowiedź: Za mały krok sprawia, że w 450 krokach wagi nie dochodzą do dobrego miejsca

Przy małym kroku strata wciąż spada, ale trening kończy się, zanim zejdzie nisko.

3. Adam przy kroku 0,5 spada poniżej 25%. Co to pokazuje?
Pokaż odpowiedź

Poprawna odpowiedź: Krok trzeba dobrać także dla Adama; za duży wybija wagi z doliny

Przy 0,001, 0,01 i 0,1 Adam przekracza 90%; kłopot robi tylko za duży krok.

Najważniejsze wnioski

  • Krok uczenia mówi, jak daleko iść; za mały stoi w miejscu, za duży przeskakuje dolinę.
  • Mała paczka daje dużo tanich, chwiejnych kroków; duża mało dokładnych i drogich.
  • Moment dodaje rozpęd i działa jak większy krok; Adam skaluje krok osobno dla każdej wagi.
  • Adam wybacza więcej, ale też ma za duży krok; najlepsze wyniki optymalizatorów są podobne.

Głębiej: wzór, kod, praktyka

Matematyka

Gradient z paczki B przykładów: g = (1/B) · Σ ∇Lᵢ(w); kroków na epokę ⌈n / B⌉.

  • SGD: w ← w − η·g.
  • SGD z momentem: v ← 0,9·v − η·g, w ← w + v. Przy stałym gradiencie v dąży do −η·g / (1 − 0,9) = −10·η·g.
  • Adam: m ← 0,9·m + 0,1·g, s ← 0,999·s + 0,001·g², w ← w − η · m̂ / (√ŝ + ε), gdzie m̂, ŝ to m, s z poprawką na start: podzielone przez 1 − 0,9ᵗ i 1 − 0,999ᵗ.
  • Zwykły SGD na dolinie o krzywiźnie λ jest stabilny tylko przy η < 2/λ.
W kodzie (Python)

Dwie rzeczy w numpy: ile kroków dają różne paczki w 5 epokach na 499 cyfrach i trzy reguły kroku na wydłużonej dolinie:

import numpy as np

# kroki w 5 epokach na 499 cyfrach: im mniejsza paczka, tym więcej kroków
n = 499
for B in [1, 4, 16, 64, n]:
    steps = int(np.ceil(n / B))
    print(f"batch {B:3d}: {steps:3d} per epoch, {5 * steps:4d} steps in 5 epochs")

# wydłużona dolina: strata L(w) = (w1^2 + 10 w2^2) / 2, start (3, 1), 50 kroków
grad = lambda w: np.array([w[0], 10 * w[1]])
loss = lambda w: (w[0] ** 2 + 10 * w[1] ** 2) / 2

def run(rule, lr, steps=50):
    w, vel, m, v = np.array([3.0, 1.0]), np.zeros(2), np.zeros(2), np.zeros(2)
    for t in range(1, steps + 1):
        g = grad(w)
        if rule == "sgd":
            w = w - lr * g
        elif rule == "momentum":
            vel = 0.9 * vel - lr * g
            w = w + vel
        else:  # adam
            m = 0.9 * m + 0.1 * g
            v = 0.999 * v + 0.001 * g ** 2
            w = w - lr * (m / (1 - 0.9 ** t)) / (np.sqrt(v / (1 - 0.999 ** t)) + 1e-8)
    return loss(w)

print("loss after 50 steps (start 9.5)")
for rule in ["sgd", "momentum", "adam"]:
    print(f"{rule:8s}", "  ".join(f"lr {lr}: {run(rule, lr):9.3g}" for lr in [0.01, 0.1, 0.25]))

Wynik

batch   1: 499 per epoch, 2495 steps in 5 epochs
batch   4: 125 per epoch,  625 steps in 5 epochs
batch  16:  32 per epoch,  160 steps in 5 epochs
batch  64:   8 per epoch,   40 steps in 5 epochs
batch 499:   1 per epoch,    5 steps in 5 epochs
loss after 50 steps (start 9.5)
sgd      lr 0.01:      1.65  lr 0.1:   0.00012  lr 0.25:  2.03e+18
momentum lr 0.01:    0.0376  lr 0.1:    0.0323  lr 0.25:    0.0154
adam     lr 0.01:      4.59  lr 0.1:    0.0144  lr 0.25:    0.0184

Zwykły SGD przy kroku 0,25 wybucha: krzywizna doliny wzdłuż w₂ to 10, a SGD jest tu stabilny tylko przy kroku poniżej 2/10 = 0,2. Moment przy tym samym kroku zostaje stabilny. Adam przy 0,01 prawie stoi, bo rusza każdą wagę o mniej więcej długość kroku: w 50 krokach przeszedł niecałe 0,5 z drogi 3. Uruchomione w numpy 2.1.3.

Dla praktyka
  • Na start: Adam z krokiem 0,001 i paczka 32. Krok 0,001 to domyślny krok Adama w PyTorch i Keras, a 32 to domyślna paczka w Keras.
  • Strata skacze albo rośnie? Zmniejsz krok kilka razy. Strata spada bardzo powoli? Zwiększ go. Krok sprawdzaj w skali logarytmicznej, jak w labie: 0,0001, 0,001, 0,01, 0,1.
  • Długi trening zwykle zaczyna większym krokiem i kończy mniejszym. To harmonogram kroku (hasło „Harmonogramy współczynnika uczenia”).
  • Porównując optymalizatory, daj każdemu jego najlepszy krok. Porównanie przy jednym, wspólnym kroku mierzy dopasowanie kroku, a nie optymalizator.

Więcej w Atlasie

Hasła encyklopedii o pojęciach z tej lekcji: