Nie jestem pewien, czy to pytanie należy tutaj, ale jest ściśle związane z metodami gradientu w optymalizacji, co wydaje się być tutaj na temat. W każdym razie możesz swobodnie przeprowadzić migrację, jeśli uważasz, że inna społeczność ma lepsze doświadczenie w tym temacie.
Krótko mówiąc, szukam krok po kroku przykładu automatycznego różnicowania w trybie wstecznym . Nie ma zbyt wiele literatury na ten temat, a istniejąca implementacja (taka jak w TensorFlow ) jest trudna do zrozumienia bez znajomości stojącej za nią teorii. Tak więc byłbym bardzo wdzięczny jeśli ktoś mógłby pokazać szczegółowo, co przekazać w , jak my go przetworzyć , a czego wyjąć obliczeniowej wykresie.
Kilka pytań, z którymi mam najwięcej trudności:
- nasiona - dlaczego w ogóle ich potrzebujemy?
- zasady odwrotnego różnicowania - wiem, jak wprowadzić różnicowanie do przodu, ale jak cofamy się? Np. W przykładzie z tej sekcji , skąd wiemy, że ?
- czy pracujemy tylko z symbolami czy przekazujemy rzeczywiste wartości ? Np. W tym samym przykładzie , czy i symbole lub wartości?
Odpowiedzi:
Powiedzmy, że mamy wyrażeniez=x1x2+sin(x1) i chcemy znaleźć pochodne dzdx1 idzdx2 . AD w trybie do tyłu dzieli to zadanie na 2 części, mianowicie do przodu i do tyłu.
Przekaż do przodu
Po pierwsze, rozkładamy nasze złożone wyrażenie na zbiór pierwotnych, tj. Wyrażeń składających się z co najwyżej jednego wywołania funkcji. Zauważ też, że zmieniam nazwę zmiennych wejściowych i wyjściowych dla zachowania spójności, chociaż nie jest to konieczne:
Zaletą tej reprezentacji jest to, że reguły różnicowania dla każdego oddzielnego wyrażenia są już znane. Na przykład wiemy, że pochodnąsin jest cos , a więc dw4dw1=cos(w1) . Wykorzystamy ten fakt w przekazaniu wstecznym poniżej.
Zasadniczo przekazanie dalej polega na ocenie każdego z tych wyrażeń i zapisaniu wyników. Powiedzmy, że nasze dane wejściowe to:x1=2 i x2=3 . Następnie mamy:
Przełęcz wsteczny
To właśnie tam zaczyna się magia i zaczyna się ona od reguły łańcucha . W swojej podstawowej formie, reguła łańcuch stwierdza, że jeśli masz zmiennąt(u(v)) , który zależy od u , który z kolei zależy od v , a następnie:
lub, jeżelit zależy od v przez kilka ścieżek / zmiennych ui , np .:
następnie (patrz dowód tutaj ):
Jeśli chodzi o graf wyrażeń, jeśli mamy końcowy węzełz i węzły wejściowe wi , a ścieżka od z do wi przechodzi przez węzły pośrednie wp (tj. z=g(wp) gdzie wp=f(wi) ), możemy znaleźć pochodną dzdwi as
Innymi słowy, aby obliczyć pochodną zmiennej wyjściowejz wrt dowolnej zmiennej pośredniej lub wejściowej wi , musimy jedynie znać pochodne jej rodziców i wzór do obliczenia pochodnej pierwotnego wyrażenia wp=f(wi) .
Przebieg wsteczny rozpoczyna się na końcu (tj.dzdz ) i propaguje wstecz do wszystkich zależności. Oto mamy (wyrażenie na „seed”):
Można to odczytać jako „zmiana wz powoduje dokładnie taką samą zmianę w z ”, co jest dość oczywiste.
Następnie wiemy, żez=w5 i tak:
Z definicjiw3=w1w2 i reguł pochodnych cząstkowych wynika, żedw3dw2=w1 . A zatem:
Co, jak już wiemy z przekazania, to:
Wreszcie,w1 przyczynia się do z poprzez w3 i w4 . Po raz kolejny z zasad pochodnych cząstkowych wiemy, że dw3dw1=w2 idw4dw1=cos(w1) . A zatem:
I znowu, biorąc pod uwagę znane dane wejściowe, możemy to obliczyć:
Sincew1 and w2 are just aliases for x1 and x2 , we get our answer:
And that's it!
This description concerns only scalar inputs, i.e. numbers, but in fact it can also be applied to multidimensional arrays such as vectors and matrices. Two things that one should keep in mind when differentiating expressions with such objects:
The power of automatic differentiation is that it can deal with complicated structures from programming languages like conditions and loops. However, if all you need is algebraic expressions and you have good enough framework to work with symbolic representations, it's possible to construct fully symbolic expressions. In fact, in this example we could produce expressiondzdw1=w2+cos(w1)=x2+cos(x1) and calculate this derivative for whatever inputs we want.
źródło