W nawracającej sieci neuronowej zwykle propagujesz w przód przez kilka kroków czasowych, „rozwijasz” sieć, a następnie w tył propagujesz w sekwencji danych wejściowych.
Dlaczego po prostu nie aktualizowałbyś wag po każdym indywidualnym kroku w sekwencji? (odpowiednik użycia długości obcięcia 1, więc nie ma nic do rozwinięcia) To całkowicie eliminuje problem znikającego gradientu, znacznie upraszcza algorytm, prawdopodobnie zmniejszy szanse utknięcia w lokalnych minimach i, co najważniejsze, wydaje się działać dobrze . Trenowałem w ten sposób model do generowania tekstu, a wyniki wydawały się porównywalne z wynikami, które widziałem w modelach przeszkolonych przez BPTT. Jestem tylko zdezorientowany, ponieważ każdy samouczek na temat RNN, które widziałem, mówi o używaniu BPTT, prawie tak, jakby był wymagany do prawidłowego uczenia się, co nie jest prawdą.
Aktualizacja: dodałem odpowiedź
Odpowiedzi:
Edycja: Popełniłem duży błąd podczas porównywania dwóch metod i musiałem zmienić swoją odpowiedź. Okazuje się, że tak to robiłem, po prostu propagując bieżący krok czasu, faktycznie zaczyna się szybciej uczyć. Szybkie aktualizacje bardzo szybko uczą się najbardziej podstawowych wzorców. Ale w przypadku większego zestawu danych i dłuższego czasu szkolenia BPTT faktycznie wychodzi na prowadzenie. Testowałem małą próbkę przez kilka epok i założyłem, że ktokolwiek zacznie wygrywać wyścig, będzie zwycięzcą. Ale to doprowadziło mnie do interesującego znaleziska. Jeśli zaczniesz trenować z powrotem propagując tylko jeden krok czasowy, następnie zmień na BPTT i powoli zwiększaj, jak daleko się propagujesz, uzyskasz szybszą konwergencję.
źródło
RNN to Deep Neural Network (DNN), gdzie każda warstwa może przyjmować nowe dane wejściowe, ale ma te same parametry. BPT jest fantazyjnym słowem dla propagacji wstecznej w takiej sieci, która sama w sobie jest fantazyjnym słowem dla Gradient Descent.
Załóżmy, że w RNN WYJŚCIA y t w każdym etapie i e r r o r t = ( y t - r t ) 2y^t
Aby poznać wagi, potrzebujemy gradientów, aby funkcja mogła odpowiedzieć na pytanie „jak bardzo zmiana parametru wpływa na funkcję straty?” i przesuń parametry w kierunku podanym przez:
To znaczy, mamy DNN, gdzie otrzymujemy informację zwrotną o tym, jak dobre są prognozy dla każdej warstwy. Ponieważ zmiana parametru zmieni każdą warstwę w DNN (timestep), a każda warstwa przyczynia się do nadchodzących wyników, należy to uwzględnić.
Weź prostą sieć z jedną warstwą jeden neuron, aby zobaczyć to częściowo jawnie:
Withδ the learning rate one training step is then:
What we see is that in order to calculate∇y^t+1 you need to calculate i.e roll out ∇y^t . What you propose is to t but not recurse further. I assume that your loss is something like
simply disregard the red partcalculate the red part forMaybe each step will then contribute a crude direction which is enough in aggregation? This could explain your results but I'd be really interested in hearing more about your method/loss function! Also would be interested in a comparison with a two timestep windowed ANN.
edit4: After reading comments it seems like your architecture is not an RNN.
RNN: Stateful - carry forward hidden stateht indefinitely
This is your model but the training is different.
Your model: Stateless - hidden state rebuilt in each stepedit2 : added more refs to DNNs edit3 : fixed gradstep and some notation edit5 : Fixed the interpretation of your model after your answer/clarification.źródło
"Unfolding through time" is simply an application of the chain rule,
The output of an RNN at time stept , Ht is a function of the parameters θ , the input xt and the previous state, Ht−1 (note that instead Ht may be transformed again at time step t to obtain the output, that is not important here). Remember the goal of gradient descent: given some error function L , let's look at our error for the current example (or examples), and then let's adjust θ in such a way, that given the same example again, our error would be reduced.
How exactly didθ contribute to our current error? We took a weighted sum with our current input, xt , so we'll need to backpropagate through the input to find ∇θa(xt,θ) , to work out how to adjust θ . But our error was also the result of some contribution from Ht−1 , which was also a function of θ , right? So we need to find out ∇θHt−1 , which was a function of xt−1 , θ and Ht−2 . But Ht−2 was also a function a function of θ . And so on.
źródło