V1TR0 Logo
V1TR0Blog
Desarrollo de SoftwareAutomatización de tareasSistemas de Información
Volver al blog
V1TR0 Technologies

Impulsando tu Éxito Digital

Desarrollo

Creamos soluciones basadas en codigo para darle vida a infraestructuras digitales de vanguardia.

Diseño

Diseñamos experiencias visuales que renuevan la experiencia de usuario, para optimizar la navegación & la gestión.

Innovación

Implementamos tecnologias de vanguardia para automatizar procesos & mejorar la eficiencia.

© 2025 V1TR0

•
Términos
Privacidad
Cookies
kerastensorflowpythonprácticamnist

Aplicación Práctica: Construcción de una Red Neuronal con Keras

2 de octubre de 2025
7 min read
Por Alvaro Efren Bolaños Scalante
Aplicación Práctica: Construcción de una Red Neuronal con Keras
  • Aplicación Práctica: Construcción de una Red Neuronal con Keras
  • 🎯 Introducción
  • 📦 Caso de Estudio: Clasificación de Dígitos (MNIST)
  • 🛠️ Paso 1: Preparación y Preprocesado de Datos
  • 1.1 Instalación de Dependencias
  • 1.2 Importar Bibliotecas
  • 1.3 Cargar el Dataset
  • 1.4 Visualizar Ejemplos
  • 1.5 Normalización
  • 1.6 Codificación One-Hot
  • 🏗️ Paso 2: Definición y Compilación del Modelo
  • 2.1 Arquitectura de la Red
  • 2.2 Resumen del Modelo
  • 2.3 Compilar el Modelo
  • 🚀 Paso 3: Entrenamiento del Modelo
  • 3.1 Entrenar
  • 3.2 Visualizar el Aprendizaje
  • 📊 Paso 4: Evaluación del Modelo
  • 4.1 Evaluar en Datos de Prueba
  • 4.2 Hacer Predicciones
  • 4.3 Visualizar Predicciones
  • 💾 Paso 5: Guardar y Cargar el Modelo
  • 5.1 Guardar el Modelo
  • 5.2 Cargar el Modelo
  • 🎨 Código Completo
  • 🎯 Ejercicios Propuestos
  • 📚 Referencias

Aplicación Práctica: Construcción de una Red Neuronal con Keras

🎯 Introducción

Tras explorar los fundamentos matemáticos, es hora de pasar de la teoría a la práctica. Utilizaremos Keras, una biblioteca de alto nivel para Deep Learning, para construir, entrenar y evaluar una red neuronal.

📦 Caso de Estudio: Clasificación de Dígitos (MNIST)

Trabajaremos con el dataset MNIST: 70,000 imágenes de dígitos escritos a mano (0-9).

1📊 Dataset MNIST:
2   - Imágenes: 28×28 píxeles en escala de grises
3   - Entrenamiento: 60,000 imágenes
4   - Prueba: 10,000 imágenes
5   - Clases: 10 (dígitos 0-9)

🛠️ Paso 1: Preparación y Preprocesado de Datos

1.1 Instalación de Dependencias

bash
1pip install tensorflow numpy matplotlib scikit-learn

1.2 Importar Bibliotecas

python
1import numpy as np
2import matplotlib.pyplot as plt
3from tensorflow import keras
4from tensorflow.keras import Sequential
5from tensorflow.keras.layers import Dense, Flatten
6from tensorflow.keras.utils import to_categorical

1.3 Cargar el Dataset

python
1# Cargar MNIST
2(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
3
4print(f"Forma de x_train: {x_train.shape}")  # (60000, 28, 28)
5print(f"Forma de y_train: {y_train.shape}")  # (60000,)
6print(f"Forma de x_test: {x_test.shape}")    # (10000, 28, 28)

1.4 Visualizar Ejemplos

python
1# Visualizar las primeras 9 imágenes
2plt.figure(figsize=(10, 10))
3for i in range(9):
4    plt.subplot(3, 3, i+1)
5    plt.imshow(x_train[i], cmap='gray')
6    plt.title(f"Etiqueta: {y_train[i]}")
7    plt.axis('off')
8plt.tight_layout()
9plt.show()

1.5 Normalización

Escalar píxeles de [0, 255] → [0, 1]:

python
1# Normalizar
2x_train = x_train.astype('float32') / 255.0
3x_test = x_test.astype('float32') / 255.0
4
5print(f"Rango de valores: [{x_train.min()}, {x_train.max()}]")
6# Salida: [0.0, 1.0]

1.6 Codificación One-Hot

Convertir etiquetas en vectores:

python
1# One-hot encoding
2y_train_encoded = to_categorical(y_train, num_classes=10)
3y_test_encoded = to_categorical(y_test, num_classes=10)
4
5print(f"Etiqueta original: {y_train[0]}")
6print(f"Etiqueta codificada:\n{y_train_encoded[0]}")
7
8# Salida:
9# Etiqueta original: 5
10# Etiqueta codificada: [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]

🏗️ Paso 2: Definición y Compilación del Modelo

2.1 Arquitectura de la Red

python
1model = Sequential([
2    # Aplanar imagen 28x28 a vector 784
3    Flatten(input_shape=(28, 28)),
4    
5    # Primera capa oculta: 128 neuronas con ReLU
6    Dense(128, activation='relu'),
7    
8    # Segunda capa oculta: 64 neuronas con ReLU
9    Dense(64, activation='relu'),
10    
11    # Capa de salida: 10 neuronas con Softmax
12    Dense(10, activation='softmax')
13])

Arquitectura Visual:

1┌─────────────┐
2│   Input     │  28×28 imagen
3│  (28, 28)   │
4└──────┬──────┘
5       │
6┌──────▼──────┐
7│  Flatten    │  Transforma a vector 784
8│   (784)     │
9└──────┬──────┘
10       │
11┌──────▼──────┐
12│  Dense      │  128 neuronas + ReLU
13│   (128)     │
14└──────┬──────┘
15       │
16┌──────▼──────┐
17│  Dense      │  64 neuronas + ReLU
18│    (64)     │
19└──────┬──────┘
20       │
21┌──────▼──────┐
22│  Dense      │  10 neuronas + Softmax
23│    (10)     │  (probabilidades por clase)
24└─────────────┘

2.2 Resumen del Modelo

python
1model.summary()

Salida:

1_________________________________________________________________
2Layer (type)                 Output Shape              Param #   
3=================================================================
4flatten (Flatten)            (None, 784)               0         
5_________________________________________________________________
6dense (Dense)                (None, 128)               100480    
7_________________________________________________________________
8dense_1 (Dense)              (None, 64)                8256      
9_________________________________________________________________
10dense_2 (Dense)              (None, 10)                650       
11=================================================================
12Total params: 109,386
13Trainable params: 109,386
14Non-trainable params: 0

2.3 Compilar el Modelo

python
1model.compile(
2    optimizer='adam',                    # Optimizador Adam
3    loss='categorical_crossentropy',     # Para clasificación multiclase
4    metrics=['accuracy']                 # Métrica a monitorear
5)

Opciones de optimizadores:

  • 1'sgd'
    : Descenso de gradiente estocástico
  • 1'adam'
    : Adam (recomendado para principiantes)
  • 1'rmsprop'
    : RMSprop

🚀 Paso 3: Entrenamiento del Modelo

3.1 Entrenar

python
1history = model.fit(
2    x_train, 
3    y_train_encoded,
4    epochs=10,              # Número de épocas
5    batch_size=32,          # Tamaño del mini-lote
6    validation_split=0.2,   # 20% para validación
7    verbose=1               # Mostrar progreso
8)

Salida durante el entrenamiento:

1Epoch 1/10
21500/1500 [======] - 3s 2ms/step - loss: 0.2645 - accuracy: 0.9234 - val_loss: 0.1345 - val_accuracy: 0.9612
3Epoch 2/10
41500/1500 [======] - 2s 1ms/step - loss: 0.1123 - accuracy: 0.9665 - val_loss: 0.1012 - val_accuracy: 0.9701
5...

3.2 Visualizar el Aprendizaje

python
1# Extraer historial
2train_loss = history.history['loss']
3val_loss = history.history['val_loss']
4train_acc = history.history['accuracy']
5val_acc = history.history['val_accuracy']
6
7# Crear gráficas
8fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
9
10# Gráfica de pérdida
11ax1.plot(train_loss, label='Entrenamiento', marker='o')
12ax1.plot(val_loss, label='Validación', marker='s')
13ax1.set_title('Pérdida durante el Entrenamiento')
14ax1.set_xlabel('Época')
15ax1.set_ylabel('Pérdida')
16ax1.legend()
17ax1.grid(True)
18
19# Gráfica de precisión
20ax2.plot(train_acc, label='Entrenamiento', marker='o')
21ax2.plot(val_acc, label='Validación', marker='s')
22ax2.set_title('Precisión durante el Entrenamiento')
23ax2.set_xlabel('Época')
24ax2.set_ylabel('Precisión')
25ax2.legend()
26ax2.grid(True)
27
28plt.tight_layout()
29plt.show()

📊 Paso 4: Evaluación del Modelo

4.1 Evaluar en Datos de Prueba

python
1test_loss, test_accuracy = model.evaluate(x_test, y_test_encoded, verbose=0)
2
3print(f"\n{'='*50}")
4print(f"📊 RESULTADOS EN DATOS DE PRUEBA")
5print(f"{'='*50}")
6print(f"Pérdida (Loss): {test_loss:.4f}")
7print(f"Precisión (Accuracy): {test_accuracy:.4f} ({test_accuracy*100:.2f}%)")
8print(f"{'='*50}")

Salida esperada:

1==================================================
2📊 RESULTADOS EN DATOS DE PRUEBA
3==================================================
4Pérdida (Loss): 0.0856
5Precisión (Accuracy): 0.9741 (97.41%)
6==================================================

4.2 Hacer Predicciones

python
1# Predecir las primeras 10 imágenes del test
2predictions = model.predict(x_test[:10])
3
4# Convertir probabilidades a clases
5predicted_classes = np.argmax(predictions, axis=1)
6true_classes = np.argmax(y_test_encoded[:10], axis=1)
7
8# Mostrar resultados
9print("\n🔮 PREDICCIONES:")
10print(f"{'Índice':<10}{'Predicho':<12}{'Real':<10}{'¿Correcto?'}")
11print("-" * 45)
12for i in range(10):
13    correcto = "✅" if predicted_classes[i] == true_classes[i] else "❌"
14    print(f"{i:<10}{predicted_classes[i]:<12}{true_classes[i]:<10}{correcto}")

4.3 Visualizar Predicciones

python
1plt.figure(figsize=(15, 6))
2for i in range(10):
3    plt.subplot(2, 5, i+1)
4    plt.imshow(x_test[i], cmap='gray')
5    
6    pred = predicted_classes[i]
7    true = true_classes[i]
8    color = 'green' if pred == true else 'red'
9    
10    plt.title(f"Pred: {pred}\nReal: {true}", color=color)
11    plt.axis('off')
12plt.tight_layout()
13plt.show()

💾 Paso 5: Guardar y Cargar el Modelo

5.1 Guardar el Modelo

python
1# Guardar el modelo completo
2model.save('modelo_mnist.h5')
3print("✅ Modelo guardado como 'modelo_mnist.h5'")
4
5# O guardar solo los pesos
6model.save_weights('pesos_mnist.h5')

5.2 Cargar el Modelo

python
1# Cargar modelo completo
2modelo_cargado = keras.models.load_model('modelo_mnist.h5')
3
4# Verificar que funciona
5test_loss_cargado, test_acc_cargado = modelo_cargado.evaluate(
6    x_test, y_test_encoded, verbose=0
7)
8print(f"Precisión del modelo cargado: {test_acc_cargado:.4f}")

🎨 Código Completo

python
1"""
2Red Neuronal para Clasificación de Dígitos MNIST
3Autor: Alvaro Efren Bolaños Scalante
4"""
5
6import numpy as np
7import matplotlib.pyplot as plt
8from tensorflow import keras
9from tensorflow.keras import Sequential
10from tensorflow.keras.layers import Dense, Flatten
11from tensorflow.keras.utils import to_categorical
12
13# ============================================
14# 1. CARGAR Y PREPROCESAR DATOS
15# ============================================
16print("📦 Cargando datos...")
17(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
18
19# Normalizar
20x_train = x_train.astype('float32') / 255.0
21x_test = x_test.astype('float32') / 255.0
22
23# One-hot encoding
24y_train = to_categorical(y_train, 10)
25y_test = to_categorical(y_test, 10)
26
27print(f"✅ Datos cargados: {x_train.shape[0]} entrenamiento, {x_test.shape[0]} prueba")
28
29# ============================================
30# 2. DEFINIR MODELO
31# ============================================
32print("\n🏗️ Construyendo modelo...")
33model = Sequential([
34    Flatten(input_shape=(28, 28)),
35    Dense(128, activation='relu'),
36    Dense(64, activation='relu'),
37    Dense(10, activation='softmax')
38])
39
40model.compile(
41    optimizer='adam',
42    loss='categorical_crossentropy',
43    metrics=['accuracy']
44)
45
46model.summary()
47
48# ============================================
49# 3. ENTRENAR
50# ============================================
51print("\n🚀 Entrenando modelo...")
52history = model.fit(
53    x_train, y_train,
54    epochs=10,
55    batch_size=32,
56    validation_split=0.2,
57    verbose=1
58)
59
60# ============================================
61# 4. EVALUAR
62# ============================================
63print("\n📊 Evaluando modelo...")
64test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
65print(f"\nPrecisión en test: {test_acc:.4f} ({test_acc*100:.2f}%)")
66
67# ============================================
68# 5. VISUALIZAR
69# ============================================
70# Gráficas de aprendizaje
71plt.figure(figsize=(14, 5))
72
73plt.subplot(1, 2, 1)
74plt.plot(history.history['loss'], label='Entrenamiento')
75plt.plot(history.history['val_loss'], label='Validación')
76plt.title('Pérdida')
77plt.xlabel('Época')
78plt.ylabel('Loss')
79plt.legend()
80plt.grid(True)
81
82plt.subplot(1, 2, 2)
83plt.plot(history.history['accuracy'], label='Entrenamiento')
84plt.plot(history.history['val_accuracy'], label='Validación')
85plt.title('Precisión')
86plt.xlabel('Época')
87plt.ylabel('Accuracy')
88plt.legend()
89plt.grid(True)
90
91plt.tight_layout()
92plt.savefig('entrenamiento.png')
93plt.show()
94
95print("\n✅ ¡Entrenamiento completado!")

🎯 Ejercicios Propuestos

  1. Cambiar la arquitectura: Prueba con más/menos capas y neuronas
  2. Probar otros optimizadores:
    1'sgd'
    ,
    1'rmsprop'
  3. Ajustar hiperparámetros: learning rate, batch size
  4. Usar Fashion-MNIST: Dataset de prendas de ropa
  5. Agregar regularización: Dropout para evitar overfitting
python
1# Ejemplo con Dropout
2from tensorflow.keras.layers import Dropout
3
4model = Sequential([
5    Flatten(input_shape=(28, 28)),
6    Dense(128, activation='relu'),
7    Dropout(0.5),  # 50% de dropout
8    Dense(64, activation='relu'),
9    Dropout(0.3),
10    Dense(10, activation='softmax')
11])

📚 Referencias

  • Torres, J. (2020). Python Deep Learning: Introducción práctica con Keras y TensorFlow 2. Marcombo.
  • Documentación de Keras: https://keras.io
  • TensorFlow Tutorials: https://www.tensorflow.org/tutorials

Anterior: ← Blog 3: Proceso de Entrenamiento

Próximo: Blog 5: Evaluación y Desafíos →