Útmutató a Deeplearning4j-hez

1. Bemutatkozás

Ebben a cikkben létrehozunk egy egyszerű ideghálózatot a deeplearning4j (dl4j) könyvtárral - ez egy modern és hatékony eszköz a gépi tanuláshoz.

Mielőtt belekezdenénk, nem azért, mert ez az útmutató nem igényli a lineáris algebra, a statisztikák, a gépi tanulás elméletének és sok más, egy jól megalapozott ML mérnök számára szükséges ismeretét.

2. Mi a mély tanulás?

A neurális hálózatok olyan számítási modellek, amelyek összekapcsolt csomópontrétegekből állnak.

A csomópontok a numerikus adatok neuronszerű feldolgozói. Adatokat vesznek a bemeneteikről, bizonyos súlyokat és függvényeket alkalmaznak ezekre az adatokra, és az eredményeket kimenetre küldik. Az ilyen hálózat kiképezhető a forrásadatok néhány példájával.

Az edzés lényegében valamilyen numerikus állapot (súly) megtakarítását jelenti a csomópontokban, ami később befolyásolja a számítást. A képzési példák tartalmazhatnak olyan elemeket, amelyek jellemzőkkel rendelkeznek, és ezeknek az osztályoknak bizonyos ismert osztályait (például „ez a 16 × 16 pixeles készlet tartalmaz egy kézzel írott„ a ”betűt).

Az edzés befejezése után egy ideghálózat képesinformációkat nyerjen új adatokból, még akkor is, ha korábban nem látta ezeket az adott adatelemeket. Egy jól modellezett és jól képzett hálózat képes felismerni a képeket, a kézzel írott leveleket, a beszédet, a statisztikai adatokat feldolgozni az üzleti intelligencia érdekében, és még sok minden mást.

A mély neurális hálózatok az utóbbi években lehetővé váltak a nagy teljesítményű és párhuzamos számítástechnika fejlődésével. Az ilyen hálózatok abban különböznek az egyszerű idegi hálózatoktóltöbb köztes (vagy rejtett) rétegből állnak. Ez a struktúra lehetővé teszi a hálózatok számára, hogy az adatokat sokkal bonyolultabban dolgozzák fel (rekurzív, visszatérő, konvolúciós módon stb.), És sokkal több információt nyerjenek ki belőle.

3. A projekt beállítása

A könyvtár használatához legalább Java 7-re van szükségünk. Néhány natív összetevő miatt ez is csak a 64 bites JVM verzióval működik.

Az útmutató megkezdése előtt ellenőrizzük, hogy teljesülnek-e a követelmények:

$ java -verzió java "1.8.0_131" Java (TM) SE futási környezet (1.8.0_131-b11 build) Java HotSpot (TM) 64 bites kiszolgáló virtuális gép (25.131-b11 build, vegyes mód)

Először adjuk hozzá a szükséges könyvtárakat a Maven-hez pom.xml fájl. Kibontjuk a könyvtár verzióját egy tulajdonságbejegyzésbe (a könyvtárak legújabb verziójához nézze meg a Maven Central adattárat):

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

Vegye figyelembe, hogy nd4j-native-platform a függőség a számos rendelkezésre álló megvalósítás egyike.

Számos különböző platformon (macOS, Windows, Linux, Android stb.) Elérhető natív könyvtárakra támaszkodik. A backendet is átkapcsolhatnánk nd4j-cuda-8.0-platform, ha a CUDA programozási modellt támogató grafikus kártyán akartunk számításokat végrehajtani.

4. Az adatok előkészítése

4.1. A DataSet fájl előkészítése

Megírjuk a gépi tanulás „Hello World” -jét - az íriszvirág adatkészlet osztályozását. Ez egy olyan adatkészlet, amelyet különböző fajok virágaiból gyűjtöttek (Iris setosa, Iris versicolor, és Iris virginica).

Ezek a fajok a szirmok és a csészelevelek hosszában és szélességében különböznek egymástól. Nehéz lenne olyan pontos algoritmust írni, amely osztályozza egy bemeneti adatelemet (azaz meghatározza, hogy az adott virág mely fajhoz tartozik). De egy jól képzett ideghálózat gyorsan és apró hibák nélkül képes osztályozni.

Ezen adatok CSV-változatát fogjuk használni, ahol a 0..3. Oszlop a faj különféle jellemzőit tartalmazza, a 4. oszlop pedig a rekord osztályát vagy a fajokat 0, 1 vagy 2 értékkel kódolva:

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. Az adatok vektorizálása és olvasása

Az osztályt számmal kódoljuk, mert az ideghálózatok számokkal működnek. A valós adatelemek szám-sorozattá (vektorokká) való átalakítását vektorizálásnak nevezzük - A deeplearning4j a datavec könyvtárat használja erre.

Először használjuk ezt a könyvtárat a vektorizált adatokkal rendelkező fájl beviteléhez. A CSVRecordReader, megadhatjuk az átugorandó sorok számát (például, ha a fájl fejlécsorral rendelkezik) és az elválasztó szimbólumot (esetünkben vesszőt):

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

A rekordok közötti ismétléshez használhatjuk a DataSetIterator felület. Az adatkészletek meglehetősen masszívak lehetnek, és az értékek oldalra helyezése vagy gyorsítótárazásának lehetősége hasznos lehet.

De kis adatkészletünk csak 150 rekordot tartalmaz, ezért olvassuk be egyszerre az összes adatot a memóriába egy hívással iterator.next ().

Megadjuk az osztály oszlopának indexét is ami esetünkben megegyezik a funkciószámmal (4) és az osztályok teljes számát (3).

Ezt is vegye figyelembe kevernünk kell az adatkészletet, hogy megszabaduljunk az osztályfájlok sorrendjétől az eredeti fájlban.

Megadunk egy állandó véletlen magot (42) az alapértelmezett helyett System.currentTimeMillis () hívást, hogy a keverés eredménye mindig ugyanaz legyen. Ez lehetővé teszi számunkra, hogy stabil eredményeket érjünk el minden alkalommal, amikor futtatjuk a programot:

DataSetIterator iterator = new RecordReaderDataSetIterator (recordReader, 150, FEATURES_COUNT, CLASSES_COUNT); DataSet allData = iterator.next (); allData.shuffle (42);

4.3. Normalizálás és felosztás

Egy másik dolog, amit edzés előtt meg kell tennünk az adatokkal, az a normalizálás. A normalizálás kétfázisú folyamat:

  • statisztikák összegyűjtése az adatokról (illeszkedés)
  • az adatok valamilyen módon történő megváltoztatása (átalakítása) az egységessé tétele érdekében

A normalizálás különböző adattípusoknál eltérhet.

Például, ha különféle méretű képeket akarunk feldolgozni, akkor először össze kell gyűjtenünk a méretstatisztikát, majd a képeket egységes méretre kell méreteznünk.

De a számok számára a normalizálás általában azt jelenti, hogy átalakítsuk őket egy úgynevezett normál eloszlássá. A NormalizerStandardize osztály ebben segíthet nekünk:

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

Most, hogy az adatok elkészültek, két részre kell osztanunk a készletet.

Az első részt egy edzésen fogják felhasználni. Az adatok második részét (amelyet a hálózat egyáltalán nem látna) felhasználjuk a betanított hálózat tesztelésére.

Ez lehetővé tenné számunkra annak ellenőrzését, hogy az osztályozás megfelelően működik-e. Az adatok 65% -át (0,65) a képzésre vesszük, a fennmaradó 35% -ot a tesztelésre hagyjuk:

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

5. A hálózati konfiguráció előkészítése

5.1. Folyékony Konfigurációkészítő

Most elkészíthetjük hálózatunk konfigurációját egy fantasztikus, folyékony építővel:

MultiLayerConfiguration configuration = new NeuralNetConfiguration.Builder () .iterations (1000) .activation (Activation.TANH) .weightInit (WeightInit.XAVIER) .learningRate (0.1). Regularization (true) .l2 (0.0001) .list () .layer ( 0, új DenseLayer.Builder (). NIn (FEATURES_COUNT) .nOut (3) .build ()) .layer (1, új DenseLayer.Builder (). NIn (3) .nOut (3) .build ()). réteg (2, új OutputLayer.Builder (LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .aktiválás (Activation.SOFTMAX) .nIn (3) .nOut (CLASSES_COUNT) .build ()) .backprop (true) .pretrain (false) .build ( );

A hálózati modell felépítésének egyszerűsített folyékony módja mellett is sok mindent meg kell emésztenünk, és sok paramétert kell módosítanunk. Bontjuk le ezt a modellt.

5.2. Hálózati paraméterek beállítása

A iterációk () a builder módszer meghatározza az optimalizálási iterációk számát.

Az iteratív optimalizálás azt jelenti, hogy többször is el kell végezni az edzéskészletet, amíg a hálózat nem konvergál jó eredményre.

Általában a valós és nagy adatkészletekről való képzés során több korszakot (teljes adatátvitel a hálózaton keresztül) és egy iterációt használunk minden korszakhoz. De mivel a kezdeti adatkészletünk minimális, egy korszakot és többszörös iterációt fogunk használni.

A aktiválás() egy olyan funkció, amely egy csomópont belsejében fut, hogy meghatározza annak kimenetét.

A legegyszerűbb aktiválási függvény lineáris lenne f (x) = x. De kiderült, hogy csak a nem lineáris függvények teszik lehetővé a hálózatok számára, hogy összetett feladatokat oldjanak meg néhány csomópont használatával.

Rengeteg különféle aktiválási funkció áll rendelkezésre, amelyeket a org.nd4j.linalg.activations.Activation enum. Szükség esetén megírhatnánk aktiválási funkciónkat is. De a megadott hiperbolikus tangens (tanh) funkciót fogjuk használni.

A weightInit () A módszer meghatározza a hálózat kezdeti súlyainak beállításának számos módját. A helyes kezdeti súlyok mélyen befolyásolhatják a képzés eredményeit. Anélkül, hogy túl sokat foglalkoznánk a matematikával, állítsuk a Gauss-eloszlás egyik formájára (WeightInit.XAVIER), mivel ez kezdetben általában jó választás.

Az összes többi súly inicializálási módszer a org.deeplearning4j.nn.weights.WeightInit enum.

Tanulási arány kulcsfontosságú paraméter, amely mélyen befolyásolja a hálózat tanulási képességét.

Sok időt tölthetnénk ennek a paraméternek a módosításával egy bonyolultabb esetben. De egyszerű feladatunkhoz elég jelentős 0,1-es értéket használunk, és beállítjuk a learningRate () építő módszer.

A neurális hálózatok képzésének egyik problémája a túlfeszültség esete amikor egy hálózat „megjegyzi” az edzés adatait.

Ez akkor történik, amikor a hálózat túl nagy súlyt állít fel az edzésadatokra, és rossz eredményeket hoz bármely más adattal szemben.

A probléma megoldásához fel fogjuk állítani az l2 rendszeresítését a vonallal .szabályozás (igaz) .l2 (0,0001). A rendszeresítés „bünteti” a hálózatot túl nagy súlyok miatt, és megakadályozza a túlfeszültséget.

5.3. Hálózati rétegek építése

Ezután létrehozunk egy sűrű (más néven teljesen összekapcsolt) rétegek hálózatát.

Az első rétegnek ugyanannyi csomópontot kell tartalmaznia, mint az edzésadatok oszlopai (4).

A második sűrű réteg három csomópontot tartalmaz. Ez az az érték, amelyet változtathatunk, de az előző réteg kimenetének ugyanannak kell lennie.

A végső kimeneti rétegnek tartalmaznia kell az osztályok számának megfelelő csomópontok számát (3). A hálózat felépítése a képen látható:

A sikeres képzés után lesz egy hálózatunk, amely négy értéket kap a bemenetein keresztül, és jelet küld a három kimenet egyikébe. Ez egy egyszerű osztályozó.

Végül a hálózat kiépítésének befejezéséhez beállítottuk a hátteret (az egyik leghatékonyabb képzési módszer), és letiltottuk az előképzést a vonallal .backprop (igaz) .pretrain (hamis).

6. Hálózat létrehozása és oktatása

Most hozzunk létre egy neurális hálózatot a konfigurációból, inicializáljuk és futtassuk:

MultiLayerNetwork modell = új MultiLayerNetwork (konfiguráció); modell.init (); model.fit (trainingData);

Most tesztelhetjük a képzett modellt az adatkészlet többi részének felhasználásával, és három osztály értékelési mutatóival ellenőrizhetjük az eredményeket:

INDArray output = model.output (testData.getFeatureMatrix ()); Értékelés eval = új értékelés (3); eval.eval (testData.getLabels (), output);

Ha most kinyomtatjuk a eval.stats (), látni fogjuk, hogy hálózatunk nagyon jó az íriszvirágok osztályozásában, bár háromszor hibáztatta az 1. osztályt a 2. osztály számára.

0-ként címkézett példák modell szerint 0: 19-szeres példákként 1-es címkével ellátott példák modellek szerint 1: 16-szoros példákként 1-es címkével ellátott példák modellek szerint 2: 3-szorosakként 2-szer 3-szoros példák ========================== =========================== =============== osztályok száma: 3 Pontosság: 0.9434 Pontosság: 0.9444 Visszahívás: 0.9474 F1 Pontszám: 0.9411 Pontosság, visszahívás és F1: makroátlagolt (3 osztály egyenlő súlyozott átlaga ) =================================================== =======================

A folyékony konfigurációs készítő lehetővé teszi számunkra, hogy gyorsan hozzáadjuk vagy módosítsuk a hálózat rétegeit, vagy módosítsunk néhány egyéb paramétert, hogy meggyőződjünk arról, javítható-e a modellünk.

7. Következtetés

Ebben a cikkben egy egyszerű, de mégis erőteljes ideghálózatot építettünk fel a deeplearning4j könyvtár használatával.

Mint mindig, a cikk forráskódja elérhető a GitHubon.


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