Crear redes neuronales convolucionales (CNN) para mejorar la visión artificial

1. Antes de comenzar

En este codelab, aprenderás a usar CNN para mejorar tus modelos de clasificación de imágenes.

Requisitos previos

Este codelab se basa en el trabajo completado en dos cuotas anteriores, Compila un modelo de visión artificial, en el que presentamos parte del código que usarás aquí, y el codelab Build convolutions and performinging, donde presentamos las convoluciones y las agrupaciones.

Qué aprenderás

  • Cómo mejorar la visión y precisión de una computadora con convoluciones

Qué compilarás

  • Capas para mejorar la red neuronal

Requisitos

Puedes encontrar el código para el resto del codelab que se ejecuta en Colab.

También deberás instalar TensorFlow y las bibliotecas que instalaste en el codelab anterior.

2. Mejorar la precisión de la visión artificial con convoluciones

Ahora, sabes cómo reconocer imágenes de moda mediante una red neuronal profunda (DNN) que contiene tres capas: la de entrada (en forma de datos de entrada), la de salida (en forma de salida) y una oculta. Experimentaste con varios parámetros que influyen en la precisión final, como diferentes tamaños de capas ocultas y la cantidad de ciclos de entrenamiento.

Para tu comodidad, vuelve a encontrar el código completo. Ejecútala y tome nota de la exactitud de la prueba que se imprime al final.

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

La precisión es, aproximadamente, del 89% en el entrenamiento y el 87% en la validación. Esto se puede mejorar aún más con convoluciones, que reduce el contenido de la imagen para centrarse en detalles específicos y distintos.

Si alguna vez hiciste procesamiento de imágenes con un filtro, las convoluciones te resultarán muy familiares.

En resumen, toman un array (generalmente 3×3 o 5×5) y lo pasan por la imagen. Si cambias los píxeles subyacentes según la fórmula de esa matriz, puedes realizar operaciones como la detección de bordes. Por ejemplo, normalmente, un 3×3 se define para la detección de bordes en la que la celda del medio es 8 y todos sus vecinos son -1. En este caso, para cada píxel se multiplicaría su valor por 8 y, luego, se resta el valor de cada vecino. Haz esto con cada píxel y obtendrás una nueva imagen con sus bordes mejorados.

Esto es perfecto para la visión artificial, ya que mejorar las funciones como los bordes ayuda a la computadora a distinguir un elemento de otro. Mejor aún, la cantidad de información necesaria es mucho menor, ya que el entrenamiento solo se realizará en las funciones destacadas.

Este es el concepto de redes neuronales convolucionales. Agrega algunas capas para realizar convoluciones antes de obtener las capas densas, y la información que vaya a las capas densas se volverá más enfocada y posiblemente más precisa.

3. Prueba el código

Ejecuta el siguiente código. Es la misma red neuronal que antes, pero esta vez con capas convolucionales agregadas primero. Tardará más tiempo, pero analice el impacto en la exactitud:

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images / 255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
  tf.keras.layers.MaxPooling2D(2, 2),
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Es probable que haya aumentado hasta un 93% en los datos de entrenamiento y un 91% en los datos de validación.

Ahora, prueba ejecutarla durante más épocas, por ejemplo, alrededor de 20, y explora los resultados. Si bien los resultados de entrenamiento pueden parecer muy buenos, los resultados de validación pueden disminuir debido a un fenómeno llamado sobreajuste.

El sobreajuste ocurre cuando la red aprende los datos del conjunto de entrenamiento demasiado bien, por lo que se especializa para reconocer solo esos datos y, como resultado, es menos efectivo ver otros datos en situaciones más generales. Por ejemplo, si entrenaste solo con tacones, la red podría ser muy buena para identificar los zapatos de tacón, pero las zapatillas podrían confundirlo.

Vuelve a observar el código y observa paso a paso cómo se crearon las convoluciones.

4. Recopila los datos

El primer paso es recopilar los datos.

Notarás que hay un cambio aquí y que se deben reformar los datos de entrenamiento. Esto se debe a que la primera convolución espera un solo tensor que contenga todo, de modo que en lugar de 60,000 elementos de 28 x 28 x 1 en una lista, tienes una sola lista en 4D que es de 60,000 x 28 x 28 x 1, y lo mismo para las imágenes de prueba. Si no lo haces, se mostrará un error cuando entrenes porque las convoluciones no reconocen la forma.

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images = training_images/255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images/255.0

5. Define el modelo

A continuación, define tu modelo. En lugar de agregar la capa de entrada en la parte superior, agregarás una capa convolucional. Los parámetros son los siguientes:

  • La cantidad de convoluciones que quieres generar. Un valor como 32 es un buen punto de partida.
  • Tamaño de la matriz convolucional (en este caso, una cuadrícula de 3 x 3).
  • La función de activación que usarás, en este caso, usa relu.
  • En la primera capa, la forma de los datos de entrada.

Seguirás la convolución con una capa de agrupación máxima, que está diseñada para comprimir la imagen manteniendo el contenido de los atributos destacados por la convolución. Si especificas (2,2) para la reducción máxima, el efecto es reducir el tamaño de la imagen en un factor de 4. Crea un arreglo de 2 x 2 píxeles y selecciona el valor más grande de píxeles. Para ello, convierte 4 píxeles en 1. Repite este cálculo en toda la imagen y, al hacerlo, se reduce a la mitad la cantidad de píxeles horizontales y a la mitad de la cantidad de píxeles verticales.

Puedes llamar a model.summary() para ver el tamaño y la forma de la red. Ten en cuenta que, después de cada capa de agrupación máxima, se reduce el tamaño de la imagen de la siguiente manera:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_2 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_5 (Dense)              (None, 10)                1290      
=================================================================

Este es el código completo para la CNN:

model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
#Add another convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
#Now flatten the output. After this you'll just have the same DNN structure as the non convolutional version
tf.keras.layers.Flatten(),
#The same 128 dense layers, and 10 output layers as in the pre-convolution example:
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])

6. Compila y entrena el modelo

Compila el modelo, llama al método de ajuste para realizar el entrenamiento y evalúa la pérdida y exactitud del conjunto de prueba.

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_acc*100))

7. Visualiza las convoluciones y las agrupaciones

Este código te muestra las convoluciones gráficamente. print (test_labels[:100]) muestra las primeras 100 etiquetas en el conjunto de prueba y puedes ver que las del índice 0, el índice 23 y el índice 28 tienen el mismo valor (9). Son todos zapatos. Observa el resultado de ejecutar la convolución en cada uno de ellos y comenzarás a ver atributos comunes entre ellos. Cuando la DNN entrena con esos datos, está trabajando con mucha menos información y, quizás, constela una combinación entre zapatos en función de esa combinación de convolución y agrupación.

print(test_labels[:100])
[9 2 1 1 6 1 4 6 5 7 4 5 7 3 4 1 2 4 8 0 2 5 7 9 1 4 6 0 9 3 8 8 3 3 8 0 7
 5 7 9 6 1 3 7 6 7 2 1 2 2 4 4 5 8 2 2 8 4 8 0 7 7 8 5 1 1 2 3 9 8 7 0 2 6
 2 3 1 2 8 4 1 8 5 9 5 0 3 2 0 6 5 3 6 7 1 8 0 1 4 2]

Ahora, puede seleccionar algunas de las imágenes correspondientes para esas etiquetas y renderizar cómo se ven siguiendo las convoluciones. Por lo tanto, en el siguiente código, FIRST_IMAGE, SECOND_IMAGE y THIRD_IMAGE son todos los índices del valor 9, un bota tobillera.

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 6
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

Debería ver algo como lo siguiente, en el que la convolución toma la esencia de la zapata y detecta eso como una característica común de todos los zapatos.

6c9109bcc640a1ec.png

8. Ejercicios

Ejercicio 1

Intenta editar las convoluciones. Cambia la cantidad de convoluciones de 32 a 16 o 64. ¿Qué impacto tiene esto en la exactitud y el tiempo de entrenamiento?

Ejercicio 2

Quita la convolución final. ¿Qué impacto tiene en la exactitud o en el tiempo de entrenamiento?

Ejercicio 3

Agrega más convoluciones. ¿qué impacto tiene esto?

Ejercicio 4

Quita todas las convoluciones, excepto la primera. ¿qué impacto tiene esto? Experimentar con él

9. Felicitaciones

Creaste tu primer CNN. Para obtener más información sobre cómo mejorar aún más los modelos de visión artificial, consulta Usa redes neuronales convolucionales (CNN) con imágenes complejas.