ML Community Day è il 9 novembre! Unisciti a noi per gli aggiornamenti da tensorflow, JAX, e più Per saperne di più

Rete neurale convoluzionale (CNN)

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza la fonte su GitHub Scarica il taccuino

Questo tutorial dimostra la formazione di una semplice rete neurale convoluzionale (CNN) per classificare le immagini CIFAR . Poiché questo tutorial utilizza l' API Keras Sequential , la creazione e l'addestramento del modello richiederanno solo poche righe di codice.

Importa flusso tensore

import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

Scarica e prepara il set di dati CIFAR10

Il set di dati CIFAR10 contiene 60.000 immagini a colori in 10 classi, con 6.000 immagini in ciascuna classe. Il set di dati è suddiviso in 50.000 immagini di addestramento e 10.000 immagini di test. Le classi si escludono a vicenda e non c'è sovrapposizione tra loro.

(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170500096/170498071 [==============================] - 11s 0us/step

Verifica i dati

Per verificare che il set di dati appaia corretto, tracciamo le prime 25 immagini dal set di addestramento e visualizziamo il nome della classe sotto ogni immagine:

class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

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])
    # The CIFAR labels happen to be arrays, 
    # which is why you need the extra index
    plt.xlabel(class_names[train_labels[i][0]])
plt.show()

png

Crea la base convoluzionale

Le 6 righe di codice seguenti definiscono la base convoluzionale utilizzando un modello comune: una pila di livelli Conv2D e MaxPooling2D .

Come input, una CNN prende tensori di forma (image_height, image_width, color_channels), ignorando la dimensione del batch. Se non conosci queste dimensioni, color_channels si riferisce a (R,G,B). In questo esempio, configurerai la tua CNN per elaborare input di forma (32, 32, 3), che è il formato delle immagini CIFAR. Puoi farlo passando l'argomento input_shape al tuo primo livello.

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

Mostriamo l'architettura del tuo modello finora:

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 4, 4, 64)          36928     
=================================================================
Total params: 56,320
Trainable params: 56,320
Non-trainable params: 0
_________________________________________________________________

Sopra, puoi vedere che l'output di ogni livello Conv2D e MaxPooling2D è un tensore di forma 3D (altezza, larghezza, canali). Le dimensioni di larghezza e altezza tendono a ridursi man mano che si approfondisce la rete. Il numero di canali di output per ogni livello Conv2D è controllato dal primo argomento (ad es. 32 o 64). In genere, poiché la larghezza e l'altezza si riducono, puoi permetterti (a livello computazionale) di aggiungere più canali di output in ogni livello Conv2D.

Aggiungi strati densi sopra

Per completare il modello, alimenterai l'ultimo tensore di output dalla base convoluzionale (di forma (4, 4, 64)) in uno o più strati Dense per eseguire la classificazione. I livelli densi prendono come input i vettori (che sono 1D), mentre l'output corrente è un tensore 3D. Innanzitutto, appiattirai (o srotolerai) l'output 3D in 1D, quindi aggiungi uno o più strati Dense in cima. CIFAR ha 10 classi di output, quindi usi un livello Dense finale con 10 output.

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))

Ecco l'architettura completa del tuo modello:

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 4, 4, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 1024)              0         
_________________________________________________________________
dense (Dense)                (None, 64)                65600     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 122,570
Trainable params: 122,570
Non-trainable params: 0
_________________________________________________________________

Il riepilogo della rete mostra che (4, 4, 64) gli output sono stati appiattiti in vettori di forma (1024) prima di passare attraverso due strati Dense.

Compila e addestra il modello

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(train_images, train_labels, epochs=10, 
                    validation_data=(test_images, test_labels))
Epoch 1/10
1563/1563 [==============================] - 7s 3ms/step - loss: 1.5216 - accuracy: 0.4446 - val_loss: 1.2293 - val_accuracy: 0.5562
Epoch 2/10
1563/1563 [==============================] - 5s 3ms/step - loss: 1.1654 - accuracy: 0.5857 - val_loss: 1.0774 - val_accuracy: 0.6143
Epoch 3/10
1563/1563 [==============================] - 5s 3ms/step - loss: 1.0172 - accuracy: 0.6460 - val_loss: 1.0041 - val_accuracy: 0.6399
Epoch 4/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.9198 - accuracy: 0.6795 - val_loss: 0.9946 - val_accuracy: 0.6540
Epoch 5/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.8449 - accuracy: 0.7060 - val_loss: 0.9169 - val_accuracy: 0.6792
Epoch 6/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.7826 - accuracy: 0.7264 - val_loss: 0.8903 - val_accuracy: 0.6922
Epoch 7/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.7338 - accuracy: 0.7441 - val_loss: 0.9217 - val_accuracy: 0.6879
Epoch 8/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.6917 - accuracy: 0.7566 - val_loss: 0.8799 - val_accuracy: 0.6990
Epoch 9/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.6431 - accuracy: 0.7740 - val_loss: 0.9013 - val_accuracy: 0.6982
Epoch 10/10
1563/1563 [==============================] - 5s 3ms/step - loss: 0.6074 - accuracy: 0.7882 - val_loss: 0.8949 - val_accuracy: 0.7075

Valuta il modello

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
313/313 - 0s - loss: 0.8949 - accuracy: 0.7075

png

print(test_acc)
0.7074999809265137

La tua semplice CNN ha raggiunto una precisione di test di oltre il 70%. Non male per poche righe di codice! Per un altro stile CNN, dai un'occhiata alla guida rapida di TensorFlow 2 per esperti che utilizza l'API di sottoclasse Keras etf.GradientTape .