kuvantunnistus koneoppimisen avulla Pythonilla, Convolutionaalinen neuroverkko

figcaption>lähde: the Irish Times, Pól Ó Muirí

tietojen esikäsittelyn jälkeen on aika rakentaa mallimme kuvantunnistustehtävän suorittamiseen. Yksi tekniikoista on konvoluution hermoverkon käyttäminen.

Tämä artikkeli seuraa kuvankäsittelystä kirjoittamaani artikkelia. Kun tiedot on saatu käyttöön kuvantunnistustehtävää varten, on aika luoda algoritmi, joka suorittaa tehtävän. Monista tekniikoista, joita käytetään kuvien tunnistamiseen monikerroksiseksi perceptron-malliksi, Convolution Neural Network (CNN) näyttää erittäin tehokkaalta. Tässä artikkelissa, näemme, miten rakentaa CNN ja miten soveltaa sitä dataset kuvia.

kun kuvantunnistusmallia aletaan rakentaa ensimmäistä kertaa, sitä on yleensä hyvä kouluttaa ja arvioida suhteellisen yksinkertaisella aineistolla.

yksi yksinkertaisimmista tehtävistä, joita voimme suorittaa, on käsinkirjoitettu numerotunnistus. Annettu kuva käsinkirjoitetusta numerosta (ts., 0, 1, …, 9), haluamme, että mallimme pystyy luokittelemaan numeerisen arvonsa oikein. Vaikka tämä tehtävä vaikuttaa suhteellisen yksinkertaiselta, sitä käytetään melko usein tosielämässä, kuten esimerkiksi automaattisesti poimimalla luottokorttinumerot kuvasta. Tietokokonaisuus, jota käytämme digitunnistukseen, on mnist-tietokokonaisuus, jota käytetään koneoppimiseen perustuvaan digitunnistukseen.

mnist (Modified National Institute of Standards and Technology) – tietokanta sisältää 60 000 koulutusesimerkkiä ja 10 000 testausesimerkkiä. Tietokanta sisältää käsinkirjoitettuja harmaasävyisiä numeroita, jotka muutettiin mahtumaan 20×20 pikselin ruutuun, joka sitten keskitettiin 28×28 kuvaan (pehmustettu välilyönneillä). Mnist-tietokantaan pääsee Pythonin kautta.

tässä artikkelissa näytän, miten Konvolutionaalinen neuroverkko koodataan kerasin, TensorFlow ‘ n korkean tason API: n avulla. Käytän TensorFlow 2.0 tässä artikkelissa.

1 – alustus

koska jokaisen harmaasävykuvan mitat ovat 28×28, kuvaa kohden on 784 pikseliä. Siksi jokainen syötekuva vastaa 784 normalisoidun liukulukuarvon tensoria välillä 0,0 – 1,0. Kuvan etiketti on yhden kuuman tensori, jossa on 10 luokkaa (jokainen luokka edustaa numeroa). Koodimme suhteen meillä on img_rows = 28, img_cols = 28 ja num_classes = 10. Näin tulo on muoto (number_examples, img_rows, img_cols) siis 60000x28x28.
toinen tärkeä perustettava elementti on satunnainen siemen, sillä haluamme pitää alkupisteen, kun tietokone luo satunnaislukusarjan.

tuomme myös mnist-aineiston.

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 – uudelleenmuotoilu ja uudelleenmuotoilu

kuten edellisessä jaksossa mainittiin, syötteillä on muoto (number_examples, img_rows, img_cols). Kuitenkin, jotta voimme käyttää tietoja meidän convolutional neuroverkko, meidän täytyy saada se NHWC-muodossa.

NHWC-formaatilla on muoto, jossa on neljä ulottuvuutta:

  1. kuvatiedostonäytteiden lukumäärä (eräkoko)
  2. kunkin kuvan korkeus
  3. jokaisen kuvan leveys
  4. kanavat kuvaa kohti

kunkin kuvan korkeus ja leveys aineistosta on img_rows ja img_cols, kun taas kanavien lukumäärä on 1 (koska kuvat ovat harmaasävyisiä).

myös jokainen pikseli sisältää harmaasävyarvon, joka kvantifioidaan kokonaisluvulla 0-255. Niinpä tietokanta normalisoidaan niin, että liukulukuarvot ovat välillä 0,0 ja 1,0. Tällöin 0,0 vastaa harmaasävypikselin arvoa 255 (puhtaan valkoinen), kun taas 1.0 vastaa harmaasävypikselin arvoa 0 (puhdas musta).

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 – Valumerkintävektorit Y

meidän on muutettava luokkamme vektoreiksi. Teemme tämän napauttamalla seuraavaa riviä:

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

saadaksesi tarkemman selityksen tähän vaiheeseen, katso tämä artikkeli.

nyt kun olemme prosessoineet tietomme, voimme alkaa rakentaa mallia.

konvoluution Neuroverkkomalli

kuten kuvankäsittelystä kirjoittamani artikkelin lopussa mainittiin, suodattimilla on valtava merkitys kuvantunnistuksessa. Käytämme suodattimia muuttaa tuloa ja poimia ominaisuuksia, joiden avulla mallimme tunnistaa tiettyjä kuvia. Erittäin korkean tason esimerkki tästä olisi käyrän tunnistava suodatin, jonka avulla mallimme voi erottaa käyrillä varustetut numerot ja käyrättömät numerot.

1 – Suodattimet

kuten kaikki neuroverkkopainot, suodattimen painot ovat koulutettavia muuttujia. Koulutamme neuroverkkomme (ytimen matriisipainojen kautta) tuottamaan suodattimia, jotka pystyvät poimimaan hyödyllisimmät piilotetut ominaisuudet.

kun syöttötiedossa on useita kanavia, suodattimella on erillinen ydinmatriisi kanavaa kohden. Mnist-aineistossa on vain yksi kanava, mutta muunlaista kuvadataa (esim.RGB) varten koulutamme mallin niin, että kunkin kanavan ydinmatriisille saadaan optimaaliset painot.

2-konvoluutio

olemme nyt saavuttaneet konvolutionaalisten neuroverkkojen polttopisteen: konvoluution. Konvoluutio kuvaa sitä, miten käytämme suodatinpainoja syöttötietoihin. Konvoluution käyttämä pääoperaatio on matriisin pistetulo eli yhteenlasku kahden matriisin alkiotulon yli.

matriisipistetuotteiden määrä konvoluutiossa riippuu syöttötiedon ja ytimen matriisin mitoista sekä stride-koosta. Stride-koko on ytimen matriisin pysty – /vaakasuuntainen Siirtymä sen liikkuessa syöttötietojen mukana.

3-pehmuste

joskus, kun teemme pistetuoteoperaation kuten aiemmin nähtiin, emme käytä riviä tai saraketta. Tämän ilmiön välttämiseksi Voimme käyttää pehmustetta.

näin ollen, jos haluamme käyttää kaikkia tulodataa konvoluutiossamme, voimme padota tulodatamatriisia 0: n kanssa. tämä tarkoittaa, että lisäämme kokonaan 0: n muodostamia rivejä / sarakkeita tulodatamatriisin reunoihin. Koska 0 kerrottuna millä tahansa numerolla johtaa arvoon 0, täyte ei vaikuta matriisin pistetuotteisiin. Tämä on tärkeää, koska emme halua lisätä mitään vääristymiä meidän konvoluutio.

4-Konvoluutiokerros

CNN: n konvoluutiokerros soveltaa tulotensoriin useita suodattimia. Vaikka jokaisella suodattimella on erillinen ydinmatriisi jokaiselle tulokanavalle, suodattimen konvoluution kokonaistulos on kaikkien tulokanavien konvoluutioiden summa.

lisäämällä suotimia konvoluutiokerrokseen kerros pystyy paremmin poimimaan piilotettuja ominaisuuksia. Tämä tulee kuitenkin lisäharjoitteluajan ja laskennallisen monimutkaisuuden kustannuksella, sillä suodattimet lisäävät malliin lisäpainoja. Lähtötiedon kanavien määrä on yhtä suuri kuin konvoluutiokerroksen käyttämien suodattimien määrä.

Pooling

vaikka konvoluutiokerros poimii tärkeitä piilotettuja ominaisuuksia, ominaisuuksien määrä voi silti olla melko suuri. Yhdistämisen avulla voimme pienentää tietojen kokoa korkeus-ja leveysmitoissa. Tämä mahdollistaa mallin suorittaa vähemmän laskutoimituksia ja lopulta kouluttaa nopeammin. Se estää myös ylilatauksen, koska se poistaa vain tärkeimmät ominaisuudet ja jättää huomiotta mahdolliset vääristymät tai epätavalliset piirteet, joita esiintyy vain muutamissa esimerkeissä.

miten yhdistäminen toimii?

konvoluution tapaan yhdistämisessä käytetään suodatinmatriiseja. Pooling-suodattimella ei kuitenkaan ole painoja, eikä se suorita matriisipistetuotteita. Sen sijaan siinä sovelletaan vähennysoperaatiota syöttötietojen alaluokkiin.

CNNs: ssä yleensä käytettävää poolaustyyppiä kutsutaan nimellä max pooling. Max-poolauksen suodattimet käyttävät Max-operaatiota saadakseen maksimimäärän kustakin syöttötietojen alimatrixista.

monikerroksiset

1 – lisäkerrosten lisääminen

kuten kaikki hermoverkot, CNNs voi hyötyä lisäkerroksista. Lisäkerrokset mahdollistavat CNN lähinnä pinota useita suodattimia yhteen käytettäväksi kuvan tiedot. Samalla tavalla kuin minkä tahansa hermoverkon rakentaminen, meidän on kuitenkin varottava, kuinka monta lisäkerrosta lisäämme. Jos malliin lisätään liian monta kerrosta, vaarana on, että se menee liian pitkälle harjoitustietoihin ja yleistyy siksi erittäin huonosti. Lisäksi jokainen lisäkerros lisää laskennallista monimutkaisuutta ja lisää mallimme harjoitusaikaa.

2 – Kasvata suotimia

yleensä kasvatamme suotimien määrää konvoluutiokerroksessa mitä syvempi se on mallissamme. Tässä tapauksessa toisessa konvoluutiokerroksessamme on 64 suodatinta, kun ensimmäisen konvoluutiokerroksen 32 suodatinta. Mitä syvempi konvoluutiokerros, sitä yksityiskohtaisemmiksi uutetut ominaisuudet tulevat. Esimerkiksi ensimmäisessä konvoluutiokerroksessa voi olla suodattimia, jotka poimivat ominaisuuksia, kuten viivoja, reunoja ja käyriä. Kun pääsemme toiselle tasolle, konvoluutiokerroksen suodattimet voisivat nyt poimia lisää erottavia piirteitä, kuten a 77: n terävä kulma tai A 88: n risteävät käyrät.

Fully-connected layer

1-Fully-connected layer

toisen pooling layer-kerroksen ulostulodataan sovelletaan täysin yhdistettyä kerrosta, jonka koko on 1024 (eli neuronien määrä kerroksessa). Yksikkömäärä on jokseenkin mielivaltainen. Tarpeeksi ollakseen tehokas, mutta ei niin paljon, että olisi liian Resurssitehokas. Täysin kytketyn kerroksen tarkoituksena on koota dataominaisuudet ennen kuin muutamme ne luokiksi. Näin malli pystyy tekemään parempia ennusteita kuin jos olisimme juuri muuntaneet poolaustuotoksen suoraan luokiksi.

2-Litistystä

mallissamme käyttämämme tiedot ovat nhwc-muotoa. Kuitenkin, jotta voidaan käyttää täysin kytketty kerros, tietojen on oltava matriisi, jossa rivien määrä edustaa erän kokoa ja sarakkeet edustavat tietojen ominaisuuksia. Tällä kertaa meidän on muokattava toisinpäin ja muututtava NHWC: stä 2-D-matriisiksi.

Dropout

1 – Co-adaptation

Co-adaptation tarkoittaa sitä, kun useat neuronit yhdessä kerroksessa poimivat syötetiedosta samoja tai hyvin samankaltaisia piilotettuja ominaisuuksia. Näin voi käydä, kun kahden eri hermosolun kytkentäpainot ovat lähes identtiset.

kun täysin kytkeytyneessä kerroksessa on suuri määrä neuroneja, yhteissopeutuminen on todennäköisempää. Tämä voi olla ongelma kahdesta syystä. Ensinnäkin, se on laskennan tuhlausta, kun meillä on redundantteja neuroneja laskemassa samaa ulostuloa. Toiseksi, jos monet neuronit poimivat samoja ominaisuuksia, se lisää näiden ominaisuuksien merkitystä mallillemme. Tämä johtaa ylituotantoon, jos päällekkäiset ominaisuudet koskevat vain harjoitussarjaa.

2-Dropout

tapa minimoida yhteissovitus täysin kytketyille kerroksille, joissa on monia neuroneja, on soveltaa dropoutia harjoittelun aikana. Pudotuksessa suljemme osan kerroksen neuroneista-nollaamalla neuronien arvot.

Soft-max-kerros

koska on olemassa 10 mahdollista numeroa MNIST-kuva voi olla, käytämme 10 neuronin täysin kytkettyä kerrosta saadaksemme luokat kullekin numeroluokalle. Softmax-funktiota käytetään luokissa muuntamaan ne per luokka-todennäköisyyksiksi.

mallin rakentaminen

nyt olemme valmiita rakentamaan mallimme. Tässä on koodi:

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'))

käyttämämme Mallityyppi on juokseva. Sekventiaali on helpoin tapa rakentaa malli Kerasissa. Sen avulla voit rakentaa mallin kerros kerrokselta.

käytämme add () – menetelmää kerrosten liittämiseksi malliimme. Varten meidän johdantoesimerkki, riittää keskittyä tiheä kerroksia yksinkertaisuuden. Jokainen tiheä () kerros hyväksyy ensimmäiseksi vaadituksi argumentikseen kokonaisluvun, joka määrittää neuronien määrän. Tason aktivointifunktion tyyppi määritellään aktivointivaltion argumentin avulla, jonka syöte on aktivointifunktion nimi merkkijonomuodossa. Esimerkkejä ovat relu, tanh, elu, sigmoid, softmax.

tässä neuroverkossa on 2 konvoluutiokerrosta, joita seuraa joka kerta yhdistävä kerros. Sitten tasata tiedot Lisätä tiheä kerros, johon sovelletaan dropout nopeudella 0,5. Lopuksi lisäämme tiheä kerros jakaa jokaisen kuvan oikean luokan.

kootaan mallia

seuraavaksi on koottava mallimme. Mallin kokoaminen vaatii kolme parametria: optimizer, loss ja metrics.

optimoija ohjaa oppimistahtia. Käytämme Adamia optimoijanamme. Adam on yleensä hyvä optimizer käyttää monissa tapauksissa. Adam optimizer säätää oppimisnopeutta koko harjoittelun ajan.

oppimistahti määrittää, kuinka nopeasti mallin optimipainot lasketaan. Pienempi oppimistahti voi johtaa tarkempiin painoihin (tiettyyn pisteeseen asti), mutta vähennys on laskenta-aika.

käytämme häviöfunktiollemme “categorical_crossentropy”. Tämä on yleisin luokitteluvalinta. Pienempi pistemäärä kertoo siitä, että malli suoriutuu paremmin.

jotta asioita olisi vielä helpompi tulkita, käytämme “tarkkuus” – mittaria nähdäksemme validointijoukon tarkkuuspisteet, kun koulutamme mallia.

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

mallin koulutus

nyt koulutamme malliamme. Harjoitteluun käytämme mallimme fit () – toimintoa seuraavin parametrein: harjoitustiedot (X_train), tavoitetiedot (Y_train), validointitiedot ja ajanjaksojen lukumäärä.

validointitiedoissamme käytämme aineistossamme annettua testisarjaa, jonka olemme jakaneet x_test-ja Y_test-arvoihin.

epookkien lukumäärä on se, kuinka monta kertaa malli käy aineiston läpi. Mitä enemmän aikakausia ajetaan, sitä enemmän malli paranee, tiettyyn pisteeseen asti. Sen jälkeen malli lakkaa parantumasta jokaisen aikakauden aikana. Meidän malli, asetamme määrä aikakaudet 3.

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

arvioi malli

nyt olemme kouluttaneet mallimme voimme arvioida sen suorituskykyä:

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

näin ollen testisarjan tarkkuus on 99,3% ja häviö 0,025, mikä on erittäin hyvä. Mallia voidaan vielä parantaa lisäämällä epookin määrää ja ottamalla käyttöön eräkoko.

tee ennusteita

Jos haluat nähdä mallimme testiaineistolle tekemät todelliset ennustukset, Voimme käyttää predict_classes-funktiota. Voimme myös tätä käyttämällä ennustaa funktio antaa array 10 numerot. Nämä luvut ovat todennäköisyyksiä, joita syötekuva kuvaa jokaista numeroa (0-9). Array-indeksi, jossa on suurin luku, edustaa mallin ennustamista. Summa kunkin array on yhtä kuin 1 (koska jokainen numero on todennäköisyys).

tämän osoittamiseksi näytämme testisarjan 4 ensimmäisen kuvan ennusteet.

Huomautus: Jos meillä on uutta dataa, voimme syöttää uuden datamme ennustusfunktioon nähdäksemme mallimme ennusteet uudesta datasta. Koska meillä ei ole uusia näkymättömiä tietoja, näytämme ennusteita testisarjan avulla toistaiseksi.

#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

div>

varsinaisten tulosten mukaan neljä ensimmäistä kuvaa ovat myös 7, 2,1 ja 0. Mallimme ennusti oikein!

koko malli

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

jatkuu…

tässä artikkelissa käsittelin kuvantunnistuksen toista osaa, jossa rakennetaan konvoluution neuroverkkoa.

toivon, että löysit tästä artikkelista sen, mitä tulit tänne hakemaan ja jää luokseni tämän kuvantunnistusmatkan seuraaviin jaksoihin!

PS: olen tällä hetkellä diplomi-insinöörin Opiskelija Berkeleyssä, ja jos haluat keskustella aiheesta, ota minuun yhteyttä. Tässä on sähköpostini.

Vastaa

Sähköpostiosoitettasi ei julkaista.