Logisztikai regresszió Java-ban

1. Bemutatkozás

A logisztikai regresszió fontos eszköz a gépi tanulás (ML) gyakorlói eszköztárában.

Ebben az oktatóanyagban feltárjuk a logisztikai regresszió mögött álló fő gondolatot.

Először kezdjük az ML paradigmák és algoritmusok rövid áttekintésével.

2. Áttekintés

Az ML lehetővé teszi számunkra az olyan problémák megoldását, amelyeket emberbarát módon fogalmazhatunk meg. Ez a tény azonban kihívást jelenthet számunkra szoftverfejlesztők számára. Megszoktuk magunkat, hogy számítógép-barát módon fogalmazzuk meg azokat a problémákat, amelyeket megfogalmazhatunk. Például emberként könnyen észlelhetjük a fotón lévő tárgyakat, vagy megteremthetjük egy kifejezés hangulatát. Hogyan fogalmazhatnánk meg egy ilyen problémát egy számítógép számára?

Annak érdekében, hogy megoldást találjunk, az ML-ben van egy speciális szakasz, az úgynevezett kiképzés. Ebben a szakaszban a bemeneti adatokat betápláljuk algoritmusunkba, hogy az megpróbáljon optimális paraméterkészletet (ún. Súlyokat) előállítani. Minél több bemenő adatot táplálhatunk az algoritmusba, annál pontosabb előrejelzéseket várhatunk tőle.

A képzés egy iteratív ML munkafolyamat része:

Az adatok megszerzésével kezdjük. Az adatok gyakran különböző forrásokból származnak. Ezért azonos formátumúvá kell tennünk. Azt is ellenőriznünk kell, hogy az adatkészlet meglehetősen reprezentálja-e a vizsgálati területet. Ha a modellt soha nem képezték piros almára, akkor alig tudja megjósolni.

Ezután meg kell építenünk egy modellt, amely fel fogja használni az adatokat, és képes lesz előrejelzéseket készíteni. Az ML-ben nincsenek előre definiált modellek, amelyek minden helyzetben jól működnek.

A megfelelő modell keresésekor könnyen előfordulhat, hogy felépítünk egy modellt, kiképezzük, megnézzük az előrejelzéseit és elvetjük a modellt, mert nem vagyunk elégedettek az általa készített jóslatokkal. Ebben az esetben vissza kell lépnünk, fel kell építenünk egy másik modellt, és ismételjük meg a folyamatot.

3. ML paradigmák

Az ML-ben az alapján, hogy milyen input adatok állnak rendelkezésünkre, három fő paradigmát emelhetünk ki:

  • felügyelt tanulás (képosztályozás, tárgyfelismerés, hangulatelemzés)
  • felügyelet nélküli tanulás (anomáliák felderítése)
  • megerősítő tanulás (játékstratégiák)

Az az eset, amelyet le fogunk írni ebben az oktatóanyagban a felügyelt tanulás tartozik.

4. ML Eszköztár

Az ML-ben van egy sor eszköz, amelyet alkalmazhatunk egy modell felépítésekor. Említsünk néhányat közülük:

  • Lineáris regresszió
  • Logisztikus regresszió
  • Ideghálózatok
  • Támogatja a vektor gépet
  • k-Legközelebbi szomszédok

Számos eszközt kombinálhatunk, ha olyan modellt építünk, amelynek nagy a prediktivitása. Valójában ebben az oktatóanyagban modellünk logisztikai regressziót és neurális hálózatokat fog használni.

5. ML könyvtárak

Annak ellenére, hogy a Java nem a legnépszerűbb nyelv az ML modellek prototípusának elkészítéséhez,megbízható eszközként ismeri el a robusztus szoftverek létrehozását számos területen, beleértve az ML-t is. Ezért találhatunk Java-ban írt ML könyvtárakat.

Ebben az összefüggésben megemlíthetjük a de facto szabványos Tensorflow könyvtárat, amelynek Java verziója is van. Egy másik említésre méltó a Deeplearning4j nevű mély tanulási könyvtár. Ez egy nagyon hatékony eszköz, és ebben az oktatóanyagban is használni fogjuk.

6. Logisztikai regresszió a számfelismerésben

A logisztikai regresszió fő gondolata egy olyan modell felépítése, amely a bemeneti adatok címkéit a lehető legpontosabban megjósolja.

Addig képezzük a modellt, amíg az úgynevezett veszteségfüggvény vagy objektív függvény el nem éri a minimális értéket. A veszteségfüggvény függ a tényleges modelljóslatoktól és a várhatóaktól (a bemeneti adatok címkéitől). Célunk a tényleges modelljóslatok és a várhatóak divergenciájának minimalizálása.

Ha nem vagyunk elégedettek ezzel a minimális értékkel, akkor fel kell építenünk egy másik modellt, és újra végre kell hajtanunk a képzést.

Annak érdekében, hogy a logisztikai regressziót működés közben lássuk, szemléltetjük a kézzel írott számjegyek felismerésével. Ez a probléma már klasszikusá vált. A Deeplearning4j könyvtárnak reális példái vannak, amelyek bemutatják az API használatát. Az oktatóanyag kóddal kapcsolatos része nagymértékben alapul MNIST osztályozó.

6.1. Beviteli adat

Bemeneti adatokként a kézírásos számjegyek jól ismert MNIST adatbázisát használjuk. Bemeneti adatokként 28 × 28 pixeles szürkeárnyalatos képeink vannak. Minden képnek természetes címkéje van, amely az a szám, amelyet a kép képvisel:

A felépítendő modell hatékonyságának megbecsülése érdekében a bemeneti adatokat oktatási és tesztkészletekre bontjuk:

DataSetIterator vonat = new RecordReaderDataSetIterator (...); DataSetIterator teszt = new RecordReaderDataSetIterator (...);

Miután a bemeneti képeket felcímkézzük és felosztjuk a két halmazra, az „adatfeldolgozás” szakaszának vége, és áttérhetünk a „modellépítésre”.

6.2. Modellépület

Mint említettük, nincsenek olyan modellek, amelyek minden helyzetben jól működnek. Mindazonáltal az ML-ben végzett sok éves kutatás után a tudósok olyan modelleket találtak, amelyek nagyon jól teljesítenek a kézzel írott számjegyek felismerésében. Itt az úgynevezett LeNet-5 modellt használjuk.

A LeNet-5 egy neurális hálózat, amely rétegek sorozatából áll, amelyek a 28 × 28 pixeles képet tízdimenziós vektorgá alakítják:

A tízdimenziós kimeneti vektor annak valószínűségét tartalmazza, hogy a bemeneti kép címkéje 0, 1 vagy 2, és így tovább.

Például, ha a kimeneti vektor formája a következő:

{0.1, 0.0, 0.3, 0.2, 0.1, 0.1, 0.0, 0.1, 0.1, 0.0}

ez azt jelenti, hogy a bemeneti kép nulla valószínűsége 0,1, az egyik 0, a kettő 0,3 stb. Látjuk, hogy a maximális valószínűség (0,3) megfelel a 3. címkének.

Merüljünk bele a modellépítés részleteibe. Elhagyjuk a Java-specifikus részleteket, és az ML koncepciókra koncentrálunk.

A modell létrehozásával a MultiLayerNetwork tárgy:

MultiLayerNetwork modell = új MultiLayerNetwork (config);

Konstruktorában el kell mennünk a MultiLayerConfiguration tárgy. Pontosan ez az objektum írja le az ideghálózat geometriáját. A hálózati geometria meghatározásához meg kell határoznunk minden réteget.

Mutassuk meg, hogyan csináljuk ezt az elsővel és a másodikkal:

ConvolutionLayer layer1 = új ConvolutionLayer .Builder (5, 5) .nIn (csatornák) .stride (1, 1) .nOut (20) .activation (Activation.IDENTITY) .build (); SubsamplingLayer layer2 = új SubsamplingLayer .Builder (SubsamplingLayer.PoolingType.MAX) .kernelSize (2, 2) .stride (2, 2) .build ();

Látjuk, hogy a rétegek definíciói jelentős mennyiségű ad-hoc paramétert tartalmaznak, amelyek jelentősen befolyásolják a teljes hálózati teljesítményt. Pontosan itt válik döntővé az a képességünk, hogy jó modellt találjunk mindenki táján.

Most készen állunk a MultiLayerConfiguration tárgy:

MultiLayerConfiguration config = new NeuralNetConfiguration.Builder () // előkészítési lépések .list () .layer (layer1) .layer (layer2) // egyéb rétegek és utolsó lépések .build ();

hogy átmegyünk a MultiLayerNetwork konstruktőr.

6.3. Kiképzés

Az általunk készített modell 431080 paramétert vagy súlyt tartalmaz. Nem fogjuk itt megadni ennek a számnak a pontos kiszámítását, de tisztában kell lennünk azzal, hogy csak taz első rétegnek több mint 24x24x20 = 11520 súlya van.

A képzési szakasz olyan egyszerű, mint:

modell.fit (vonat); 

Kezdetben a 431080 paramétereknek vannak véletlenszerű értékei, de az edzés után megszereznek néhány olyan értéket, amelyek meghatározzák a modell teljesítményét. Értékelhetjük a modell prediktivitását:

Értékelés eval = modell.értékelés (teszt); logger.info (eval.stats ());

A LeNet-5 modell meglehetősen nagy, csaknem 99% -os pontosságot ér el egyetlen edzés iteráció (korszak) alatt is. Ha nagyobb pontosságot akarunk elérni, akkor több sorrendet kell végrehajtanunk egy sima használatával for-loop:

for (int i = 0; i <korszakok; i ++) {modell.fit (vonat); vonat.reset (); teszt.reset (); } 

6.4. Jóslás

Most, amikor betanítottuk a modellt, és elégedettek vagyunk a tesztadatokkal kapcsolatos előrejelzéseivel, kipróbálhatjuk a modellt néhány teljesen új bemeneten. Ennek érdekében hozzunk létre egy új osztályt MnistPrediction amelybe képet töltünk fel egy fájlból, amelyet a fájlrendszerből választunk ki:

INDArray image = new NativeImageLoader (magasság, szélesség, csatornák) .asMatrix (fájl); új ImagePreProcessingScaler (0, 1) .transform (kép);

A változó kép tartalmazza a képünket 28 × 28 szürkeárnyalatosra csökkentve. Táplálhatjuk a modellünkre:

INDArray output = model.output (kép);

A változó Kimenet tartalmazza a kép valószínűségét, hogy nulla, egy, kettő stb.

Játsszunk most egy kicsit, írjunk egy 2-es számjegyet, digitalizáljuk ezt a képet és adjuk hozzá a modellt. Valami ilyesmit kaphatunk:

Mint látjuk, a 0,99 maximális értékű komponens indexe kettő. Ez azt jelenti, hogy a modell helyesen ismerte fel a kézzel írott számjegyünket.

7. Következtetés

Ebben az oktatóanyagban ismertettük a gépi tanulás általános fogalmait. Ezeket a fogalmakat logisztikai regressziós példán szemléltettük, amelyet kézzel írott számfelismerésre alkalmaztunk.

Mint mindig, a megfelelő kódrészleteket is megtalálhatjuk a GitHub-tárunkban.