bildigenkänning med maskininlärning på Python, Faltningsnätverk

källa: The Irish Times, p usci l usci Muir usci

efter förbehandling av data är det dags att bygga vår modell för att utföra bildigenkänningsuppgiften. En av tekniken använder faltning neurala nätverk.

den här artikeln följer artikeln jag skrev om bildbehandling. När du har gjort data tillgängliga för bildigenkänningsuppgift är det dags att skapa en algoritm som ska utföra uppgiften. Bland många tekniker som används för att känna igen bilder som multilayer perceptron-modell, verkar Convolution Neural Network (CNN) som en mycket effektiv. I den här artikeln kommer vi att se hur man bygger en CNN och hur man applicerar den på en dataset av bilder.

När vi börjar bygga en bildigenkänningsmodell för första gången är det vanligtvis bra att träna och utvärdera den på en relativt enkel dataset.

en av de enklaste uppgifterna vi kan utföra är handskriven siffraigenkänning. Med tanke på en bild av en handskriven siffra (dvs., 0, 1, …, 9), vi vill att vår modell ska kunna klassificera sitt numeriska värde korrekt. Även om denna uppgift verkar relativt enkel, används den faktiskt ganska ofta i verkligheten, som att automatiskt extrahera kreditkortsnummer från en bild. Datamängden som vi kommer att använda för siffraigenkänning är MNIST-datasetet, vilket är datasetet som används för maskininlärningsbaserad siffraigenkänning.

mnist-databasen (Modified National Institute of Standards and Technology) innehåller 60 000 träningsexempel och 10 000 testexempel. Databasen innehåller handskrivna siffror i gråskala som ändrades för att passa i en 20×20 pixelruta, som sedan centrerades i en 28×28-bild (vadderad med blanksteg). Mnist-databasen är tillgänglig via Python.

i den här artikeln kommer jag att visa dig hur du kodar ditt Konvolutionella neurala nätverk med keras, Tensorflows API på hög nivå. Jag använder tensorflow 2.0 i den här artikeln.

1-initiering

eftersom varje gråskalebild har dimensioner 28×28 finns det 784 pixlar per bild. Därför motsvarar varje ingångsbild en tensor av 784 normaliserade flyttalsvärden mellan 0,0 och 1,0. Etiketten för en bild är en het tensor med 10 klasser (varje klass representerar en siffra). När det gäller vår kod har vi img_rows = 28, img_cols = 28 och num_classes = 10. Således har ingången form (number_examples, img_rows, img_cols) därmed 60000x28x28. ett annat viktigt element att ställa in är det slumpmässiga fröet eftersom vi vill behålla startpunkten när en dator genererar en slumptalssekvens.

vi importerar också MNIST dataset.

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 – omformning och omskalning

som nämnts i föregående avsnitt har ingångar form (number_examples, img_rows, img_cols). Men för att kunna använda data med vårt konvolutionella neurala nätverk måste vi få det till NHWC-format.

nhwc-format har en form med fyra dimensioner:

  1. antal bilddata (batchstorlek)
  2. höjd på varje bild
  3. bredd på varje bild
  4. kanaler per bild

höjden och bredden på varje bild från datauppsättningen är img_rows och img_cols, medan antalet kanaler är 1 (eftersom bilderna är gråskala).

dessutom innehåller varje pixel ett gråskalevärde kvantifierat med ett heltal mellan 0 och 255. Så, databasen normaliseras för att ha flyttalsvärden mellan 0,0 och 1,0. I detta fall motsvarar 0,0 ett gråskalepixelvärde på 255 (rent vitt), medan 1.0 motsvarar ett pixelvärde i gråskala på 0 (ren svart).

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 – Casting etikettvektorer Y

Vi måste omvandla våra klasser till vektorer. Vi gör detta genom att trycka på följande rad:

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

för att få en bättre förklaring av detta steg bör du se den här artikeln.

Nu när vi har bearbeta våra data, kan vi börja bygga ut modell.

Convolution Neural Network model

som nämnts i slutet av artikeln jag skrev om bildbehandling spelar Filter en stor roll i bildigenkänning. Vi använder filter för att omvandla ingångar och extrahera funktioner som gör att vår modell kan känna igen vissa bilder. Ett mycket högnivåexempel på detta skulle vara ett kurvdetekteringsfilter, vilket gör att vår modell kan skilja mellan siffror med kurvor och siffror utan kurvor.

1-Filter

liksom alla neurala nätverksvikter är filtrets vikter träningsbara variabler. Vi tränar vårt neurala nätverk (via kärnmatrisvikterna) för att producera filter som kan extrahera de mest användbara dolda funktionerna.

när indata har flera kanaler kommer ett filter att ha en separat kärnmatris per kanal. MNIST-datasetet har bara en kanal, men för andra typer av bilddata (t.ex. RGB) skulle vi träna modellen för att få optimala vikter för varje kanals kärnmatris.

2-Konvolution

Vi har nu nått fokuspunkten för konvolutionella neurala nätverk: konvolutionen. Faltningen representerar hur vi tillämpar våra filtervikter på ingångsdata. Huvudoperationen som används av en faltning är matrispunktprodukten, dvs en summering över den elementvisa produkten av två matriser.

antalet matrispunktprodukter i en faltning beror på dimensionerna för ingångsdata och kärnmatris, liksom stegstorleken. Stegstorleken är den vertikala / horisontella förskjutningen av kärnmatrisen när den rör sig längs ingångsdata.

3-Padding

Ibland, när vi gör punktproduktoperationen som sett tidigare, använder vi inte en rad eller en kolumn. För att undvika detta fenomen kan vi använda stoppning.

således, om vi vill använda alla indata i vår konvolution, kan vi padda indatamatrisen med 0 ‘s. det betyder att vi lägger till rader/kolumner som helt och hållet består av 0’ S till kanterna på indatamatrisen. Eftersom 0 multiplicerat med valfritt antal resulterar i 0 påverkar inte vadderingen matrix dot-produkter. Detta är viktigt eftersom vi inte vill lägga till några snedvridningar i vår faltning.

4-Faltningslager

ett faltningslager i en CNN tillämpar flera filter på ingångstensorn. Medan varje filter har en separat kärnmatris för var och en av ingångskanalerna, är det totala resultatet av ett filters faltning summan av krökningarna över alla ingångskanaler.

genom att lägga till fler filter i ett faltningslager kan skiktet bättre extrahera dolda funktioner. Detta kommer dock på bekostnad av ytterligare träningstid och beräkningskomplexitet, eftersom filter ger extra vikter till modellen. Antalet kanaler för utgångsdata är lika med antalet filter som faltningsskiktet använder.

Pooling

medan faltningsskiktet extraherar viktiga dolda funktioner kan antalet funktioner fortfarande vara ganska stort. Vi kan använda pooling för att minska storleken på data i höjd-och bredddimensionerna. Detta gör att modellen kan utföra färre beräkningar och i slutändan träna snabbare. Det förhindrar också överfitting, genom att extrahera endast de mest framträdande dragen och ignorera potentiella snedvridningar eller ovanliga funktioner som finns i endast ett fåtal exempel.

hur fungerar pooling?

i likhet med en faltning använder vi filtermatriser vid sammanslagning. Poolfiltret har dock inga vikter och utför inte heller matrix dot-produkter. Istället tillämpar den en reduktionsoperation på underavsnitt av ingångsdata.

den typ av pooling som vanligtvis används i CNN kallas max pooling. Filtren för max pooling använder max-funktionen för att få maximalt antal i varje undermatris av ingångsdata.

flera lager

1-Lägga till extra lager

liksom alla neurala nätverk kan CNN dra nytta av ytterligare lager. De ytterligare lagren tillåter en CNN att i huvudsak stapla flera filter tillsammans för användning på bilddata. Men i likhet med att bygga ett neuralt nätverk måste vi vara försiktiga med hur många ytterligare lager vi lägger till. Om vi lägger till för många lager i en modell riskerar vi att ha det överpassat till träningsdata och därför generaliserar mycket dåligt. Dessutom lägger varje ytterligare lager till beräkningskomplexitet och ökar träningstiden för vår modell.

2-öka filter

vi ökar vanligtvis antalet filter i ett faltningslager ju djupare det är i vår modell. I det här fallet har vårt andra faltningsskikt 64 filter, jämfört med de 32 filtren i det första faltningsskiktet. Ju djupare faltningsskiktet desto mer detaljerat blir de extraherade funktionerna. Till exempel kan det första faltningsskiktet ha filter som extraherar funktioner som linjer, kanter och kurvor. När vi kommer till den andra nivån kan filtren i fällningsskiktet nu extrahera mer Utmärkande egenskaper, såsom den skarpa vinkeln på en 77 eller de korsande kurvorna på en 88.

helt anslutet lager

1-helt anslutet lager

vi applicerar ett helt anslutet lager av storlek 1024 (dvs antalet neuroner i skiktet) till utgångsdata för det andra poolskiktet. Antalet enheter är något godtyckligt. Tillräckligt för att vara kraftfull, men inte så mycket som att vara för resurskrävande. Syftet med det helt anslutna lagret är att aggregera datafunktionerna innan vi konverterar dem till klasser. Detta gör det möjligt för modellen att göra bättre förutsägelser än om vi bara hade konverterat poolutgången direkt till klasser.

2-plattning

de data vi har använt i vår modell är av nhwc-format. För att kunna använda ett helt anslutet lager behöver vi dock data vara en matris, där antalet rader representerar batchstorleken och kolumnerna representerar datafunktionerna. Den här gången måste vi omforma i motsatt riktning och konvertera från NHWC till en 2D-matris.

Dropout

1-samanpassning

samanpassning avser när flera neuroner i ett lager extraherar samma eller mycket liknande dolda funktioner från indata. Detta kan hända när anslutningsvikterna för två olika neuroner är nästan identiska.

När ett helt anslutet lager har ett stort antal neuroner är samanpassning mer sannolikt att inträffa. Detta kan vara ett problem av två skäl. För det första är det slöseri med beräkning när vi har överflödiga neuroner som beräknar samma utgång. För det andra, om många neuroner extraherar samma funktioner, lägger det till mer betydelse för dessa funktioner för vår modell. Detta leder till överfitting om de dubbla extraherade funktionerna är specifika för endast träningsuppsättningen.

2-Dropout

hur vi minimerar samanpassning för helt anslutna lager med många neuroner är genom att applicera dropout under träning. I dropout stänger vi slumpmässigt en del av ett lagers neuroner vid varje träningssteg genom att nollställa neuronvärdena.

Soft-max Layer

eftersom det finns 10 möjliga siffror som en mnist-bild kan vara, använder vi ett 10 neuron helt anslutet lager för att få klasserna för varje sifferklass. Softmax-funktionen tillämpas på klasserna för att konvertera dem till per klass sannolikheter.

bygga modellen

Nu är vi redo att bygga vår modell. Här är koden:

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

modelltypen som vi kommer att använda är Sekventiell. Sekventiell är det enklaste sättet att bygga en modell i Keras. Det låter dig bygga ett modelllager för lager.

vi använder add () – metoden för att bifoga lager till vår modell. För vårt inledande exempel räcker det att fokusera på täta lager för enkelhet. Varje tätt () lager accepterar som sitt första nödvändiga argument ett heltal som anger antalet neuroner. Typen av aktiveringsfunktion för skiktet definieras med hjälp av argumentet activation optional, vars ingång är namnet på aktiveringsfunktionen i strängformat. Exempel är relu, tanh, elu, sigmoid, softmax.

i detta neurala nätverk har vi 2 faltningslager följt varje gång av ett poollager. Sedan plattar vi data för att lägga till ett tätt lager på vilket vi tillämpar dropout med en hastighet på 0,5. Slutligen lägger vi till ett tätt lager för att fördela varje bild med rätt klass.

kompilera modellen

Därefter måste vi kompilera vår modell. Att sammanställa modellen tar tre parametrar: optimizer, loss och metrics.

optimeraren styr inlärningshastigheten. Vi kommer att använda ‘adam’ som vår optimizer. Adam är i allmänhet en bra optimerare att använda i många fall. Adam optimizer justerar inlärningshastigheten under hela träningen.

inlärningshastigheten bestämmer hur snabbt de optimala vikterna för modellen beräknas. En mindre inlärningshastighet kan leda till mer exakta vikter (upp till en viss punkt), men minskningen är beräkningstiden.

Vi kommer att använda ‘categorical_crossentropy’ för vår förlustfunktion. Detta är det vanligaste valet för klassificering. En lägre poäng indikerar att modellen presterar bättre.

för att göra det ännu enklare att tolka använder vi mätvärdet ‘noggrannhet’ för att se noggrannhetspoängen på valideringsuppsättningen när vi tränar modellen.

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

träna modellen

nu ska vi träna vår modell. För att träna använder vi funktionen’ fit () ‘ på vår modell med följande parametrar: träningsdata (X_train), måldata (Y_train), valideringsdata och antalet epoker.

för våra valideringsdata kommer vi att använda testuppsättningen som tillhandahålls oss i vår dataset, som vi har delat in i X_test och Y_test.

antalet epoker är antalet gånger modellen kommer att gå igenom data. Ju fler epoker vi kör, desto mer kommer modellen att förbättras, upp till en viss punkt. Efter den tiden kommer modellen att sluta förbättras under varje epok. För vår modell ställer vi in antalet epoker till 3.

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

utvärdera modellen

nu har vi tränat vår modell kan vi utvärdera dess prestanda:

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

således har vi en noggrannhet på 99,3% och en förlust av 0.025 på testuppsättningen vilket är mycket bra. Vi kan fortfarande förbättra modellen genom att öka antalet epoker och genom att införa en batchstorlek.

gör förutsägelser

Om du vill se de faktiska förutsägelser som vår modell har gjort för testdata kan vi använda funktionen predict_classes. Vi kan också till detta genom att använda predict-funktionen kommer att ge en array med 10 siffror. Dessa siffror är sannolikheten för att inmatningsbilden representerar varje siffra (0-9). Arrayindexet med det högsta antalet representerar modellförutsägelsen. Summan av varje array är lika med 1 (eftersom varje tal är en sannolikhet).

för att visa detta kommer vi att visa förutsägelserna för de första 4 bilderna i testuppsättningen.

Obs: Om vi har nya data kan vi mata in våra nya data i predict-funktionen för att se de förutsägelser som vår modell gör på de nya data. Eftersom vi inte har några nya osynliga data kommer vi att visa förutsägelser med hjälp av testuppsättningen för tillfället.

#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

de faktiska resultaten visar att de fyra första bilderna också är 7, 2,1 och 0. Vår modell förutspådde korrekt!

hela modellen

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

att fortsätta…

i den här artikeln tacklade jag den andra delen av bildigenkänning som bygger ett neuralt nätverk.

Jag hoppas att du hittade vad du kom hit för i den här artikeln och stanna hos mig för nästa avsnitt av denna bildigenkänningsresa!

PS: Jag är för närvarande en civilingenjörsstudent vid Berkeley, och om du vill diskutera ämnet, kontakta mig gärna. Här är min e-post.

Lämna ett svar

Din e-postadress kommer inte publiceras.