Image recognition met Machine Learning Python, Convolutional Neurale Netwerk

bron: de irish times, Pól Ó Muirí

Na pre-processing van de gegevens, is het tijd om ons te bouwen model voor het uitvoeren van de Afbeelding erkenning taak. Een van de technieken is het gebruik van Convolution neuraal netwerk.

Dit artikel volgt het artikel dat ik schreef over beeldverwerking. Nadat de gegevens beschikbaar zijn gemaakt voor de taak voor beeldherkenning, is het tijd om een algoritme te maken dat de taak zal uitvoeren. Onder de vele technieken die worden gebruikt om beelden te herkennen als multilayer perceptron model, Convolution Neural Network (CNN) verschijnt als een zeer efficiënte. In dit artikel zullen we zien hoe een CNN te bouwen en hoe deze toe te passen op een dataset van afbeeldingen.

wanneer we voor het eerst een beeldherkenningsmodel beginnen te bouwen, is het meestal een goed idee om het te trainen en te evalueren op een relatief eenvoudige dataset.

een van de eenvoudigste taken die we kunnen uitvoeren is handgeschreven cijferherkenning. Gegeven een afbeelding van een handgeschreven cijfer (d.w.z., 0, 1, …, 9), we willen dat ons model zijn numerieke waarde correct kan classificeren. Hoewel deze taak lijkt relatief eenvoudig, het wordt eigenlijk gebruikt vrij vaak in het echte leven, zoals het automatisch extraheren van creditcardnummers uit een foto. De dataset die we zullen gebruiken voor cijferherkenning is de MNIST-dataset, de dataset die wordt gebruikt voor op machine learning gebaseerde cijferherkenning.

De MNIST-databank (Modified National Institute of Standards and Technology) bevat 60.000 opleidingsvoorbeelden en 10.000 testvoorbeelden. De database bevat handgeschreven cijfers met grijswaarden die aangepast werden om te passen in een 20×20 pixel box, die vervolgens werd gecentreerd in een 28×28 afbeelding (opgevuld met witruimte). De MNIST database is toegankelijk via Python.

In dit artikel zal ik u laten zien hoe u uw convolutionele neurale netwerk codeert met behulp van keras, TensorFlow ‘ s high-level API. Ik gebruik tensorflow 2.0 in dit artikel.

1-initialisatie

aangezien elke afbeelding met grijswaarden 28×28 afmetingen heeft, zijn er 784 pixels per afbeelding. Daarom komt elke invoerafbeelding overeen met een tensor van 784 genormaliseerde drijvende-kommawaarden tussen 0.0 en 1.0. Het label voor een afbeelding is een one-hot tensor met 10 klassen (elke klasse vertegenwoordigt een cijfer). In termen van onze code hebben we img_rows = 28, img_cols = 28 en num_classes = 10. De invoer heeft dus vorm (number_examples, img_rows, img_cols) dus 60000x28x28.
Een ander belangrijk element om op te zetten is de random seed omdat we het startpunt willen behouden wanneer een computer een willekeurige getallenreeks genereert.

we importeren ook de 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 – Reshaping en rescaling

zoals vermeld in de vorige paragraaf, hebben ingangen vorm (number_examples, img_rows, img_cols). Echter, om de gegevens te gebruiken met ons convolutioneel neuraal netwerk, moeten we het in NHWC-formaat krijgen.

NHWC-formaat heeft een vorm met vier dimensies:

  1. aantal afbeeldingen (batchgrootte)
  2. hoogte van elke afbeelding
  3. breedte van elke afbeelding
  4. kanalen per afbeelding

de hoogte en breedte van elke afbeelding uit de dataset is img_rows en img_cols, terwijl het aantal kanalen 1 is (omdat de afbeeldingen grijswaarden hebben).

ook bevat elke pixel een grijswaardewaarde gekwantificeerd door een geheel getal tussen 0 en 255. Dus, de database is genormaliseerd om drijvende komma waarden tussen 0.0 en 1.0. In dit geval komt 0.0 overeen met een pixelwaarde in grijswaarden van 255 (zuiver wit), terwijl 1.0 komt overeen met een pixelwaarde in grijswaarden van 0 (zuiver zwart).

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 label vectoren Y

We moeten onze klassen omzetten in vectoren. We doen dit door te tikken op de volgende regel:

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

Om een betere uitleg van deze stap, moet u raadpleegt u dit artikel.

nu we onze gegevens hebben verwerkt, kunnen we beginnen met het opbouwen van een model.

Convolution Neural Network model

zoals vermeld aan het einde van het artikel dat ik schreef over beeldverwerking, spelen filters een grote rol in beeldherkenning. We gebruiken filters om ingangen te transformeren en extraheren functies die ons model in staat stellen om bepaalde beelden te herkennen. Een zeer hoog niveau voorbeeld hiervan zou een curve detecting filter, die ons model in staat stelt om onderscheid te maken tussen cijfers met curves en cijfers zonder curves.

1 – Filters

net als alle neurale netwerkgewichten zijn de gewichten van het filter trainbare variabelen. We trainen ons neurale netwerk (via de kernel matrix gewichten) om filters te produceren die de meest bruikbare verborgen functies kunnen extraheren.

wanneer de invoergegevens meerdere kanalen hebben, zal een filter een aparte kernelmatrix per kanaal hebben. De MNIST-dataset heeft slechts één kanaal, maar voor andere soorten beeldgegevens (bijvoorbeeld RGB) zouden we het model trainen om optimale gewichten te verkrijgen voor de kernelmatrix van elk kanaal.

2-convolutie

we hebben nu het brandpunt van convolutionele neurale netwerken bereikt: de convolutie. De convolution geeft aan hoe we onze filtergewichten toepassen op de invoergegevens. De belangrijkste bewerking die door een convolutie wordt gebruikt is het matrix dot product, dat wil zeggen een optelling over het element-wise product van twee matrices.

het aantal matrix Dot producten in een convolutie hangt af van de afmetingen van de input data en kernel matrix, evenals de paginagrootte. De stapgrootte is de verticale / horizontale offset van de kernelmatrix wanneer deze langs de invoergegevens beweegt.

3-Padding

soms gebruiken we geen rij of kolom als we de dot-productbewerking uitvoeren zoals we eerder zagen. Om dit fenomeen te voorkomen kunnen we padding gebruiken.

dus, als we alle invoergegevens in onze convolutie willen gebruiken, kunnen we de invoerdatamatrix met 0 ‘s opvullen. dit betekent dat we rijen/kolommen die volledig uit 0’ s bestaan aan de randen van de invoerdatamatrix toevoegen. Aangezien 0 vermenigvuldigd met een willekeurig getal resulteert in 0, heeft de opvulling geen invloed op matrix dot producten. Dit is belangrijk omdat we geen vervormingen willen toevoegen aan onze convolutie.

4-Convolutielaag

een convolutielaag in een CNN past meerdere filters toe op de input tensor. Hoewel elk filter een aparte kernelmatrix heeft voor elk van de invoerkanalen, is het totale resultaat van de convolutie van een filter de som van de convoluties over alle invoerkanalen.

door meer filters toe te voegen aan een convolutielaag kan de laag beter verborgen functies extraheren. Dit gaat echter ten koste van extra trainingstijd en computationele complexiteit, omdat filters extra gewichten toevoegen aan het model. Het aantal kanalen voor de uitvoergegevens is gelijk aan het aantal filters dat de convolutielaag gebruikt.

Pooling

hoewel de convolutielaag belangrijke verborgen functies extraheert, kan het aantal functies nog steeds vrij groot zijn. We kunnen pooling gebruiken om de grootte van de gegevens in de hoogte en breedte afmetingen te verminderen. Hierdoor kan het model minder berekeningen uitvoeren en uiteindelijk sneller trainen. Het voorkomt ook overbevissing, door alleen de meest opvallende kenmerken te extraheren en potentiële verstoringen of ongewone kenmerken te negeren die in slechts een paar voorbeelden worden gevonden.

Hoe werkt pooling?

vergelijkbaar met een convolutie gebruiken we filtermatrices in pooling. Het pooling filter heeft echter geen gewicht, noch voert het matrix dot producten uit. In plaats daarvan wordt een reductieoperatie toegepast op subsecties van de invoergegevens.

het type pooling dat gewoonlijk in CNNs wordt gebruikt, wordt max pooling genoemd. De filters van Max pooling gebruiken de max operatie om het maximum aantal in elke submatrix van de invoergegevens te verkrijgen.

meerdere lagen

1 – extra lagen toevoegen

net als alle neurale netwerken kan CNNs profiteren van extra lagen. De extra lagen staan een CNN toe om in wezen meerdere filters samen te stapelen voor gebruik op de afbeeldingsgegevens. Echter, net als bij het bouwen van een neuraal netwerk, moeten we voorzichtig zijn met hoeveel extra lagen we toevoegen. Als we te veel lagen aan een model toevoegen, lopen we het risico dat het te veel aan de trainingsgegevens wordt toegevoegd en daardoor zeer slecht generaliseert. Bovendien voegt elke extra laag computationele complexiteit toe en verhoogt de trainingstijd voor ons model.

2 – Verhoog filters

We verhogen meestal het aantal filters in een convolutielaag hoe dieper het in ons model is. In dit geval heeft onze tweede convolutielaag 64 filters, vergeleken met de 32 filters van de eerste convolutielaag. Hoe dieper de convolutielaag, hoe gedetailleerder de geëxtraheerde functies worden. De eerste convolutielaag kan bijvoorbeeld filters bevatten die functies zoals lijnen, randen en krommen extraheren. Wanneer we op het tweede niveau komen, kunnen de filters van de convolutielaag nu meer onderscheidende kenmerken extraheren, zoals de scherpe hoek van een 77 of de kruisende krommen van een 88.

volledig verbonden laag

1-volledig verbonden laag

We passen een volledig verbonden laag van grootte 1024 (d.w.z. het aantal neuronen in de laag) toe op de uitvoergegevens van de tweede poolinglaag. Het aantal eenheden is enigszins willekeurig. Genoeg om krachtig te zijn, maar niet zozeer om te veel grondstoffen te gebruiken. Het doel van de volledig verbonden laag is om de gegevensfuncties samen te voegen voordat we ze converteren naar klassen. Hierdoor kan het model betere voorspellingen doen dan wanneer we de pooling output direct naar klassen hadden geconverteerd.

2-afvlakking

de gegevens die we in ons model hebben gebruikt, zijn van het NHWC-formaat. Om een volledig verbonden laag te gebruiken, moeten de gegevens echter een matrix zijn, waarbij het aantal rijen de batchgrootte vertegenwoordigt en de kolommen de gegevensfuncties weergeven. Deze keer moeten we in de tegenovergestelde richting hervormen en van NHWC converteren naar een 2-D matrix.

Dropout

1-Co-adaptatie

Co-adaptatie verwijst naar wanneer meerdere neuronen in een laag dezelfde of zeer vergelijkbare verborgen kenmerken uit de inputgegevens halen. Dit kan gebeuren wanneer de verbindingsgewichten voor twee verschillende neuronen bijna identiek zijn.

wanneer een volledig verbonden laag een groot aantal neuronen heeft, is co-adaptatie waarschijnlijker. Dit kan om twee redenen een probleem zijn. Ten eerste is het een verspilling van berekeningen als we redundante neuronen hebben die dezelfde output berekenen. Ten tweede, als veel neuronen dezelfde functies extraheren, voegt het meer betekenis toe aan die functies voor ons model. Dit leidt tot overbevissing als de duplicaat geëxtraheerde functies alleen specifiek zijn voor de trainingsset.

2-Dropout

de manier waarop we co-adaptatie minimaliseren voor volledig verbonden lagen met veel neuronen is door dropout toe te passen tijdens de training. Bij dropout sluiten we willekeurig een deel van de neuronen van een laag af bij elke trainingsstap door de neuronwaarden te nul te stellen.

Soft-max laag

omdat er 10 mogelijke cijfers zijn die een MNIST-afbeelding kan zijn, gebruiken we een 10 neuron volledig verbonden laag om de klassen voor elke cijferklasse te verkrijgen. De Softmax-functie wordt toegepast op de klassen om ze om te zetten in kansen per klasse.

het model bouwen

nu zijn we klaar om ons model te bouwen. Hier is de code:

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

het modeltype dat we zullen gebruiken is sequentieel. Sequentieel is de makkelijkste manier om een model te bouwen in Keras. Hiermee kunt u laag voor laag een model bouwen.

we gebruiken de methode add () om lagen aan ons model te koppelen. Voor de doeleinden van ons inleidende voorbeeld, volstaat het om zich te concentreren op dichte lagen voor eenvoud. Elke dichte () laag accepteert als eerste vereiste argument een geheel getal dat het aantal neuronen specificeert. Het type activeringsfunctie voor de laag wordt gedefinieerd met behulp van het optionele argument activering, waarvan de invoer de naam van de activeringsfunctie in string-formaat is. Voorbeelden zijn relu, tanh, elu, sigmoid, softmax.

in dit neurale netwerk hebben we telkens 2 convolutielagen gevolgd door een poolende laag. Vervolgens maken we de gegevens plat om een dichte laag toe te voegen waarop we dropout toepassen met een snelheid van 0,5. Tot slot voegen we een dichte laag toe om elke afbeelding met de juiste klasse toe te wijzen.

het model compileren

vervolgens moeten we ons model compileren. Het compileren van het model neemt drie parameters: optimizer, verlies en metrics.

De optimizer bepaalt de leersnelheid. We zullen ‘adam’ gebruiken als onze optimizer. Adam is over het algemeen een goede optimizer om te gebruiken voor veel gevallen. De adam optimizer past de leersnelheid tijdens de training aan.

de leersnelheid bepaalt hoe snel de optimale gewichten voor het model worden berekend. Een kleinere Leersnelheid kan leiden tot meer nauwkeurige gewichten (tot een bepaald punt), maar de inkrimping is de rekentijd.

We zullen ‘categorical_crossentropy’ gebruiken voor onze verliesfunctie. Dit is de meest voorkomende keuze voor classificatie. Een lagere score geeft aan dat het model beter presteert.

om het nog makkelijker te interpreteren te maken, gebruiken we de’ accuracy ‘ – metriek om de nauwkeurigheidsscore op de validatieset te zien wanneer we het model trainen.

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

Training van het model

nu zullen we ons model trainen. Om te trainen gebruiken we de functie’ fit () ‘ op ons model met de volgende parameters: trainingsgegevens (X_train), doelgegevens (Y_train), validatiegegevens en het aantal tijdperken.

voor onze validatiegegevens gebruiken we de testset die aan ons is verstrekt in onze dataset, die we hebben opgesplitst in X_test en Y_test.

het aantal tijdperken is het aantal keren dat het model door de gegevens zal bladeren. Hoe meer tijdperken we draaien, hoe meer het model zal verbeteren, tot op een bepaald punt. Na dat punt zal het model stoppen met verbeteren tijdens elk tijdperk. Voor ons model stellen we het aantal tijdperken in op 3.

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

het Evalueren van het model

Nu hebben we getraind ons model kunnen we evalueren van de prestaties:

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

Dus, we hebben een nauwkeurigheid van 99,3% en een verlies van 0.025 op de proef stellen en dat is heel goed. We kunnen het model nog steeds verbeteren door het aantal epoch te verhogen en een batchgrootte in te voeren.

maak voorspellingen

Als u de werkelijke voorspellingen wilt zien die ons model heeft gemaakt voor de testgegevens, kunnen we de functie predict_classes gebruiken. We kunnen dit ook met behulp van de predict functie een array met 10 getallen geven. Deze getallen zijn de waarschijnlijkheid dat de invoerafbeelding elk cijfer vertegenwoordigt (0-9). De array-index met het hoogste aantal vertegenwoordigt de modelvoorspelling. De som van elke array is gelijk aan 1 (aangezien elk getal een waarschijnlijkheid is).

om dit te laten zien, zullen we de voorspellingen voor de eerste 4 afbeeldingen in de testset tonen.

Opmerking: Als we nieuwe gegevens hebben, kunnen we onze nieuwe gegevens invoeren in de predict-functie om de voorspellingen te zien die ons model maakt op de nieuwe gegevens. Aangezien we geen nieuwe ongeziene gegevens hebben, zullen we voorlopig voorspellingen laten zien met behulp van de testset.

#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 werkelijke resultaten laten zien dat de eerste vier afbeeldingen zijn ook 7, 2,1 en 0. Ons model correct voorspeld!

geheel model

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

wordt vervolgd…

In dit artikel heb ik het tweede deel van beeldherkenning behandeld, dat een neuraal netwerk van convoluties bouwt.

Ik hoop dat je gevonden hebt waarvoor je hier kwam in dit artikel en blijf bij me voor de volgende afleveringen van deze beeldherkenningsreis!

PS: Ik ben momenteel een Master of Engineering Student aan Berkeley, en als je het onderwerp wilt bespreken, voel je vrij om me te bereiken. Hier is mijn e-mail.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.