html
Construyendo una Red Neuronal Simple para la Clasificación de Dígitos con Keras y MNIST
Tabla de Contenidos
- Introducción a las Redes Neuronales para la Clasificación de Dígitos
- Entendiendo el Conjunto de Datos MNIST
- Configurando el Entorno
- Cargando y Explorando el Conjunto de Datos MNIST
- Preprocesamiento de Datos: Remodelado y Codificación One-Hot
- Construyendo el Modelo de Red Neuronal con Keras
- Compilando el Modelo: Función de Pérdida y Optimizador
- Entrenando el Modelo: Ajuste y Validación
- Evaluando el Modelo: Precisión y Predicciones
- Visualizando la Estructura de la Red Neuronal
- Optimizando el Entrenamiento: Utilizando GPUs
- Conclusión
Introducción a las Redes Neuronales para la Clasificación de Dígitos
Las redes neuronales han revolucionado la forma en que las máquinas interpretan y analizan datos, especialmente en el ámbito del reconocimiento de imágenes. La clasificación de dígitos, donde el objetivo es identificar con precisión dígitos escritos a mano, sirve como un ejemplo por excelencia para que los principiantes comprendan los fundamentos de las redes neuronales. Al aprovechar bibliotecas populares como Keras y conjuntos de datos como MNIST, construir un clasificador de dígitos efectivo se vuelve accesible y educativo.
Entendiendo el Conjunto de Datos MNIST
El MNIST (Modified National Institute of Standards and Technology) es un pilar en la comunidad de aprendizaje automático. Comprende 70,000 imágenes en escala de grises de dígitos escritos a mano (0-9), cada una con un tamaño de 28x28 píxeles. El conjunto de datos se divide en 60,000 imágenes de entrenamiento y 10,000 imágenes de prueba, lo que lo hace ideal para entrenar y validar modelos de aprendizaje automático.
Características Clave de MNIST:
- Tamaño: 70,000 imágenes (60k entrenamiento, 10k prueba)
- Dimensiones de la Imagen: 28x28 píxeles
- Clases: 10 (dígitos del 0 al 9)
- Escala de Grises: Cada valor de píxel varía de 0 (negro) a 255 (blanco)
Configurando el Entorno
Antes de sumergirse en el proceso de construcción del modelo, es esencial configurar el entorno de desarrollo. Asegúrate de tener Python instalado y considera usar entornos como Anaconda para gestionar paquetes y dependencias de manera fluida.
Bibliotecas Requeridas:
- NumPy: Para operaciones numéricas
- Matplotlib: Para visualización de datos
- Keras: Para construir y entrenar redes neuronales
- Scikit-learn: Para utilidades de preprocesamiento
- Pandas: Para manipulación de datos
Comandos de Instalación:
1
pip install numpy matplotlib keras scikit-learn pandas
Cargando y Explorando el Conjunto de Datos MNIST
Keras simplifica el proceso de acceso al conjunto de datos MNIST a través de su módulo datasets
. Aquí se muestra cómo cargar e inspeccionar los datos:
123456789
import numpy as npimport matplotlib.pyplot as pltfrom keras.datasets import mnist # Cargar datos de dígitos escritos a mano de MNIST(X_train, y_train), (X_test, y_test) = mnist.load_data() print(X_train.shape) # Salida: (60000, 28, 28)print(X_test.shape) # Salida: (10000, 28, 28)
Salida:
12
(60000, 28, 28)(10000, 28, 28)
Esto revela que hay 60,000 imágenes de entrenamiento y 10,000 imágenes de prueba, cada una con dimensiones de 28x28 píxeles.
Visualizando Imágenes de Ejemplo
Para tener una idea de los datos, visualicemos una imagen de muestra:
1234
img = X_train[250].reshape(28,28)plt.imshow(img, cmap="gray")plt.title(f"Etiqueta de Dígito de Muestra: {y_train[250]}")plt.show()
Salida:
Nota: La imagen real mostrará un dígito escrito a mano correspondiente a la etiqueta.
Preprocesamiento de Datos: Remodelado y Codificación One-Hot
El preprocesamiento de datos es un paso crucial en los flujos de trabajo de aprendizaje automático. Para las redes neuronales, es esencial formatear los datos adecuadamente y codificar las etiquetas.
Remodelando los Datos
Las redes neuronales requieren datos de entrada en una forma específica. Para el conjunto de datos MNIST, aplanaremos las imágenes de píxeles 28x28 en un array 1D de 784 elementos.
12345
from keras.utils import to_categorical # Remodelar y normalizar los datos de imagenX_train = X_train.reshape(60000, 28, 28).astype('float32') / 255X_test = X_test.reshape(10000, 28, 28).astype('float32') / 255
Codificando las Etiquetas con One-Hot
La codificación one-hot transforma las etiquetas categóricas en una matriz binaria, lo cual es más adecuado para el entrenamiento.
123456
# Codificar las etiquetas con one-hoty_train = to_categorical(y_train, num_classes=10)y_test = to_categorical(y_test, num_classes=10) print(y_train.shape) # Salida: (60000, 10)print(y_test.shape) # Salida: (10000, 10)
Salida:
12
(60000, 10)(10000, 10)
Esto indica que cada etiqueta ahora está representada como un vector binario de 10 dimensiones.
Construyendo el Modelo de Red Neuronal con Keras
Keras ofrece una API amigable para construir y entrenar redes neuronales. Construiremos un modelo Secuencial simple que comprende múltiples capas densas.
Arquitectura del Modelo
A continuación, una visión general de la estructura del modelo:
- Capa Flatten: Convierte los datos de imagen 2D en un array 1D.
- Capa Densa 1: 100 neuronas con activación sigmoid.
- Capa Densa 2: 144 neuronas con activación sigmoid.
- Capa de Salida: 10 neuronas (una por cada dígito) con activación softmax.
Explicación de las Capas
- Capa Flatten: Transforma los datos de entrada de una matriz 2D (28x28) a un vector 1D (784) para alimentar las capas densas.
- Capas Densas: Estas son capas completamente conectadas donde cada neurona recibe entrada de todas las neuronas de la capa precedente. Las funciones de activación introducen no linealidad:
- Activación Sigmoid: Produce valores entre 0 y 1, útil para clasificación binaria pero menos común en capas ocultas para problemas multiclase.
- Activación Softmax: Convierte las salidas de la capa final en distribuciones de probabilidad sobre las 10 clases.
Construyendo el Modelo:
123456789
from keras.models import Sequentialfrom keras.layers import Dense, Flatten # Crear un modelo de Red Neuronal simplemodel = Sequential()model.add(Flatten(input_shape=(28,28)))model.add(Dense(100, activation='sigmoid'))model.add(Dense(144, activation='sigmoid'))model.add(Dense(10, activation='softmax'))
Resumen del Modelo
Para visualizar la estructura del modelo y los parámetros:
1
model.summary()
Salida:
12345678910111213141516
Model: "sequential_1"_______________________________________________________________Layer (type) Output Shape Param # ===============================================================flatten_1 (Flatten) (None, 784) 0 _______________________________________________________________dense_3 (Dense) (None, 100) 78500 _______________________________________________________________dense_4 (Dense) (None, 144) 14444 _______________________________________________________________dense_5 (Dense) (None, 10) 1450 ===============================================================Total params: 94,494Trainable params: 94,494Non-trainable params: 0_______________________________________________________________
Este resumen proporciona información sobre la forma de salida de cada capa y el número de parámetros que se entrenarán.
Compilando el Modelo: Función de Pérdida y Optimizador
Antes del entrenamiento, el modelo debe ser compilado con una función de pérdida y un optimizador especificados.
- Función de Pérdida: Mide qué tan bien las predicciones del modelo coinciden con las etiquetas reales.
- Categórica de Entropía Cruzada: Adecuada para problemas de clasificación multiclase.
- Optimizador: Actualiza los pesos del modelo para minimizar la función de pérdida.
- Optimizador Adam: Un método eficiente de descenso de gradiente estocástico que adapta la tasa de aprendizaje.
Compilando el Modelo:
1
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
Entrenando el Modelo: Ajuste y Validación
El entrenamiento implica alimentar el modelo con datos y permitir que aprenda patrones a través de múltiples épocas.
- Épocas: Número de veces que el conjunto de datos completo pasa a través de la red.
- Datos de Validación: Utilizados para evaluar el rendimiento del modelo en datos no vistos después de cada época.
Proceso de Entrenamiento:
1
history = model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
Salida de Ejemplo:
12345
Epoch 1/101875/1875 [==============================] - 4s 2ms/step - loss: 0.9009 - acc: 0.7596 - val_loss: 0.3685 - val_acc: 0.8892...Epoch 10/101875/1875 [==============================] - 4s 2ms/step - loss: 0.2251 - acc: 0.9314 - val_loss: 0.2267 - val_acc: 0.9303
Al final de 10 épocas, el modelo alcanza aproximadamente una precisión del 93% tanto en los conjuntos de datos de entrenamiento como de validación, lo que indica un modelo bien desempeñado.
Evaluando el Modelo: Precisión y Predicciones
Después del entrenamiento, es crucial evaluar el rendimiento del modelo y hacer predicciones sobre nuevos datos.
Haciendo Predicciones
12
# Prediciendo en el conjunto de pruebapredictions = model.predict(X_test)
Cada predicción consiste en una distribución de probabilidad sobre las 10 clases. Para determinar la clase predicha:
12345
import numpy as np # Convertir probabilidades a etiquetas de clasepredicted_classes = np.argmax(predictions, axis=1)true_classes = np.argmax(y_test, axis=1)
Visualizando Predicciones
Visualicemos algunas imágenes de prueba junto con sus etiquetas predichas y verdaderas:
12345678910111213
import matplotlib.pyplot as plt def plot_prediction(index): img = X_test[index].reshape(28,28) plt.imshow(img, cmap="gray") plt.title(f"Etiqueta Verdadera: {true_classes[index]} | Predicha: {predicted_classes[index]}") plt.show() # Graficando la primera imagen de pruebaplot_prediction(0) # Graficando otra muestraplot_prediction(25)
Salida:
Muestra la imagen con títulos que indican tanto la etiqueta verdadera como la predicción del modelo.
Precisión del Modelo
El modelo logró una precisión del 93% en el conjunto de validación, demostrando su capacidad para generalizar bien en datos no vistos. Para un rendimiento mejorado, se puede explorar un mayor ajuste y arquitecturas más complejas.
Visualizando la Estructura de la Red Neuronal
Comprender la arquitectura de una red neuronal puede ayudar a entender cómo fluyen los datos y ocurren las transformaciones. A continuación, se muestra una representación visual de la red neuronal construida:
1234567891011121314151617181920212223242526272829303132333435363738394041
import matplotlib.pyplot as plt def draw_neural_net(ax, left, right, bottom, top, layer_sizes): ''' Dibuja un diagrama de red neuronal. :param ax: Objeto de Ejes de Matplotlib :param left: Límite izquierdo :param right: Límite derecho :param bottom: Límite inferior :param top: Límite superior :param layer_sizes: Lista que contiene el número de neuronas en cada capa ''' n_layers = len(layer_sizes) v_spacing = (top - bottom)/float(max(layer_sizes)) h_spacing = (right - left)/float(n_layers - 1) # Dibujar neuronas for n, layer_size in enumerate(layer_sizes): layer_top = v_spacing*(layer_size - 1)/2. + (top + bottom)/2. for m in range(layer_size): circle = plt.Circle((n*h_spacing + left, layer_top - m*v_spacing), v_spacing/4., color='w', ec='k', zorder=4) ax.add_artist(circle) # Dibujar conexiones for n, (layer_size_a, layer_size_b) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])): layer_top_a = v_spacing*(layer_size_a - 1)/2. + (top + bottom)/2. layer_top_b = v_spacing*(layer_size_b - 1)/2. + (top + bottom)/2. for m in range(layer_size_a): for o in range(layer_size_b): line = plt.Line2D([n*h_spacing + left, (n + 1)*h_spacing + left], [layer_top_a - m*v_spacing, layer_top_b - o*v_spacing], c='k') ax.add_artist(line) # Dibujando la red neuronalfig = plt.figure(figsize=(12, 12))ax = fig.gca()ax.axis('off')draw_neural_net(ax, .1, .9, .1, .9, [784, 100, 144, 10])plt.show()
Salida:
Este diagrama ilustra el flujo desde las neuronas de entrada (784) a través de capas ocultas hasta las neuronas de salida (10).
Optimizando el Entrenamiento: Utilizando GPUs
Entrenar redes neuronales, especialmente las profundas, puede ser computacionalmente intensivo y llevar mucho tiempo. Aprovechar las Unidades de Procesamiento Gráfico (GPUs) puede acelerar significativamente el proceso de entrenamiento. Aquí se explica cómo utilizar GPUs con Keras:
- Garantizar la Compatibilidad de la GPU:
- Instalar NVIDIA CUDA Toolkit y cuDNN.
- Verificar que tu GPU sea compatible con TensorFlow (el backend para Keras).
- Instalar TensorFlow Compatible con GPU:
1
pip install tensorflow-gpu
- Configurar TensorFlow para Usar la GPU:
TensorFlow detecta y utiliza automáticamente las GPUs. Sin embargo, puedes especificar configuraciones de GPU explícitamente si es necesario.
12345678910
import tensorflow as tf gpus = tf.config.list_physical_devices('GPU')if gpus: try: # Restringir TensorFlow para usar solo la primera GPU tf.config.set_visible_devices(gpus[0], 'GPU') tf.config.experimental.set_memory_growth(gpus[0], True) except RuntimeError as e: print(e)
Beneficios de Usar GPUs:
- Procesamiento Paralelo: Las GPUs pueden manejar múltiples cálculos simultáneamente, ideales para operaciones matriciales en redes neuronales.
- Entrenamiento Más Rápido: Los modelos entrenan significativamente más rápido, permitiendo más experimentación e iteraciones rápidas.
Nota: Optimizar el uso de la GPU puede requerir configuraciones adicionales basadas en configuraciones específicas del sistema.
Conclusión
Construir una red neuronal simple para la clasificación de dígitos usando Keras y el conjunto de datos MNIST es una excelente introducción al mundo del aprendizaje automático y el aprendizaje profundo. Al seguir esta guía, has aprendido a:
- Entender y preprocesar el conjunto de datos MNIST.
- Construir un modelo de red neuronal con Keras.
- Entrenar y evaluar el rendimiento del modelo.
- Visualizar la arquitectura de la red.
- Optimizar el entrenamiento utilizando GPUs.
Aunque el modelo discutido logra una precisión respetable, hay amplio margen para la mejora. Explorar arquitecturas más complejas, experimentar con diferentes funciones de activación o implementar técnicas de regularización puede llevar a un rendimiento mejorado. A medida que continúas tu viaje en el aprendizaje automático, construir sobre estos fundamentos te permitirá abordar proyectos más intrincados y de mayor impacto.
¡Feliz Programación!