Eine Frage haben? Verbinden Sie sich mit der Community im TensorFlow Forum Visit Forum

Convolutional Neural Network (CNN)

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

Dieses Tutorial zeigt, wie man ein einfaches Convolutional Neural Network (CNN) trainiert, um CIFAR-Bilder zu klassifizieren. Da in diesem Tutorial die Keras Sequential API verwendet wird, benötigen Sie zum Erstellen und Trainieren Ihres Modells nur wenige Codezeilen.

TensorFlow importieren

import tensorflow as tf

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

Laden Sie den CIFAR10-Datensatz herunter und bereiten Sie ihn vor

Der CIFAR10-Datensatz enthält 60.000 Farbbilder in 10 Klassen mit 6.000 Bildern in jeder Klasse. Der Datensatz ist in 50.000 Trainingsbilder und 10.000 Testbilder unterteilt. Die Klassen schließen sich gegenseitig aus und es gibt keine Überschneidungen zwischen ihnen.

(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

Überprüfen Sie die Daten

Um zu überprüfen, ob der Datensatz korrekt aussieht, zeichnen wir die ersten 25 Bilder aus dem Trainingssatz und zeigen den Klassennamen unter jedem Bild an:

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

Erstellen Sie die Faltungsbasis

Die folgenden 6 Codezeilen definieren die Faltungsbasis mit einem gemeinsamen Muster: einem Stapel von Conv2D- und MaxPooling2D- Layern.

Als Eingabe verwendet ein CNN Formtensoren (image_height, image_width, color_channels) und ignoriert dabei die Batch-Größe. Wenn Sie mit diesen Dimensionen noch nicht vertraut sind, bezieht sich color_channels auf (R,G,B). In diesem Beispiel konfigurieren Sie Ihr CNN für die Verarbeitung von Eingaben der Form (32, 32, 3), dem Format von CIFAR-Bildern. Sie können dies tun, indem Sie das Argument input_shape an Ihre erste Ebene übergeben.

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

Lassen Sie uns die bisherige Architektur Ihres Modells anzeigen:

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
_________________________________________________________________

Oben sehen Sie, dass die Ausgabe jeder Conv2D- und MaxPooling2D-Ebene ein 3D-Formtensor (Höhe, Breite, Kanäle) ist. Die Breiten- und Höhenabmessungen nehmen tendenziell ab, wenn Sie tiefer in das Netzwerk eindringen. Die Anzahl der Ausgabekanäle für jede Conv2D-Schicht wird durch das erste Argument gesteuert (zB 32 oder 64). Da Breite und Höhe kleiner werden, können Sie es sich (rechnerisch) leisten, in jeder Conv2D-Ebene mehr Ausgabekanäle hinzuzufügen.

Fügen Sie dichte Schichten oben hinzu

Um das Modell zu vervollständigen, führen Sie den letzten Ausgabetensor aus der Faltungsbasis (der Form (4, 4, 64)) in eine oder mehrere dichte Schichten ein, um eine Klassifizierung durchzuführen. Dichte Ebenen verwenden Vektoren als Eingabe (die 1D sind), während die aktuelle Ausgabe ein 3D-Tensor ist. Zuerst glätten (oder entrollen) Sie die 3D-Ausgabe auf 1D und fügen dann eine oder mehrere dichte Ebenen darüber hinzu. CIFAR hat 10 Ausgabeklassen, sodass Sie eine abschließende Dichteschicht mit 10 Ausgaben verwenden.

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

Hier ist die vollständige Architektur Ihres Modells:

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
_________________________________________________________________

Die Netzwerkzusammenfassung zeigt, dass (4, 4, 64) Ausgaben in Formvektoren (1024) abgeflacht wurden, bevor sie durch zwei dichte Schichten gingen.

Kompilieren und trainieren Sie das Modell

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

Bewerten Sie das Modell

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

Ihr einfaches CNN hat eine Testgenauigkeit von über 70 % erreicht. Nicht schlecht für ein paar Zeilen Code! Für einen anderen CNN-Stil sehen Sie sich den TensorFlow 2-Schnellstart für Expertenbeispiel an , das die Keras-Unterklassen-API undtf.GradientTape .