Próbuję wytrenować pojedynczy perceptron (1000 jednostek wejściowych, 1 wyjście, brak ukrytych warstw) na 64 losowo generowanych punktach danych. Używam Pytorch za pomocą optymalizatora Adama:
import torch
from torch.autograd import Variable
torch.manual_seed(545345)
N, D_in, D_out = 64, 1000, 1
x = Variable(torch.randn(N, D_in))
y = Variable(torch.randn(N, D_out))
model = torch.nn.Linear(D_in, D_out)
loss_fn = torch.nn.MSELoss(size_average=False)
optimizer = torch.optim.Adam(model.parameters())
for t in xrange(5000):
y_pred = model(x)
loss = loss_fn(y_pred, y)
print(t, loss.data[0])
optimizer.zero_grad()
loss.backward()
optimizer.step()
Początkowo strata szybko maleje, zgodnie z oczekiwaniami:
(0, 91.74887084960938)
(1, 76.85824584960938)
(2, 63.434078216552734)
(3, 51.46927261352539)
(4, 40.942893981933594)
(5, 31.819372177124023)
Około 300 iteracji błąd sięga prawie zera:
(300, 2.1734419819452455e-12)
(301, 1.90354676465887e-12)
(302, 2.3347573874232808e-12)
Trwa to przez kilka tysięcy iteracji. Jednak po zbyt długim treningu błąd zaczyna się ponownie zwiększać:
(4997, 0.002102422062307596)
(4998, 0.0020302983466535807)
(4999, 0.0017039275262504816)
Dlaczego to się dzieje?
perceptron
pytorch
Bai Li
źródło
źródło
Odpowiedzi:
Ta niewielka niestabilność na końcu zbieżności jest cechą Adama (i RMSProp) ze względu na to, jak szacuje średnie wielkości gradientu w ostatnich krokach i dzieli je.
Jedną rzeczą, którą Adam robi, jest utrzymanie ruchomej średniej geometrycznej ostatnich gradientów i kwadratów gradientów. Kwadraty gradientów służą do dzielenia (kolejnej średniej kroczącej) bieżącego gradientu w celu podjęcia decyzji o bieżącym kroku. Jednak gdy gradient staje się i pozostaje bardzo bliski zeru, spowoduje to, że kwadraty gradientu staną się tak niskie, że albo będą miały duże błędy zaokrąglania, albo będą faktycznie zerowe, co może wprowadzić niestabilność (na przykład długoterminowy stabilny gradient w jeden wymiar robi względnie mały krok od do powodu zmian w innych parametrach ), a rozmiar kroku zacznie skakać, zanim ponownie się uspokoi.10- 10 10- 5
To faktycznie sprawia, że Adam jest mniej stabilny i gorzej dla twojego problemu niż bardziej podstawowe zejście gradientu, zakładając, że chcesz zbliżyć się do liczbowo bliskiego zerowej straty, jak pozwalają na to obliczenia.
W praktyce w przypadku problemów z głębokim uczeniem się, nie zbliżasz się tak bardzo do konwergencji (a w przypadku niektórych technik regularyzacji, takich jak wczesne zatrzymanie, i tak nie chcesz), więc zazwyczaj nie jest to praktyczne zmartwienie dotyczące rodzajów problemów, które Adam został zaprojektowany dla.
Możesz faktycznie zobaczyć, jak to się dzieje w przypadku RMSProp w porównaniu różnych optymalizatorów (RMSProp to czarna linia - obserwuj ostatnie kroki, gdy tylko osiągnie cel):
Możesz sprawić, by Adam był bardziej stabilny i mógł zbliżyć się do prawdziwej konwergencji poprzez zmniejszenie wskaźnika uczenia się. Na przykład
Optymalizacja potrwa dłużej. Używając10- 7 .
lr=1e-5
musisz trenować przez ponad 20 000 iteracji, zanim zobaczysz niestabilność, a niestabilność jest mniej dramatyczna, wartości krążą wokółźródło
Powód jest dokładnie taki, jak wspomniany w drugiej odpowiedzi, ze świetną sugestią, aby użyć mniejszego współczynnika uczenia się, aby uniknąć tego problemu przy małych gradientach.
Mogę wymyślić kilka podejść:
Możesz przyciąć gradienty górną / dolną granicą, ale nie gwarantuje to zbieżności i może spowodować zamrożenie treningu przez uwięzienie w lokalnych minimach i nigdy się z niego nie wydostanie.
Trenuj z większą wielkością partii, większą liczbą epok i ze zmniejszoną szybkością uczenia się. Teraz nie mam żadnego praktycznego dowodu, że zwiększenie wielkości partii skutkuje lepszymi gradientami, ale z tego, co zaobserwowałem w obliczu problemów podobnych do twojego, prawie zawsze pomogło.
Jestem pewien, że istnieją inne metody (takie jak cykliczny współczynnik uczenia się itp.), Które próbują znaleźć optymalny współczynnik uczenia się na podstawie statystyk.
źródło