Neuronové sítě Cascade Correlation
Transkript
Neuronové sítě Cascade Correlation
České vysoké učení technické v Praze Fakulta elektrotechnická Diplomová práce Neuronové sítě Cascade Correlation Minh Duc Do Vedoucí práce: Ing. Jan Drchal Studijní program: Elektrotechnika a informatika strukturovaný magisterský Obor: Výpočetní technika Květen 2009 1 2 Poděkování Mé poděkování patří především vedoucímu práce, panu Ing. Janu Drchalovi a oponentovi, panu Ing. Pavlu Kordíkovi Ph.D.za věcné připomínky během práce a za čas, kterou tomu věnoval. 3 Prohlášení Prohlašuji, že jsem práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém seznamu. Nemám závažný důvod proti užití tohoto školního díla ve smyslu § 60 Zákona č. 121-2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon). V Praze dne 4 5 Abstract The goal of this work is to implement a general library in language Java for neural network, which would be using the learning algorithm Cascade-Correlation. Cascade-Correlation itself uses other learning algorithms and during the learning process it changes the structure of the neural network by adding new hidden layers. This learning algorithm is supposed to work faster in compare to the widely known Backpropagation. It should also provide better results in the case of more difficult problems. At the end the librabry will be integrated into the project GAME for data mining as one of an alternative learning modul. Abstrakt Cílem této práce je seznámit se s problematikou neuronových sítí a vytvořit obecně použitelnou knihovnu v programovacím jazyce Java realizující neuronovou síť využívající učícího algoritmu Cascade-Correlation. Cascade-Correlation interně používá jiné učící algoritmy a během učení mění strukturu neuronové sítě přidáváním nových skrytých vrstev. Tento algoritmus by měl konvergovat rychleji než běžný Backpropagation a hlavně lépe řešit složitější problémy. Nakonec je třeba tuto knihovnu začlenit do již existujícího projektu GAME pro dolování dat jako jeden z alternativních učících modulů. 6 Obsah 1. Úvod ............................................................................................................................... 10 2. Popis problému a specifikace cíle ............................................................................... 111 3. Teoretický úvod............................................................................................................ 122 3.1 Umělé neuronové sítě ......................................................................................... 122 3.2 Učení sítě ............................................................................................................ 144 3.2.1 Trénovací množina........................................................................................ 144 3.2.2 Kdy je síť naučena ........................................................................................ 155 3.2.3 Algoritmus Backpropagation (zpětného šíření) ............................................ 155 3.2.4 Algoritmus Quickpropagation ........................................................................ 19 3.2.5 Algoritmus R-propagation ............................................................................ 222 3.2.6 Algoritmus Cascade Correlation................................................................... 255 4. Realizace ......................................................................................................................... 29 4.1 Analýza a návrh řešení............................................................................................. 29 4.1.1 Neuronová síť ................................................................................................. 29 4.1.2 Aktivační funkce............................................................................................. 32 4.1.3 Učící algoritmy ............................................................................................. 322 4.1.4 Výpočet parciální derivace ........................................................................... 344 4.1.5 Implementační detaily................................................................................... 345 5. Testování....................................................................................................................... 366 5.1 Testování funkčnosti.............................................................................................. 366 5.1.1 Problém XOR................................................................................................ 377 5.1.2 Problém dvojité spirály ................................................................................. 388 5.2 Testování v GAME .................................................................................................. 42 5.2.1 Testování Cascade Correlation v GAME ..................................................... 422 5.2.2 Cascade Correlation vs Backpropagation ..................................................... 488 6. Závěr ............................................................................................................................... 51 7. Seznam literatury......................................................................................................... 533 A. Uživatelská příručka .....................................................................................................55 A.1 Načtení dat ze souboru............................................................................................ 555 A.2 Tvorba neuronové sítě............................................................................................. 555 A.3 Generování výstupu a získání chyby ...................................................................... 577 A.4 Trénování sítě.......................................................................................................... 577 Obsah CD............................................................................................................................ 60 7 Seznam obrázků 3.1.1 základní model neuronu Mculloh-Pittsův percpeton 13 3.1.2 aktivační funkce 13 3.2.3.1 algoritmus zpětného šíření 16 3.2.6.1 algoritmus Cascade Correlation 26-27 4.1.1.1 diagram tříd neuronové sítě 30 4.1.2.1 hierarchie aktivačních funkcí 32 4.1.3.1 hierarchie učících algorimů 33 4.1.4.1 hierarchie funkcí pro výpočet parciálních derivací 34 5.1.1.1 klasifikační graf pro XOR 37 5.1.2.1 zobrazení spirály v kartézské rovině 38 5.1.2.2 klasifikační graf pro dvojtou spirálu 39-41 5.2.1.1 strukturní model setosy (Cascade Correlation neurony) 43 5.2.1.2 3D visualizace modelu setosy (Cascade Correlation neurony) 44 5.2.1.3 3D projekce výstupu setosy (Cascade Correlation neurony) 44 5.2.1.4 strukturní model versicolor (Cascade Correlation neurony) 45 5.2.1.5 3D visualizace modelu versicolor (Cascade Correlation neurony) 45 5.2.1.6 3D projekce výstupu versicolor (Cascade Correlation neurony) 46 5.2.1.7 strukturní model virginica (Cascade Correlation neurony) 46 5.2.1.8 3D visualizace modelu virginica (Cascade Correlation neurony) 47 5.2.1.9 3D projekce výstupu virginica (Cascade Correlation neurony) 47 5.2.2.1 strukturní model setosy (Cascade Correlation a Backpropagation neurony 49 5.2.2.2 strukturní model versicolor(Cascade Correlation a Backpropagation neurony) 49 5.2.2.3 strukturní model virginica (Cascade Correlation a Backpropagation neurony) 50 8 9 Kapitola 1 1. Úvod 0B V této práci se zabývám neuronovými sítěmi a jejich trénovacími metodami. Hlavní pozornost jsem věnoval učícímu algoritmu Cascade Correlation, který vyvinul Scott E. Fahlman. Cascade Correlation je jakýsi meta-algoritmus, který interně používá jiné učící algoritmy. Narozdíl od jiných učících algoritmů (Backprogation, Resilient-propagation...) Cascade Correlation modifikuje samotnou strukturu neuronové sítě. Zatímco je zcela běžné během učení korigovat váhy za účelem minimalizace chyb, Cascade Correlation v každé iteraci přidává také novou vrstvu skrytých neuronů a tímto způsobem se vytvoří kaskádní struktura. Implementovaný Cascade Correlation bude tvořit jádro knihovny, která má být posléze součástí projektu GAME. Projekt GAME je vyvíjená na katedře výpočetní techniky ČVUT. Je to je nástroj pro vytěžování dat. Používá evoluční metody k vytvoření modelů, zahrnuje optimalizační metody a visualizační prostředky. GAME používá různé učící algoritmy a kombinuje je navzájem, aby dosáhl co nejlepších výsledků. Přestože prvotním účelem aplikace je jeho použití v rámci projektu GAME, chtěl jsem, aby knihovna mohla být samostatně použitelná třeba jako demonstrativní ukázka, na které by si studenti mohli v praxi vyzkoušet funkčnost neuronových sítí, z tohoto důvodu jsem realizoval Backpropagation, Quickpropagation a Resilient-Propagation zcela odděleně od Cascade Correlation, mohou proto být použity samostatně. Rovněž jsem usiloval o co největší flexibilitu a znovupoužitelnost, aby v budoucnu nebyl problém v případě nutnosti knihovnu jednoduše rozšířit o nové funkce. Proto jsem dbal na důsledné zavádění interfaců, toto se sice může zdát jako těžkopádné řešení, učinil jsem ale tak kvůli zachování obecnosti a univerzálnosti řešení. Knihovna je implementována v Javě. Volba použitého jazyka byla jednak vynucena faktem, že GAME je napsán v Javě, ale ani platformově nezávislost jazyku Java není nezanedbatelná. Je sice možné naprogramovat knihovnu v jiném jazyce a poté ji propojit s GAME za použití „wrapperů”, bylo by to však zbytečně komplikované. Pro interní proměnné a funkce používám anglické termíny, neboť se mi zdají výstižnější a mnohdy stručnější. 10 Kapitola 2 2. Popis problému a specifikace cíle 1B Existuje mnoho učících algoritmů neuronových sítí, například klasický Backpropagation, Quickpropagation atd.. Ale právě Backpropagation se vyznačuje pomalou konvergenci a malou efektivitou zejména u větších problémů, proto jsem se zaměřil v této prácí na algoritmus Cascade Correlation, jehož autorem je Scott E. Fahlman. Tento algoritmus se dokáže velmi dobře poprat s známými nedostatky Backpropagationu jako step-size problém a moving-target problém (konkrétněji v dalších částech) a hlavně při složitějších úloh, které jsou pro Backpropagation prakticky neřešitelné, vykazuje dobré výsledky s rozumným počtem skrytých neuronů. Hlavním cílem je navrhnout a implementovat obecnou knihovnu pro neuronové sítě. Následně realizovat a na tuto síť vyzkoušet algoritmus Cascade Correlation. Tento algoritmus sám používá jiné učící algoritmy, je tedy jakýmsi meta-algoritmem Nejjednodušší volbou je Backpropagation. Tento algoritmus je zde z demonstračních a testovacích důvodu také implementován, avšak z již výše uvedených důvodů vyplývá, že Backpropagation je pro Cascade Correlation nevhodný. Scott E. Fahlman ve své práci doporučuje Quickpropagation. Ja jsem se rozhodl vyzkoušet kromě Quickpropagation i Resilient-Propagation považovaného za asymptoticky stejně rychlý jako Quickpropagation a navíc je parametrově málo závislý, tedy že volba parametrů tolik neovlivňuje úspěšnost algoritmu. Dalším cílem je co nejvíce udělat knihovnu obecnou a flexibilní vůči možným budoucím změnám. To by usnadnilo pozdější rozšíření a začlenění nových funkcí nebo algoritmů. 11 Kapitola 3 3Teoretický úvod 2B 3.1 Umělé neuronové sítě Umělé neuronové sítě vycházejí z biologického základu, tedy z neuronového systému biologických organismů. Skutečné neuronové sítě jsou však mnohem dokonalejší. Stejně jako v biologickém světe se umělá neuronová síť skládá z množství základních jednotek nazývaných umělé neurony, které jsou navzájem různě propojené synapsemi. Zatímco v biologických organismech neuronovou síť tvoří miliardy neuronů, v umělé verzi je tento počet podstatně nižší a to je další nedostatek umělých neuronových sítí. Umělá neuronová síť je určena pro distribuované paralelní zpracování dat. Obecně se můžeme na neuronovou síť dívat jako na funkci T, která transformuje vstupní vektor X na výstupní vektor Y . Y T(X ) Výkonným prvkem je neuron. Budu se zde zaměřovat pouze na neuron typu perceptron. Neuron může mít více vstupů, ale vždy jen jeden výstup. Vstupy mohou být vnější vstupy nebo informace předané jinými neurony z předchozí vstvy. Neuron tedy zpracovává vstupní údaje a výslednou informaci vystaví na výstup. Nejčastěji zpracování vstupů probíhá podle následujícího vztahu n Y S ( wi xi ) i 1 kde, y je výstup neboli aktivita neuronu, xi je i-tý vstup neuronu, vstupů je celkem N, wi přestavuje hodnotu i-té synaptické váhy, S je přenosovou funkcí neuronu Θ představuje prahovou hodnotu 12 w1 w2 . . .. .. wn-1 wn Output y Θ Obr. 3.1.1:Základní model neuronu Mculloch-Pittsův perceptron Výraz v závorce se někdy označuje jako vnitřní potenciál neuronu. Přenosová funkce je někdy taky označena jako aktivační funkce, převádí vnitřní potenciál neuronu do definovaného oboru výstupních hodnot. Nejčastěji se lze setkat s těmito funkcemi (viz. Obrázek 3.1.2): lineární, dvouhodnotová, sigmoida a hyperbolická tangenta. Obr. 3.1.2a: lineární aktivační funkce Obr. 3.1.2b: dvouhodnotová aktivační funkce Obr. 3.1.2c: sigmoida Obr. 3.1.2d: hyperbolická tangenta 13 Matematický zápis sigmoidy je: S ( x) 1/(1 e x ) 3.2 Učení sítě Hlavní vlastností neuronových sítí je jejich schopnost se učit. Při učení dochází v neuronové síti ke změnám, kterými se síť adaptuje na řešení daného problému. Učení se realizuje nastavováním synapsí, popřípadě změnou struktury sítě. Pomocí nastavení vah na synapsích se reguluje síla vstupních signálů přenášených synapsemi. Vahám se na začátku přidělí počáteční hodnoty, které mohou být zvolené náhodně nebo vybrané podle nějakého podobného příkladu. Učení může být dvojího druhu. Existuje učení s učitelem a bez učitele. Při učení s učitelem jsme schopni určit, který výstup je správný. Váhy pak modifikujeme zpětně použitím algoritmu podle toho, jak moc se skutečný výstup liší od námi očekávaného výstupu. Poté se síti předloží nový vstup a celý proces se zopakuje. Učení bez učitele nemá žádné vnější kritérium správnosti. Algoritmus učení je navržen tak, že hledá ve vstupních datech vzorky se společnými vlastnostmi. Proces učení lze rozdělit na několik typů podle toho, v kterém okamžiku, respektivě po kolika trénovacích vzorcích, jsou váhy modifikovány. Jedná se o dávkový (batch), inkrementální (incremental) a stochastický (stochastic). Zatímco inkrementální metoda upravuje váhy neuronových spojení po předložení každého trénovacího vzoru, dávková metoda s tímto krokem čeká až po předložení celé trénovací množiny. U stochastické metody se váhy sice upravují rovněž po každém vzoru, tyto vzory jsou však vybírány náhodně. Obecně je učení dávkovou metodou spíše rychlejší než inkrementální, ale její nevýhodou je větší paměťová náročnost. 3.2.1 Trénovací množina 12B Všechny platné vstupní vektory, které síti předkládáme, tvoří vstupní množinu. Ta je v některých případech malá, nebo alespoň spočetná, jindy může mít dokonce nekonečný počet prvků. Velikost vstupní množiny hraje důležitou roli. Velmi často není možné 14 předložit celou vstupní množinu a musíme vhodně vybrat reprezentanty vystihující prostor vstupních dat. Této podmnožině se říká trénovací nebo učící množina. Výběr vzorů z učící množiny nemusí být sekvenční, ale také náhodný. U některých problémů je vhodné, aby se některé vzory předkládaly síti častěji než jiné. Časový interval, během kterého síti předložíme každý vzor učící množiny alespoň jednou, se nazývá epocha. K naučení sítě obvykle je potřeba stovky až tisíce epoch. 3.2.2 Kdy je síť naučena 13B Síť je naučena, je-li splněna předem zadaná podmínka. Tou může být například dosažení předepsaného počtu trénovacích epoch. Mnohem lepší podmínkou samozřejmě je dosažení velké shody sítě s nějakým exaktně zadaným kritériem, který nejčastěji bývá pokles globální chyby pod předem stanovenou mez. Výstup neuronové sítě se bude vždy odchýlovat od očekaváného výstupu. Jak bychom tedy měli tyto výstupy „zaokrouhlovat”, od které meze bychom mohli daný výstup považovat za očekávaný výstup. Scott E. Fahlman navrhuje převzít takzvané kritérium threshold and margin používané ve světě logických obvodů, kde je-li rozsah možných výstupních hodnot od 0.0 do 1.0, pak hodnoty menší než 0.4 se považují za 0.0 a hodnoty větší než 0.6 se považují za 1.0. Je-li rozsah výstupních hodnot jiný, stačí pouze rozpětí přeškálovat. 3.2.3 Algoritmus Backpropagation (zpětného šíření) 14B Tento algoritmus je vhodný pro učení vstevnatých sítí s dopředným šířením signálu. Učení probíhá metodou učení s učitelem. Podle způsobu, jakým se vypočítávají váhy, je to algoritmus iterační. Algoritmus učení zrazorněném na Obr. 3.2.3.1 lze shrnout do následujícího pseudokódu: repeat repeat vyber_vzor_z_trénovací_množiny; přilož_vybraný_vzor_na_vstupy_sítě; vypočti_výstupy_sítě porovnej_výstupy_s_požadovanými_hodnotami modifikuj_váhy until vybrány_všechny_vzory_z_trénovací_množiny until globální_chyba < kritérium 15 Obr. 3.2.3.1 diagram algoritmu zpětného šíření Globální chybou je v algoritmu míněna např. střední kvadratická odchylka (RMS) počítaná přes všechny vzory trénovací množiny: ERMS m (y mn dmn ) 2 , n kde n je počet neuronů výstupní vrstvy a m mohutnost trénovací množiny. Algoritmus zpětného šíření používá gradientní sestup, konkrétně takto minimalizuje tzv. energetickou funkci sítě, která je definována následovně: E 1 n ( yi di )2 , 2 i 1 kde n je počet výstupů sítě, yi je i-tý výstup a di je i-tý požadovaný výstup. Budu dále předpokládat, že jednotlivé neurony používají přenosovou funkci sigmoidu. Tento předpoklad se uplatní především ve výrazech parciální derivace při vysvětlování algoritmus zpětného šíření, vždy ale uvedu i obecný tvar, do kterého by bylo možné, v případě použití jiné přenosové funkce, dosadit příslušný výraz pro zvolenou přenosovou funkci. Vycházím tedy z toho, že chování neuronů popisuje následující rovnice: 16 n y S ( wi xi ) i 1 S ( ) 1 , 1 e kde γ je koeficient, který určuje strmost křivky v počátku souřadné soustavy. Vypočítáme-li pariální derivace pro všechny váhy, dostaneme vektor, který určuje lokální gradient energetické funkce. Energetická funkce je funkcí složenou, proto musíme parciální derivaci rozepsat jako: E E yio i wijo yio i wijo E E ( yi o di ) kde yi o je derivací energie, tedy yi o yi o i o je derivací sigmoidy výstupních neuronů. Tuto derivaci nyní provedu. Jde opět o složenou funkci (racionálně lomená funkce, derivuje se podle proměnné v exponentu. Výsledkem je vztah: yi o yi o (1 yi o ) o i Dále platí: n i o wijo y hj io j 1 2io y hj wijo Složíme-li tyto dílčí výsledky dostáváme: 2 E ( yio di ) yio (1 yio ) y hj o wij 17 Tímto jsme získali hledaný lokální gradient energetického prostoru, ze kterého vypočteme hodnoty, kterými budeme váhy upravovat. Vektor přírůstku W vypočteme ze vztahu W E , který má platnost pro všechny váhy v neuronové síti, tedy nejen pro výstupní vrstvu. Jinak řečeno váhy upravujeme vždy η násobkem záporné hodnoty gradientu. Změna známenka je nezbytná, jelikož gradient má směr k vrcholu (maximu) a my hledáme údolí(minimum). Pro výstupní vrstvu platí: wijo (t ) io (t ) y hj (t ) io (t ) io (t ) kde io (t ) ( yio di ) S `( ) Koeficient η určuje rychlost učení (learning rate) a určuje tzv. velikost kroku (step-size). Váhy a prahy se ve skrytých vrstvách počítají na základě stejných úvah jako váhy a prahy vrstvy výstupní. Problém ale spočívá v tom, že neumíme stanovit chybu výstupu. Nejsou totiž známy hodnoty, kterých mají výstupy neuronů skrytých vrstev nabývat. Pro každou 2 E váhu skryté vrstvy spočteme wh ij dle vztahu: 2 E E yko ko yih ih wijh yko ko yih ih wijh ih skryté vrstvy vypočteme tak, že vynásobíme chybu ko výstupní vrstvy (popřípadě následující skryté vrstvy) hodnotou příslušného váhového koeficientu dle následující rovnice: n ih yih (1 yih ) wkio ko k 1 18 ih (t ) ih (t ) wijh (t 1) wijh (t ) wijh (t ) ih (t 1) ih (t ) ih (t ) xj(t) je j-tý výstup neuronové sítě (pouze pokud se jedná o skrytou vrstvu bezprostředně následující vstupy sítě) nebo j-tý výstup předcházející skryté vrstvy (ostatní skryté vrstvy). Výraz pro výpočet lze zobecnit pro celou síť následovně: n ih 1 yih 1 (1 yih 1 ) wkio ko , k 1 kde skryté vrstvy jsou číslovány vzestupně směrem od vstupů k výstupům. Pokud tento vztah aplikujeme postupně od výstupní vrstvy ke vstupům, vypčteme hodnoty pro celou síť. Odtud získal algoritmus zpětného šíření svůj název, protože chybu šíříme zpětně od výstupů ke vstupům. Nejčastější modifikace základního algoritmu spočívá v zavedení setrvačnosti(momentum). wijo (t ) io (t ) y hj (t ) wijo (t 1) io (t ) io (t ) io (t 1) Koeficient je tzv. setrvačnost, která nám říká, jak dlouho se budeme držet určitého směru, než zabočíme podle nové změny gradientu. Toto bylo přidáno do algoritmu dodatečně pro překonávání lokálních minim. 3.2.4 Algoritmus Quickpropagation 15B Ještě dříve než se dostanu k samotnému algoritmu Quickpropagation, zmíním se o několik úpravách navržených Scott E. Fahlman, které vedou ke zlepšení chování výše zmíněného Backpropagation. Tyto modifikace jsou dále použitelné i v rámci Quickpropagation. Je-li u neuronových jednotek aplikovana přenosová funkce sigmoida, velmi často se objevuje tzv. flat-spot problém, kdy se hodnota derivace blíží nule. U standardního 19 Backpropagation, se chyba sítí šíří zpětně. Chyba je posléze v každém neuronu vynásobena derivací hodnoty neuronu o j . Tato derivace se rovná o j (1 o j ) . Hodnota derivace se blíží nule, jakmile se výstupní hodnota neuronu blíží 0.0 nebo 1.0. Ačkoliv taková výstupní hodnota reprezentuje maximální možnou chybu, neuron, jehož výstupní hodnota se blíží 0.0 nebo 1.0 propaguje zpětně předchozím vrstvám jen malý zlomek této chyby. Takovému neuronu může trvat velmi dlouho, než se dostane z takového „hluchého místa” (flat-spot). Pokud bychom chybu zaokrouhlovali nebo dokonce ignorovali malé chyby, mohl by neuron být „uvězněn“ v tomto stavu navždy. Scott E. Fahlman proto navrhuje přičíst konstantu 0.1 k derivaci. Místo aby se hodnoty derivace pohybovaly od 0.0 do 0.25, budou nyní v rozmezí od 0.1 do 0.35 a zpět do 0.1. Tato modifikace by mohla vést až k dvojnásobnému zrychlení procesu učení. Nyní se konečně dostáváme k samotnému algoritmu Quickpropagation. Jak jsem již výše zmínil, Backpropagation pracuje s parciální derivací prvního stupně podle jednotlivých vah, které se pak použijí při gradientním sestupu. Pokud v každé iteraci provedeme nekonečně malý krok, je zaručeno, že najdeme lokální minimum a bylo empiricky dokázano, že pro mnoha problémů to bude zároveň minimum globální nebo aspoň minimum přijatelné. My ovšem nechceme provádět nekonečně malý krok, ba naopak. Aby byl proces učení co nejrychlejší, je třeba provést co největší možný krok, aniž bychom přešli přes lokální minimum. Bohužel první parciální derivace poskytuje velmi málo indicií o tom, jak velký krok je ještě bezpečný. Použijeme proto druhou parciální derivaci. Pro každou váhu si uchováme parciální derivaci E / w(t 1) z předchozí iterace. V momentu výpočtu nové váhy máme tedy k dispozici jak E / w(t ) , tak E / w(t 1) . Dále se předpokládá, že chyba vůči křivce vah může být aproximována parabolou a že změna sklonu chybové křivky u každé váhy není ovlivněn změnami ostatních vah ve stejném okamžiku. Pro každou váhu použijeme předchozí a současný sklon chyby a váhovou změnu mezi dvěma body, kde byly sklony naměřeny, k určení paraboly a posléze provedeme krok tak, abychom skončili rovnou v minimu paraboly. Výpočet probíhá následovně: w(t ) S (t ) w(t 1) , S (t 1) S (t ) kde S (t ) a S (t 1) jsou současné a předchozí hodnoty E / w(t ) Podle této rovnice . pokud je současný sklon menší než předchozí ale stejného směru, váha se bude měnit taky 20 ve stejném směru. Velikost změny závisí na míru redukce předchozím krokem. Pokud současný sklon je opačného směru než předchozí, potom jsme přešli přes lokální minimum. V takovém případě dalším krokem se dostaneme někam mezi předchozí a současnou pozicí. Třetí možný případ nastane, když současný sklon je stejného směru jako předchozí, ale větší nebo stejně veliký. Pokud v takovém připadě použijeme danou rovnici bez úprav, mohli bychom nakonec ocitnout v situaci, kdy by byl krok nekonečně veliký a vzdálovali bychom se od lokálního minima. Zavedeme proto parametr , tzv. maximální růstový faktor (maximum growth factor) . Žádný krok nesmí být větší než hodnota převyšující - krát předchozí změnu váhy. Pokud je rovnicí spočítaná změna příliš veliká, použije se předchozí změnu vynásobenou faktorem. Protože předchozí rovnice pracuje s předchozí změnou, potřebujeme nějakým způsobem nastartovat celý učící proces v první iteraci nebo pokud byla poslední změna nulová, proto k w(t ) přičteme -násobek současného sklonu, pokud mají současný a předchozí sklon opačná známenka. Celý výpočet probíhá tedy následovně: wij (n) ij (n) E (n) ij ( n ) wij (n 1) wij E ( n) wij ij (n) E E (n 1) ( n) wij wij ij (n) max , if ij (n) infinite or ij (n) > max E or ij (n) wij (n 1) (n) >0 wij ij (n) = ij (n) , else ij (n) = o , if E (n) wij (n 1) <0 wij or wij (n 1) =0 ij (n) =0 , else Scott E. Fahlman uvádí, že jeho testy prokazují, že Quickpropagation je znatelně rychlejší a vykazuje dobrou škálovatelnost. 21 3.2.5 Algoritmus R-propagation 16B R-propagation (Rprop) je zkrátkou pro Resilient-propagation. Základním principem Rprop je eliminace neproduktivního vlivu velikosti parciální derivace na změny vah, proto bere v úvahu pouze znaménko derivace při určení směru změny vah. Velikost změny je určena ij(t ) . else E if wij (t ) E if wij (t ) 0 , wij(t ) ij(t ) 0 , wij(t ) ij(t ) wij(t ) 0 kde E wij (t ) je parciální derivace přes celou trénovací množinu. Jak tedy vypočteme E wij ( t 1) if E wij ( t 1) if else , E wij (t ) * E wij (t ) * 0, ij(t ) ij(t 1) 0, ij(t ) ij(t 1) ij(t ) ? ij(t ) ij(t 1) kde 0 1 Jinými slovy pokaždé, kdy parciální derivaci příslušné váhy wij změní své znaménko, což indikuje, že poslední změna byla příliš velká a dostali jsme se přes lokální minimum, je hodnota ij(t ) snížena o faktor . Jestli derivace zachovává svoje znaménko, hodnota je zvětšena, aby se zrychlila konvergenci. Navíc v případě změny znaménka je hodnota E wij ( t 1) 22 ij(t ) resetována na 0. Abychom redukovali počet vstupních parametrů, jsou hodnoty a nastaveny jako konstanty. Hodnota musí být jednak dostatečně velká, aby umožňovala rychlou konvergenci v místech s nízkou monotonností, ale také aby zároveň nedošlo neustále ke změně znaménka parciální derivace, tedy k přeskoku přes lokální minimum. Experimentálně se ukazuje, že hodnota 1.2 pro a 0.5 pro dává dobré výsledky. ij(t ) , značena jako 0 , a maximální hodnotu ij(t ) , značena jako max . Na začátku učení jsou ij(t ) inicializovány na 0 . Za 0 se většinou volí 0.1. max představuje horní limit, aby nebyla změna příliš velká. Pro max se osvědčila hodnota 50. Velmi často se u Rprop používá ještě min , který má zabránit příliš Rprop má dva parametry, počáteční hodnotu rychlému zaseknutí se v neoptimálním lokáním minimu, je nastaven na 1e-6. 23 Následující preudokód zachycuje celý algoritmus. i, j :ij (t ) o E (t 1) 0 wij Repeat i, j : E (t ) wij For all weights and biases{ E E if (t 1) * (t ) 0 then{ wij wij ij (t ) min(ij (t 1) * ,max ) Compute gradient E wij (t ) sign (t ) *ij (t ) w ij wij (t 1) wij (t ) wij (t ) E E (t 1) (t ) wij wij } E E else if (t 1) * (t ) 0 then{ wij wij ij (t ) max(ij (t 1) * ,min ) E (t 1) 0 wij } E E (t 1) * (t ) 0 then{ else if wij wij E wij (t ) sign (t ) *ij (t ) w ij wij (t 1) wij (t ) wij (t ) E E (t 1) (t ) wij wij } } Until (converged) 24 3.2.6 Algoritmus Cascade Correlation 17B Autorem algoritmu Cascade correlation je opět Scott E. Fahlman, který tento algoritmus představil jako řešení pro nedostatky, které Backpropagation má. Jedná se především o tzv. step-size a moving-target problém. O step-size problému jsem se již zmínil v předchozí části. Moving-target problém spočívá v nesehranosti jednotlivých neuronů při gradientním sestupu. Každý neuron se snaží upravovat váhy, tak jak se „domnívá”, že je nejlepší, bohužel každý neuron má k dispozici pouze informace o chybě předané z předchozích vrstev a svůj input. Neurony ve stejné vrstvě nemají možnost vzájemné komunikace a lokálně nejlepší krok z pohledu jednoho neuronu nemusí v součtu celé sítě dávat globálně optimální krok. Způsob, jak zabránit moving-target problém, je povolit změny jen u několik váh nebo neuronů v daném okamžiku. Cascade Correlation aplikuje extrémní případ této techniky a povoluje změnu pouze u jednoho neuronu, respektivě povoluje změny vah vstupních synapsí jednoho neuron. Cascade Correlation se vyznačuje dvěma charakteristikami. Tou první charakteristikou je kaskádní architektura. Jednotlivé neurony skryté vrstvy jsou přidávány postupně a po přidání nejsou na ně aplikovány žádné změny. Druhou charakteristikou je samotný algoritmus, kterým se generuje a přidává nový neuron. Pro každý nový skrytý neuron se snažíme maximalizovat korelaci mezi výstupní hodnotou skrytého neuronu a residuálním chybovým signálem výstupu, který chceme eliminovat. Kaskádní architektura je ilustrována na Obr. 3.2.6.1 (převzato z práce Scott E. Fahlman). Na začátku má síť několik vstupních neuronů a jeden či více výstupních neuronů, avšak žádné skryté neurony. Každý vstupní neuron je propojen s každým výstupním neuronem. Použijeme rovněž jeden bias vstup, jehož hodnota je konstana 1.0. Postupně přídáváme skryté neurony. Každý nový skrytý neuron je propojen s neurony vstupní vrstvy a neurony předchozí skryté vrstvy. Po přidání jsou váhy vstupních propojení nového skrytého neuronu „zmraženy“ a během trénování jsou modifikovány pouze váhy výstupních propojení (vstupní propojení do výstupních neuronů sítě). Každý nový skrytý neuron představuje rovněž novou vrstvu. Na obrázku 3.2.6.1 čtverečky vyznačují zmražená propojení a naopak křížky propojení, která budou opakovaně trénována. 25 Obr. 3.2.6.1a počáteční stav sítě během učení Cascade Correlation Obr. 3.2.6.1b struktura sítě po přidání prvního skrytého neuronu 26 Obr. 3.2.6.1c struktura sítě po přidání druhého skrytého neuronu Trénovací algoritmus začíná tedy s žádnými skrytými neurony. Přímá propojení mezi vstupy a výstupy sítě jsou trénovana tak dlouho, dokud registrujeme znatelnou redukci chyby nebo dokud nebude překročen limit počtu iterací. V takovém případě vypočteme ještě jednou chybu sítě, pokud je výsledek pro nás přijatelný je učící proces ukončen, v opačném případě se pokusíme dosáhnout lepších výsledků přidáním dalšího skrytého neuronu. To provedeme tak, že nejprve do sítě začleníme tzv. kandidáta, nový skrytý neuron, který má propojeny své vstupí synapse, nikoliv ještě výstupní, tedy není prozatím propojen s výstupními neurony sítě. Modifikujeme váhy vstupních propojení neuronu pomocí gradientní výstupu, tak abychom maximalizovali korelaci s residuální chybou sítě. Tato korelace S je definována následovně : S o | (V V )( E p p ,o Eo) | p kde o je nějaký výstup sítě, ve kterém je měřena chyba, a p je trénovací jednotka (prvek trénovací množiny). V a Eo jsou hodnoty zprůměrované přes celou trénovací množinu. Abychom mohli maximalizovat S, potřebujeme si spočítat S / wi , parciální derivaci S s ohledem na jednotlivé váhy propojení. S / wi o ( E p ,o Eo ) f p` I i , p p ,o 27 ` kde o je znaménko korelace mezi hodnotou kandidáta a výstupem o sítě, f p je derivace pro vzor p trénovací množiny a I i , p je vstup, který kandidát dostává od i-tého neuronu při vzoru p.V momentu, kdy dosáhneme maxima korelace, propojíme výstupy kandidáta s výstupy sítě, zmrazíme vstupy kandidáta a opět trénujeme výstupní propojení sítě. Protože se v předpisu pro korelaci S objevuje absolutní hodnota, hraje roli jen velikost korelace, nikoliv znaménko korelace. Místo angažování jednoho kandidáta, můžeme v každé iteraci pracovat s celým pool kandidátů a pak na konci vybrát z nich ten s nejlepší korelaci, toho posléze použijeme jako nový skrytý neuron. Použití poolu má dvě výhody. Značně redukuje možnost nevrátně do sítě začlenit špatný neuron také zrychluje proces učení. 28 Kapitola 4 4 Realizace 3B 4.1 Analýza a návrh řešení 18B Pro implementaci jsem si vybral jazyk Java, jednak kvůli tomu, že projekt GAME je naprogramován v jazyku Java, ale také kvůli přenositelnosti a objektovému přístupu. Pro implementaci samotné knihovny jsem použil volně přístupný Netbeans. Při návrhu řešení jsem velmi dbal na přehlednost a objektově orientovaný přístup. Celý návrh se dá rozdělit do dvou relativně ucelených celků. Jednu část tvoří objekty spojené se strukturou samotné neuronové sítě a druhou tvoří její nadstavbu v podobě učících algoritmů. Podle teorie návrhových vzorů bychom k „výrobě“ objektů mohli použít návrhové vzory Factory a Singleton, jenže tato aplikace není dostatečně rozsáhlá k tomu, aby se toto použití vyplatilo a není třeba uměle a násilně aplikovat populární metody objektově orientované analýzy na úkor praktičnosti. 4.1.1 Neuronová síť 19B Neuronová síť se skládá z neuronů a synapsí. Tuto strukturní hierarchii jsem zachoval i při navrhování objektů (viz. Obr. 4.1.1.1). Základními objekty jsou tedy instance třídy Neuron a Synapse. Pro pohodlnější práci, obzvláště v učících algoritmech, jsem se rozhodl pro obousměrnou realizaci vztahu neuron–synapse, tedy neuron a příslušné synapse disponují vzájemnými odkazy na sebe. Každý neuron obsahuje odkazy na dvě skupiny synapsí. Vstupní synapse, incoming synapses, a výstupní synapse, outgoing synapses. Neurony jsou tří základních druhů, vstupní, skryté a výstupní. Tato skutečnost je ve třídě Neuron vyjádřen pomocí interní vlastnosti (proměnné). V neuronové síti se používá ještě bias. Narozdíl od projektu SNNS jsem se rozhodl, bias reprezentovat jako přídavný vstup, který je konstantně nastaven na hodnotu 1. Reprezentovat bias jako interní vlastnost neuronu a provést separátně výpočet 29 nové hodnoty biasu během každé epochy je podle mě nepraktické a snížuje homogenitu věci. Kromě základních datových vlastností (viz. Obr. 4.1.1.1), disponují jednotlivé třídy metodami specifikující chování objektů. Když jsem přemyšlel o tom, které metody či vlastnosti by měly být ve třídách, vyvstaly dvě možné přístupy. Buď v jednotlivých třídách, jejichž objekty budou následně tvořit samotnou strukturu neuronové sítě (Neuron, Synapse, NeuronLayer...) budou implementovány jen základní vlastnosti bezprostředně související s daným objektem, tedy že veškeré výpočty spojené s učícím procesem budou prováděny v oddělených třídách, nebo část výpočtu v souladu s objektově orientovaným přístupem bude přesunuta do výše zmíněných tříd. Já jsem si zvolil druhou variantu, která mi připadala přirozenější, přehlednější čili taky méně chybová. Obr. 4.1.1.1 diagram tříd tvořících strukturu neuronové sítě V tomto duchu dokážou tedy objekty třídy Neuron provést výpočet delta hodnoty nebo-li residuální chyby. Tato hodnota se pak dále používá k výpočtu parciální derivace. Zde uvádím seznam nejdůležitějších metod třídy Neuron. //spočítá delta hodnotu pro neurony výstupní vrstvy void calculateDelta (double desiredOutput) 30 //spočítá delta hodnotu pro neurony skryté vrstvy void calculateDelta() //spočítá výstupní hodnotu daného neuronu void calculateOutput() //spočítá derivaci void calculateDerivative() //vrací typ neuronu NeuronType type() Neurony se sdružují do neuronové vrstvy (neuron layer). Vrstvu tvoří neurony stejně vzdálené od vstupů sítě, vzdáleností se v tomto případě rozumí nejmenší počet synapsí, přes které se vzruch postupně šíří k danému neuronu. Implementace třídy NeuronLayer reprezentující neuronovou vrstvu zjednodušuje jak dopředný výpočet výstupní hodnoty sítě, tak i zpětnou propagaci chyby, neboť toto probíhá v podstatě po vrstvách. Synapse mají odkaz na výchozí a cílový neuron. Stav synapse je charakterizován třemi hodnotami, váhou, parciální derivací a šířícím signálem, tedy hodnotou z výchozího neuronu do cílového. Na začátku učení se často váhy inicializují na náhodné hodnoty. K tomu slouží funkce generateWeight, náhodná inicializace tedy probíhá distribuovaně v jednotlivých synapsích. Pro úplnost ještě uvádím nejdůležitější metody třídy Synapse. //náhodně generuje váhu synapsí v daném intervalu boolean generateWeight(double lowerBound, double upperBound) //přičte, popřípadě odečte, hodnotu k váze synapse void addWeight(double weightChange) //nastavuje velikost kroku při učení RProp void setStepSize (double stepSize) //vrácí přenašenou hodnotu double transmittedValue() //vrácí parciální derivaci double currentSlope() 31 4.1.2 Aktivační funkce 20B Srdcem každého neuronu je aktivační funkce, přestože velmi často si vystačíme se sigmoidní funkcí, nelze vyloučit použití jiné funkce, která by byla pro daný problém vhodnější. Kvůli možnosti pozdějšího rozšíření je opět definován jednotné rozhraní pro aktivační funkce (viz. Obr. 4.1.2.1). I přestože rozhraní je velmi jednoduché a má pouze pár metod, jejichž funkčnost je zřejmá, věřím že má smysl. double calculateOutput(double input) double calculateDerivative(double input) double calculateDerivative(double input) Obr. 4.1.2.1 hierarchie tříd reprezentujících aktivační funkce 4.1.3 Učící algoritmy 21B Protože už v rámcí této práce budeme používat více učících algoritmů, je dobré, i do budoucna, pro ně definovat jednotné rozhraní. 32 Obr. 4.1.3.1 hierarchie tříd reprezentujících učící algoritmy Jak je vidět i z Obr. 4.1.3.1 algoritmy používané v rámci Cascade Correlation (RProp, Backpropagation, Quickpropagation) jsou implementovány odděleně jako plnohodnotné učící algoritmy, toto umožňuje jednak jejich samostatné využití, tak i flexibilitu Cascade Correlation, nic nám totiž nebrání naprogramovat nějaký jiný algoritmus, který by implementoval dané rozhraní a předat ji Cascade Correlation pro vnitřní použití. Interface ILearningAlgorithm předepisuje tedy následující metody: //hlavní učící metoda void train(......) //modifikace vah void modifyWeights(.....) //vrácí typ učícího algoritmu String getType(.....) Stěžejní metodou je metoda train, která volá metodu modifyWeights k úpravě vah. Metoda modifyWeights předpokládá validity parciálních derivací v momentu výpočtu. Jedním z parametrů metody modifyWeights je množina synapsí, která má být trénovaná. Metoda je tímpadem připravena pro použití v Cascade Correlation, kde učení proběhne vždy pouze na podmnožině synapsí. Metoda getType slouží spíše k ladícím účelům a vrácí string definující použitý učící algoritmus. Jak jsem již zmínil, chtěl jsem aby byla výsledná implementace znovupoužitelná pro i potenciálně jiné případy nikoliv pouze pro GAME, zavedl jsem proto u všech učících algoritmů jak učení typu continuous , tedy k modifikaci vah dochází po vystavení každého 33 vzoru, tak i batch, kdy se váhy modifikují až po aplikování celé trénovací množiny. Zpravidla je konvergence u batch verze rychlejší. Ačkoliv během procesu trénování je v drtivé většině snaha o minimalizaci chyby, tak se u algoritmu Cascade Correlation setkáváme s maximalizací korelace, proto každý učící algoritmus by měl umět provádět také maximalizaci na základě paricálních derivací. To zda se bude provádět minimalizaci nebo maximalizaci lze nastavit pomocí proměnné trainMode, která je předána metodě modifyWeights jako vstupní parametr. Možné hodnoty jsou TrainMode.minimize a TrainMode.maximize. Defaultně je nastavený minimalizační mód. Je-li vyžadována maximalizace, změní se na začátku znaménka u parciálních derivací na znaménka opačná. 4.1.4 Výpočet parciální derivace 2B Každý učící algoritmus musí nepochybně v sobě obsahovat odezvu na zprávu vyžadující trénování neuronové sítě, v rámci které jistě dojde k modifikaci váh synapsí. Každý učící algoritmus tedy nějakým způsobem používá parciální derivaci počítanou vzhledem k váze synapsí. Může se však stát, že pro různé problémy se liší způsob výpočtu paricální derivace. Jako jeden z takových příkladů lze uvést samotný Cascade Correlation, který může použít Quickpropagation jak ve fázi trénování synapsí výstupních neuronů, tak i ve fázi trénování kandidátních neuronů skryté vrstvy, pokaždé je však výpočet paricální derivace rozdílný, proto jsem použil oddělenou třídu pro výpočet parciální derivace, respektivě rozhraní, které bude posléze implementován v konkrétních případech. Obr. 4.1.4.1 Hierarchie tříd reprezentujících funkce pro výpočet parciální derivace 34 Rozhraní ISlopeCalcFunction obsahuje následující dvě metody, jedna je použita při continuous způsobu trénování a druhá při batch trénování. void calculateSlope(SlopeCalcParams params, TrainingSet trainingSet) void calculateSlope(SlopeCalcParams params, TrainingPattern traningPattern) 4.1.5 Implementační detaily 23B Je třeba si ujasnit, jakým způsobem budou realizovány množiny prvků jako množina synapsí určitého neuronu či množina neuronů jedné vrstvy, takových příkladů bych mohl uvést více. Automaticky bych mohl použít klasické pole, koneckonců jedná se o množinu prvků stejného typu, jenže struktura neuronové sítě se bude v průběhu učení Cascade Correlation značně měnit, jen připomenu třeba průběžné přidávání skrytých neuronů, v takovém případě by volba polí znamenala ustavičné inicializace nových polí větší kapacity a následné otrocké překopírování hodnot. Druhou možností je využít výhod, které Java a její bohaté knihovny nabízejí. Mám na mysli ArrayListy. Práce s ArrayListy je výrazně pohodnější a flexibilnější, zvláště když v našem případě se vesměs jednají o množiny, jejichž velikost se dynamicky mění během běhu aplikace Teoreticky bychom mohli použít klasické pole inicializované rezervně na větší kapacitu, než je v daném momentu potřeba, to je ale přesně to, co dělají Arraylisty, neboť Arraylisty jsou interně implementovány jako pole. Potřebuji-li nějakým způsobem se postupně dostat ke všem prvkům, pak pro takovýhle případ existuje v Javě iterátor. Iterátor dokáže postupně vystavit všechny prvky množiny, přitom je tento proces optimalizován. 35 Kapitola 5 5 Testování 4B 5.1 Testování funkčnosti 24B Na několika případech ověřím správnou funkčnost implementovaného algoritmu Cascade Correlation, konkrétně to budou problémy XOR a dvojitá spirála. Ale ještě předtím jsem se musel rozhodnout, který algoritmus použít v rámci Cascade Correlation. Na výběr jsem měl buď Quickpropagation nebo Resilient-Propagation. Hledal jsem proto nejprve ideální nastavení obou algoritmů, respektivě především Quickropagation, neboť tento algoritmus je mnohem více závislý na hodnotách svých parametrů. Quickpropagation má parametrů hned 3 a to epsilon, momentum rate a maximum growth factor. Zatímco s epsilonem a momentum rate se setkáváme také u Backpropagation a pro tyto parametry jsou použil typické hodnoty, parametr maximum growth factor je zcela specifický pro Quickpropagation, zkoumal jsem proto, jak jeho hodnota ovlivňuje úspěšnost Quickpropagation. Daný vliv jsem zkoumal na problému XOR a došel jsem k podobným závěrům jako Scott E. Fahlman. Ideální je zvolit si hodnotu mezi 1.5 a 2.5. Zvolíme-li příliš velkou hodnotu setkáme se s velmi chaotickým chováním a síť se nenaučí. Na druhé straně je-li zase hodnota přílíš malá, je kovergence extrémně pomalá. V případě Resilient-Propagation se osvědčily doporučené hodnoty. Pro úplnost uvádím hodnoty použitých parametrů obou algoritmů. parametry Quickpropagation : epsilon = 0.2 momentum rate = 0.1 maximum growth factor = 2.0 parametry Resilient-Propagation: eta minus = 0.5 eta plus = 1.2 36 Porovnání použití Quickpropagation a Resilient-Propagation v Cascade Correlation jsem prováděl rovněž na problému XOR s následujícími výsledky : Algoritmus Počet pokusů Počet úspěšných pokusů Průměrný počet kroků jednoho pokusu Quickpropagation 100 100 534 Resilient-Propagation 100 100 401 Zdá se, že Cascade Correlation používaný v kombinaci s Resilient-Propagation je v tomto případě rychlejší. Domnívám se, že Resilient-Propagation nebyl rychlejší kvůli tomu, že je ze své podstaty lepším algoritmem. Problémem Quickpropagation je, že jeho úspěšnost příliš závisí na volbě hodnot parametrů a pro různé problémy mají parametry různé ideální hodnoty. Při dalším testování budu tedy v rámci Cascade Correlation používat ResilientPropagation. 5.1.1 Problém XOR 25B Na tento problém jsem pustil Cascade Correlation 100-krát. Algoritmus byl ve všech případech úspěšný a velmi rychlý. Ve všech případech už po přidání jednoho skrytého neuronu spadla chyba pod stanovený limit (0.0001). Na obrázku 5.1.1.1 je pak vidět projekční graf, kde je v rovině zobrazen výstup sítě v závislosti na 2 vstupech. Jen pro srovnání síť s jedním skrytým neuronem potřebuje průměrně 3000 epoch než se uspěšně naučí algoritmem Backpropagation. Problém Počet pokusů Počet úspěšných pokusů Průměrný počet epoch jednoho pokusu XOR 100 100 401 37 Obr. 5.1.1.1 Klasifikační graf pro XOR 5.1.2 Problém dvojité spirály 26B Problém dvojité spirály spočívá ve schopnosti sítě rozpoznat dvě třídy bodů, které v rovině tvoří dvě spirály (viz. Obr. 5.1.2.1). Obr. 5.1.2.1 grafické zobrazení bodů spirály v kartézské rovině. Křížky tvoří jednu třídu a kroužky druhou. Obrázek je převzatý z [15] Původně sloužil tento problém k demonstraci schopnosti vícevrstevných sítí řešit lineárně neseparovatelný problém. Nyní se používá také k ověření rychlosti a kvality algoritmů. Jedná se o poměrně složitý problém,se kterým si standardní Backpropagation neumí poradit. Přestože pán Fahlman tvrdí, že Cascade Correlation se dokáže vypořádat s tímto problémem, mé pokusy toto tvrzení nepotvrdily. Pomocí Cascade Correlation s ResilientPropagation se nepovedlo naučit síť tak, aby rozpoznal všech 194 bodů tvořící spirály. Zkoušel jsem proto zvýšit počet povolených skrytých neuronů v síti na 33. Tímto krokem jsem dosáhl částečného úspěchu. Abych zjistil, zda implementovaný Cascade Correlation funguje, nechal jsem si visualizovat projekční graf výstupu po každém přidání skrytého neuronu. 38 Obr. 5.1.2.2a projekční graf výstupu před přidáním skrytých neuronů Obr. 5.1.2.2b projekční graf výstupu po přidání 1 skrytého neuronu Obr. 5.1.2.2c projekční graf výstupu po přidání 2 skrytých neuronů Obr. 5.1.2.2d projekční graf výstupu po přidání 3 skrytých neuronů Obr. 5.1.2.2e projekční graf výstupu po přidání 5 skrytých neuronů Obr. 5.1.2.2f projekční graf výstupu po přidání 7 skrytých neuronů 39 Obr. 5.1.2.2g projekční graf výstupu po přidání 9 skrytých neuronů Obr. 5.1.2.2h projekční graf výstupu po přidání 11 skrytých neuronů Obr. 5.1.2.2i projekční graf výstupu po přidání 15 skrytých neuronů Obr. 5.1.2.2j projekční graf výstupu po přidání 19 skrytých neuronů Obr. 5.1.2.2k projekční graf výstupu po přidání 24 skrytých neuronů Obr. 5.1.2.2l projekční graf výstupu po přidání 29 skrytých neuronů 40 Obr. 5.1.2.2m projekční graf výstupu po přidání 33 skrytých neuronů Jak je vidět na obrazcích, postupně jsou separovány dvě skupiny bodů, z nichž každá tvoří spirálu. Implementovaný algoritmus tedy očividně funguje, avšak vždy zůstanou několik málo bodů (v tomto konkrétním případě to jsou 3 body), které síť špatně zařadí. Zkoušel jsem tedy Cascade Correlation s Quickpropagation. Snažil jsem různě nastavovat parametry Quickpropagation, nedosáhl jsem však znatelného zlepšení, výsledky byly velmi podobné jako s Resilient-Propagation. Po dlouhém bádání a procházení některými implementacemi v Matlabu či Lispu, jsem zjistil, se občas se k výpočtu korelace mezi kandidátním neuronem a výstupními neurony používá odlišný vzorec než ten, který uvádí Fahlman ve své práci a to takovýhle: S o | (V E p. p ,o Eo) / SumSqError | p kde, SumSqError E p ,o .E p ,o o p Ale ani s touto modifikací jsem nedosáhl lepších výsledků. Bohužel jsem nenašel žádnou přístupnou implementaci, se kterou by bylo možné porovnat své řešení. Projekt SNNS je velmi špatně zdokumentovaný a taky nestabilní. Práce prezentováná panem Fahlmanem je poměrně stručná a neuvádí detailně specifikace implementace, nebylo proto možné provést rozumné porovnání. Domnívám se, že k úspěšnému vyřešení problému dvojité spirály, je třeba Cascade Correlation vhodně modifikovat a také šikovně vyladit jednotlivé parametry. Roli může hrát také fakt, jak jsou vstupní data prezentována či kódovana. Mně se 41 nepovedlo zjistit ideální nastavení, dokázal jsem však, že implementovaný algoritmus funguje. 5.2 Testování v GAME 27B V prostředí GAME jsem testoval na problému Iris úspěšnost Cascade Correlation vůči ostatním typům neuronu. Výhodou Iris je, že patří mezi problémy s daty z reálného světa, kdy trénovací množinu tvoří tři třídy dat, každá o velikosti 50 vzorků a vztahují se ke 3 typům kosatců. Klasifikace je založena na 4 vstupech, délky a šířky kališních a okvětních lístků. Jedna třída je lineárně separovatelné zbylé dvě nikoliv. Informace o tomto problému jsem čerpal z webové stránky UCI machine-learning repository. Testování v GAME jsem rozdělil do 2 částí. Nejrpve jsem testoval úspěšnost neuronů typu Cascade Correlation samostatně a pak jsem je dal do konfrontace s neurony typu Backpropagation. Ještě bych měl zmínit s jakým nastavením Cascade Correlation byly testy prováděny. Jako vnitřní algoritmus Cascade Correlation jsem použil Resilient-Propagation. Z důvodů časové náročnosti jsem musel výrazně omezit maximální počet povolených skrytých neuronů a také maximální počet iterací během trénování výstupních a kandidátních neuronů. Navíc během testování jsem zjistil, že tato omezení nijak nezhoršuje úspěšnost učení. Pro všechna testování jsem tedy nastavil parametry takto. Hodnoty parametrů byly zjištěny na základě pokusů prováděných na problému Iris. Cílem bylo, aby učení bylo dostatečně přesné, ale ne moc časově náročné. maximální počet skrytých neuronů : 4 maximální počet iterací pro trénování výstupu: 100 maximální počet iterací pro trénování kandidátů: 100 5.2.1 Testování Cascade Correlation v GAME 28B S pomocí Cascade Correlation se GAME dokázal velmi dobře vypořádat s problémem Iris. Jak je velmi dobře vidět na následujících grafech, pouze 3 až 4 vrstvy neuronů stačí k reducki chyby na velmi malou až nulovou hodnotu. Podotýkám, že grafy zobrazují typické výsledky tohoto problému, jinak samozřejmě každý pokus vyjde trochu jinak. 42 Obr. 5.2.1.1 strukturní model setosy. Síť se skládá pouze z Cascade Correlation neuronů. Výstupní neuron je větší kolečko Setosa je lineárně separovatelná, proto zde stačí pouze 2 mnohdy i 1 vrstva neuronů. Na 3D grafu (Obr. 5.2.1.2) je ještě názorněji zobrazena struktura sítě včetně postupné klasifikace třídy setosy. Obr. 5.2.1.3 pak ukazuje detailně výsledný klasifikační obraz výstupu. Je vidět jak se všechny body třídy setosy povedly jednoznačně oddělit. 43 Obr. 5.1.1.2 3D visualizace modelu setosy - síť pouze z Cascade Correlation neuronů. Modré bod reprezentují třídu setosu. Síť používá pouze 2 ze 4 vstupů Obr. 5.2.1.3 3D projekce výstupu Setosy - síť pouze z Cascade Correlation neuronů. Modré body reprezentující třídu setosu jsou sítí jasně separované od ostatních 44 Dále uvádím stejné grafy pro modely versicolor a virginica . Obr. 5.2.1.4 strukturní model versicolor - síť pouze z Cascade Correlation neuronů 45 Obr. 5.2.1.5 3D visualizace modelu versicolor – síť z Cascade Correlation neuronů. Můžeme zpozorovat jak se postupně zpřesňuje oddělení třídy versicolor od ostatních Obr. 5.2.1.6 3D projekce výstupu versicolor – síť z Cascade Correlation neuronů. Zde můžeme v detailu vidět, jak je problematické určit hranici mezi třídami versicolor a virginica 46 Obr. 5.2.1.7 strukturní model virginica – síť z Cascade Correlation neuronů Obr. 5.2.1.8 3D visualizace modelu viginica - síť z Cascade Correlation neuronů 47 Obr. 5.2.1.9 3D projekce výstupu virginica – síť z Cascade Correlation neuronů Třídy versicolor a virginica nejsou od sebe lineárně separovatelné, proto je i na grafech vidět, že je docela problematické tyto dvě třídy od sebe oddělit, i přesto jsem dosáhl poměrně malých chyb, řádově 1E-4. 5.2.2 Cascade Correlation vs Backpropagation 29B Zde GAME v každé vrstvě vybere z neuronů typu Cascade Correlation a Backpropagation ty s lepšími výsledky. Zajímalo mě kolik neuronů typu Cascade Correlation přežije na úkor neuronů typu Backpropagation nebo naopak. Následující grafy jednotlivých modelů Irisu reprezentativně demonstrují výsledky testování. 48 Obr. 5.2.2.1 strukturní model setosy – síť z Cascade Correlation a Backpropagation neuronů Obr. 5.2.2.2 strukturní model versicolor – síť z Cascade Correlation a Backpropagation neuronů (Backpropagation neuron je v grafu označen jako „Perceptron net“) 49 Obr. 5.2.2.3 strukturní model virginica – síť z Cascade Correlation a Backpropagation neuronů Jak je vidět z grafů, Cascade Correlation jasně vytlačil Backpropagation a přežívá v GAME v podstatně větším množstvím. Udělal jsem ještě jedno porovnání. V tomto případě jsem rozdělil vstupní data k problému Iris na dvě skupiny, na trénovací a testovací množinu. Nechal jsem GAME vytvořit dvě naučené sítě, jedna se skládala pouze z Cascade Correlation neuronů a druhá pouze z Backpropagation neuronů a porovnával jsem úspěšnost těchto dvou sítí správně kvalifikovat jednotlivé vzorky z trénovací a také z testovací množiny. Překvapivě zde byly oba typy řádově stejně úspěšné (prováděl jsem 20 měření pro každý typ), úspěšnost se pohybovala průměrně jen kolem 94%, hledal jsem proto vysvětlení a při detailnějším zkoumání jsem zjistil, že špatný výsledek Cascade Correlation je paradoxně způsoben faktem, že Cascade Correlation je až příliš úspěšný a dochází k jevu přeučení, kdy se síť vytrénuje přesně na míru trénovacím datům a pak nefunguje tak dobře na testovacích datech. Je nejspíš vhodné Cascade Correlation modifikovat tak, aby se učení zastavilo, je-li globální chyba příliš malá. 50 Kapitola 6 6 Závěr 5B Během práce jsem se bohužel potýkal s poměrně velkým nedostatkem studijních materiálů. Informace o Cascade Correlation jsem utržkovitě získával z nejrůznějších zdrojů. Většina zdrojů ale víceméně kopírovala text ze zprávy pana Fahlmana. Všechny použité zdroje uvádím v referencích. Chybělo hlavně vysvětlení algoritmu v kontextu reálné aplikace. Musel jsem se spoléhat na metodu reverzního inženýrství, kdy jsem zkoumal části kódu psaného v Matlabu či Lispu. Jedinou známou aplikací zahrnující algoritmus Cascade Correlation je projekt SNNS vyvíjený univerzitou ve Stuttgartu. Tento projekt však postrádá přehlednou programátorskou dokumentaci, proto bylo případné porovnání velmi složité. I přes tyto potíže jsem úspěšně implementoval algoritmus Cascade Correlation. Jeho správnou funkčnost jsem ověřil na problému XOR a dvojté spirály. Především u dvojté spirály bylo testování z důvodů uvedených v předchozím odstavci velmi pracné. Přestože bylo evidentní, že algoritmus funguje, nebyla klasifikace trénovacích vzorků stoprocentní, proto jsem se nespokojil s obdrženými výsledky a hledal ideální nastavení. Zkoušel jsem použít v rámci Cascade Correlation jak Quickpropagation tak i Resilient-propagation. Pro tyto algortimy jsem nastavil parametry na různé hodnoty a hledal optimální nastavení. Bohužel i po velké snaze, kdy jsem zvýšil počet skrytých neuronů, jsem dosáhl jen částečného úspěchu. Úspěšnost se sice zvýšila, ale nebylo to stále stoprocentní. Domnívám se, že by byla třeba nějaká modifikace Cascade Correlation nebo vhodnější způsob kódování vstup. Úspěšně jsem integroval knihovnu do projektu GAME. Cascade Correlation jsem začlenil do GAME ve dvou formách, Cascade Correlation neuron a Cascade Correlation model. Zatímco neuron funguje jako jeden z mnoha možných elementů, ze kterých GAME vytvoří síť, tak aby dosáhl co nejlepších výsledků, model je ucelený učící modul, který se dá samostatně použít na nějaký problém. Povedlo se mi taky ověřit, že Cascade Correlation by mohl najít v projektu uplatnění a úspěšně konkurovat jiným typům algoritmů. Implementoval jsem grafické rozhraní, přes které jsou parametry Cascade Correlation jednoduše nastavitelné Také jsem odhalil důležitou vlastnost Cascade Correlation, že má tendenci se přeučit a upozornil na nutnost kontroly procesu učení. 51 Výsledky mých testů prováděných v prostředí GAME na Iris datech ukazují, že Cascade Correlation by mohl být rychlejší a učinnější než Backpropagation, překonává nedostatky Backpropagation, což by mělo vést k rychlejší konvergenci a k menším výsledným topologiím. Pro potvrzení by však bylo vhodné provést testy na dalších datech. Spolu s Cascade Correlation se mi povedlo vytvořit obecnou knihovnu v Javě, která dokáže simulovat činnost neuronové sítě. Kromě Cascade Correlation knihovna zahrnuje také algoritmy Backpropagation, Quickpropagation a Resilient-propagation. Tyto algoritmy je možno použít zcela samostatně a nezávisle na Cascade Correlation, proto si myslím, že knihovna je schopna velmi dobře sloužit jako demonstrativní ukázka funkčnosti neuronových sítí a také pro jejich vzájemné porovnávání na různých úlohách. Původní záměr navrhnout knihovnu tak, aby nebyl větší problém v budoucnu ji jakkoliv rozšířit, se mi podařilo naplnit. Existuje i několik věcí, na které nezbyl v této práci prostor a které by byly užitečné implementovat. Tím nejdůležitějším je doplnit knihovnu o možnost offline předvýpočtu potřebných hodnot (výstupní hodnota, derivace,...) všech neuronů a synapsí. Toto by výrazně zrychlilo jednotlivé algoritmy, protože k tomuto výpočtu dochází opakovaně během jedné epochy. Práce na tomto projektu mi umožnila podrobněji se seznámit s problematikou neuronových sítí, poznal jsem jak je těžké, ba nemožné, najít takový algoritmus, který by dobře fungoval na všechny problémy. 52 Kapitola 7 7 Seznam literatury 6B [1] Šnorek M.: Neuronové sítě a neuropočítače skripta ČVUT, Praha, 2002 [2] Scott E. Fahlman, Christian Lebiere: The Cascade-Correlation Learning Algorithm Carnegie Mellon University, Pittsburgh, 1990 [3] Scott E. Fahlman: An Empirical Study of Learning Speed in Back-Propagation Networks Technical Report CMU-CS-88-162, 1988 [4] Markus Hoehfeld, Scott E. Fahlman: Learning with Limited Numerical Precision Using the Cascade-Correlation Alg. Technical Report CMU-CS-91-130, Carnegie Mellon University, 1991 [5] Karthik Balakrishnan: Faster Learning Approximations of Back-Propagation by Handling Flat-Spots Department of Computer Science, Iowa State University [6] W. Schiffman, M. Joost, R. Werner: Optimization of the Backpropagation Algorithm for Training Multilayer Perceptrons Technical Report, University of Koblenz, 1994 [7] Sam Waugh, Anthony Adams, Fiona Tweedie: Computational Stylistics using Artificial Neural Networks University of Tasmania, University of Glasgow [8] Sam Waugh: Extensions to Cascade-Correlation Training University of Tasmania 53 [9] Mitchell A. Potter: A Genetic Cascade-Correlation Learning Algorithm George Mason University [10] José Demisio Simões: The Cascade-Correlation Neural Network Growing Algorithm using the Matlab Environment Instituto Nacional de Pesquisas Espaciais [11] Martin Riedmiller, Heinrich Braun: RPROP – A Fast Adaptive Learning Algorithm University of Karlsruhe [12] Martin Riedmiller: Rprop – Description and Implementation Details Technical Report, University of Karlsruhe, 1994 [13] Christian Igel, Michael Hüsken: Improving the Rprop Learning Algorithm In Proceedings of the second International Symposium on Neural Computation NC2000, Ruhr-Universität, Bochum 2000 [14] N.K. Treadgold, T. D. Gedeon: A Cascade Network Algorithm Employing Progressive RPROP The University of New South Wales, Australia [15] J.R. Álvarez-Sánchez: Injecting Knowledge into the Solution of the Two-Spiral Problem Departamento Inteligencia Artificial, UNED, Madrid [16] Projekt SNNS: http://www.ra.cs.uni-tuebingen.de/SNNS/ HU U [17] Neural Networks – A Systematic Introduction: http://page.mi.fu-berlin.de/rojas/neural/index.html.html HU [18] Neural Networks – A Systematic Introduction: http://page.mi.fu-berlin.de/rojas/neural/index.html.html HU 54 U U Uživatelská příručka A.1 Načtení dat ze souboru 7B Součástí knihovny je také třída InputFileReader mající na starost načtení trénovacích vzorků ze souboru. Zde jsem nevymyšlel žádné složité struktury a použil co nejjednodušší řešení. Očekává se, že na začátku souboru by měly být informace o tom, kolik je vstupů a výstupů a po té už následují jednotlivé trénovací vzorky. Soubor je analyzován po řádcích. Takhle třeba vypadá část obsahu souboru s daty k problému dvojté spirály. inputs 2 outputs 1 0.9 0.5 1.0 0.8885418610828182 0.5772857814140816 1.0 0.8624450473698125 0.6501296542355353 1.0 0.8229939647790657 0.7158176674422301 1.0 0.7719641466102106 0.7719641466102105 1.0 0.7115440502651562 0.8165980446844308 1.0 0.6442422168145339 0.8482315161004081 1.0 0.5727836970598633 0.8659083546119746 1.0 ........ …. … Jednotlivé elementy jsou v předchozím příkladě odděleny mezerou. Není to ale podmínkou, za oddělovače (delimiter) může být zvolen jakýkoliv jiný symbol, který je předán metodě extractInputFile jako parametr. TrainingSet extractInputFile(String delimiter, boolean normalize) Parametr normalize říká, jestli chceme aby vstupní hodnoty byly normalizovány do intervalu <0 , 1>. A.2 Tvorba neuronové sítě 8B Pro tvorbu neuronové sítě je třeba vytvořit instanci třídy NeuralNetwork. Než se dostanu podrobněji k popisu konstruktoru třídy , je třeba si vyjasnit jeden pojem. Plně propojená síť je taková, ve které je každý neuron propojen synapsemi se všemi neurony předchozí vrstvy. Třeba algoritmus Cascade Correlation očekává na začátku plně propojenou neuronovou síť 55 o dvou vrstev, vstupní a výstupní. Tady je trochu poznat, že knihovna byla navržena pro Cascade Correlation. Konstruktor třídy NeuralNetwork umožňuje automatické vytvoření dvouvrstevné sítě bez skrytých neuronů s možností plně propojit neurony. Samozřejmě lze vytvořit jakkoukoliv neuronovou síť, v takovém případě si však nevystačím pouze s konstruktorem a pak lze konstruktor chapat jako nutný první avšak nikoliv postačující krok. Jakákoliv neuronová síť musí zcela jistě obsahovat vstupní a výstupní vrstvu, konstruktor vypadá tedy následovně. NeuralNetwork(int inputsNumber, int outputsNumber,int biasNumber, IActivationFunction activationFunction, boolean connect) Jako parametr předáváme počet vstupů, výstupů, bias neuronů a zvolenou aktivační funkci. Je-li parametr connect true, zároveň se plně propojí vstupní vrstvu s výstuní. Pokud ale potřebuji strukturně jinou neuronovou síť, můžu použit nějakou z následujících metod: //vytvoří novou vrstvu o dané velikosti a typu NeuronLayer createLayer(int neuronsNumber, LayerType layerType, int neuronId, int biasNumber,IActivationFunction activationFunction) //plně propojí dvě vrstvy public void fullyConnectLayers(NeuronLayer layerFrom, NeuronLayer layerTo, boolean randomWeight) //propojí dvě neurony void connectNeurons(Neuron sourceNeuron, Neuron destinationNeuron, double weight) Následující příklad vytvoří neuronovou síť tří vrstev, tedy s jednou skrytou vrstvou. Jednotlivé vrstvy jsou plně propojené. NeuralNetwork network = new NeuralNetwork(2,1,1, new ActivationFunctionSigmoid (),false); NeuronLayer hiddenLayer = network.createLayer(1, LayerType.hidden, network.neuronId, 0, new ActivationFunctionSigmoid ()); network.addHiddenLayer(hiddenLayer, 1); network.fullyConnectLayers(network.layers().get(0), network.layers().get(1), true); 56 network.fullyConnectLayers(network.layers().get(1), network.layers().get(2), true); network.fullyConnectLayers(network.layers().get(0), network.layers().get(2), true); A.3 Generování výstupu a získání chyby 9B Proces šíření signálu lze rozdělit do dvou etap. Nejprve je třeba síť „nakrmit“ vstupními hodnotami a poté spustit postupné dopředné propagace signálu. Ekvivalentně existují ve třídě NeuralNetwork dvě metody. Metoda InjectInput(...) vystaví na vstupní neurony vstupní hodnoty a metoda bubbleThrough() provede dopřednou propagaci. V tomto okamžiku máme na výstupních neuronech výstupní hodnoty odpovídající daným vstupům. K získání výstupních hodnot pro další zpracování slouží metoda extractOutput(). Následující příklad uvádí typické použití. NeuralNetwork network = new NeuralNetwork(2,1,1, new ActivationFunctionSigmoid (),false); network.injectInput(Pattern inputs); network.bubbleThrough(); double [] outputValues = network.extractOutpu(); double MSE = network.calculateSquaredError(Pattern desiredOutputs); Pomocí metody calculateSquaredError(...) lze získat chybu sítě. Tato metoda je ještě dvakrát přetížena. Jednou je parametrem nikoliv očekávané výstupní hodnoty, ale celá trénovací množina, chyba je tedy počítaná v takovém případě přes tuto celou trénovací množinu. Podruhé je parametrem kompletní trénovací vzorek tedy jak vstupní, tak i očekávané výstupní hodnoty. Tyto dvě přetížené verze se samy postarají o „nakrmení“ a následnou propagaci sítí. A.4 Trénování sítě 10B Mám-li načtenou trénovací množinu a neuronovou síť vytvořenou, nezbývá než síť trénovat. Trénovací algoritmus potřebuje mít k dispozici danou neuronovou síť, tu dostane jako parametr ve svém konstruktoru při vytvoření instance stejně jako parametry specifické pro jednotlivé učící algoritmy, dále obecné parametry ovlivňující proces výpočtu parciální derivace. Jedná se o trénovací mód (maximalizace či minimalizace), množinu synapsí k trénování, decay a nakonec také samotnou neuronovou síť. Všechny tyto parametry jsou 57 pro jednodušší předávání sdruženy do struktury třídy SlopeCalcParams. Uvedu zde dvě ukázky. V první ukázce je síť trénovaná pomocí Quickpropagation pro problém XOR a v druhé se uplatní Cascade Correlation na problém dvojté spirály. Ukázka 1: NeuralNetwork network = new NeuralNetwork(2,1,1, new ActivationFunctionSigmoid(),false); NeuronLayer hiddenLayer = network.createLayer(1, LayerType.hidden, network.neuronId, 0, new ActivationFunctionSigmoid ()); network.addHiddenLayer(hiddenLayer, 1); network.fullyConnectLayers(network.layers().get(0), network.layers().get(1), true); network.fullyConnectLayers(network.layers().get(1), network.layers().get(2), true); network.fullyConnectLayers(network.layers().get(0), network.layers().get(2), true); QuickPropagation quick = new QuickPropagation(network); SlopeCalcParams info = new SlopeCalcParams(); info.mode = TrainMode.minimize; info.neuralNetwork = network; info.synapsesToTrain = network.synapses(); Ukázka 2: try{ InputFileReader inputReader = new InputFileReader (inputFile); TrainingSet trainingSet = inputReader.extractInputFile(“ “, false); int inputsNumber = trainingSet.getTrainingPattern(0).inputsNumber(); int outputsNumber = trainingSet.getTrainingPattern(0).desiredOutputsNumber(); NeuralNetwork network = new NeuralNetwork(inputsNumber, outputsNumber, 1, new ActivationFunctionSigmoid(),true); CascadeCorrelation cascadeCorrelation = new CascadeCorrelation(network); 58 cascadeCorrelation.trainNetwork(trainingSet); } catch(IOException ex){ throw new Exception (“TestNeuralNetwork: testSpiral -> “ + ex.getMessage()); } 59 B Obsah CD 1B Struktura dat na přiloženém CD a nejdůležitější soubory jsou: Readme.txt - textový soubor s popisem CD doc/. - dokumentace - tato práce dp.pdf html/. index.html - spustitelna aplikace run/. automat.zip src/. tests/. - úvodní stránka vygenerované dokumentace - spustitelna aplikace společně s nutnými moduly - adresář zdrojových kódů - testovací soubory 60
Podobné dokumenty
Stáhnout příspěvek v pdf
s pojmem východní emotikon. Ten odkazuje k emotikonům původem z Japonska,
které jsou typičtější a frekventovanější ve východní Asii. Jejich opakem jsou západní
(či evropské) emotikony, za jejichž t...
Evaluation of Progression of Single Units Waveform
Lukáš Tůma: ANALÝZA SIGNÁLŮ BIOLOGICKÝCH NEURONŮ