képfelismerés a Python gépi tanulásával, konvolúciós neurális hálózaton

forrás: the Irish Times, P), P), P), P), P), P), P), P), C), P), P), P), P), P), P), P), P), P), p), p), p), p), p), p),

az adatok előfeldolgozása után, itt az ideje, hogy a képfelismerő feladat végrehajtásához modellünket építsük fel. Az egyik technika a konvolúciós neurális hálózat.

Ez a cikk a képfeldolgozásról írt cikket követi. Miután elérhetővé tette az adatokat a képfelismerési feladathoz, itt az ideje létrehozni egy algoritmust, amely elvégzi a feladatot. A képek többrétegű perceptron modellként történő felismerésére használt számos technika közül a konvolúciós neurális hálózat (CNN) nagyon hatékonynak tűnik. Ebben a cikkben látni fogjuk, hogyan kell felépíteni egy CNN-t, és hogyan kell alkalmazni a képek adatkészletére.

amikor először építünk fel egy képfelismerő modellt, általában jó ötlet egy viszonylag egyszerű adatkészleten kiképezni és értékelni.

az egyik legegyszerűbb feladat, amelyet elvégezhetünk, a kézírásos számjegyfelismerés. Adott egy kézzel írt számjegy képe (pl., 0, 1, …, 9), Azt akarjuk, hogy modellünk képes legyen helyesen osztályozni numerikus értékét. Bár ez a feladat viszonylag egyszerűnek tűnik, valójában meglehetősen gyakran használják a való életben, például automatikusan kivonják a hitelkártya-számokat egy képből. A számjegy felismeréshez használt adatkészlet az MNIST adatkészlet, amely a gépi tanuláson alapuló számjegy felismeréshez használt adatkészlet.

az MNIST (Modified National Institute of Standards And Technology) adatbázis 60 000 képzési és 10 000 tesztelési példát tartalmaz. Az adatbázis szürkeárnyalatos, kézzel írt számjegyeket tartalmaz, amelyeket átméreteztek, hogy elférjenek egy 20×20 pixeles dobozban, amelyet aztán egy 28×28-as kép középpontjába helyeztek (szóközökkel kitöltve). Az MNIST adatbázis Pythonon keresztül érhető el.

ebben a cikkben megmutatom, hogyan kell kódolni a konvolúciós neurális hálózatot a keras, a TensorFlow magas szintű API segítségével. Ebben a cikkben a tensorflow 2.0-t használom.

1-inicializálás

mivel minden szürkeárnyalatos kép mérete 28×28, képenként 784 Pixel van. Ezért minden bemeneti kép 784 0,0 és 1,0 közötti normalizált lebegőpontos érték tenzorának felel meg. A kép címkéje egy forró tenzor, 10 osztállyal (minden osztály egy számjegyet jelent). A kódunkat tekintve img_rows = 28, img_cols = 28 és num_classes = 10. Így a bemenet alakja (number_examples, img_rows, img_cols) tehát 60000x28x28.
Egy másik fontos eleme, hogy hozzanak létre a véletlen mag, mint azt akarjuk, hogy a kiindulási pont, amikor a számítógép generál egy véletlen számsorozat.

importáljuk az MNIST adatkészletet is.

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as npseed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)# input image dimensions
num_classes = 10 # 10 digits
img_rows, img_cols = 28, 28 # number of pixels
# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

2 – átformálás és átméretezés

az előző szakaszban említettek szerint a bemenetek alakja van (number_examples, img_rows, img_cols). Ahhoz azonban, hogy az adatokat konvolúciós neurális hálózatunkkal felhasználhassuk, NHWC formátumba kell vinnünk.

az NHWC formátum Négy dimenzióval rendelkezik:

  1. képadatminták száma (kötegméret)
  2. Az egyes képek magassága
  3. Az egyes képek szélessége
  4. csatornák képenként

az adatkészletből származó egyes képek magassága és szélessége img_rows és img_cols, míg a csatornák száma 1 (mivel a képek szürkeárnyalatosak).

ezenkívül minden pixel tartalmaz egy szürkeárnyalatos értéket, amelyet egy 0 és 255 közötti egész szám határoz meg. Tehát az adatbázis normalizálódik, hogy lebegőpontos értékei 0,0 és 1,0 között legyenek. Ebben az esetben a 0,0 255 (tiszta fehér) szürkeárnyalatos pixelértéknek felel meg, míg az 1.A 0 0 (tiszta fekete) szürkeárnyalatos pixelértéknek felel meg.

X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1) 
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255

3 – Címkevektorok öntése Y

osztályainkat vektorokká kell átalakítanunk. Ezt a következő sor megérintésével végezzük:

Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)

a lépés jobb magyarázatához olvassa el ezt a cikket.

most, hogy feldolgoztuk az adatainkat, elkezdhetjük építeni a modellt.

Convolution neurális hálózati modell

amint azt a Képfeldolgozásról írt cikk végén említettem, a szűrők hatalmas szerepet játszanak a képfelismerésben. Szűrőket használunk a bemenetek átalakítására és olyan funkciók kivonására, amelyek lehetővé teszik modellünk számára bizonyos képek felismerését. Nagyon magas szintű példa erre egy görbe detektáló szűrő, amely lehetővé teszi modellünk számára, hogy megkülönböztesse a görbékkel rendelkező számjegyeket és a görbék nélküli számjegyeket.

1-szűrők

mint minden neurális hálózati súly, a szűrő súlya is kiképezhető változó. Neurális hálózatunkat (a kernel mátrix súlyain keresztül) kiképezzük olyan szűrők előállítására, amelyek képesek kivonni a leghasznosabb rejtett funkciókat.

Ha a bemeneti adatoknak több csatornája van, a szűrőnek csatornánként külön kernelmátrixa lesz. Az MNIST adatkészletnek csak egy csatornája van, de más típusú képadatokhoz (például RGB) kiképeznénk a modellt, hogy optimális súlyokat kapjunk az egyes csatornák kernelmátrixához.

2-konvolúció

most elértük a konvolúciós neurális hálózatok fókuszpontját: a konvolúciót. A konvolúció azt mutatja, hogy hogyan alkalmazzuk a szűrő súlyunkat a bemeneti adatokra. A konvolúció által használt fő művelet a mátrixpont-termék, azaz két mátrix elemenkénti szorzatának összegzése.

a konvolúcióban lévő mátrix ponttermékek száma a bemeneti adatok és a kernel mátrix méretétől, valamint a lépés méretétől függ. A lépésméret a kernelmátrix függőleges/vízszintes eltolása, amikor a bemeneti adatok mentén mozog.

3-Padding

néha, amikor a dot termék műveletet a korábban látott módon végezzük, nem használunk sort vagy oszlopot. Ennek a jelenségnek a elkerülése érdekében használhatunk párnázást.

így, ha a konvolúciónkban az összes bemeneti adatot fel akarjuk használni, akkor a bemeneti adatmátrixot 0-kkal írhatjuk be. ez azt jelenti, hogy teljes egészében 0-ból álló sorokat/oszlopokat adunk a bemeneti adatmátrix széleihez. Mivel a 0 szorozva bármilyen számmal 0-t eredményez, a párnázás nem befolyásolja a mátrix ponttermékeket. Ez azért fontos, mert nem akarunk torzulásokat hozzáadni a konvolúciónkhoz.

4-konvolúciós réteg

a CNN konvolúciós rétege több szűrőt alkalmaz a bemeneti tenzorra. Míg minden szűrőnek külön kernelmátrixa van az egyes bemeneti csatornákhoz, a szűrő konvolúciójának összesített eredménye az összes bemeneti csatorna konvolúcióinak összege.

további szűrők hozzáadása a konvolúciós réteghez lehetővé teszi a réteg számára a rejtett funkciók jobb kibontását. Ez azonban további képzési idő és számítási komplexitás árán történik, mivel a szűrők extra súlyokat adnak a modellhez. A kimeneti adatok csatornáinak száma megegyezik a konvolúciós réteg által használt szűrők számával.

összevonása

míg a konvolúciós réteg fontos rejtett funkciókat von ki, a funkciók száma továbbra is elég nagy lehet. A pooling segítségével csökkenthetjük az adatok méretét a magasság és a szélesség méreteiben. Ez lehetővé teszi a modell számára, hogy kevesebb számítást végezzen, és végül gyorsabban edzjen. Ezenkívül megakadályozza a túlcsordulást azáltal, hogy csak a legszembetűnőbb tulajdonságokat vonja ki, és figyelmen kívül hagyja a lehetséges torzulásokat vagy a csak néhány példában található ritka jellemzőket.

hogyan működik a pooling?

a konvolúcióhoz hasonlóan szűrőmátrixokat is használunk a poolingban. Azonban a pooling szűrő nem rendelkezik súlyokkal, és nem is végez matrix dot termékeket. Ehelyett redukciós műveletet alkalmaz a bemeneti adatok alszakaszaira.

a CNNs-ben általában használt összevonás típusát max poolingnak nevezzük. A max pooling szűrői a max művelettel kapják meg a bemeneti adatok minden egyes részmátrixában a maximális számot.

több réteg

1-további rétegek hozzáadása

mint minden neurális hálózat, a CNN-ek is profitálhatnak további rétegekből. A további rétegek lehetővé teszik a CNN számára, hogy lényegében több szűrőt rakjon össze a képadatokhoz való felhasználás céljából. Bármely neurális hálózat kiépítéséhez hasonlóan azonban óvatosnak kell lennünk, hogy hány további réteget adunk hozzá. Ha túl sok réteget adunk hozzá egy modellhez, fennáll annak a veszélye, hogy túlságosan illeszkedik a képzési adatokhoz, ezért nagyon rosszul általánosítunk. Ezenkívül minden további réteg növeli a számítási komplexitást és növeli a modellünk képzési idejét.

2-szűrők növelése

általában növeljük a szűrők számát egy konvolúciós rétegben, minél mélyebb a modellünkben. Ebben az esetben a második konvolúciós rétegünk 64 szűrővel rendelkezik, szemben az első konvolúciós réteg 32 szűrőjével. Minél mélyebb a konvolúciós réteg, annál részletesebb lesz a kibontott funkciók. Az első konvolúciós réteg például tartalmazhat olyan szűrőket, amelyek kivonják a vonalakat, éleket és görbéket. Amikor eljutunk a második szintre, a konvolúciós réteg szűrői most több megkülönböztető tulajdonságot vonhatnak ki, például egy 77 éles szögét vagy egy 88 metsző görbéit.

teljesen összekapcsolt réteg

1-teljesen összekapcsolt réteg

1024 méretű, teljesen összekapcsolt réteget (azaz a rétegben lévő neuronok számát) alkalmazunk a második egyesítő réteg kimeneti adataira. Az egységek száma kissé önkényes. Elég ahhoz, hogy erőteljes legyen, de nem annyira, hogy túl erőforrás-igényes legyen. A teljesen összekapcsolt réteg célja az adatfunkciók összesítése, mielőtt osztályokká konvertálnánk őket. Ez lehetővé teszi a modell számára, hogy jobb előrejelzéseket készítsen, mintha csak az összevonási kimenetet konvertáltuk volna közvetlenül osztályokba.

2-simítás

a modellünkben használt adatok NHWC formátumúak. A teljesen összekapcsolt réteg használatához azonban az adatoknak mátrixnak kell lenniük, ahol a Sorok száma a köteg méretét, az oszlopok pedig az adatfunkciókat jelöli. Ezúttal át kell alakítanunk az ellenkező irányba, és át kell alakítanunk az NHWC-ről egy 2-D mátrixra.

lemorzsolódás

1-Co-adaptáció

A Co-adaptáció arra utal, amikor egy réteg több neuronja ugyanazokat vagy nagyon hasonló rejtett funkciókat vonja ki a bemeneti adatokból. Ez akkor fordulhat elő, ha két különböző Neuron csatlakozási súlya közel azonos.

Ha egy teljesen összekapcsolt réteg nagyszámú neuronnal rendelkezik, akkor nagyobb valószínűséggel fordul elő az együttadaptáció. Ez két okból is problémát jelenthet. Először is, a számítás pazarlása, amikor redundáns idegsejtjeink ugyanazt a kimenetet számolják. Másodszor, ha sok neuron ugyanazokat a tulajdonságokat vonja ki, akkor nagyobb jelentőséget tulajdonít ezeknek a tulajdonságoknak a modellünk számára. Ez túlcsorduláshoz vezet, ha az ismétlődő kibontott funkciók csak a képzési készletre jellemzőek.

2-lemorzsolódás

a sok neuronnal teljesen összekapcsolt rétegek együttes adaptációjának minimalizálása a lemorzsolódás alkalmazása edzés közben. A lemorzsolódás során véletlenszerűen leállítjuk a réteg neuronjainak egy részét minden edzési lépésben az idegsejtek értékeinek nullázásával.

Soft-max réteg

mivel 10 lehetséges számjegy lehet egy MNIST kép, 10 neuron teljesen összekapcsolt réteget használunk az egyes számjegyosztályok osztályainak megszerzéséhez. A Softmax függvényt alkalmazzák az osztályokra, hogy osztályonkénti valószínűségekké alakítsák őket.

A modell felépítése

most készen állunk a modell felépítésére. Itt van a kód:

from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropoutmodel = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))

a modell típusa, amelyet használni fogunk, szekvenciális. A szekvenciális a legegyszerűbb módszer egy modell felépítésére Kerasban. Ez lehetővé teszi, hogy rétegenként építsen egy modellt.

az add() módszerrel rétegeket csatolunk a modellünkhöz. Bevezető példánk céljaira elegendő a sűrű rétegekre összpontosítani az egyszerűség érdekében. Minden sűrű () réteg elfogadja első szükséges argumentumaként egy egész számot, amely meghatározza az idegsejtek számát. A réteg aktiválási funkciójának típusát az aktiválási opcionális argumentum segítségével határozzuk meg, amelynek bemenete az aktiválási funkció neve string formátumban. Ilyenek például a relu, tanh, elu, sigmoid, softmax.

ebben a neurális hálózatban 2 konvolúciós réteg van, amelyet minden alkalommal egy pooling réteg követ. Ezután az adatokat simítjuk, hogy sűrű réteget adjunk hozzá, amelyre 0,5-es sebességgel alkalmazzuk a lemorzsolódást. Végül hozzáadunk egy sűrű réteget, hogy minden képet a megfelelő osztályhoz rendeljünk.

A modell összeállítása

ezután össze kell állítanunk a modellünket. A modell összeállítása három paramétert igényel: optimalizáló, veszteség és mutatók.

az optimalizáló szabályozza a tanulási sebességet. Mi lesz az ‘adam’, mint a mi optimalizáló. Adam általában egy jó optimalizáló használni sok esetben. Az adam optimizer az edzés során beállítja a tanulási arányt.

a tanulási arány határozza meg, hogy milyen gyorsan számítják ki a modell optimális súlyait. A kisebb tanulási Arány pontosabb súlyokat eredményezhet (egy bizonyos pontig), de a csökkentés a számítási idő.

a ‘categorical_crossentropy’ – t fogjuk használni veszteségfüggvényünkhöz. Ez a leggyakoribb választás az osztályozáshoz. Az alacsonyabb pontszám azt jelzi, hogy a modell jobban teljesít.

annak érdekében, hogy a dolgok még könnyebben értelmezhetők legyenek, a ‘pontosság’ metrikát használjuk a pontossági pontszám megtekintéséhez az érvényesítési készleten, amikor kiképezzük a modellt.

#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)

A modell kiképzése

most kiképezzük a modellünket. A kiképzéshez a’ fit () ‘ funkciót használjuk modellünkön a következő paraméterekkel: képzési adatok (X_train), céladatok (Y_train), validációs adatok, valamint a korszakok száma.

érvényesítési adatainkhoz az adatkészletünkben megadott tesztkészletet fogjuk használni, amelyet x_testre és Y_testre osztottunk.

a korszakok száma az a szám, ahányszor a modell átmegy az adatokon. Minél több korszakot futunk, annál jobban javul a modell egy bizonyos pontig. Ezt követően a modell minden korszakban leáll. Modellünk esetében a korszakok számát 3-ra állítjuk be.

#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)

értékelje a modell

most már képzett a modell tudjuk értékelni a teljesítményét:

# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)
# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)

így 99,3% – os pontossággal és 0,025-ös veszteséggel rendelkezünk a tesztkészleten, ami nagyon jó. A modellt még javíthatjuk az epoch számának növelésével és a tételméret bevezetésével.

jóslatok készítése

Ha meg szeretné tekinteni a modellünk által a tesztadatokra tett tényleges előrejelzéseket, használhatjuk a predict_classes függvényt. Azt is, hogy ezt a segítségével megjósolni függvény ad egy tömb 10 számok. Ezek a számok azok a valószínűségek, amelyeket a bemeneti kép minden számjegyet képvisel (0-9). A legmagasabb számú tömb index a modell előrejelzését jelenti. Az egyes tömbök összege 1 (mivel minden szám valószínűség).

ennek bemutatásához megmutatjuk a tesztkészlet első 4 képének előrejelzéseit.

Megjegyzés: Ha új adataink vannak, akkor új adatainkat bevihetjük a predict függvénybe, hogy lássuk a modellünk által az új adatokra vonatkozó előrejelzéseket. Mivel nincs új láthatatlan adatunk,előrejelzéseket fogunk mutatni a tesztkészlet használatával.

#predict first 4 images in the test set
model.predict_classes(X_test)

#predict first 4 images in the test set
model.predict(X_test)

We can see that our model predicted 7, 2, 1 and 0 for the first four images.

Let’s compare this with the actual results.

#actual results for first 4 images in test set
y_test

a tényleges eredmények azt mutatják, hogy az első négy kép is 7, 2,1 és 0. Modellünk helyesen megjósolta!

teljes modell

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as np
seed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)
# input image dimensions
num_classes = 10 # 10 digitsimg_rows, img_cols = 28, 28 # number of pixels# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropout
model = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)#predict first 4 images in the test set
model.predict(X_test)model.predict_classes(X_test)#actual results for first 4 images in test set
Y_test

folytatandó…

ebben a cikkben a képfelismerés második részével foglalkoztam, amely egy konvolúciós neurális hálózatot épít.

remélem megtaláltad, amiért idejöttél ebben a cikkben, és maradj velem a képfelismerő utazás következő epizódjaiban!

PS: jelenleg a Berkeley mérnöki hallgatója vagyok, és ha meg akarja vitatni a témát, nyugodtan keressen meg. Itt az e-mailem.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.