Hlavní navigace

Biologické algoritmy (6) - Neuronové sítě

12. 12. 2012
Doba čtení: 5 minut

Sdílet

Po delší odmlce pokračuje seriál o biologicky inspirovaných algoritmech jako jsou evoluční algoritmy, neuronové sítě, konvoluční neuronové sítě a další. V dnešním díle implementujeme v jazyce Java algoritmus neuronové sítě. Neuronovou síť naučíme řešit praktický problém – rozpoznávat scénu na fotografiích.

Úvod do problému

Mějme sadu mnoha fotografií. Několik fotografií připravených pro tuto úlohu je znázorněno na obrázku dole. Našim cílem bude vytvořit aplikaci, která bude schopná rozlišit scénu na fotkách. Budeme rozlišovat mezi krajinou, skenem dokumentu, noční scénou a interiérem.

Aby takové rozlišení scény bylo skutečně jednoznačně rozhodnutelné, bylo by vhodné rozpoznávat jednotlivé objekty a jejich kompozici – např. detekovat nebe, stromy, nábytek a další objekty na fotografiích. Tento přístup je ovšem velmi komplexní a náročný na implementaci. Omezíme se na jednodušší příznaky, které nám o scéně mohou něco prozradit.

O scéně nám může mnoho prozradit vzájemná kompozice barev na různých místech v obrázku. Např. převažuje-li nahoře v obrázku modrá a dole zelená, lze usoudit, že nahoře je nejspíše nebe a dole zeleň – fotografie by se tak mohla klasifikovat jako krajina. Toto je výrazné zjednodušení problému, které může vést k nesprávné klasifikaci scény, nicméně zvolené scény, které hledáme – krajina, sken dokumentu, noční scéna a interiér – se vzájemně výrazně odlišují, a proto toto zjednodušení bude pro tyto druhy scén zcela postačující. Pro další rozlišení např. interiéru obývacího pokoje a kuchyně bychom si s takovým zjednodušením už nevystačili.

Barevnou kompozici budeme považovat za základní faktor pro rozlišení scén. Z fotografie můžeme barevnou kompozici snadno zjistit. Dále musí existovat nějaká neznámá funkce, která na vstup dostane kompozici barev a na výstupu bude přiřazená scéna. Jak tato neznámá funkce ale vypadá? Půjde-li o krajinu, ukázali jsme si, že zhruba tušíme, jak by kompozice mohla vypadat (nahoře modrá, dole zelená). Ale určitě i jiné kompozice barev mohou být považovány za krajinu. Dostáváme se tak k tomu, že podíváme-li se na obrázek, můžeme snadno říci: „ANO, funkce na základě příznaků správně přiřadila k obrázku typ scény“, ale bohužel už neumíme tuto funkci navrhnout tak, aby byla optimální. Pomocí neuronové sítě a jejím učením výpočet této neznáme funkce napodobíme (aproximujeme).

Popis programu

Stáhněte si připravený program v Javě. Ve zdrojovém kódu najdete tři třídy: Window, která se stará o vykreslení okna; NeuralNetwork, která realizuje činnost neuronové sítě; Neural, která obsahuje metodu main() a spouští aplikaci.

Společně s programem najdete v balíčku sadu obrázků: 1.jpg – 10.jpg krajina, 11.jpg – 20.jpg skén, 21.jpg – 30.jpg noční scéna a 31.jpg – 40.jpg interiér. Tato sada bude použita pro naučení neuronové sítě. Použití větší sady k učení by vedlo k přesnějšímu učení a tudíž i lepší klasifikaci.

Výpočet příznaků – barevné kompozice

Budeme potřebovat vypočítat tzv. histogram barev. Uvažujme paletu 64 různých barev – např. pole o délce 64. Fotografie má samozřejmě barev více, proto barvy na fotografií přiřadíme metodou nejbližšího souseda k těmto 64 vybraným. Budeme procházet každý pixel obrázku a jeho barvu přiřadíme k nejbližší barvě z těch 64 a zvýšíme počet této barvy. Na konci budeme vědět, kolik kterých barev v obrázku bylo.

Zároveň potřebujeme znát přibližnou pozici jednotlivých barev (např. nahoře je více modré a dole více zelené). Obrázek rozdělíme na čtyři oblasti tak, jak je to uvedeno na obrázku níže a v každé z těchto čtyř oblastí vypočteme histogram výše popsaným způsobem.

Popsaný výpočet lépe ilustruje další 64barevný obrázek, kde je vidět, kolik kterých barev je ve které ze čtyř oblastí.

Množství všech 64 barev ve všech čtyřech oblastech tak dává 64×4 = 256 číselný popis každého obrázku. Tento popis obsahuje v sobě zakódovanou informaci o obrázku. Každý obrázek tak lze reprezentovat vektorem o 256 dimenzích (1D polem o velikosti 256).

Výpočet histogramu barev má na starosti metoda double[] getHistogram(BufferedImage img).

Implementace neuronové sítě

Pro realizaci MLP feed forward neuronové sítě, kterou použijeme, není třeba implementovat každý neuron samostatně. Ve skutečnosti lze přenos mezi neurony realizovat formou násobení matic, čímž se výpočet výrazně zjednodušuje a zrychluje.

Ve třídě NeuralNetwork jsou proto deklarovány tři 2D pole (matice) typu double: weights1, weights2, weights3. Matice weights1 realizuje přenos mezi vstupní vrstvou a první skrytou vrstvou. Matice weights2 realizuje přenos mezi první a druhou skrytou vrstvou a matice weights3 mezi druhou skrytou a výstupní vrstvou.

Také jsou tam deklarovány tři matice: dWeights1, dWeights2, dWeights3. Tyto matice představují aktualizaci – změnu váh jednotlivých neuronů při každém kroku učení.

Matice weights1 a dWeights1 mají nInput+1 řádků a nLayer1 sloupců. Matice weights2 a dWeights2 mají nLayer1+1 řádků a nLayer2 sloupců. A matice weights3 a dWeights3 mají nLayer2+1 řádků a nOutput sloupců. Přitom nInput značí počet vstupů – v našem případě 256 vstupů pro každý obrázek, nLayer1 a nLayer 2 značí velikost první a druhé skryté vrstvy a nakonec nOutput značí počet výstupů – v našem případě 4 protože rozlišujeme mezi čtyřmi typy scén.

Ve třídě NeuralNetwork je také implementována metoda void plus(double[][] a, double[][] b, double times), která sčítá obě matice. Přesněji, provádí nad maticemi operaci: C = A+t*B.

Metoda void randomizeWeights() inicializuje váhy před učením neuronové sítě – a sice nastaví váhy na náhodná čísla.

Dále jsou zde implementovány metody double[] classify(double[] input) a void learnBPROP(double[][] inputData, double[][] outputData, double learnSpeed, double momentum) pro klasifikaci a učení pomocí algoritmu Backpropagation.

Klasifikace

Klasifikace probíhá velmi jednoduše. Třikrát se vynásobí matice a po každém násobení se aplikuje aktivační funkce. Tento postup je znázorněn na dalším obrázku. V prvním kroku – násobení vektoru maticí a ve druhém kroku aplikace aktivační funkce. Vektor, který takto dostaneme, použijeme pro násobení se druhou maticí weights2 a nakonec další vzniklý vektor pro násobení s maticí weights3. Výstupní vektor, který dostaneme potom již bude výsledek klasifikace. Aktivační funkce je funkce Sigmoid, která má matematické vyjádření: 1/(1+exp-γ×x).

Učení (Backpropagation)

Algoritmus Backpropagation je následující:

  1. vybere se vzorek
  2. neuronová síť provede klasifikaci
  3. výsledek klasifikace se porovná s očekávaným výstupem a vypočtou se změny vah podle odchylky
  4. váhy neuronové sítě se aktualizují a vybere se další vzorek podle kroku 1.

Implementujeme algoritmus Backpropagation s momentem. Moment zajišťuje rychlejší učení a zabraňuje uvíznutí v lokálním extrému v průběhu učení – síť se tak může naučit kvalitněji. Na moment je třeba nahlížet jako na zrychlení. Aktualizují-li se váhy na po sobě jdoucích vzorcích stále stejným směrem, lze učení zrychlit tím, že se budou váhy aktualizovat výrazněji. Budeme si pamatovat předchozí změny vah v maticích dWeights1, dWeights2 a dWeights3 a při aktualizaci vah neuronové sítě zvýšíme změnu i o tyto předešlé hodnoty.

Algoritmus učení je implementován v metodě learnBPROP(double[][] inputData, double[][] outputData, double learnSpeed, double momentum).

Výsledek

Po spuštění program načte všech 40 obrázků (1.jpg – 40.jpg) a vypočte na nich 256 příznaků pro každý obrázek. Na těchto popisech se neuronová síť naučí. Potom se načte nový (neznámý) obrázek night.jpg a program vypíše výsledek klasifikace.

Cloud 24 - tip 1

V průběhu učení program vypisuje úspěšnost klasifikace v procentech. Po naučení by úspěšnost na těchto trénovacích obrázcích měla být okolo 97,5 %.

Příště

V příštím díle se seznámíme s pokrokovější neuronovou sítí – tzv. Neocognitron. Jedná se o neuronovou síť, která je navržena na základě poznatků o procesech v lidském oku.

Byl pro vás článek přínosný?