Dzięki W.S. za odpowiedź.
Nie ma za co :)
Na laborkach pisaliśmy prosty programik do rozpoznawania literek wykorzystujący sieć jednowarstwową uczoną regułą Delta. O metodzie backpropagation tylko trochę usłyszałem na wykładzie i trochę też poczytałem na necie.
Nie myl reguły z metodą... Reguła delta odnosi się do pewnego sposobu uczenia sieci natomiast metoda po prostu uczy :). Zauważ skąd się bierze ta delta w tych wzorach... Funkcję błędu masz: E(k) = 1/2(y-z)2 (wole oznaczenie d zamiast z ale niech będzie :P). Z jest pewną stałą tj. naszym celem, natomiast y jest tym co zwraca sieć tj. Y = f(suma Wjf(suma WjiXi)) -> idąc dalej mamy: E(k) = 1/2(f(suma Wjf(suma WjiXi)) - z)2 -> jeśli obliczysz sobie stąd pochodną po Wj lub Wji to wyjdzie Ci Twoja delta itd. Chodzi mi o to, że metoda backpropagation jest zwykłą metodą gradientową (np. najszybszego spadku) natomiast reguła delta jest w nią tak jakby "wpisana"...
Co do wektora uczącego to na początek będę to tylko zdjęcia znaków "idealnych" (śćiągnięte z wikipedi)
W sumie O.k. -> jak na jakąś pracę szkolną. Pamiętaj, że w takim wypadku Twoja próba wynosić będzie jedynie 43 dane
stowrzyć dodatkowe znaki drogowe przedstawione pod różnym kątem nachylenia.
Tak jak napisałem wcześniej ja się zajmuję SSN pod innym kontem i rozpoznawanie wzorców mnie raczej nie interesuje jednak zastanawiam się co Ty chcesz stworzyć? tzn. jak to ma wyglądać i do czego służyć? Bo jeśli zadaniem programu będzie jedynie próba rozpoznania znaku, który sam jej podasz w odpowiedniej wielkości to w sumie chyba będzie O.k. ale takie podejście jest chyba mało praktyczne ^^
Co do struktóry którą opisałeś to nie widzę w niej warstwy wejściowej??
A co uważasz za "warstwę wejściową"? Bo chyba masz jakąś inną definicję od mojej :). Sieć ma 3 rodzaje warstw: wejściową (zmienne wejściowe), ukrytą (Twoja funkcja aktywacji) oraz wyjściową (to co zwraca) tj. warstwa wejściowa to są te twoje 2500 zmiennych; ukryta 100 neuronów i wyjściowa 43 wyjścia.
Wspomniałeś tylko o ilości neuronów w warstwie ukrytej i warstwie wyjściowej Jaka powinna być ilość neuronów dla pierwszej warstwy??
to zależy od problemu i możliwości dojścia do tych zmiennych :) -> w dodatku ty masz zmienne binarne...
Mam wrzucić taki sam sygnał (2500 zmiennych reprezentujących dany znak) dla każdego neuronu w pierwszej warstwie?? Jeśli nie to co mam ustawić na wejściach pozostałych neuronów w pierwszej warstwie??
Jeśli dobrze zrozumiałem to tak.
Żeby uprościć powiedzmy, że masz 9 zmiennych, które przyjęły następującą wartość: Z = [0,0,1,0,1,1,1,0,1]^T (T - od transponowana ^^). Teraz gdy masz powiedzmy 3 neurony to do każdego wrzucasz ten sam wektor ze zmiennymi. Pamiętaj, że w każdym neuronie są inne wagi dlatego każdy neuron zwróci inną wartość.
Ja to rozwiązuję w ten sposób, że tworzę tablicę dwuwymiarową z wagami z tym, że jeden wymiar jest dla j-neuronu a drugi dla i-zmiennej np. double zmienne[3][9]; :)
Ok dzięki za uwagę, będę musiał jeszcze raz wygenerować moje pliki txt zaiwerające zbinaryzowane ciągi reprezentujące moje znaki, lub użyję funkcji sigmoidalnej unipolarnej. A jeśli będę używał funkcji unipolarnej (0,1) to wtedy wagi dla całej sieci neuronowej muszę równiejż losować z zakresu (0,1) ??
Zacznę od końca: Nie, wagi zawsze powinny być ujemne i dodatnie! najlepiej właśnie z przedziału (-1,1).
Chyba funkcja sigmoidalna unipolarna byłaby lepsza w tym wypadku.
Zastanawiam się również czy rzeczywiście konieczne jest zmienianie tych zmiennych na -1 i 1... Moje obawy dot. tego, że jak na wyjściu sieć wskaże Ci -1 a powinno być 1 to błąd wyjdzie Ci 4 (y-z)2 -> (-1-1)2 = 4 Natomiast jak sieć zwróci Ci 1 a powinno być 0 to błąd wyniesie 1 a także gdy sieć zwróci Ci -1 to błąd również będzie 1 (-1/1 - 0)^2 = 1 => dlatego chyba jednak powinieneś właśnie albo zmienić funkcję albo dane wzorcowe wprowadzać w postaci -1 i 1...
Właśnie sobie uświadomiłem, że źle się zrozumieliśmy: zmienne możesz wprowadzać w zakresie 0,1 nawet przy funkcji bipolarnej natomiast w wektorze z danymi powinieneś używać liczb -1 i 1 - znowu namieszałem ^^. Może jeszcze inaczej załóżmy, że w k-próbie uczysz sieć np. znaku STOP dlatego twoje z w funkcji celu (E(k) = 1/2(y-z)2) dla STOP-u wynosi 1 i -1 dla reszty znaków tj. gdy założymy, że pierwszy neuron wyjściowy odpowiada za znak stopu, drugi za zakaz wjazdu a trzeci za "nie parkować" a twoje neurony zwróciły wynik w postaci: Y1 = 0,23, Y2 = -0,12, Y3 = 0,43 (Y1,2,3 odpowiadają wyjściom neuronów pierwszego drugiego i trzeciego) to twój błąd policzysz następująco: E(k1) = (0,23 - 1)2, E(k2) = (-0,12-(-1))2 i E(k3) = (0,23 - (-1))2 -> mam nadzieję, że jest to zrozumiałe :)
więc jeśli wykonam 1000 razy naukę, za każdym razem podstawiając kolejny znak z ciągu uczącego to czy wykonanie tych 1000 kroków jest wykonaniem jednej epoki?? A nauczanie kończymy po wykonaniu określonej ilości epok lub jeśli błąd jest dostatecznie mały?
Tak, jeśli masz próbę np. 1000 zdjęć to przeanalizowanie wszystkich to jedna "epoka" tzn. musisz uczyć sieć wiele razy na tej samej próbie aż się nauczy.
Zazwyczaj naukę kończy się po określonej liczbie iteracji - w zadaniach praktycznych nie wiesz jaki błąd jest wystarczający, żeby przerwać naukę. Zazwyczaj daje się również ograniczenia czasowe do nauki (pamiętaj, że im większa sieć (również im więcej zmiennych) tym proces nauki trwa dłużej - a przy tylu zmiennych co Ty masz (2500) może on trwać latami ^^ -> dlatego nie wiem, czy nie powinieneś skorzystać z jakiejś liniowej sieci np. RBF lub SVM chociaż z tą drugą nie miałem do czynienia :/).
Nie bardzo wiem w którym miejscu mi będzie potrzebna suma wszystkich pochodnych. Co masz na myśli że mam odjąć "jakąś" jej część??
zobacz swoje zdjęcie ze wzorami ^^. Ten dziwny znaczek (eta) przed deltą to jest właśnie ta "część" :)
Może jeszcze inaczej: (niestety nie ma tu LaTeXa :/) wzór na naukę masz taki: Wij(k+1) = Wij(k)+ep(k) (e -> to siła zmiany (właśnie ta eta) natomiast p to kierunek (pochodna) :P)). Teraz mamy wzór na błąd (funkcja celu): E(k) = suma(dla każdego wyjścia od i=1 do M=np.43) 1/2(Ykm-Zk)^2. Ykm (dla okresu k i neuronu wyjściowego m) wynosi: Ykm = f(suma Wjmf(suma WijXi))
gdzie f to oczywiście funkcja np. bipolarna. Zauważ, że obliczając pochodną po Wjm będziesz "ignorował" pozostałe wagi Wj (traktując je jako stałe) natomiast inaczej jest przy obliczaniu wag Wji, gdyż one mają wpływ na każdy neuron warstwy wyjściowej - dlatego obliczając pochodną po Wij z w/w funkcji będziesz musiał w rzeczywistości z sumować pochodne z każdego neuronu wyjściowego (mam nadzieję, że się nie rąbnąłem w tych dywagacjach :D)
4.3. Jeżeli skupimy się na wyliczaniu błędu w warstwie ostatniej dla m-tego neuronu to wykonujemy następujące obliczenia?:
- Błąd_m = Y'_m * (Y_m - Z_m)
czyli błąd dla m-tego neuronu to iloczyn: pochodnej m-tego neuronu z różnicą odpowiedzi neuronu z wzorcem (1 jeśli neuron rozpoznaje prawidłowy znak lub -1 jeśli to nie jest znak rozpoznawany przez dany neuron)
Nie myl obliczania błędu z tą regułą delta i całą nauką sieci. Błąd to zwyczajna różnica między wartością zadaną a wynikiem naszej sieci (najczęściej podniesiony do kwadratu -> co wynika z rozkładu normalnego ale to już inna bajka :) ). Może lepiej powtórzę to co napisałem wcześniej tj. rozwinę przykład:
załóżmy, że uczymy sieć 3 znaków. Do sieci wrzucamy 4 zmiennych boolowskich (0 lub 1). sieć ma 2 neurony ukryte i 3 wyjściowe. Znaki, których uczymy to: STOP-u (za który będzie odpowiedzialny pierwszy neuron wyjściowy), zakaz wjazdu (2 neuron) i nakaz jazdy prosto (3 neuron). Powiedzmy, że mamy 5 zdjęć znaków (2 stopu, 2 zakazu i 1 nakazu). W związku z powyższym nasz wektor uczący będzie wyglądał np. tak: dane_uczące = {STOP,ZAKAZ,STOP, ZAKAZ, NAKAZ} -> celowo zmieniłem kolejność bo nie musi być taka sama ale tak będzie łatwiej zrozumieć :].
Dlatego, że mamy tylko 5 danych (zdjęć) sieć będzie się uczyć tylko na ich podstawie.
teraz tak:
rozpatrujemy pierwsze zdjęcie:
nasz wektor wejściowy wygląda np. tak: [1,0,0,1]
- Wrzucamy ten wektor do każdego (czyli do dwóch) neuronu (tj. mnożymy każdą zmienną przez wagę w każdym neuronie (łącznie będzie ich 8 -> (2x4)
- sumy tych iloczynów w każdym neuronie wrzucamy do funkcji aktywacji
- funkcja zwraca nam jak jakąś liczbę (w bipolarnej będzie to liczba z zakresu (-1,1)
- załóżmy, że pierwszy neuron zwrócił wynik 0.37 a drugi -0.12
- wyniki z tych wyjść wrzucamy do neuronów wyjściowych mnożąc je wcześniej przez wagi (ukryte) stojące przy każdym neuronie (łącznie będzie ich 6 -> 2x3 = 6
- sumy przemnożonych sygnałów przez wagi wrzucamy do funkcji aktywacji w każdym neuronie. Sieć zwraca nam powiedzmy następujące wyniki: Y1 = 0.12, Y2 = -0.65, Y3 = 0.77
- Liczymy nasz błąd (pomijam 1/2 przed błędem) tj. E(k) = suma: (0.12-1)2 + (-0.65-(-1))2 + (0.77-(-1))^2 = ...
Uwagi do pkt-u 7:
przy liczeniu błędu w pierwszym neuronie wartość Y1 odejmujemy od 1 tj. nasze Z = 1 (gdyż ten neuron jest odpowiedzialny za znak STOP-u, który teraz rozpatrujemy)
W pozostałych neuronach od Y2 i Y3 odejmujemy wartość -1 -> zauważ, że gdybyśmy odjęli te wartości od zera (0) to wynik błędu dla Y2, który jest bliski poprawnej odpowiedzi (-0.77 znaczy, że na pewno nie jest to znak ZAKAZ-u) byłby większy od Y3, a który jest znacznie dalej od poprawnej odpowiedzi (tj. stwierdzenia, że nie jest to znak NAKAZ-u)
- Obliczamy pochodne i zmieniamy wagi Wj i Wji w każdym neuronie
- ze zmienionymi wagami rozpatrujemy kolejne zdjęcie tj. znak ZAKAZ-u
- nasze nowe zmienne wejściowe wynoszą powiedzmy: [0,1,1,1]
reszta jest identyczna poza liczeniem błędu tj. załóżmy, że nasze wyniki w tej iteracji wyniosły: Y1 = 0.45, Y2 = -0.9, Y3 = -0.15
to licząc błąd będziemy mieli: E(k) = suma: (0.45 - (-1))2 + (-0.9-1)2 + (-0.15 - (-1))^2
Jak zauważyłeś teraz rozważając wynik z pierwszego neuronu tj. Y1 odejmujemy od niego -1 (a nie 1 jak poprzednio gdyż teraz rozważamy inne zdjęcie) a dopiero w drugim mamy różnicę między wynikiem a 1
Mam nadzieję, że jest będzie to już jasna - trochę się rozpisałem (mam nadzieję, że nie za bardzo chaotycznie :)
Pozdrawiam,
S.W.
P.S.
Na którym roku i na jakim kierunku jesteś?</quote>