Classificazione base: Classifica immagini di capi d'abbigliamento

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza il sorgente su GitHub Scarica il notebook

Questa guida allena un modello di rete neurale a classificare immagini di capi d'abbigliamento, come scarpe da ginnastica e magliette. E' normale che tu non comprenda tutti i dettagli; questa è una panoramica rapidissima di un programma completo TensorFlow con i dettagli spiegati durante il percorso.

Questa guida usa tf.keras, un'API di alto livello per costruire ed addestrare modelli in TensorFlow.


from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
2.1.0

Importare il dataset Fashion MNIST

Questa guida usa il dataset Fashion MNIST che contiene 70,000 immagini in toni di grigio di 10 categorie. Le immagini mostrano singoli articoli di abbigliamento a bassa risoluzione (28 per 28 pixel), come visibile sotto:

Fashion MNIST sprite
Figura 1. Fashion-MNIST samples (by Zalando, MIT License).
 

Fashion MNIST va inteso come l'equivalente del classico dataset MNIST —spesso usato come "Hello, World" dei programmi di machine learning per la visione computerizzata. Il dataset MNIST contiene immagini di caratteri scritti a mano (0, 1, 2, ecc.) in un formato identico a quello degli articoli di abbigliamento che useremo qui.

Questa guida usa Fashion MNIST per varietà, e perchè costituisce un problema leggermente più impegnativo del tipico MNIST. Entrambe i dataset sono relativamente piccoli e sono usati per verificare che un algoritmo lavori come previsto. Sono un buon punto di partenza per provare e correggere gli errori del codice.

Qui, 60,000 immagini sono utilizzate per addestrare la rete e 10,000 immagini per valutare quanto accuratamente la rete ha imparato a classificare immagini. Potete accedere al Fashion MNIST direttamente da TensorFlow. Importare e caricare i dati Fashion MNIST direttamente da TensorFlow:

fashion_mnist = keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

Il caricamento dei dati restituisce quattro vettori NumPy:

  • I vettori train_images e train_labels sono gli insiemi di addestramento—i dati che il modello usa per imparare.
  • Il modello è verificato con l' insieme di verifica, i vettori test_images, e test_labels.

Le immagini sono vettori di 28x28 NumPy, in cui i valori dei pixel vanno da 0 a 255. Le etichette sono un vettore di interi, da 0 a 9. Esse corrispondono alle classi di capi di abbigliamento rappresentate dalle immagini:

Label Class
0 T-shirt/top
1 Trouser
2 Pullover
3 Dress
4 Coat
5 Sandal
6 Shirt
7 Sneaker
8 Bag
9 Ankle boot

Ogni immagine è mappata in una singola etichetta. Dato che i nomi delle classi non sono inclusi nel dataset, vengono memorizzati qui, per usarli successivamente durante la visualizzazione delle immagini:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

Esplorare i dati

Esploriamo il formato dei dati prima di allenare il modello. Il seguito mostra che ci sono 60,000 immagini nell'insieme di addestramento, con ciascuna immagine rappresentata con 28 x 28 pixel:

train_images.shape
(60000, 28, 28)

Analogamente, nell'insieme di addestramento, ci sono 60,000 etichette:

len(train_labels)
60000

Ogni etichetta è un intero tra 0 e 9:

train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)

Ci sono 10,000 immagini nel insieme di verifica. Di nuovo, ogni immagine è rappresentata come 28 x 28 pixel:

test_images.shape
(10000, 28, 28)

E l'insieme di verifica contiene 10,000 etichette di immagini:

len(test_labels)
10000

Pre-elaborare i dati

Prima di allenare la rete, i dati devono essere pre-elaborati. Osservando la prima immagine dell'insieme di addestramento, si noterà che i valori dei pixel cadono nell'intervallo da 0 a 255:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

png

Questi valori vanno scalati in un intervallo tra 0 e 1 prima di darli in pasto al modello della rete. Per fare ciò, si dividono i valorei per 255. E' importante che l'insieme di addestramento e l'insieme di verifica siano pre-elaborati nello stesso modo:

train_images = train_images / 255.0

test_images = test_images / 255.0

Per verificare che i dati siano nella forma corretta e che tutto sia pronto per costruire e allenare la rete, visualizziamo le prime 25 immagini del insieme di addestramento e visualizziamo il nome della classe sotto a ciascuna immagine.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

png

Costruire il modello

La costruzione della rete neurale richiede di configurare i livelli del modello, quindi la compilazione del modello.

Inizializzare i livelli

L'elemento costruttivo di base di una rete neurale è il livello. I livelli estraggono rappresentazioni dai dati con cui vengono alimentati. Sperabilmente, queste rappresentazioni sono significative per il problema che si sta trattando.

La maggior parte del deep learning consiste nel collegare tra loro livelli semplici. La maggior parte dei livelli, come tf.keras.layers.Dense, hanno parametri che sono imparati durante l'allenamento.

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

Il primo livello in questa rete, tf.keras.layers.Flatten, trasforma il formato delle immagini da un array bi-dimensionale (di 28 per 28 pixel) in un array uni-dimensionale (di 28 * 28 = 784 pixel). Pensate a questi livelli come righe non impilate di pixel dell'immagine. Questo livello non ha parametri da imparare; esso si limita a rifirmattare i dati.

Dopo la normalizzazione dei pixel, la rete consiste di due livelli tf.keras.layers.Dense. Questi sono livelli neurali strettamente connessi, o completamente connessi. Il primo livello Denso ha 128 nodi (o neuroni). Il secondo (ed ultimo) livello è un livello softmax a 10 nodi che restituisce un vettore di 10 valori di probabilità la cui somma è 1. Ogni nodo contiene un valore che indica la probabilità che l'immagine corrente appartenga ad una delle 10 classi.

Compilare il modello

Prima che il modello sia pronto per l'apprendimento, è necessaria qualche impostazione in più. Queste sono aggiunte durante i passi di compilazione del modello:

  • Funzione perdita —Misura quanto è accurato il modello durante l'apprendimento. La volontà è di minimizzare questa funzione per "dirigere" il modello nella giusta direzione.
  • Ottimizzatore —Indica com'è aggiornato il modello sulla base dei dati che tratta e della sua funzione perdita.
  • Metriche —Usate per monitorare i passi di addestramento e verifica. L'esempio seguente usa come accuratezza, la frazione delle immagini che sono classificate correttamente.
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

Addestrare il modello

L'addestramento del modello di rete neurale richiede i seguenti passi:

  1. Alimentare il modello con i dati di addestramento. In questo esempio, i dati di addestramento sono nei vettori train_images e train_labels.
  2. Il modello impara ad associare immagini ed etichette.
  3. Chiedere al modello di fare previsioni su un insieme di prova—in questo esempio, il vettore test_images.
  4. Verificare che le previsioni corrispondano alle etichette del vettore test_labels. Per iniziare l'addestramento, chiamare il metodo model.fit—chiamato così perchè "allena" il modello sui dati di addestramento:
model.fit(train_images, train_labels, epochs=10)
Train on 60000 samples
Epoch 1/10
60000/60000 [==============================] - 4s 62us/sample - loss: 0.4974 - accuracy: 0.8245
Epoch 2/10
60000/60000 [==============================] - 3s 54us/sample - loss: 0.3782 - accuracy: 0.8635
Epoch 3/10
60000/60000 [==============================] - 3s 54us/sample - loss: 0.3386 - accuracy: 0.8752
Epoch 4/10
60000/60000 [==============================] - 3s 56us/sample - loss: 0.3134 - accuracy: 0.8854
Epoch 5/10
60000/60000 [==============================] - 3s 54us/sample - loss: 0.2948 - accuracy: 0.8912
Epoch 6/10
60000/60000 [==============================] - 4s 58us/sample - loss: 0.2806 - accuracy: 0.8951
Epoch 7/10
60000/60000 [==============================] - 3s 56us/sample - loss: 0.2687 - accuracy: 0.8993
Epoch 8/10
60000/60000 [==============================] - 3s 53us/sample - loss: 0.2578 - accuracy: 0.9038
Epoch 9/10
60000/60000 [==============================] - 3s 54us/sample - loss: 0.2484 - accuracy: 0.9071
Epoch 10/10
60000/60000 [==============================] - 3s 55us/sample - loss: 0.2393 - accuracy: 0.9099

<tensorflow.python.keras.callbacks.History at 0x7fee5cf72320>

Mentre il modello si allena, vengono visualizzate le metriche di perdita e accuratezza. Questo modello raggiunge un'accuratezza di circa 0.88 (o 88%) sui dati di addestramento.

Valutare l'accuratezza

Successivamente, valutare come si comporta il modello sul dataset di test:

test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

print('\nTest accuracy:', test_acc)
10000/10000 - 1s - loss: 0.3474 - accuracy: 0.8840

Test accuracy: 0.884

Per scoprire che l'accuratezza sul datase di test è leggermente inferiore rispetto a quella sul dataset di addestramento. Questa differenza tra l'accuratezza in addestramento e l'accuratezza in test rappresenta l' overfitting. L'overfitting è quando un modello di machine learning ha prestazioni peggiori su input nuovi, mai visti prima, che sui dati di addestramento.

Fare previsioni

Una volta addestrato il modello, puoi usarlo per fare previsioni su altre immagini.

predictions = model.predict(test_images)

Qui, il modello ha previsto l'etichetta per ciascuna immagine nell'insieme di test. Diamo un'ochiata alla prima previsione:

predictions[0]
array([1.1472246e-09, 8.3733437e-12, 2.2165390e-10, 1.4233447e-13,
       4.3003373e-10, 1.7100327e-03, 8.8558044e-10, 1.2245594e-03,
       2.1470631e-08, 9.9706537e-01], dtype=float32)

Una prevsione è un vettore di 10 numeri. Essi rappresentano la "confidenza" del modello che l'immagine corrisponda a ciascuno dei 10 diversi articoli di abbigliamento. E si può vedere quale etichetta ha il valore più alto di confidenza:

np.argmax(predictions[0])
9

Così, il modello è più condidente che l'immagine sia uno stivaletto, o class_names[9]. L'esame dell'etichetta di test ostra che questa classificazione è corretta:

test_labels[0]
9

Mettendo ciò in forma grafica, si può osservare l'insieme completo delle previsioni sulle 10 classi.

def plot_image(i, predictions_array, true_label, img):
  predictions_array, true_label, img = predictions_array, true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  predictions_array, true_label = predictions_array, true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

Osserviamo la 0esima immagine, le previsioni, e il vettore delle previsioni. Le etichette previste correttamente sono in blu e le previsioni non corrette sono in rosso. Il numero da la percentuale (su 100) dell'etichetta prevista.

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], test_labels)
plt.show()

png

i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], test_labels)
plt.show()

png

Rappresentiamo diverse immagini con le rispettive previsioni. Notiamo che il modello può sbagliare anche quando è molto confidente.

# Plot the first X test images, their predicted labels, and the true labels.
# Color correct predictions in blue and incorrect predictions in red.
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

png

Infine, usiamo il modello addestrato per fare una previsione su una singola immagine.

# Grab an image from the test dataset.
img = test_images[1]

print(img.shape)
(28, 28)

I modelli tf.keras sono ottimizzati per fare previsioni su batch, o collezioni, di esempi in una volta. Di conseguenza, anche se state usando una singola immagine, è necessario aggiungerla ad una lista:

# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))

print(img.shape)
(1, 28, 28)

Ed ora andiamo a prevedere l'etichetta corretta per questa immagine:

predictions_single = model.predict(img)

print(predictions_single)
[[4.2537275e-05 2.2998520e-10 9.7777677e-01 4.2235673e-11 2.2066597e-02
  3.5941410e-11 1.1403177e-04 1.1152678e-16 4.0841791e-10 2.0124073e-15]]
plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)

png

model.predict restituisce una lista di liste—una lista per ogni immagine nel batch di dati. Prendiamo la previsione per la nostra (unica) immagine nel batch:

np.argmax(predictions_single[0])
2

E il modello prevede l'etichetta secondo le aspettative.

#@title MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.