Sztuczna inteligencja/SI Moduł 12

From Studia Informatyczne

Spis treści

Sieci neuronowe - wprowadzenie

Sieci neuronowe są jedną z wielu możliwych realizacji aproksymatora regresyjnego. Swoją popularność zawdzięczają w pewnej mierze analogiom biologicznym – można w nich upatrywać niezwykle uproszczonych modeli naturalnych struktur neuronowych. Przykładem sieci neuronowych, chyba najbardziej rozpowszechnionym, jest perceptron wielowarstwowy, któremu poświęcimy tę lekcję. Inne rozpowszechnione struktury sieci neuronowych to architektury ze sprzężeniem zwrotnym (tzw. sieci Hopfielda), realizujące układy dynamiczne, oraz architektury samoorganizujące (tzw. sieci Kohonena), realizujące algorytm grupowania. Tematyka sieci neuronowych jest dość dobrze opisana w literaturze uzupełniającej, do której odsyłamy bardziej zainteresowanych. Poniżej naszkicujemy podstawowe zagadnienia związane z wykorzystaniem perceptronu jako metody regresji oraz z metodami uczenia się stosowanymi dla tej sieci.

Definicja perceptronu wielowarstwowego

Perceptron wielowarstwowy jest aproksymatorem nieliniowym R^n \to R^m. Graficzna postać sieci jest następująca:

Grafika:SI M12 01.png

Węzeł grafu sieci odpowiada pojedynczemu neuronowi. Krawędź odpowiada połączeniu między neuronami (tzw. połączenie synaptyczne) – jest skierowana od wyjścia jednego do wejścia drugiego neuronu, co odpowiada jednokierunkowemu przepływowi danych.

Neuron działa w taki sposób, że dokonuje się ważonego sumowania wartości wejść, obliczając wartość, zwaną pobudzeniem h_i\,:

h_i = \sum_{j=1..n} w_{ij} x_j + w_{i0}\,

Wygodnie jest założyć, że neuron otrzymuje jeszcze jedno wejście x_0\, o wartości równej stale jedynce. Przy takim założeniu, pobudzenie da się zapisać prościej jako

h_i = \sum_{j=0..n} w_{ij} x_j\,

Wyjście neuronu powstaje w wyniku podania pobudzenia na funkcję aktywacji g\,:

y_i = g(h_i)\,

W przypadku sieci neuronowych, funkcja aktywacji ma kształt litery „s” – jest monotonicznie rosnąca z asymptotami poziomymi w nieskończonościach. Najczęściej przyjmuje się funkcję tangens hiperboliczny:

g(x) = \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}

przyjmującą wartość z zakresu \bf [–1,1], względnie funkcję logistyczną:

g(x) = \frac{1}{1+e^{-x}}

o wartościach z zakresu \bf [0,1].

Neurony zgrupowane są w warstwy w taki sposób, że między neuronami tej samej warstwy nie ma połączeń, a połączenia występują jedynie między neuronami sąsiadujących warstw.

Wyróżnia się warstwę neuronów wyjściowych (zwaną krótko warstwą wyjściową), których wyjście jest jednocześnie wyjściem z sieci. Pozostałe warstwy są nazywane ukrytymi, gdyż wyjścia neuronów w nich się znajdujących nie są „widoczne” na wyjściu sieci.

Dla neuronów wyjściowych można przyjąć, że funkcja aktywacji jest funkcją liniową.


Tak więc sieć neuronowa jest w swojej istocie pewnym wzorem, który da się przedstawić w formie graficznej. Wzór ten brzmi (w nieco nieformalnym zapisie):

y_i = \sum w_{ij} g \left ( \sum_{k} w_{jk} g \left ( ... \left ( \sum_t w_{st} x_t \right ) \right ) \right )

Wielokrotne ważone sumowanie i przekształcanie funkcją aktywacji ma miejsce tyle razy, ile jest warstw neuronów w sieci, dlatego w powyższym wzorze pojawiają się trzy kropki. Jak więc widać, wyjście sieci neuronowej jest funkcją jej wejścia, przy czym funkcja ta jest parametryzowana zestawem parametrów \mathbf w.

Interpretacja znaczenia parametrów sieci

Spróbujmy zrozumieć znaczenie poszczególnych parametrów, analizując przykładowe sieci zawierające jeden neuron wyjściowy z liniową funkcją aktywacji oraz jedną warstwę nieliniowych neuronów.

Na początek skoncentrujmy się na najprostszej sieci, mających jedno wejście i jedno wyjście (a zatem aproksymowana jest funkcja R \to R). Rozważmy sieć o dwóch neuronach ukrytych i jednym wyjściu liniowym. Opisuje ją wzór:

y=w_{10} + w_{11} g(w_{20} + w_{21} x) + w_{12} g(w_{30} + w_{31} x)\,

Znaczenie parametrów pojedynczego neuronu warstwy ukrytej jest następujące. Wartości proporcji w_{20}/w_{21}\,, w_{30}/w_{31}\, służą do przesuwania wykresu funkcji g\, wzdłuż osi OX. Z kolei parametry w_{21}, w_{31}\, wpływają na „stromość” wykresu funkcji g(h_2)\,, g(h_3)\,. Tak więc, manipulując oboma parametrami, jesteśmy w stanie uzyskać funkcję o różnej „stromości”, różnie położoną na osi OX.

Grafika:SI M12 02.png

Grafika:SI M12 03.png

Parametry warstwy wyjściowej służą określeniu stopnia „wymieszania” wyjść neuronów ukrytych. Im większa wartość wagi w_{1i}\,, tym większy mnożnik użyty do wykresu wyjścia neuronu i-tego (dodajmy, że przyjęcie ujemnej wagi w_{1i}\, powoduje odbicie wykresu funkcji wyjścia neuronu względem osi OX).

Grafika:SI M12 04.png

Z kolei w przypadku sieci o dwóch wejściach, aproksymującej funkcję R^2 \to R, z dwoma neuronami ukrytymi i jednym liniowym wyjściowym, mamy wzór:

y=w_{10} + w_{11} g(w_{20}+w_{21} x_1 + w_{22} x_2) + w_{12} g(w_{30} + w_{31} x_1 + w_{32} x_2)\,

Wagi w_{20}, w_{21}, w_{22}\, odpowiadają za sposób ułożenia w przestrzeni powierzchni, odpowiadającej funkcji g(w_{20} + w_{21} x_1 + w_{22} x_2)\, – powierzchnia ta ma poziomice ułożone wzdłuż prostej o równaniu w_{20} + w_{21} x_1 + w_{22} x_2 = 0\,, a w przekroju poprzecznym do poziomic ma kształt funkcji g\,. Zmieniając współczynniki wagowe, dokonujemy obrotów i przemieszczeń tej powierzchni, nie zmieniając jednak jej zasadniczego kształtu.

Wpływ wag perceptronu na jakość aproksymacji

Rzecz jasna wielce niepraktyczne byłoby dobieranie wartości współczynników wagowych sieci neuronowej „na oko” poprzez ręczne manipulacje tymi wartościami. Dlatego można zastosować to samo podejście, z którym mieliśmy już do czynienia w regresji liniowej i przeprowadzić regresję nieliniową.

Zasada jest podobna. Zakładamy, że sieć neuronowa ma jedno wyjście i wiele wejść. Oznaczymy aproksymowaną funkcję przez y(\mathbf{x}), natomiast wyjście sieci przez \hat y(\mathbf{x}). Dysponujemy pewnym zbiorem T = \{(\mathbf{x}, y(\mathbf{x}))\}, zwanym zbiorem uczącym. Zdefiniujmy funkcję reszt r(\mathbf{x}) = \hat y(\mathbf{x}) - y(\mathbf{x}). Zauważmy, że zarówno \hat y(\mathbf{x}), jak i r(\mathbf{x}) są funkcjami nie tylko wektora argumentów \mathbf{x}, ale i wektora wag \mathbf{w}.

Załóżmy, że miarą błędu jest błąd średniokwadratowy:

\left \| e(x) \right \| = \int r^2 (x)\, dx

W praktyce nie jesteśmy w stanie obliczyć powyższej całki, gdyż nie dysponujemy wartościami y(\mathbf{x}) dla dowolnej wartość argumentu, lecz tylko dla zbioru uczącego. Dlatego zamiast całką posługujemy się wartością błędu średniokwadratowego, obliczanego na zbiorze trenującym:

V(\mathbf{w}) = \frac{1}{n_T} \sum_T r^2(x)

gdzie n_T\, jest liczbą elementów zbioru trenującego. Jeśli nie będzie to budzić wątpliwości, wartość V(\mathbf{w}) będziemy dalej nazywać błędem sieci.

Teraz możemy już sformułować zadanie przeszukiwania, które leży u podstaw algorytmu uczenia sieci neuronowej. Przestrzeń przeszukiwań jest przestrzenią wektorów \mathbf w, a zatem jest to przestrzeń kartezjańska R^{n_w}\,, gdzie n_w\, jest liczbą wag sieci. W przykładach rozważanych powyżej wartość n_w\, jest równa odpowiednio: siedem (dla sieci z jednym wejściem) i dziewięć (dla sieci z dwoma wejściami). W nieco bardziej realistycznych przypadkach wartość n_w\, może się wahać od kilkudziesięciu do nawet kilkuset.

W przestrzeni przeszukiwań jest zdefiniowany funkcja, przyporządkowująca wektorowi wag \mathbf w wartość błędu V(\mathbf w). Przeszukiwanie ma na celu znalezienie takiego punktu (czyli wektora wag \mathbf w), dla którego wartość błędu V(\mathbf w) jest minimalna – uczenie sieci jest więc zadaniem minimalizacji błędu w przestrzeni wag aproksymatora.

Powstaje pytanie – jak stwierdzić, że dla konkretnego wektora wag w przypada minimum błędu V(\mathbf{w})? Jeśli wiemy, że jest dokładnie jedno takie minimum, a tak jest przy aproksymatorach liniowych, można obliczyć wartość gradientu błędu – będzie się on zerować w minimum. W przypadku aproksymatorów nieliniowych może być wiele minimów lokalnych, jednak zerowanie gradientu błędu jest warunkiem koniecznym istnienia minimum funkcji w punkcie.

Przystąpmy zatem do obliczenia gradientu. Dla neuronu wyjściowego (patrz rysunek) mamy:

\frac{\partial V}{\partial w_i} = \frac{1}{n_T} \sum_T 2 e(\mathbf x) \frac{\partial e(\mathbf x)}{\partial w_i} = \frac{2}{n_T} \sum_T e(\mathbf x) \frac{\partial \hat y(\mathbf x)}{\partial w_i}

a ponieważ dla każdego neuronu:

{\partial y_i \over \partial w_{ij}} = g'(h_i) {\partial h_i \over \partial w_{ij}} = g'(h_i) y_i

dostaniemy zatem:

{\partial V \over \partial w_i} = {2 \over n_T} \sum_T e(\mathbf x) g'(h) y_i

Grafika:SI M12 05.png

Dla neuronu warstwy ukrytej, którego wyjście jest dostarczane do neuronu wyjściowego (patrz rysunek), mamy:

{\partial V \over \partial w_{ij}} = {1 \over n_T} \sum_T 2 e(\mathbf x) {\partial e(\mathbf x) \over \partial w_{ij}} = {2 \over n_T} \sum_T e(\mathbf x) {\partial e(\mathbf x) \over \partial y_i} {\partial y_i \over \partial w_{ij}} = {2 \over n_T} \sum_T e(\mathbf x) {\partial \hat y(\mathbf x) \over \partial y_i} {\partial y_i \over \partial w_{ij}}

a ponieważ dla każdego neuronu:

{\partial y_i \over \partial y_j} = g'(h_i) {\partial h_i \over \partial y_j} = g'(h_i) w_{ij}

dostaniemy zatem:

{\partial V \over \partial w_{ij}} = {2 \over n_T} \sum_T e(\mathbf x) w_i g'(h) g'(h_i) y_i

Grafika:SI M12 06.png

Dla neuronu znajdującego się warstwę głębiej mamy:

{\partial V \over \partial w_{jk}} = {1 \over n_T} \sum_T 2 e(\mathbf x) {\partial e(\mathbf x) \over \partial w_{jk}} = {2 \over n_T} \sum_T e(\mathbf x) {\partial e(\mathbf x) \over \partial y_i} \sum_j {\partial y_i \over \partial y_j} {\partial y_j \over \partial w_{jk}} =
= {2 \over n_T} \sum_T e(\mathbf x) w_i g'(h) \sum_j w_{ij} g'(h_i) g'(h_j) y_k

Grafika:SI M12 07.png

Oznaczmy:

\delta(\hat y) = e(\mathbf x) g'(h)
\delta(y_i) = w_i \delta(\hat y) g'(h)
\delta(y_j) = \sum_j w_{ij} \delta{y_i} g'(h_j)\,

Możemy zatem zapisać:

{\partial V \over \partial w_i} = {2 \over n_T} \sum_T \delta(\hat y) y_i {\partial V \over \partial w_i} = {2 \over n_T} \sum_T \delta(y_i) y_j {\partial V \over \partial w_i} = {2 \over n_T} \sum_T \delta(y_j) y_k

O swoistej urodzie gradientu funkcji błędu względem wag sieci świadczy fakt, że do obliczenia gradientu względem wag warstwy ukrytej wystarczy informacja o gradiencie wag warstwy, która po niej następuje. Z tej przyczyny sposób obliczania gradientu jest nazywany algorytmem wstecznej propagacji błędu – błąd propaguje wzdłuż wag sieci w kierunku od wyjścia do wejścia.

Spełnienie warunku koniecznego istnienia minimum funkcji w punkcie nie daje oszacowania wartości funkcji błędu w tym punkcie. Powstaje zatem pytanie – czy dla dowolnej aproksymowanej funkcji istnieje sieć neuronowa, której błąd aproksymacji będzie nie większy niż pewien założony limit. Odpowiedzi na to pytanie udziela poniższe twierdzenie.

Twierdzenie o uniwersalnych właściwościach aproksymacyjnych

Załóżmy, że:

D \subset R^n jest zbiorem otwartym, skończonej miary
f: R^n \to R jest funkcją ciągłą, taką że dla każdego \mathbf e \in D \left | f(\mathbf x) \right | < \infty
\hat y(\mathbf x) jest funkcją postaci:
\hat y(\mathbf x) = \sum_{i=1..N} g(\mathbf{w}_i^T \mathbf x)
gdzie g(\mathbf x) jest funkcją ciągłą, ograniczoną i monotoniczną.

Wówczas:

dla każdego \epsilon > 0 istnieje taki zbiór wektorów wag \{\mathbf{w}_1,..., \mathbf{w}_N\}, że dla każdego x \in D

\left | \hat y(\mathbf x) - f(\mathbf x) \right | < \epsilon

Tak więc na mocy powyższego twierdzenia wiemy, że istnieje taka struktura sieci neuronowej, w której da się zrealizować aproksymację z dowolnie małym błędem. Analizując gradient, umiemy także stwierdzić, czy zestaw wag sieci jest minimum lokalnym funkcji błędu. Pozostaje rzecz najtrudniejsza – wyznaczyć taki zestaw wag, który jest nie tylko minimum lokalnym, lecz globalnym funkcji błędu.

Uczenie sieci

Jedną z najpowszechniej chyba stosowanych metod minimalizacji błędu sieci neuronowej jest przeszukiwanie przestrzeni wag według algorytmu wzrostu. Algorytm wychodzi z ustalonego arbitralnie wektora wag, po czym oblicza wektor gradientu funkcji błędu i jako nowy wektor wag przyjmuje wektor znajdujący się na półprostej wyprowadzonej w kierunku minus gradientu. Taką metodę nazywa się często metodą wstecznej propagacji błędu, a jej algorytm jest podany poniżej.

Algorytm uczenia perceptronu

t=0\,
inicjuj \mathbf{w}^{(0)}
powtarzaj
\mathbf{w}^{(t+1)} = \mathbf{w}^{(t)} - \eta \nabla V (\mathbf{w}^{(t)})
t = t + 1\,
dopóki \left \| \nabla V(\mathbf{w}^{(t)}) \right \| > \epsilon

Gradient funkcji błędu \nabla V(\mathbf{w}^{(t)}) można obliczyć, korzystając z zasady wstecznej propagacji błędu, sumując iloczyny \delta(y_j)y_k\, po wszystkich elementach zbioru trenującego T\,. Taki sposób uczenia nazywa się „trybem blokowym”. Istnieje jednak inna możliwość – zamiast wykorzystywać cały zbiór trenujący, można wziąć jedynie jego podzbiór T' \subset T (np. losowowybrany podzbiór, w szczególności podzbiór jednoelementowy), w każdej iteracji algorytmu uczenia wybierany na nowo, i obliczać gradient \nabla V(\mathbf{w}^{(t)}) dla elementów zbioru T'\,. Jeśli ponumerujemy elementy zbioru T\,, a podzbiór T'\, będzie jednoelementowy i będzie zawierać za każdym razem element z T\, o kolejnym numerze porządkowym, to taki tryb uczenia nazywa się uczeniem sekwencyjnym.

Przyjęcie trybu blokowego powoduje, że możliwie najdokładniej przybliżana jest wartość gradientu funkcji błędu. Jeśli funkcja błędu obliczana dla zbioru T\, ma „wąskie” minima lokalne – takie, których stwierdzenie nie jest możliwe po usunięciu choć jednego elementu zbioru T\, – to przypuszczalnie nie odpowiadają one minimum globalnemu. Posłużenie się jedynie podzbiorem T'\,, w dodatku zmieniającym się z iteracji na iterację, pozwala algorytmowi skoncentrować się na „szerokich” minimach funkcji błędu, co czyni metodę uczenia nieco odporniejszą na minima lokalne. Wtedy jednak należy się liczyć z faktem, że warunek zatrzymania – spadek normy gradientu błędu poniżej założonego poziomu – może nie być spełniony. Można ten problem ominąć, zwiększając wartość \epsilon\,, albo ustalić apriori liczbę iteracji algorytmu.

Powyższy algorytm wykonuje krok w kierunku minus gradientu; szerokość tego kroku jest stałą krotnością gradientu (reguluje to współczynnik uczenia \eta\,). Takie postępowanie może prowadzić do bardzo długotrwałego procesu uczenia, jeśli gradient funkcji błędu ma małą „długość” (norma gradientu jest niewielką liczbą). Małe wartości gradientu z kolei występują w dwóch sytuacjach: gdy neurony są bliskie nasyceniu (tzn. wartości gradientu funkcji aktywacji g'(h_i)\, są małe) albo gdy mamy do czynienia z minimum funkcji błędu (patrz poniższy rysunek).

Grafika:SI M12 08.png

W tym pierwszym przypadku, po wykonaniu ruchu w kierunku minus gradientu, znajdujemy się w nowym punkcie, w którym gradient ma najczęściej ten sam kierunek (a nierzadko i tę samą wartość) co poprzednio. Z tą sytuacją mamy do czynienia dla punktu w_1\,. W tym drugim przypadku, po wykonaniu podobnego kroku mamy najczęściej do czynienia ze zmianą kierunku i wartości gradientu (tak jest przykładowo dla punktu w_2\,). Obserwacje te stanowią motywację metody przyspieszenia algorytmu uczenia perceptronu, polegającej na dodaniu „momentu bezwładności”. Algorytm wygląda następująco:

Algorytm uczenia perceptronu z momentem bezwładności

inicjuj \mathbf w^{(0)}
\Delta \mathbf w^{(0)} = \eta \nabla V(\mathbf w^{(0)})
\mathbf{w}^{(1)} = \mathbf w^{(0)} - \Delta \mathbf w^{(0)}
t = 1\,
powtarzaj
\Delta \mathbf w^{(t)} = \eta \nabla V(\mathbf w^{(t)}) + \alpha \Delta \mathbf w^{(t-1)}
\mathbf w^{(t+1)} = \mathbf w^{(t)} - \Delta \mathbf w^{(t)}
t = t + 1\,
dopóki \left \| \nabla V(\mathbf w^{(t)}) \right \| > \epsilon

Współczynnik \alpha jest momentem bezwładności i spełnia warunek 0 < \alpha < 1\,.

Jeśli zachodzi pierwszy z omawianych wcześniej przypadków (gradient w przybliżeniu niezmienny wzdłuż kierunku swoich zmian), wówczas efektywny współczynnik uczenia wynosi w przybliżeniu \eta (1 + \alpha)^k\,, gdzie k\, jest liczbą kroków, w których gradient jest w przybliżeniu niezmienny. A zatem w kolejnych iteracjach algorytm uczenia wykonuje coraz większy krok, co pozwala przyspieszyć jego działanie. Z kolei gdy w kolejnych krokach gradient różni się, krok się zmniejsza. Przykładowo, dla \nabla V(\mathbf w^{(t)}) = - \nabla V(\mathbf w^{(t-1)}), efektywny współczynnik uczenia wyniesie \eta (1 - \alpha)\,, co pozwala na dokładniejszą lokalizację minimum lokalnego funkcji błędu.

Omawiane algorytmy uczenia sieci korzystają z warunku koniecznego istnienia minimum funkcji w punkcie. Oznacza to, że wektor wag \mathbf w^{(t)} będzie zdążać do takiego wektora, dla którego przypada minimum lokalne funkcji błędu, niekoniecznie będące minimum globalnym. Nie jest znany algorytm dający gwarancję znalezienia minimum globalnego dowolnej funkcji w R^n\,, a zatem nie możemy liczyć na gwarancję wyznaczenia optymalnego wektora wag. Można jednak zwiększyć prawdopodobieństwo wyznaczenia minimum globalnego, stosując np. techniki omawiane we wcześniejszej lekcji poświęconej metodom przeszukiwania wykorzystującym losowość.