Implementación 2

Construiremos una red neuronal convolucional para clasificar imagenes utilizando la base de datos Fashion MNIST y desarrollada en TensorFlow.

El dataset Fashion MNIST es un conjunto de datos de imágenes utilizado comúnmente para entrenar y evaluar algoritmos de aprendizaje automático, especialmente en tareas de clasificación de imágenes. Fue creado por la compañía de tecnología alemana Zalando

El conjunto contiene 70,000 imágenes en escala de grises de 28x28 píxeles entiquetados en 10 categorías diferentes de artículos de moda. Las categorias son: T-shirt/top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag y Ankle boot

Importamos los módulos necesarios

import numpy as np 
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Softmax
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.losses import SparseCategoricalCrossentropy
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import seaborn as sns
import matplotlib.pyplot as plt

Fashion MNIST Dataset

Cargar el conjunto de datos Fashion MNIST

fashion_mnist = tf.keras.datasets.fashion_mnist

Para ver la información del dataset

fashion_mnist.load_data

Tambien podemos ver la referencia de conjunto de datos en la siguiente url: https://www.tensorflow.org/api_docs/python/tf/keras/datasets/fashion_mnist/load_data

Definimos una lista que donde el indice representa el nombre de la etiqueta

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

Preprocesamiento de datos

Este dataset no es necesario utilizar una función para obtener el conjuto de entrenamiento y de prueba, el conjunto ya viene dividido por default.

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

Visualización de una imagen

Es necesario fijar el índice de la imagen que vamos a visualizar

index = 10

Obtener la imagen de la prenda y su etiqueta

image = train_images[index]
label = train_labels[index]

Imprimimos la representación matricial (numérica) de la imagen

print(image)

Mostramos la imagen con Matplotlib

plt.figure(figsize=(3, 3))
plt.imshow(image, cmap=plt.cm.gray)
plt.title(f'Etiqueta número: {label} es {class_names[label]}')
plt.show()

Preprocesamiento de datos

Notemos la longitud del conjunto de entrenamiento y de test son respectivamente:

print(train_images.shape)
print(test_images.shape)

Normalizar las imágenes para normalizar los valores de píxeles

# Normalizar las imágenes para que los valores estén en el rango [0, 1]
train_images = train_images / 255.0
test_images = test_images / 255.0

Red neuronal convolucional

# Crear el modelo de CNN
model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    Flatten(),
    Dense(64, activation='relu'),
    Dense(10)
])

Resumen del modelo anterior:

  • Entrada de la imagen: Una imagen de 28x28 píxeles con un canal (blanco y negro).

  • Primera capa Conv2D: Aplica 32 filtros 3x3, resultando en 32 mapas de características de 26x26.

  • Primera capa MaxPooling2D: Reduce el tamaño de cada uno de los 32 mapas de características a 13x13.

  • Segunda capa Conv2D: Aplica 64 filtros 3x3 a cada uno de los 32 mapas de características, resultando en 64 mapas de características de 11x11.

  • Segunda capa MaxPooling2D: Reduce el tamaño de cada uno de los 64 mapas de características a 5x5.

  • Tercera capa Conv2D: Aplica 64 filtros 3x3, resultando en 64 mapas de características de 3x3.

  • Flatten: Aplana los mapas de características a un vector de 576 características.

  • Dense (64 unidades): Reducción de dimensionalidad y aprendizaje de patrones globales.

  • Dense (10 unidades): Salida final con 10 unidades (una para cada clase de Fashion MNIST).

Cada convolución extrae características y patrones más complejos a medida que profundiza en la red, permitiendo al modelo hacer predicciones más precisas sobre la clase de las imágenes. Cada filtro aprende a detectar diferentes características de la imagen, como bordes, texturas o patrones específicos:

La cantidad de filtros en una capa convolucional afecta la capacidad del modelo para aprender características representativas de los datos. En general, más filtros permiten al modelo aprender una variedad más amplia de características, pero también incrementan la complejidad computacional y el número de parámetros del modelo.

Compilar el modelo

Crear un optimizador Adam con una tasa de aprendizaje del 0.001

# Tasa de aprendizaje deseada
learning_rate = 0.001
adam_optimizer = Adam(learning_rate=learning_rate)
model.compile(optimizer=adam_optimizer,
              loss=SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

Se compila el modelo utilizando el optimizador Adam y la función de pérdida de entropía cruzada categórica dispersa (sparse_categorical_crossentropy) para la clasificación. El parámetro from_logits=True indica que la salida de tu modelo no ha pasado por una función de activación como softmax y son logits.

Los logits son los valores brutos de salida de la última capa del modelo, y pueden ser cualquier número real, no necesariamente entre 0 y 1. La función SparseCategoricalCrossentropy con from_logits=True primero aplicará una función softmax internamente para convertir los logits en probabilidades antes de calcular la pérdida.

También se puede usar directamente el nombre del optimizador ('adam') en el argumento optimizer de la función compile.

Entrenar el modelo

model.fit(train_images, train_labels, epochs=10, validation_data=(test_images, test_labels))

Se entrena el modelo en los datos de entrenamiento utilizando fit. Se especifica el número de épocas, el tamaño del lote y la proporción de validación para monitorear el rendimiento del modelo durante el entrenamiento.

Evaluación

Evaluar el modelo en el conjunto de prueba

# Evaluar el modelo
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

Se evalúa el rendimiento del modelo en el conjunto de prueba utilizando evaluate. Se obtienen la pérdida y la precisión del modelo en los datos de prueba.

Predicciones

probability_model = Sequential([model, Softmax()])
predictions = probability_model.predict(test_images)
predicted_labels = np.argmax(predictions, axis=1)

Calcular la matriz de confusión

# Calcular matriz de confusión
cm = confusion_matrix(test_labels, predicted_labels)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)

Se calculan las predicciones del modelo en el conjunto de prueba y se obtienen las clases predichas. Se calcula la matriz de confusión utilizando confusion_matrix.

Visualizar la matriz de confusión y mostrar la sensibilidad para cada clase

# Graficar matriz de confusión
fig, ax = plt.subplots(figsize=(10, 10))
disp.plot(ax=ax)
plt.show()

BONUS:

Codigo para graficar una imagen con su etiqueta predicha

def plot_image(i, predictions_array, true_label, img):
    true_label, img = true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img.reshape((28, 28)), cmap=plt.cm.binary)

    predicted_label = tf.argmax(predictions_array).numpy()
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                         100*tf.reduce_max(predictions_array).numpy(),
                                         class_names[true_label]),
                                         color=color)

# Graficar algunas predicciones
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

num_rows = 5
num_cols = 3
num_images = num_rows * num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
    plt.subplot(num_rows, 2*num_cols, 2*i+1)
    plot_image(i, predictions[i], test_labels, test_images)

plt.tight_layout()
plt.show()

Last updated