I was assigned to implement multilayer neural network with back-propagation learning algorithm. The input was standardized text file (two examples) and one of my tasks was to create one additional example, learn the net and make some conclusions. I used Python language for the implementation.
Mým úkolem bylo naimplementovat vícevrstvou neuronovu síť v libovolném programovacím jazyce, vyzkoušet program na dvou příkladech a vymyslet příklad vlastní.
Zvolil jsem objektově-orientovaný jazyk Python, který je dostupný pro všechny systémy na platformě x86 (kromě jiných). Celý program sestává z dvou tříd a několika pomocných funkcí, spouští a nastavuje se z příkazové řádky:
python mbpnn.py konfigurační_soubor.txt [počet_kroků],
kde prvním parametrem je konfigurační soubor a druhým nepovinným parametrem je počet opakování (standardně nastaven na 40 tisíc kroků).
Výstupem programu je přehled výstupních parametrů a všechny spočtené výstupy testovacích vstupů. Ukázka:
Testovaci vzorky ['xor_result']:
['+0.000', '+0.000'] -> ['+0.007']
['+0.000', '+1.000'] -> ['+0.988']
['+1.000', '+0.000'] -> ['+0.988']
['+1.000', '+1.000'] -> ['+0.009']
Popis tříd je dostupný v podobě jednoho HTML souboru. Hlavní algoritmus je ve třídě NN reprezentující vlastní neuronovou síť. V konstruktoru se vytvoří základní struktury, což je seznam počtu elementů v jednotlivých vrstvách (n), matice aktivačních hodnot (a), matice vah (w) a matice posledních změn (c). Poslední matice se používá k výpočtu vlivu z předchozího kroku.
Metoda update provádí šíření signálu, metoda backPropagate pak zpětné šíření, výpočet chyby a úpravy vah. Obě na vstupu očekávají vektory (v případě jazyka Python konkrétně seznamy nebo n-tice), metoda backPropagate navíc obě konstanty ovlivňující proces učení. Metoda train pak provádí vlastní učení. Vstupem je jí počet kroků a zmíněné konstanty. Poslední metoda je metoda test, která provede otestování nad dodaným vzorkem (opět vektor) a výstup na obrazovku.
Třída ConfigFile je zodpovědná za korektní načtení textového souboru s konfigurací sítě a vzorky. Provádí také interpolaci vstupů a třídu lze reprezentovat textově pro informativní účely.
Formální popis všech metod a funkcí je pro přehlednost uveden na samostatné stránce.
Dva základní příklady (lekar.txt a pr_ob.txt) jsem doplnil o známý problém funkce XOR (xor.txt). Všechny tři soubory zpracuje program do několika tisíc kroků (tedy v řádech sekund), poslední problém (XOR) však vyžadoval odlišný přístup, který se nyní pokusím popsat.
Základní topologie je jednoduchá. Síť je vytvořena podle nastavení, přičemž ke vstupní a ke všem skrytým vrstvám je přidán jeden neuron navíc, jako práh. Jako aktivační funkce je brán sigmoid, váhy jsou nastaveny náhodně v intervalu [-1, 1] a hodnoty jsou interpolovány na interval [0, 1]. Již toto nastavení stačilo k velmi rychlému učení u obou zadaných příkladů, ale můj problém XORu konvergoval (resp. chyba konvergovala) velmi pomalu (nebo vůbec), v některých případech až za několik desítek minut. (Obvykle klesala chyba velmi pomalu až k nějakému prahu - tzv. brakepoint - po kterém již probíhala konvergence rychleji).
O mnoho lepšího výsledku jsem dosahoval po odstranění prahového neuronu z poslední skryté vrstvy. Topologie neuronové sítě se pak redukovala na pouhé 3-2-1 neurony (počty neuronů v jednotlivých vrstvách). To už byla konvergence lepší, velmi často i úspěšná (zhruba do 50 tisíc kroků). Stále jsem však nebyl spokojen.
Řešení jsem posléze nalezl v použití jiné aktivační funkce, která se hodila jak pro řešení zadaných testovacích dat, tak i na problém XOR. Hyberbolický tangens mi zredukoval počet kroků až na několik tisíc. Úspěšnost při řešení všech zadání byla 100%.
Zajímavé bylo, že nebylo nutné interpolovat vstup do jiného intervalu, než [0, 1]. Nejdříve jsem si myslel, že bude nutné použít interval jiný, jinak že nebude funkce tahn úspěšně konvergovat. Nebylo to však vůbec nutné.
$ python mbpnn.py xor.txt
NEURONOVA SIT:
Pocet vrstev: 2
Pocet vstupu: 2
Vstupy: [['x', '0', '1'], ['y', '0', '1']]
Pocty neuronu: [2, 1]
Koef. uceni: 0.500000
Koef. vlivu pr. kroku: 0.150000
Trenovaci mnozina: [[[0.0, 0.0], [0.0]], [[0.0, 1.0], [1.0]], [[1.0, 0.0], [1.0]], [[1.0, 1.0], [0.0]]]
Testovaci mnozina: [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]
Trenuji sit [3, 2, 1]
Chyba = 1.604523
Chyba = 0.016659
Chyba = 0.002823
Chyba = 0.001405
Chyba = 0.000924
...vynecháno...
Chyba = 0.000077
Chyba = 0.000074
Chyba = 0.000071
Chyba = 0.000069
Testovaci vzorky ['xor_result']:
['+0.000', '+0.000'] -> ['+0.000']
['+0.000', '+1.000'] -> ['+0.992']
['+1.000', '+0.000'] -> ['+0.992']
['+1.000', '+1.000'] -> ['-0.000']
Hyberbolický tangens: http://de.wikipedia.org/wiki/Tanh