Algorytm wstecznej propagacji


19

Mam lekką dezorientację na wstecznej propagacji błędów algorytmu stosowanego w perceptronu wielowarstwowego (MLP).

Błąd jest regulowana przez funkcję kosztów. W wstecznej propagacji błędów, staramy się dostosować ciężar warstw ukrytych. Błąd wyjściowy, który rozumiem, to znaczy e = d - y[Bez indeksów dolnych].

Pytania są następujące:

  1. W jaki sposób można uzyskać błąd w ukrytej warstwie? W jaki sposób można go obliczyć?
  2. Jeśli propaguję go z powrotem, czy powinienem użyć go jako funkcji kosztu filtra adaptacyjnego, czy powinienem użyć wskaźnika (w języku C / C ++) do aktualizacji wagi?

NN jest raczej przestarzałą technologią, więc obawiam się, że nie dostaniesz odpowiedzi, ponieważ nikt tutaj jej nie używa ...

@mbq: Nie wątpię w twoje słowa, ale jak dojść do wniosku, że NN to „przestarzała technologia”?
Steffen

1
@steffen Poprzez obserwację; Mam na myśli, że oczywiste jest, że nikt znaczący ze społeczności NN nie wyjdzie i nie powie: „Cześć chłopaki, porzućmy życie i bawmy się czymś lepszym!”, Ale mamy narzędzia, które osiągają taką samą lub lepszą dokładność bez całej tej ambiwalencji i nigdy Trening -ending. I ludzie upuszczają NN na ich korzyść.

5
To miało jakąś prawdę, kiedy to powiedział, @mbq, ale nie więcej.
jerad

1
@jerad Całkiem proste - po prostu nie widziałem jeszcze żadnego uczciwego porównania z innymi metodami (Kaggle nie jest uczciwym porównaniem z powodu braku przedziałów ufności dla dokładności - szczególnie, gdy wyniki wszystkich drużyn z wysokim wynikiem są tak blisko jak w konkursie Merck), ani żadna analiza solidności optymalizacji parametrów - co jest znacznie gorsze.

Odpowiedzi:


27

Pomyślałem, że odpowiem na samodzielny post dla każdego, kto jest zainteresowany. Będzie to wykorzystywało notację opisaną tutaj .

Wprowadzenie

Ideą propagacji wstecznej jest zestaw „przykładów szkoleniowych”, których używamy do szkolenia naszej sieci. Każdy z nich ma znaną odpowiedź, dzięki czemu możemy podłączyć je do sieci neuronowej i dowiedzieć się, jak bardzo było źle.

Na przykład dzięki rozpoznawaniu pisma odręcznego miałbyś wiele znaków odręcznych obok tego, co naprawdę były. Następnie sieć neuronowa może zostać przeszkolona poprzez propagację wsteczną, aby „nauczyć się” rozpoznawać każdy symbol, a następnie, gdy zostanie mu później przedstawiony nieznany odręczny znak, może zidentyfikować, co jest poprawnie.

W szczególności wprowadzamy próbkę szkoleniową do sieci neuronowej, sprawdzamy, jak dobrze sobie radzi, a następnie „przesuwamy się wstecz”, aby dowiedzieć się, jak bardzo możemy zmienić wagi i odchylenie każdego węzła, aby uzyskać lepszy wynik, a następnie odpowiednio je dostosować. W miarę, jak to robimy, sieć „uczy się”.

Istnieją również inne kroki, które mogą być uwzględnione w procesie szkolenia (na przykład rezygnacja), ale skupię się głównie na propagacji wstecznej, ponieważ o to właśnie chodziło w tym pytaniu.

Częściowe pochodne

Pochodna cząstkowa jest pochodnąfw odniesieniu do pewnej zmiennejx.faxfax

Na przykład, jeśli , ffa(x,y)=x2)+y2), ponieważy2jest po prostu stałą w odniesieniu dox. Podobnie,ffx=2xy2x, ponieważx2jest po prostu stała względemy.fy=2yx2y

Gradient funkcji, oznaczonej , jest funkcją zawierającą pochodną cząstkową dla każdej zmiennej w f. Konkretnie:f

,

f(v1,v2,...,vn)=fv1e1++fvnen

gdzie jest wektorem jednostkowym wskazującym w kierunku zmiennej v 1 .eiv1

Teraz, kiedy mamy obliczyli dla niektórych funkcji f , jeśli są w pozycji ( v 1 , V, 2 , . . . , V n ) , to może "Przesuń w dół" f przechodząc w kierunku - F ( V 1 , V, 2 , . . . , v n ) .ff(v1,v2,...,vn)ff(v1,v2,...,vn)

W naszym przykładzie , wektory jednostkowe to e 1 = ( 1 , 0 ) i e 2 = ( 0 , 1 ) , ponieważ v 1 = x i v 2 = y , i te wektory jest skierowany w kierunku x i y osi. Zatem f ( x , yf(x,y)=x2+y2e1=(1,0)e2=(0,1)v1=xv2=yxy .f(x,y)=2x(1,0)+2y(0,1)

Teraz, aby „zsunąć” naszą funkcję , powiedzmy, że jesteśmy w punkcie ( - 2 , 4 ) . Następnie musielibyśmy przejść w kierunku - f ( - 2 , - 4 ) = - ( 2 - 2 ( 1 , 0 ) + 2 4 ( 0 , 1 ) ) = - ( ( - 4 , 0) ) +f(2,4) .f(2,4)=(22(1,0)+24(0,1))=((4,0)+(0,8))=(4,8)

Wielkość tego wektora pokaże nam, jak strome jest wzgórze (wyższe wartości oznaczają, że wzgórze jest bardziej strome). W tym przypadku mamy .42+(8)28.944

Gradient Descent

Produkt Hadamard

Produkt Hadamarda dwóch macierzy , jest podobny do dodawania macierzy, z tym wyjątkiem, że zamiast dodawać macierze elementami, mnożymy je elementami.A,BRn×m

Formalnie, podczas gdy dodawanie macierzy wynosi , gdzie C R n × m takie, żeA+B=CCRn×m

,

Cji=Aji+Bji

Produkt Hadamarda , gdzie C R n × m taki, żeAB=CCRn×m

Cji=AjiBji

Obliczanie gradientów

(większość tego rozdziału pochodzi z książki Neilsena ).

Mamy szereg prób treningowych, , gdzie S R jest pojedyncza próbka szkolenia wejściowego i e r oznacza oczekiwaną wartość wyjściowa w tej próbce treningowego. Posiadamy również sieć neuronową, która składa się z uprzedzeń W. i ciężary B . r służy do zapobiegania pomyłkom w stosunku do i , j oraz k używanych w definicji sieci sprzężenia zwrotnego.(S,E)SrErWBrijk

Następnie, określenia funkcji kosztu, , które ma w naszej sieci neuronowej i jeden przykład szkolenia i wyjść, jak to dało.C(W,B,Sr,Er)

Zwykle stosuje się koszt kwadratowy, który określa

C(W,B,Sr,Er)=0.5j(ajLEjr)2

gdzie L jest wyjście naszej sieci neuronowej, biorąc pod uwagę próbki wejściowe S RaLSr

Następnie chcemy znaleźć orazCCwji dla każdego węzła w naszej sprzężonej sieci neuronowej.Cbji

Możemy nazwać to gradient na każdy neuron ponieważ uważamy S R i E R jako stałe, ponieważ nie możemy ich zmieniać, gdy staramy się nauczyć. I to ma sens - chcemy poruszać się w kierunku W i B, który minimalizuje koszty, a przejście w kierunku ujemnym gradientu względem W i B to zrobi.CSrErWBWB

Aby to zrobić, definiujemy jako błąd neuronujw warstwiei.δji=Czjiji

Rozpoczynamy od obliczeniowych podłączając S R w naszym sieci neuronowych.aLSr

Następnie obliczamy błąd naszej warstwy wyjściowej , przezδL

.

δjL=CajLσ(zjL)

Które można również zapisać jako

.

δL=aCσ(zL)

Następnie znajdujemy błąd pod względem błędu w następnej warstwie δ i + 1 , za pośrednictwemδiδi+1

δi=((Wi+1)Tδi+1)σ(zi)

Teraz, gdy mamy błąd każdego węzła w naszej sieci neuronowej, obliczanie gradientu w odniesieniu do naszych wag i odchyleń jest łatwe:

Cwjki=δjiaki1=δi(ai1)T

Cbji=δji

Zauważ, że równanie błędu warstwy wyjściowej jest jedynym równaniem zależnym od funkcji kosztu, więc niezależnie od funkcji kosztu trzy ostatnie równania są takie same.

Jako przykład otrzymujemy kwadratowy koszt

δL=(aLEr)σ(zL)

L1th

δL1=((WL)TδL)σ(zL1)
=((WL)T((aLEr)σ(zL)))σ(zL1)

which we can repeat this process to find the error of any layer with respect to C, which then allows us to compute the gradient of any node's weights and bias with respect to C.

I could write up an explanation and proof of these equations if desired, though one can also find proofs of them here. I'd encourage anyone that is reading this to prove these themselves though, beginning with the definition δji=Czji and applying the chain rule liberally.

For some more examples, I made a list of some cost functions alongside their gradients here.

Gradient Descent

Now that we have these gradients, we need to use them learn. In the previous section, we found how to move to "slide down" the curve with respect to some point. In this case, because it's a gradient of some node with respect to weights and a bias of that node, our "coordinate" is the current weights and bias of that node. Since we've already found the gradients with respect to those coordinates, those values are already how much we need to change.

We don't want to slide down the slope at a very fast speed, otherwise we risk sliding past the minimum. To prevent this, we want some "step size" η.

Then, find the how much we should modify each weight and bias by, because we have already computed the gradient with respect to the current we have

Δwjki=ηCwjki

Δbji=ηCbji

Thus, our new weights and biases are

wjki=wjki+Δwjki
bji=bji+Δbji

Using this process on a neural network with only an input layer and an output layer is called the Delta Rule.

Stochastic Gradient Descent

Now that we know how to perform backpropagation for a single sample, we need some way of using this process to "learn" our entire training set.

One option is simply performing backpropagation for each sample in our training data, one at a time. This is pretty inefficient though.

A better approach is Stochastic Gradient Descent. Instead of performing backpropagation for each sample, we pick a small random sample (called a batch) of our training set, then perform backpropagation for each sample in that batch. The hope is that by doing this, we capture the "intent" of the data set, without having to compute the gradient of every sample.

For example, if we had 1000 samples, we could pick a batch of size 50, then run backpropagation for each sample in this batch. The hope is that we were given a large enough training set that it represents the distribution of the actual data we are trying to learn well enough that picking a small random sample is sufficient to capture this information.

However, doing backpropagation for each training example in our mini-batch isn't ideal, because we can end up "wiggling around" where training samples modify weights and biases in such a way that they cancel each other out and prevent them from getting to the minimum we are trying to get to.

To prevent this, we want to go to the "average minimum," because the hope is that, on average, the samples' gradients are pointing down the slope. So, after choosing our batch randomly, we create a mini-batch which is a small random sample of our batch. Then, given a mini-batch with n training samples, and only update the weights and biases after averaging the gradients of each sample in the mini-batch.

Formally, we do

Δwjki=1nrΔwjkri

and

Δbji=1nrΔbjri

where Δwjkri is the computed change in weight for sample r, and Δbjri is the computed change in bias for sample r.

Then, like before, we can update the weights and biases via:

wjki=wjki+Δwjki
bji=bji+Δbji

This gives us some flexibility in how we want to perform gradient descent. If we have a function we are trying to learn with lots of local minima, this "wiggling around" behavior is actually desirable, because it means that we're much less likely to get "stuck" in one local minima, and more likely to "jump out" of one local minima and hopefully fall in another that is closer to the global minima. Thus we want small mini-batches.

On the other hand, if we know that there are very few local minima, and generally gradient descent goes towards the global minima, we want larger mini-batches, because this "wiggling around" behavior will prevent us from going down the slope as fast as we would like. See here.

One option is to pick the largest mini-batch possible, considering the entire batch as one mini-batch. This is called Batch Gradient Descent, since we are simply averaging the gradients of the batch. This is almost never used in practice, however, because it is very inefficient.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.