Crear redes neuronales convolucionales (CNN) para mejorar la visión artificial
Acerca de este codelab
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.
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.