Gradientowa propagacja wsteczna poprzez pomijanie połączeń ResNet

22

Jestem ciekawy, w jaki sposób gradienty są propagowane wstecz przez sieć neuronową przy użyciu modułów ResNet / pomijania połączeń. Widziałem kilka pytań na temat ResNet (np. Sieć neuronowa z połączeniami pomijanymi ), ale to pytanie dotyczy konkretnie wstecznej propagacji gradientów podczas treningu.

Podstawowa architektura jest tutaj:

wprowadź opis zdjęcia tutaj

Przeczytałem ten artykuł, Badanie resztkowych sieci do rozpoznawania obrazów , aw części 2 rozmawiają o tym, jak jednym z celów ResNet jest umożliwienie krótszej / wyraźniejszej ścieżki gradientu do wstecznej propagacji do warstwy podstawowej.

Czy ktoś może wyjaśnić, w jaki sposób gradient przepływa przez ten typ sieci? Nie do końca rozumiem, w jaki sposób operacja dodawania i brak sparametryzowanej warstwy po dodaniu pozwala na lepszą propagację gradientu. Czy ma to coś wspólnego z tym, że gradient nie zmienia się podczas przepływu przez operator dodawania i jest jakoś rozdzielany bez mnożenia?

Ponadto rozumiem, w jaki sposób można rozwiązać problem znikającego gradientu, jeśli gradient nie musi przepływać przez warstwy ciężaru, ale jeśli nie ma przepływu gradientu przez ciężarki, w jaki sposób są one aktualizowane po przejściu wstecz?

Szymon, Szymek
źródło
Tylko idiotyczne pytanie: dlaczego przekazujemy x jako pominięcie połączenia i nie obliczamy odwrotności (F (x)), aby uzyskać x na końcu. Czy to jest przyczyną złożoności obliczeniowej?
Yash Kumar Atri
Nie rozumiem the gradient doesn't need to flow through the weight layers, o co ci chodzi?
anu

Odpowiedzi:

13

Dodaj wysyła gradient z powrotem na oba wejścia. Możesz się o tym przekonać, uruchamiając w tensorflow:

import tensorflow as tf

graph = tf.Graph()
with graph.as_default():
    x1_tf = tf.Variable(1.5, name='x1')
    x2_tf = tf.Variable(3.5, name='x2')
    out_tf = x1_tf + x2_tf

    grads_tf = tf.gradients(ys=[out_tf], xs=[x1_tf, x2_tf])
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        fd = {
            out_tf: 10.0
        }
        print(sess.run(grads_tf, feed_dict=fd))

Wydajność:

[1.0, 1.0]

Tak więc gradient będzie wynosić:

  • przekazywane z powrotem do poprzednich warstw, niezmienione, poprzez połączenie pomijania warstw, a także
  • przekazywane do bloku z ciężarkami i używane do ich aktualizacji

Edycja: pojawia się pytanie: „jaka jest operacja w punkcie, w którym połączenie autostrady i blok sieci neuronowej łączą się ponownie, na dole Ryciny 2?”

Odpowiedź brzmi: są zsumowane. Możesz to zobaczyć na podstawie wzoru z Rysunku 2:

wydajnośćfa(x)+x

Mówi to, że:

  • wartości w magistrali ( )x
  • są dodawane do wyników przekazywania wartości magistrali przez sieć, tj.xfa(x)
  • aby dać wynik z bloku resztkowego, który oznaczyłem tutaj jakowydajność

Edycja 2:

Przepisywanie w nieco innych słowach:

  • w kierunku do przodu dane wejściowe płyną w dół magistrali
    • w punktach wzdłuż magistrali pozostałe bloki mogą nauczyć się dodawać / usuwać wartości do wektora magistrali
  • w kierunku do tyłu gradienty płyną z powrotem w kierunku autobusu
    • po drodze gradienty aktualizują pozostałe bloki, przez które przechodzą
    • pozostałe bloki same również nieznacznie zmodyfikują gradienty

Bloki resztkowe modyfikują gradienty przepływające do tyłu, ale nie ma żadnych funkcji „squash” ani „aktywacji”, przez które przepływają gradienty. Funkcje „zgniatania” / „aktywacji” powodują problem gradientu eksplozji / zanikania, więc usuwając je z samej magistrali, znacznie łagodzimy ten problem.

Edycja 3: Osobiście wyobrażam sobie siatkę w mojej głowie jako poniższy schemat. Jest topologicznie identyczny z rysunkiem 2, ale bardziej wyraźnie pokazuje, jak magistrala przepływa prosto przez sieć, podczas gdy pozostałe bloki po prostu stukają z niej wartości i dodają / usuwają jakiś mały wektor względem magistrali:

wprowadź opis zdjęcia tutaj

Hugh Perkins
źródło
1
jeśli gradient jest również przepuszczany przez bloki wagi (tak jak w zwykłych sieciach), to skąd bierze się korzyść z resnetu? Jasne, pozwala to na przejście gradientu bezpośrednio do wejścia podstawowego, ale jak to zwiększa wydajność, gdy druga ścieżka jest trenowana normalnie?
Simon
3
Widzę. Tak więc jeden gradient przeskakuje prosto z powrotem do x, a drugi propaguje się przez wagi z powrotem do x. czy sumują się, gdy osiągną x, ponieważ x podzielił się na 2 ścieżki? jeśli tak, to czy gradient nadal się nie zmienia, gdy przesuwa się z powrotem przez te warstwy?
Simon
1
Gradienty płyną w dół stosu bez zmian. Jednak każdy blok wprowadza własne zmiany gradientu do stosu, po zastosowaniu aktualizacji wagi i wygenerowaniu własnego zestawu gradientów. Każdy blok ma zarówno wejście, jak i wyjście, a gradienty wypłyną z wejścia z powrotem do gradientu „autostrada”.
Hugh Perkins
1
@RonakAgrawal dodał edycję pokazującą operację sumy z rysunku 2 i wyjaśniającą ją
Hugh Perkins
1
dodałem drugą edycję, zmieniając nieco moje wyjaśnienie :)
Hugh Perkins