image-recognition-in-python-met-tensorflow

Wat leer je in deze tutorial?

Wat is TensorFlow?

TensorFlow is een Python package voor machine learning en is ontwikkeld door Google. TensorFlow focust specifiek op neural networks.

Neural networks zijn machine learning algoritmes die vooral bij voorspellingen met beeld-, geluid- en tekstdata gebruikt worden.

Google gebruikt het zelf bijvoorbeeld voor het verbeteren van zoekresultaten en vertalingen. TensorFlow is populair en wordt door veel bedrijven gebruikt, voorbeelden hiervan zijn Airbnb, PayPal en Twitter. Airbnb gebruikt TensorFlow bijvoorbeeld om objecten in foto’s van verblijfsruimtes te classificeren, om klanten zo van goede informatie te voorzien. PayPal gebruikt het om complexe fraudegevallen te detecteren bij financiële transacties.

Neural networks kenmerken zich door een complexe modelstructuur waardoor ook complexe voorspellingen gedaan kunnen worden. TensorFlow biedt hierbij met behulp van onder andere de TensorFlow module Keras gemakkelijke abstractielagen waardoor weinig regels code nodig zijn om complexe neural networks te creëren.

De naam TensorFlow is als volgt te verklaren: Een tensor is een vector of matrix en is de standaard vorm van dataopslag binnen deep learning. Deze data wordt vervolgens in stappen verwerkt, de flow.

Dataset van Zalando kledingstukken voor image recognition

In deze tutorial gaan we een model samenstellen om afbeeldingen te classificeren als een bepaald kledingstuk (ook wel image recognition of in het Nederlands beeldherkenning genoemd). Hiervoor gebruiken we een dataset met duizenden foto’s van Zalando.

image-recognition-python-tensorflow

Allereerst importeren we de benodigde packages voor deze tutorial. Zorg ervoor dat je TensorFlow versie 2 geïnstalleerd hebt.

In [1]:
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

We importeren module Keras uit package TensorFlow voor het model, Numpy om met matrixen te kunnen werken en module Pyplot uit package Matplotlib voor visualisaties.

Vanuit TensorFlow kunnen we direct al gebruik maken van de Zalando dataset. Dit is in deze tutorial gemakkelijk omdat we hierdoor gemakkelijk met deze data kunnen werken, zonder dat we lokaal afbeeldingen uit moeten lezen en omzetten naar een formaat wat we voor het model kunnen gebruiken.

In onderstaande code verkrijgen we de data die bestaat uit train- en testdata. Beide delen bestaan weer uit afbeeldingen en bijbehorende labels. Wat dit inhoudt bekijken we hierna.

In [2]:
dataset_fashion = keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = dataset_fashion.load_data()

print("Train images:", len(train_images))
print("Test images:", len(test_images))
Train images: 60000
Test images: 10000

We zien dat de traindata uit train- en testdata uit 60.000 en 10.000 afbeeldingen bestaat.

Met onderstaande code bekijken we de details van een willekeurige afbeeldingen.

In [3]:
print(train_images[1].shape)
train_images[1]
(28, 28)
Out[3]:
array([[  0,   0,   0,   0,   0,   1,   0,   0,   0,   0,  41, 188, 103,
         54,  48,  43,  87, 168, 133,  16,   0,   0,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   1,   0,   0,   0,  49, 136, 219, 216, 228, 236,
        255, 255, 255, 255, 217, 215, 254, 231, 160,  45,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,  14, 176, 222, 224, 212, 203, 198, 196,
        200, 215, 204, 202, 201, 201, 201, 209, 218, 224, 164,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0, 188, 219, 200, 198, 202, 198, 199, 199,
        201, 196, 198, 198, 200, 200, 200, 200, 201, 200, 225,  41,   0,
          0,   0],
       [  0,   0,   0,   0,  51, 219, 199, 203, 203, 212, 238, 248, 250,
        245, 249, 246, 247, 252, 248, 235, 207, 203, 203, 222, 140,   0,
          0,   0],
       [  0,   0,   0,   0, 116, 226, 206, 204, 207, 204, 101,  75,  47,
         73,  48,  50,  45,  51,  63, 113, 222, 202, 206, 220, 224,   0,
          0,   0],
       [  0,   0,   0,   0, 200, 222, 209, 203, 215, 200,   0,  70,  98,
          0, 103,  59,  68,  71,  49,   0, 219, 206, 214, 210, 250,  38,
          0,   0],
       [  0,   0,   0,   0, 247, 218, 212, 210, 215, 214,   0, 254, 243,
        139, 255, 174, 251, 255, 205,   0, 215, 217, 214, 208, 220,  95,
          0,   0],
       [  0,   0,   0,  45, 226, 214, 214, 215, 224, 205,   0,  42,  35,
         60,  16,  17,  12,  13,  70,   0, 189, 216, 212, 206, 212, 156,
          0,   0],
       [  0,   0,   0, 164, 235, 214, 211, 220, 216, 201,  52,  71,  89,
         94,  83,  78,  70,  76,  92,  87, 206, 207, 222, 213, 219, 208,
          0,   0],
       [  0,   0,   0, 106, 187, 223, 237, 248, 211, 198, 252, 250, 248,
        245, 248, 252, 253, 250, 252, 239, 201, 212, 225, 215, 193, 113,
          0,   0],
       [  0,   0,   0,   0,   0,  17,  54, 159, 222, 193, 208, 192, 197,
        200, 200, 200, 200, 201, 203, 195, 210, 165,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,  47, 225, 192, 214, 203, 206,
        204, 204, 205, 206, 204, 212, 197, 218, 107,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   1,   6,   0,  46, 212, 195, 212, 202, 206,
        205, 204, 205, 206, 204, 212, 200, 218,  91,   0,   3,   1,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,  11, 197, 199, 205, 202, 205,
        206, 204, 205, 207, 204, 205, 205, 218,  77,   0,   5,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   3,   0,   2, 191, 198, 201, 205, 206,
        205, 205, 206, 209, 206, 199, 209, 219,  74,   0,   5,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   2,   0,   0, 188, 197, 200, 207, 207,
        204, 207, 207, 210, 208, 198, 207, 221,  72,   0,   4,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   2,   0,   0, 215, 198, 203, 206, 208,
        205, 207, 207, 210, 208, 200, 202, 222,  75,   0,   4,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 212, 198, 209, 206, 209,
        206, 208, 207, 211, 206, 205, 198, 221,  80,   0,   3,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 204, 201, 205, 208, 207,
        205, 211, 205, 210, 210, 209, 195, 221,  96,   0,   3,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 202, 201, 205, 209, 207,
        205, 213, 206, 210, 209, 210, 194, 217, 105,   0,   2,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 204, 204, 205, 208, 207,
        205, 215, 207, 210, 208, 211, 193, 213, 115,   0,   2,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0, 204, 207, 207, 208, 206,
        206, 215, 210, 210, 207, 212, 195, 210, 118,   0,   2,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 198, 208, 208, 208, 204,
        207, 212, 212, 210, 207, 211, 196, 207, 121,   0,   1,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 198, 210, 207, 208, 206,
        209, 213, 212, 211, 207, 210, 197, 207, 124,   0,   1,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0, 172, 210, 203, 201, 199,
        204, 207, 205, 204, 201, 205, 197, 206, 127,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0, 188, 221, 214, 234, 236,
        238, 244, 244, 244, 240, 243, 214, 224, 162,   0,   2,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   1,   0,   0, 139, 146, 130, 135, 135,
        137, 125, 124, 125, 121, 119, 114, 130,  76,   0,   0,   0,   0,
          0,   0]], dtype=uint8)

Te zien is dat dit is opgebouwd uit een matrix van 28 rijen en kolommen. Hierbij zijn de waarden gelijk aan 0-255. Dit betekent praktisch dat elke afbeelding uit 28 bij 28 pixels bestaat, en elke waarde staat voor de kleur van een pixel: 0 is wit en 255 is zwart.

Dit is gemakkelijk te visualiseren met Matplotlib:

In [4]:
plt.imshow(train_images[1], cmap=plt.cm.binary);

Hier is duidelijk een tshirt in te herkennen. Het bijbehorende label van deze afbeelding bekijken we met onderstaande code.

In [5]:
train_labels[1]
Out[5]:
0

Dit geeft de categorie aan. We kunnen met de volgende code achterhalen welke labels er zijn en hoeveel dit er in totaal zijn.

In [6]:
unique_labels = np.unique(train_labels)
print(len(unique_labels))
unique_labels
10
Out[6]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8)

Er zijn 10 verschillende labels wat betekent dat de dataset uit 10 verschillende soorten kleding bestaat. Vanuit de documentatie is te achterhalen wat de betekenis van een label is. Dit passen we als volgt toe:

In [7]:
label_names = ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]

label_names[train_labels[1]]
Out[7]:
'T-shirt/top'

We hebben gezien dat de data numerieke waarden 0 tot en met 255 bevat. Om de data goed voor te bereiden voor het model normaliseren we dit naar waarden tussen 0 en 1. Dit kan in dit geval gemakkelijk door waarden door 255 te delen.

In [8]:
train_images = train_images / 255
test_images = test_images / 255

print(np.min(train_images))
print(np.max(train_images))
0.0
1.0
Zelf machine learning modellen ontwikkelen? Schrijf je in voor een van onze data science trainingen.


Modelleren

Nu we de data in een goed formaat tot onze beschikking hebben kunnen we het image recognition model in Python aan gaan maken. Dit wordt een neural network. Een neural network is typisch opgebouwd uit een serie van meerdere lagen (layers). Hierbij heb je de input layer waarin de data het model binnenkomt en de output layer die de waarden van de voorspellingen geeft. Hiertussen kunnen meerdere zogeheten hidden layers aanwezig zijn. Elke layer bestaat uit meerdere nodes (neurons).

Model voor beeldherkenning (image recognition) aanmaken

In de volgende code maken we een Python image recognition model aan wat we opbouwen uit een serie lagen.

In [9]:
model = keras.Sequential()

model.add(keras.layers.Flatten(input_shape=(28,28)))
model.add(keras.layers.Dense(128, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"))

De eerste laag die we aanmaken heeft type Flatten met een input_shape=(28,28). Dit is de input layer en door type Flatten zorgen we ervoor dat een afbeelding die uit 28 rijen van 28 waarden om wordt gezet in één lijst van 28*28 = 784 waarden.

De tweede en derde laag zijn Dense layers. Dit zijn standaard layers waarbij de nodes van een layer met alle nodes van de naastgelegen layers verbonden zijn. De eerste Dense layer is de hidden layer. We kiezen hier 128 nodes. Dit getal is vrij te kiezen. Activation “relu” staat voor rectified linear unit. Dit is een methode waarop de nodes activeren.

De derde layer is ook een Dense layer, dit is de output layer. Omdat er 10 soorten kleding in de data aanwezig zijn is het aantal nodes hier gelijk aan 10. Activation “softmax” zorgt ervoor dat de 10 waarden opgeteld 1 zijn. Dit geeft hierdoor de kans bij een voorspelling voor elk van de mogelijke kledingstukken.

Er is een methode waarin we de configuratie van ons model samengevat kunnen weergeven om te controleren of dit aan onze verwachtingen voldoet.

In [10]:
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________

Model configureren

Nu de structuur van het model staat is de volgende stap om te specificeren hoe het model geoptimaliseerd en beoordeeld moet worden.

In [11]:
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])

Hierin is optimizer ”adam” het algoritme wat beschrijft de parameters in het model aanpast. Hierbij wordt de loss function gebruikt om het verschil tussen voorspelling en werkelijke waarde uit te drukken. Voor hier is het alleen belangrijk om te weten dat er meerdere soorten optimizers en loss functions zijn. Er kunnen meerdere metrics opgegeven worden waarmee voorspellingen te beoordelen zijn. Hier kiezen we de accuracy wat procentueel laat zien hoeveel voorspellingen juist zijn.

Model trainen

Alles is nu gereed om het model op de traindata te kunnen trainen. Dit kan met de .fit() methode. Met epochs=5 zorgen we ervoor dat de data 5 keer opnieuw door het model gebruikt wordt tijdens het trainen.

In [12]:
model.fit(x=train_images, y=train_labels, epochs=5)
Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 6s 97us/sample - loss: 0.4965 - accuracy: 0.8258
Epoch 2/5
60000/60000 [==============================] - 4s 73us/sample - loss: 0.3754 - accuracy: 0.8637
Epoch 3/5
60000/60000 [==============================] - 4s 71us/sample - loss: 0.3345 - accuracy: 0.8782
Epoch 4/5
60000/60000 [==============================] - 5s 76us/sample - loss: 0.3140 - accuracy: 0.8846
Epoch 5/5
60000/60000 [==============================] - 4s 75us/sample - loss: 0.2940 - accuracy: 0.8910
Out[12]:
<tensorflow.python.keras.callbacks.History at 0x29b31d86048>

Het model is nu getraind op de traindata. Hierbij is een nauwkeurigheid van 89% behaald.

Model opslaan

Nu we een getraind model hebben kunnen we dit opslaan om later te gebruiken, of om het met anderen te delen. Hier zijn verschillende methoden voor, in dit voorbeeld gebruiken we het .h5 formaat.

In [13]:
model.save("model.h5")

Model openen

Een opgeslagen model is weer te openen en kan zo hergebruikt worden. Hierdoor bespaar je je de tijd van het trainen.

In [14]:
saved_model = keras.models.load_model("model.h5")
saved_model
Out[14]:
<tensorflow.python.keras.engine.sequential.Sequential at 0x29b31ec81d0>

Te zien is dat het inderdaad een TensorFlow model is wat geopend is.

Voorspellen met het Python image recognition model: alle testdata

Onze dataset bestaat uit train- en testdata. We hebben het model getraind met de traindata waarbij we een nauwkeurigheid van 89% hebben behaald. Dat is mooi, maar we weten nog niet hoe het model presteert op nieuwe data. Om hier een beeld van te vormen gaan we voorspellingen met het model doen op de testdata. Met de .predict() methode kunnen met het model voorspellingen worden gedaan.

In [15]:
predictions = saved_model.predict(test_images)

Hiermee doen we in één keer voorspellingen voor de volledige testdata. Laten we een specifiek datapunt bekijken.

In [16]:
predictions[10]
Out[16]:
array([1.2464239e-04, 2.7330550e-05, 2.1159260e-01, 3.3763337e-07,
       7.7158540e-01, 1.1517837e-07, 1.6662065e-02, 1.6896454e-08,
       6.3644252e-06, 1.2216248e-06], dtype=float32)

De output layer van het model bestaat uit 10 nodes: één voor elk mogelijk kledingstuk. We krijgen als uitkomst van onze voorspelling dan ook een lijst met 10 getallen, de kans voor elk van de mogelijke kledingstukken.

Met de volgende code vinden we de positie van de hoogste kans.

In [17]:
np.argmax(predictions[10])
Out[17]:
4

Het vierde getal heeft de hoogste score. Hier kunnen we de bijbehorende naam bijzoeken.

In [18]:
label_names[np.argmax(predictions[10])]
Out[18]:
'Coat'

Er is dus voorspeld dat dit een jas moet zijn. Laten we dit controleren door hiervoor de afbeelding te bekijken.

In [24]:
plt.imshow(test_images[10], cmap=plt.cm.binary);

Op basis van deze test lijkt het model het goed te doen op nieuwe data, maar dit was natuurlijk slechts een steekproef.

Model evalueren

Om te zien hoe het model presteert op de volledige testdata gebruiken we de .evaluate() methode.

In [25]:
saved_model.evaluate(x=test_images, y=test_labels)
10000/10000 [==============================] - 0s 49us/sample - loss: 0.3518 - accuracy: 0.8702
Out[25]:
[0.3518407985448837, 0.8702]

We zien hier nogmaals dat de testdata uit 10.000 afbeeldingen bestond, en dat het model hier met een accuracy van 0.8702 voorspellingen wist te doen. Dit betekent dat 87% van de voorspellingen op voor het model nieuwe data, de testdata, correct is. Voor de traindata was dit 89%. Dit ziet er dus erg goed uit.

Voorspellen met het model: individuele voorspellingen

We hebben gezien hoe we met de .predict() methode in Python aan beeldherkenning kunnen doen met ons model. Dit hebben we gedaan voor alle items uit de testdata. Laten we tot slot bekijken we hoe we dit voor individuele afbeeldingen doen.

Hiervoor maken we een functie waarin we de voorspelling voor een bepaalde afbeelding doen. Let er hierbij op dat het model input verwacht als 28*28 matrices in een list. Dit garanderen we voor individuele voorspellingen met .reshape(). Vervolgens bepalen we de naam van het voorspelde label, en de werkelijke naam. Dit plotten we als geheel.

In [31]:
def show_prediction(number):
    prediction = saved_model.predict(test_images[number].reshape(1, 28, 28))
    prediction_name = label_names[np.argmax(prediction)]
    actual_name = label_names[test_labels[number]]
    plt.imshow(test_images[number], cmap=plt.cm.binary);
    plt.title("Actual: {} & Predicted: {}".format(actual_name, prediction_name))
    plt.show()
    
show_prediction(9856)

Nu dit als functie beschikbaar is kunnen we ook gemakkelijk de voorspellingen doen voor een reeks aan verschillende afbeeldingen.

In [30]:
for number in [5668, 214, 789]:
    show_prediction(number)
Zelf machine learning modellen ontwikkelen? Schrijf je in voor een van onze data science trainingen.


Wat je moet onthouden over image recognition in Python met TensorFlow

TensorFlow is een veelgebruikt machine learning package wat veelgebruikt wordt voor neural networks en is ontwikkeld door Google. Het abstraheert de complexe wiskundige logica waardoor maar enkele regels code nodig zijn voor een uitgebreide modelstructuur. Met TensorFlow hebben we een neural network gemaakt voor image recognition/ beeldherkenning. Dit model hebben we opgebouwd uit verschillende layers. Het model is op te slaan voor hergebruik. De bruikbaarheid van het model hebben we geëvalueerd door voorspelling te doen op voor het model nieuwe data, de testdata.

Machine learning specialist worden?

Wil jij snel op stoom zijn met machine learning? Volg dan onze Data Science opleiding. In vier dagen nemen we je mee in de basis van Python en statistiek. Er is geen voorkennis vereist. Je leert zelfstandig machine learning modellen ontwikkelen en toepassen. Voor wie al ervaring heeft met programmeren in Python is het ook mogelijk om alleen de laatste twee dagen mee te doen; dit is onze machine learning training.

Download één van onze opleidingsbrochures voor meer informatie

by: