Sprievodca deeplearning4j

1. Úvod

V tomto článku vytvoríme jednoduchú neurónovú sieť s knižnicou deeplearning4j (dl4j) - moderným a výkonným nástrojom pre strojové učenie.

Než začneme, neznamená to, že táto príručka nevyžaduje hlboké znalosti lineárnej algebry, štatistiky, teórie strojového učenia a mnohých ďalších tém potrebných pre dobre založeného inžiniera ML.

2. Čo je to Deep Learning?

Neurónové siete sú výpočtové modely, ktoré pozostávajú z navzájom prepojených vrstiev uzlov.

Uzly sú neurónové procesory číselných údajov. Berú dáta zo svojich vstupov, aplikujú na ne nejaké váhy a funkcie a výsledky posielajú na výstupy. Takúto sieť je možné trénovať pomocou niekoľkých príkladov zdrojových údajov.

Cvičenie v podstate spočíva v ukladaní určitého číselného stavu (váh) v uzloch, čo neskôr ovplyvní výpočet. Príklady tréningu môžu obsahovať dátové položky s funkciami a niektoré známe triedy týchto položiek (napríklad „táto sada 16 × 16 pixelov obsahuje ručne písané písmeno„ a “).

Po ukončení tréningu neurónová sieť môžeodvodiť informácie z nových údajov, aj keď predtým tieto konkrétne údajové položky nevidel. Dobre vymodelovaná a dobre vyškolená sieť dokáže rozpoznať obrázky, ručne písané listy, reč, spracovať štatistické údaje, aby priniesla výsledky pre business intelligence, a oveľa viac.

Hlboké neurónové siete boli možné v posledných rokoch s pokrokom vo vysoko výkonných a paralelných výpočtoch. Takéto siete sa v tom líšia od jednoduchých neurónových sietípozostávajú z viacerých medziľahlých (alebo skrytých) vrstiev. Táto štruktúra umožňuje sieťam spracovávať údaje oveľa komplikovanejším spôsobom (rekurzívnym, rekurentným, konvolučným spôsobom atď.) A extrahovať z nich oveľa viac informácií.

3. Inštalácia projektu

Aby sme mohli knižnicu používať, potrebujeme minimálne Java 7. Kvôli niektorým natívnym komponentom tiež pracuje iba s 64-bitovou verziou JVM.

Predtým, ako začneme s príručkou, skontrolujte, či sú splnené požiadavky:

$ java -version java verzia „1.8.0_131“ Java (TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot (TM) 64-bitový server VM (build 25.131-b11, zmiešaný režim)

Najprv si do Mavenu pridáme požadované knižnice pom.xml spis. Extrahujeme verziu knižnice do záznamu vlastnosti (najnovšiu verziu knižníc nájdete v úložisku Maven Central):

 0.9.1 org.nd4j nd4j-native-platform $ {dl4j.version} org.deeplearning4j deeplearning4j-core $ {dl4j.version} 

Poznač si to nd4j-native-platform závislosť je jednou z niekoľkých dostupných implementácií.

Spolieha sa na natívne knižnice dostupné pre mnoho rôznych platforiem (macOS, Windows, Linux, Android atď.). Mohli by sme tiež prepnúť backend na platforma nd4j-cuda-8.0, ak by sme chceli vykonávať výpočty na grafickej karte, ktorá podporuje programovací model CUDA.

4. Príprava údajov

4.1. Príprava súboru DataSet

Napíšeme „Hello World“ strojového učenia - klasifikáciu dátovej sady kvetu dúhovky. Toto je súbor údajov, ktoré boli zhromaždené z kvetov rôznych druhov (Iris setosa, Iris versicolora Iris virginica).

Tieto druhy sa líšia dĺžkou a šírkou okvetných lístkov a sepálov. Bolo by ťažké napísať presný algoritmus, ktorý klasifikuje položku vstupných údajov (t. J. Určuje, k akému druhu konkrétna kvetina patrí). Ale dobre trénovaná neurónová sieť ju dokáže klasifikovať rýchlo a s malými chybami.

Použijeme verziu týchto údajov vo formáte CSV, kde stĺpce 0..3 obsahujú rôzne vlastnosti druhu a stĺpec 4 obsahuje triedu záznamu alebo druh kódovaný hodnotou 0, 1 alebo 2:

5.1,3.5,1.4,0.2,0 4.9,3.0,1.4,0.2,0 4.7,3.2,1.3,0.2,0 … 7.0,3.2,4.7,1.4,1 6.4,3.2,4.5,1.5,1 6.9,3.1,4.9,1.5,1 …

4.2. Vektorizácia a čítanie údajov

Triedu kódujeme číslom, pretože neurónové siete pracujú s číslami. Transformácia dátových položiek z reálneho sveta na série čísel (vektorov) sa nazýva vektorizácia - deeplearning4j na to používa knižnicu datavec.

Najskôr použijeme túto knižnicu na zadanie súboru s vektorizovanými údajmi. Pri vytváraní CSVRecordReader, môžeme určiť počet riadkov, ktoré sa majú preskočiť (napríklad ak má súbor riadok hlavičky) a symbol oddeľovača (v našom prípade čiarka):

try (RecordReader recordReader = new CSVRecordReader (0, ',')) {recordReader.initialize (new FileSplit (new ClassPathResource ("iris.txt"). getFile ())); //…}

Na opakovanie záznamu môžeme použiť ktorúkoľvek z viacerých implementácií súboru DataSetIterator rozhranie. Množiny údajov môžu byť pomerne rozsiahle a mohla by sa vám hodiť schopnosť stránkovať alebo ukladať hodnoty do vyrovnávacej pamäte.

Náš malý súbor údajov však obsahuje iba 150 záznamov, takže po načítaní načítajme všetky údaje naraz do pamäte iterator.next ().

Ďalej zadáme index stĺpca triedy ktorý je v našom prípade rovnaký ako počet funkcií (4) a celkový počet tried (3).

Pamätajte tiež na to musíme zamiešať množinu údajov, aby sme sa zbavili usporiadania tried v pôvodnom súbore.

Namiesto predvolenej hodnoty určíme konštantné náhodné semeno (42) System.currentTimeMillis () hovor tak, aby boli výsledky premiešania vždy rovnaké. To nám umožňuje získať stabilné výsledky pri každom spustení programu:

DataSetIterator iterátor = nový RecordReaderDataSetIterator (recordReader, 150, FEATURES_COUNT, CLASSES_COUNT); DataSet allData = iterator.next (); allData.shuffle (42);

4.3. Normalizácia a rozdelenie

Ďalšou vecou, ​​ktorú by sme mali urobiť s dátami pred tréningom, je normalizácia. Normalizácia je dvojfázový proces:

  • zhromažďovanie niektorých štatistík o údajoch (prispôsobenie)
  • zmena (transformácia) údajov, aby boli jednotné

Normalizácia sa môže líšiť pre rôzne typy údajov.

Napríklad, ak chceme spracovať obrázky rôznych veľkostí, mali by sme najskôr zhromaždiť štatistiku veľkostí a potom ich zväčšiť na jednotnú veľkosť.

Normalizácia však pre čísla zvyčajne znamená ich transformáciu do takzvaného normálneho rozdelenia. The Normalizátor Štandardizovať trieda nám s tým môže pomôcť:

DataNormalization normalizer = new NormalizerStandardize (); normalizer.fit (allData); normalizer.transform (allData);

Teraz, keď sú údaje pripravené, je potrebné rozdeliť množinu na dve časti.

Prvá časť sa použije na školení. Druhú časť dát (ktoré by sieť vôbec nevidela) použijeme na otestovanie trénovanej siete.

To by nám umožnilo overiť, či klasifikácia funguje správne. Vezmeme 65% údajov (0,65) na školenie a zvyšok ponecháme na testovanie 35%:

SplitTestAndTrain testAndTrain = allData.splitTestAndTrain (0,65); DataSet trainingData = testAndTrain.getTrain (); DataSet testData = testAndTrain.getTest ();

5. Príprava konfigurácie siete

5.1. Plynulý konfigurátor konfigurácie

Teraz môžeme vytvoriť konfiguráciu našej siete pomocou efektného plynulého nástroja na vytváranie:

Konfigurácia MultiLayerConfiguration = nový NeuralNetConfiguration.Builder () .iterations (1000) .activation (Activation.TANH) .weightInit (WeightInit.XAVIER) .learningRate (0,1) .regularizácia (true) .l2 (0,0001) .list () .layer ( 0, nový DenseLayer.Builder (). NIn (FEATURES_COUNT) .nOut (3) .build ()) .layer (1, nový DenseLayer.Builder (). NIn (3) .nOut (3) .build ()). vrstva (2, nový OutputLayer.Builder (LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .activation (Activation.SOFTMAX) .nIn (3) .nOut (CLASSES_COUNT) .build ()) .backprop (true) .pretrain (false) .build ( );

Aj pri tomto zjednodušenom plynulom spôsobe budovania sieťového modelu je tu veľa čo stráviť a veľa vyladiť parametre. Pozrime sa na tento model.

5.2. Nastavenie sieťových parametrov

The iterácie () metóda builder určuje počet optimalizačných iterácií.

Iteratívna optimalizácia znamená vykonávanie viacerých prechodov na cvičnej množine, kým sa sieť nezblíži k dobrému výsledku.

Zvyčajne pri tréningu na skutočných a veľkých súboroch údajov používame viac epoch (úplné odovzdanie údajov cez sieť) a jednu iteráciu pre každú epochu. Ale keďže náš počiatočný súbor údajov je minimálny, použijeme jednu epochu a viac iterácií.

The aktivácia () je funkcia, ktorá beží vo vnútri uzla na určenie jeho výstupu.

Najjednoduchšia aktivačná funkcia by bola lineárna f (x) = x. Ukázalo sa však, že iba nelineárne funkcie umožňujú sieťam riešiť zložité úlohy pomocou niekoľkých uzlov.

Existuje veľa rôznych aktivačných funkcií, ktoré môžeme vyhľadať v org.nd4j.linalg.activations.Activation enum. V prípade potreby by sme mohli napísať aj našu aktivačnú funkciu. Použijeme ale poskytnutú funkciu hyperbolického tangensu (tanh).

The weightInit () metóda určuje jeden z mnohých spôsobov nastavenia počiatočných váh pre sieť. Správne počiatočné hmotnosti môžu mať výrazný vplyv na výsledky tréningu. Bez toho, aby sme sa príliš učili matematiku, nastavme to na formu Gaussovej distribúcie (WeightInit.XAVIER), pretože to je zvyčajne dobrá voľba na začiatok.

Všetky ostatné metódy inicializácie hmotnosti nájdete v org.deeplearning4j.nn.weights.WeightInit enum.

Miera učenia je rozhodujúcim parametrom, ktorý zásadne ovplyvňuje schopnosť siete učiť sa.

V zložitejšom prípade sme mohli stráviť veľa času ladením tohto parametra. Ale pre našu jednoduchú úlohu použijeme dosť významnú hodnotu 0,1 a nastavíme ju na learningRate () staviteľská metóda.

Jedným z problémov s trénovaním neurónových sietí je prípad nadmerného vybavenia keď si sieť „zapamätá“ údaje o tréningu.

To sa stane, keď sieť nastaví nadmerne vysoké váhy pre tréningové dáta a prinesie zlé výsledky pri akýchkoľvek iných dátach.

Na vyriešenie tohto problému nastavíme regularizáciu l2 s čiarou .regularizácia (true) .l2 (0,0001). Regularizácia „penalizuje“ sieť za príliš veľké váhy a zabráni nadmernému vybaveniu.

5.3. Budovanie sieťových vrstiev

Ďalej vytvoríme sieť hustých (tiež známych ako plne pripojených) vrstiev.

Prvá vrstva by mala obsahovať rovnaké množstvo uzlov ako stĺpce v tréningových údajoch (4).

Druhá hustá vrstva bude obsahovať tri uzly. Toto je hodnota, ktorú môžeme variovať, ale počet výstupov v predchádzajúcej vrstve musí byť rovnaký.

Výsledná výstupná vrstva by mala obsahovať počet uzlov zodpovedajúci počtu tried (3). Štruktúra siete je znázornená na obrázku:

Po úspešnom zaškolení budeme mať sieť, ktorá cez svoje vstupy prijíma štyri hodnoty a vysiela signál na jeden z jej troch výstupov. Toto je jednoduchý klasifikátor.

Nakoniec dokončíme budovanie siete, nastavíme spätné šírenie (jedna z najefektívnejších výcvikových metód) a deaktivujeme predtréningovku s linkou .backprop (true) .pretrain (false).

6. Vytváranie a školenie siete

Teraz vytvorme neurónovú sieť z konfigurácie, inicializujme ju a spustime:

Model MultiLayerNetwork = nová MultiLayerNetwork (konfigurácia); model.init (); model.fit (trainingData);

Teraz môžeme testovaný model otestovať pomocou zvyšku množiny údajov a výsledky overiť pomocou hodnotiacich metrík pre tri triedy:

Výstup INDArray = model.output (testData.getFeatureMatrix ()); Hodnotenie eval = nové hodnotenie (3); eval.eval (testData.getLabels (), výstup);

Ak teraz vytlačíme eval.stats (), uvidíme, že naša sieť je celkom dobrá v klasifikácii kvetov dúhovky, aj keď trikrát omylom zamenila triedu 1 za triedu 2.

Príklady označené ako 0 klasifikované podľa modelu ako 0: 19 krát Príklady označené ako 1 klasifikované podľa modelu ako 1:16 krát Príklady označené ako 1 klasifikované podľa modelu ako 2: 3 krát Príklady označené ako 2 klasifikované podľa modelu ako 2: 15 krát == ========================= Skóre ========================== ================ Počet tried: 3 Presnosť: 0,9434 Presnosť: 0,9444 Recall: 0,9474 Skóre F1: 0,9411 Precision, recall & F1: priemerná hodnota v makrách (rovnako vážený priemer 3 tried) ) ================================================== ========================

Plynulý konfigurátor konfigurácií nám umožňuje rýchlo pridávať alebo upravovať vrstvy siete alebo upravovať niektoré ďalšie parametre, aby sme zistili, či je možné náš model vylepšiť.

7. Záver

V tomto článku sme vytvorili jednoduchú, ale výkonnú neurónovú sieť pomocou knižnice deeplearning4j.

Zdrojový kód článku je ako vždy k dispozícii na stránkach GitHub.


$config[zx-auto] not found$config[zx-overlay] not found