Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Red neuronal convolucional (CNN)

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

Este tutorial demuestra el entrenamiento de una red neuronal convolucional (CNN) simple para clasificar imágenes CIFAR . Debido a que este tutorial utiliza la API secuencial de Keras , la creación y el entrenamiento de nuestro modelo tomarán solo unas pocas líneas de código.

Importar TensorFlow

import tensorflow as tf

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

Descargue y prepare el conjunto de datos CIFAR10

El conjunto de datos CIFAR10 contiene 60.000 imágenes en color en 10 clases, con 6.000 imágenes en cada clase. El conjunto de datos se divide en 50.000 imágenes de entrenamiento y 10.000 imágenes de prueba. Las clases son mutuamente excluyentes y no hay superposición entre ellas.

(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 los datos

Para verificar que el conjunto de datos se vea correcto, tracemos las primeras 25 imágenes del conjunto de entrenamiento y muestremos el nombre de la clase debajo de cada imagen.

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], cmap=plt.cm.binary)
    # 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 convolucional

Las 6 líneas de código siguientes definen la base convolucional utilizando un patrón común: una pila de capas Conv2D y MaxPooling2D .

Como entrada, una CNN toma tensores de forma (image_height, image_width, color_channels), ignorando el tamaño del lote. Si es nuevo en estas dimensiones, color_channels se refiere a (R, G, B). En este ejemplo, configurará nuestra CNN para procesar entradas de forma (32, 32, 3), que es el formato de las imágenes CIFAR. Puede hacer esto pasando el argumento input_shape a nuestra primera capa.

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

Vamos a mostrar la arquitectura de nuestro modelo hasta ahora.

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
_________________________________________________________________

Arriba, puede ver que la salida de cada capa Conv2D y MaxPooling2D es un tensor de forma 3D (alto, ancho, canales). Las dimensiones de ancho y alto tienden a encogerse a medida que profundiza en la red. El número de canales de salida para cada capa Conv2D se controla mediante el primer argumento (por ejemplo, 32 o 64). Normalmente, a medida que el ancho y la altura se reducen, puede permitirse (computacionalmente) agregar más canales de salida en cada capa Conv2D.

Agregue capas densas en la parte superior

Para completar nuestro modelo, alimentará el último tensor de salida de la base convolucional (de forma (4, 4, 64)) en una o más capas densas para realizar la clasificación. Las capas densas toman vectores como entrada (que son 1D), mientras que la salida actual es un tensor 3D. Primero, aplanará (o desenrollará) la salida 3D a 1D, luego agregará una o más capas densas en la parte superior. CIFAR tiene 10 clases de salida, por lo que usa una capa densa final con 10 salidas y una activación softmax.

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

Aquí está la arquitectura completa de nuestro modelo.

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
_________________________________________________________________

Como puede ver, nuestras salidas (4, 4, 64) se aplanaron en vectores de forma (1024) antes de pasar por dos capas densas.

Compilar y entrenar el modelo

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 [==============================] - 4s 3ms/step - loss: 1.5295 - accuracy: 0.4441 - val_loss: 1.3232 - val_accuracy: 0.5301
Epoch 2/10
1563/1563 [==============================] - 4s 3ms/step - loss: 1.1693 - accuracy: 0.5868 - val_loss: 1.0998 - val_accuracy: 0.6113
Epoch 3/10
1563/1563 [==============================] - 4s 3ms/step - loss: 1.0127 - accuracy: 0.6444 - val_loss: 1.0281 - val_accuracy: 0.6422
Epoch 4/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.9099 - accuracy: 0.6806 - val_loss: 0.9073 - val_accuracy: 0.6825
Epoch 5/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.8317 - accuracy: 0.7088 - val_loss: 0.9311 - val_accuracy: 0.6761
Epoch 6/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.7722 - accuracy: 0.7287 - val_loss: 0.8591 - val_accuracy: 0.7061
Epoch 7/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.7173 - accuracy: 0.7490 - val_loss: 0.8435 - val_accuracy: 0.7126
Epoch 8/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.6719 - accuracy: 0.7650 - val_loss: 0.8738 - val_accuracy: 0.7058
Epoch 9/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.6330 - accuracy: 0.7782 - val_loss: 0.8754 - val_accuracy: 0.7061
Epoch 10/10
1563/1563 [==============================] - 4s 3ms/step - loss: 0.5975 - accuracy: 0.7901 - val_loss: 0.8497 - val_accuracy: 0.7167

Evaluar el modelo

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 - 1s - loss: 0.8497 - accuracy: 0.7167

png

print(test_acc)
0.71670001745224

Nuestro sencillo CNN ha logrado una precisión de prueba de más del 70%. ¡Nada mal para unas pocas líneas de código! Para ver otro estilo de CNN, vea un ejemplo usando la API de subclases de Keras y untf.GradientTape aquí .