Implementación

Construiremos una red neuronal convolucional un ejemplo de una red neuronal convolucional (CNN) para clasificar dígitos escritos a mano en el conjunto de datos MNIST, que es un problema de clasificación de imágenes.

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
from tensorflow.keras.optimizers import Adam
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.metrics import confusion_matrix, recall_score
import seaborn as sns
import matplotlib.pyplot as plt

MNIST Dataset

Cargar el conjunto de datos MNIST de dígitos escritos a mano

digits = load_digits()

Exploramos el dataset

digits.keys()

El resultado es:

dict_keys([
    'data', 'target', 'frame',
    'feature_names', 'target_names', 'images', 
    'DESCR'
])

Imprimimos la llave DESCR para obtener la información del conjuto de datos

print(digits.DESCR)

Visualización de una imagen

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

index = 0

Obtener la imagen del dígito y su etiqueta

image = digits.images[index]
label = digits.target[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'Dígito: {label}')
plt.show()

Preprocesamiento de datos

Dividir los datos en conjuntos de entrenamiento y prueba

X_train, X_test, y_train, y_test = train_test_split(
    digits.data, digits.target,
    test_size=0.2, random_state=42
)

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

print(X_train.shape)
print(X_test.shape)

Notamos como se ve el primer elemento de la variable X_train

reshaped_tensor = tf.reshape(X_train[0], shape=(8, 8))
print(reshaped_tensor)

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

# Normalizar los datos
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

El StandardScaler y el MinMaxScaler son transformadores en la biblioteca scikit-learn que se utilizan para preprocesar los datos antes de alimentarlos a un modelo de aprendizaje automático. Ambos son métodos de escalado que ajustan los datos para que tengan ciertas propiedades que pueden mejorar el rendimiento del modelo.

  1. StandardScaler:

    • El StandardScaler es utilizado para estandarizar características eliminando la media y escalando a la varianza unitaria. Esto significa que, después de aplicar el StandardScaler, la media de cada característica será 0 y la varianza será 1.

    • El StandardScaler es útil cuando las características de entrada tienen distribuciones diferentes y varianzas diferentes. Por ejemplo, es común aplicar este escalado cuando se utilizan algoritmos que asumen que las características están centradas en 0 y tienen varianza en el mismo orden de magnitud.

  2. MinMaxScaler:

    • El MinMaxScaler transforma las características escalándolas a un rango específico, generalmente entre 0 y 1.

    • El MinMaxScaler es útil cuando se quiere ajustar las características dentro de un rango específico o cuando se utilizan algoritmos sensibles a la escala de las características.

En resumen, el StandardScaler se utiliza para estandarizar las características a una media de 0 y varianza de 1, mientras que el MinMaxScaler se utiliza para escalar las características a un rango específico, generalmente entre 0 y 1.

Ahora notamos como se ve el primer elemento de la variable X_train después de la normalización

reshaped_tensor = tf.reshape(X_train[0], shape=(8, 8))
# Redondeamos para tener una mejor visualizacion 
reshaped_tensor =  tf.floor(reshaped_tensor * 100) / 100
print(reshaped_tensor)
# Redimensionar el tensor a la forma (total, 8, 8)
X_train = tf.reshape(X_train, (X_train.shape[0], 8, 8))
X_test = tf.reshape(X_test, (X_test.shape[0], 8, 8))

Red neuronal convolucional

# Crear el modelo de CNN
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
    activation='relu',
    input_shape=(8, 8, 1)),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

Creamos un modelo secuencial de Keras, que es una pila lineal de capas. Este modelo incluye:

  • Una capa convolucional con 32 filtros, un tamaño de kernel de 3x3, y la función de activación ReLU.

  • Una capa de max pooling para reducir el tamaño espacial de la salida.

  • Una capa flatten para aplanar los datos antes de pasar a las capas densas.

  • Una capa densa con 128 unidades y la función de activación ReLU.

  • Una capa de salida densa con 10 unidades (una para cada clase) y la función de activación softmax.

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',
    loss='sparse_categorical_crossentropy',
    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.

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(X_train, y_train, epochs=10, batch_size=32, validation_split=0.2)

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

loss, accuracy = model.evaluate(X_test, y_test)
print(f'Loss: {loss}, Accuracy: {accuracy}')

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.

Calcular la matriz de confusión y la sensibilidad (recall)

y_pred = model.predict(X_test)
y_pred_classes = np.argmax(y_pred, axis=1)

conf_matrix = confusion_matrix(y_test, y_pred_classes)
sensitivity = recall_score(y_test, y_pred_classes, average=None)

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. Se calcula la sensibilidad (recall) para cada clase utilizando recall_score.

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

# Visualizar la matriz de confusión como una imagen de colores
plt.figure(figsize=(10, 8))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.title('Confusion Matrix')
plt.show()

# Mostrar la sensibilidad (recall) para cada clase
print('Sensitivity (Recall) for each class:')
for i in range(10):
    print(f'Class {i}: {sensitivity[i]}')

Se visualiza la matriz de confusión como una imagen de colores utilizando sns.heatmap. Se muestra la sensibilidad (recall) para cada clase.

El recall mide la proporción de instancias positivas que fueron correctamente identificadas por el modelo sobre el total de instancias positivas en el conjunto de datos. En otras palabras, el recall indica qué tan efectivo es el modelo para encontrar todas las instancias positivas en comparación con el total de instancias positivas reales en el conjunto de datos.

  • Un recall de 1.0 (100%) significa que el modelo identifica todas las instancias positivas correctamente, es decir, no hay falsos negativos.

  • Un recall de 0.0 (0%) indica que el modelo no identifica ninguna instancia positiva correctamente, es decir, todos los casos positivos son clasificados como negativos (falsos negativos).

En resumen, un recall alto es deseable en problemas donde la detección de instancias positivas es crítica, mientras que un recall bajo puede indicar que el modelo necesita mejorar su capacidad para identificar verdaderos positivos.

Last updated