Understanding Activation Functions in Neural Networks
Avinash Sharma V
Follow
Mar 30, 2017 – 10 min read
Ostatnio mój kolega zadał mi kilka pytań typu „dlaczego mamy tak wiele funkcji aktywacji?”, „dlaczego jedna działa lepiej niż druga?”, „skąd wiemy, której z nich użyć?”, „czy to twarda matematyka?” i tak dalej. Pomyślałem więc, dlaczego nie napisać artykułu na ten temat dla tych, którzy są zaznajomieni z siecią neuronową tylko na poziomie podstawowym i dlatego zastanawiają się nad funkcjami aktywacji i ich „dlaczego jak-matematyka!”.
UWAGA: Ten artykuł zakłada, że masz podstawową wiedzę o sztucznym „neuronie”. Zalecam zapoznanie się z podstawami sieci neuronowych przed przeczytaniem tego artykułu dla lepszego zrozumienia.
Funkcje aktywacji
Co więc robi sztuczny neuron? Najprościej mówiąc, oblicza „sumę ważoną” swoich danych wejściowych, dodaje uprzedzenie, a następnie decyduje, czy powinien zostać „odpalony”, czy nie (tak, funkcja aktywacji to robi, ale pójdźmy z prądem przez chwilę).
Więc rozważmy neuron.
Teraz, wartość Y może być czymkolwiek z zakresu od -inf do +inf. Neuron tak naprawdę nie zna granic tej wartości. Więc jak zdecydujemy, czy neuron powinien się zapalić czy nie (dlaczego taki wzorzec odpalania? Ponieważ nauczyliśmy się tego z biologii, że tak właśnie działa mózg, a mózg jest działającym świadectwem niesamowitego i inteligentnego systemu).
W tym celu postanowiliśmy dodać „funkcje aktywacji”. Aby sprawdzić wartość Y wytwarzaną przez neuron i zdecydować, czy zewnętrzne połączenia powinny uznać ten neuron za „odpalony” czy nie. Albo raczej powiedzmy – „aktywowany” lub nie.
Funkcja krokowa
Pierwszą rzeczą, która przychodzi nam do głowy, jest to, co powiesz na funkcję aktywacji opartą na progu? Jeśli wartość Y jest powyżej pewnej wartości, zadeklaruj ją jako aktywowaną. Jeśli jest mniejsza niż próg, to powiedz, że nie jest. Hmm świetnie. To może zadziałać!
Funkcja aktywacji A = „aktywowana” jeśli Y > próg else nie
Alternatywnie, A = 1 jeśli y> próg, 0 w przeciwnym razie
Cóż, to co właśnie zrobiliśmy jest „funkcją krokową”, zobacz poniższy rysunek.
Jej wyjście wynosi 1 ( aktywowana) gdy wartość > 0 (próg) i wyprowadza 0 ( nie aktywowana) w przeciwnym wypadku.
Świetnie. Więc to tworzy funkcję aktywacji dla neuronu. Nie ma żadnych pomyłek. Jednak są pewne wady tego rozwiązania. Aby zrozumieć to lepiej, pomyśl o następującym.
Załóżmy, że tworzysz klasyfikator binarny. Coś, co powinno powiedzieć „tak” lub „nie” ( aktywować lub nie aktywować ). Funkcja Step mogłaby to dla ciebie zrobić! To jest dokładnie to co robi, mówi 1 lub 0. Teraz pomyśl o przypadku użycia, w którym chciałbyś, aby wiele takich neuronów było połączonych, aby wprowadzić więcej klas. Klasa1, klasa2, klasa3 itd. Co się stanie, jeśli więcej niż jeden neuron zostanie „aktywowany”. Wszystkie neurony dadzą na wyjściu 1 (z funkcji krokowej). Co teraz zdecydujesz? Która klasa to jest? Hmm trudne, skomplikowane.
Chciałbyś, aby sieć aktywowała tylko 1 neuron, a inne powinny być 0 ( tylko wtedy mógłbyś powiedzieć, że sklasyfikowała poprawnie/ zidentyfikowała klasę ). Ah! To jest trudniejsze do trenowania i zbieżności w ten sposób. Byłoby lepiej, gdyby aktywacja nie była binarna i zamiast tego mówiłaby „50% aktywowane” lub „20% aktywowane” i tak dalej. I wtedy, jeśli więcej niż 1 neuron aktywuje, można by znaleźć, który neuron ma „najwyższą aktywację” i tak dalej ( lepiej niż max, softmax, ale zostawmy to na razie ).
W tym przypadku również, jeśli więcej niż 1 neuron mówi „100% aktywowany”, problem nadal istnieje.Wiem! Ale..ponieważ istnieją pośrednie wartości aktywacji dla wyjścia, uczenie może być gładsze i łatwiejsze ( mniej wiggly ) i szanse na więcej niż 1 neuron jest 100% aktywowany jest mniejsza w porównaniu do funkcji kroku podczas szkolenia ( również w zależności od tego, co trenujesz i dane ).
Ok, więc chcemy coś, aby dać nam pośrednie ( analogowe ) wartości aktywacji, a nie mówiąc „aktywowane” lub nie ( binarne ).
Pierwszą rzeczą, która przychodzi nam do głowy byłaby funkcja liniowa.
Funkcja liniowa
A = cx
Funkcja liniowa, gdzie aktywacja jest proporcjonalna do wejścia ( które jest sumą ważoną z neuronu ).
W ten sposób daje zakres aktywacji, więc nie jest to aktywacja binarna. Zdecydowanie możemy połączyć kilka neuronów razem i jeśli więcej niż 1 strzela, moglibyśmy wziąć max ( lub softmax) i zdecydować w oparciu o to. Więc to też jest ok. Następnie, jaki jest z tym problem?
Jeśli jesteś zaznajomiony z zejściem gradientowym dla szkolenia, zauważyłbyś, że dla tej funkcji pochodna jest stała.
A = cx, pochodna względem x jest c. Oznacza to, że gradient nie ma związku z X. Jest to stały gradient i zejście będzie na stałym gradiencie. Jeśli jest błąd w przewidywaniu, to zmiany dokonane przez wsteczną propagację są stałe i nie zależą od zmiany danych wejściowych delta(x) !!!
To nie jest takie dobre! ( nie zawsze, ale wytrzymaj ze mną ). Jest też inny problem. Pomyśl o połączonych warstwach. Każda warstwa jest aktywowana przez funkcję liniową. Ta aktywacja z kolei trafia do następnego poziomu jako wejście, a druga warstwa oblicza sumę ważoną na tym wejściu, a ono z kolei wystrzeliwuje w oparciu o inną liniową funkcję aktywacji.
Nieważne ile mamy warstw, jeśli wszystkie są liniowe w naturze, ostateczna funkcja aktywacji ostatniej warstwy jest niczym innym jak tylko liniową funkcją wejścia pierwszej warstwy! Zatrzymaj się na chwilę i pomyśl o tym.
To oznacza, że te dwie warstwy ( lub N warstw ) mogą być zastąpione przez jedną warstwę. Ach! Właśnie straciliśmy możliwość układania warstw w ten sposób. Bez względu na to, jak układamy, cała sieć jest nadal równoważna pojedynczej warstwie z liniową aktywacją ( kombinacja funkcji liniowych w sposób liniowy jest nadal inną funkcją liniową ).