📝 Tarea: Implementación de una Red Neuronal Avanzada (CNN o LSTM)¶

🎯 Objetivo¶

El objetivo de esta actividad es aplicar un modelo de red neuronal profunda especializado (LSTM o CNN) para resolver un problema de clasificación supervisada. Con este ejercicio los estudiantes explorarán arquitecturas más avanzadas que los MLP, enfocadas en patrones secuenciales (LSTM) o patrones espaciales/locales (CNN), entendiendo su funcionamiento básico y cómo se entrenan en la práctica.

📊 Tipo de problema¶

  • Clasificación supervisada: el modelo aprende a asignar etiquetas de clase a partir de un conjunto de ejemplos previamente conocidos.
  • Dependiendo del dataset elegido, la variable objetivo puede ser:

    • Binaria (dos clases, p. ej. positivo/negativo).
    • Multiclase (más de dos clases, p. ej. categorías A, B, C…).

🔍 Variable objetivo¶

  • Es una variable categórica.
  • El modelo debe aprender a predecir la clase correcta en función de los patrones presentes en los datos (secuencias o imágenes).

⚙️ ¿Cómo se modela con LSTM o CNN?¶

  1. Capa de entrada

    • Para LSTM: los datos se organizan como una secuencia temporal (ej. series de valores en el tiempo).
    • Para CNN: los datos se organizan en matrices de características donde el modelo aprende patrones locales (ej. imágenes, texto representado como embeddings, datos tabulares con estructura).
  2. Capas ocultas

    • LSTM: cada celda mantiene una “memoria” de lo anterior en la secuencia, lo que permite capturar dependencias temporales.
    • CNN: aplica filtros convolucionales que detectan patrones locales (bordes, formas, repeticiones) y los combinan en niveles superiores.
  3. Capa de salida

    • Para clasificación binaria: una neurona con activación sigmoide → devuelve una probabilidad entre 0 y 1.
    • Para multiclase: tantas neuronas como clases, con activación softmax → devuelve una distribución de probabilidades sobre las clases.
  4. Función de pérdida

    • Binaria: entropía cruzada binaria.
    • Multiclase: entropía cruzada categórica.
  5. Entrenamiento

    • El modelo ajusta sus parámetros mediante retropropagación.
    • Se trabaja con lotes de datos (mini-batches) y múltiples épocas de entrenamiento.
  6. Evaluación

    • Matriz de confusión y métricas: accuracy, precision, recall, F1-score.
    • En multiclase, se recomienda también macro/micro promedio de métricas.

📂 Dataset¶

  • El dataset dependerá de la modalidad elegida:

    • LSTM: usar una serie temporal (ejemplo: valores de sensores, secuencias numéricas, texto).
    • CNN: usar un dataset de imágenes o datos con estructura matricial (ejemplo: MNIST para dígitos escritos a mano).

📋 Instrucciones generales¶

  1. Selecciona un dataset adecuado (serie temporal o imágenes).
  2. Define el problema de clasificación (binaria o multiclase).
  3. Prepara los datos en el formato correcto (secuencias para LSTM, matrices para CNN).
  4. Construye y entrena una red LSTM o CNN básica.
  5. Evalúa su desempeño con métricas apropiadas.
  6. Interpreta los resultados: ¿qué patrones parece haber aprendido? ¿qué limitaciones observas?

Opción 1 Low-Code: Visualizando el Aprendizaje de una CNN con MNIST¶

🎯 Objetivo¶

Entrenar una red neuronal convolucional (CNN) para clasificar imágenes de dígitos escritos a mano (MNIST), y visualizar qué características aprende cada capa. Al final, se evaluará el modelo con una matriz de confusión y un reporte de clasificación.

📦 Parte 1: Definición y entrenamiento del modelo¶

from tensorflow.keras import Input, Model
from tensorflow.keras import layers

# Definir la entrada de la red (una imagen de 28x28 en escala de grises)
inputs = Input(shape=(alto, ancho, 1))   # 👈 CAMBIA AQUÍ alto, ancho, de la imagen

# Primer bloque convolucional: detecta bordes y patrones simples
x = layers.Conv2D(8, (3, 3), activation='relu', name='conv1')(inputs)
x = layers.MaxPooling2D((2, 2))(x)  # Reduce la dimensión y conserva lo más relevante

# Segundo bloque convolucional: detecta combinaciones más complejas (curvas, esquinas)
x = layers.Conv2D(16, (3, 3), activation='relu', name='conv2')(x)
x = layers.MaxPooling2D((2, 2))(x)

# Capa densa para clasificación final
x = layers.Flatten()(x)
x = layers.Dense(64, activation='relu')(x)
outputs = layers.Dense(clases, activation='softmax')(x)  # 👈 CAMBIA AQUÍ a 10, clases posibles (0-9)

# Compilar el modelo
model = Model(inputs=inputs, outputs=outputs)
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Mostrar resumen del modelo
print(model.summary())

# Entrenar el modelo por 5 épocas
model.fit(x_train, y_train, epochs=5, validation_split=0.1)

🧠 Preguntas para reflexionar (Parte 1)¶

  1. ¿Por qué usamos una entrada de tamaño (28, 28, 1)? ¿Qué representa cada dimensión?
  2. En la primera capa convolucional usamos 8 filtros de tamaño 3×3. ¿Qué significan estos filtros?
  3. ¿Qué efecto tiene MaxPooling2D sobre la salida de la convolución?
  4. ¿Por qué la última capa tiene 10 neuronas y qué significa la función softmax en este contexto?
  5. Observa el model.summary() y explica:

    • ¿Cómo cambia el tamaño del tensor a lo largo de las capas?
    • ¿Por qué disminuyen las dimensiones espaciales?
    • ¿Por qué aumenta el número de filtros?

🔍 Parte 2: Visualización de mapas de activación¶

# Seleccionar una imagen del conjunto de prueba
img = x_test[0:1]

# Crear un modelo que devuelva las salidas intermedias de las capas convolucionales
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers if 'conv' in layer.name]
feature_model = models.Model(inputs=model.input, outputs=layer_outputs)

# Obtener los mapas de características
feature_maps = feature_model.predict(img)

# Visualizar los mapas de cada capa
import matplotlib.pyplot as plt

for i, fmap in enumerate(feature_maps):
    num_filters = fmap.shape[-1]
    plt.figure(figsize=(12, 4))
    for j in range(num_filters):
        plt.subplot(1, num_filters, j+1)
        plt.imshow(fmap[0, :, :, j], cmap='viridis')
        plt.axis('off')
    plt.suptitle(f"Feature Maps from Conv Layer {i+1}")
    plt.show()

🧠 Pregunta (Parte 2)¶

Describe lo que observas en los mapas de características:

  • ¿La primera capa detecta bordes o contornos?
  • ¿La segunda capa comienza a detectar formas más complejas como bucles o esquinas?
  • ¿Qué tanto se reduce la imagen con las capas de MaxPooling?

📊 Parte 3: Evaluación del modelo¶

from sklearn.metrics import classification_report, ConfusionMatrixDisplay
import numpy as np

# Predecir clases
y_pred_probs = model.predict(x_test)
y_pred = np.argmax(y_pred_probs, axis=1)  # Convertir probabilidades en etiquetas

# Matriz de confusión
ConfusionMatrixDisplay.from_predictions(
    y_test, y_pred,
    cmap='Blues',
    colorbar=False,
    display_labels=np.arange(10)
)
plt.title("Confusion Matrix - MNIST Classification")
plt.grid(False)
plt.tight_layout()
plt.show()

# Reporte de métricas por clase
print("Classification Report:\n")
print(classification_report(y_test, y_pred))

🧠 Preguntas (Parte 3)¶

  1. ¿Qué dígitos fueron más fáciles de clasificar?
  2. ¿Dónde se cometieron más errores? ¿En qué clases?
  3. ¿Qué métrica destacarías en el reporte (precision, recall, f1-score) y por qué?

Opción 2 Informe Ejecutivo: Clasificación de Dígitos con Redes Convolucionales¶

Esta actividad tiene como objetivo aplicar un modelo de red neuronal convolucional (CNN) para resolver un problema de clasificación de imágenes de dígitos escritos a mano, usando el conjunto de datos MNIST. Además de entrenar el modelo, se analizará el proceso de aprendizaje a través de mapas de activación y se evaluará su desempeño con una matriz de confusión y un reporte de clasificación.

📝 Instrucciones¶

1. Definición de arquitectura y entrenamiento del modelo¶

Se construyó una red neuronal convolucional que recibe imágenes de tamaño 28×28×1 (escala de grises). La arquitectura incluye:

  • Dos capas convolucionales con activación ReLU
  • Dos capas de reducción espacial con MaxPooling
  • Una capa densa intermedia
  • Una capa de salida con 10 neuronas y softmax

📄 Resumen del modelo:

input → Conv2D(8 filtros) → MaxPool → Conv2D(16 filtros) → MaxPool → Flatten → Dense(64) → Dense(10)

🧩 Actividad:

  • ¿Por qué la imagen de entrada es de forma (28, 28, 1)?
  • ¿Qué función cumple la capa Flatten?
  • ¿Por qué la capa de salida tiene 10 neuronas?
  • Explica cómo cambia el tamaño de los datos en cada etapa del modelo.

2. Visualización de mapas de activación¶

Se seleccionó una imagen del dígito 7 del conjunto de prueba y se visualizaron los mapas de activación producidos por cada filtro en las dos capas convolucionales.

🧩 Actividad:

  • ¿Qué tipo de patrones observas en los filtros de la primera capa (Conv1)?
  • ¿Qué detectan los filtros de la segunda capa (Conv2)? ¿Cómo se diferencian de la primera?
  • ¿Por qué es importante este tipo de visualización para interpretar una CNN?

3. Evaluación del modelo con matriz de confusión¶

Después del entrenamiento, se evaluó el modelo usando todo el conjunto de prueba. La siguiente figura muestra la matriz de confusión con los resultados obtenidos:

🧩 Actividad:

  • ¿Qué dígitos fueron clasificados correctamente con mayor frecuencia?
  • ¿En qué clases se cometieron más errores de confusión?
  • ¿Qué implicaciones tiene esto para una posible aplicación práctica?

Después del entrenamiento, se evaluó el modelo CNN con el conjunto de prueba. Se presentan a continuación la matriz de confusión y el reporte de clasificación por clase, que permiten analizar el desempeño del modelo para cada dígito.

📄 Reporte de clasificación (conjunto de prueba):

              precision    recall  f1-score   support

           0       0.97      1.00      0.98       980
           1       0.99      0.99      0.99      1135
           2       0.98      0.99      0.98      1032
           3       0.99      0.98      0.99      1010
           4       0.98      1.00      0.99       982
           5       0.99      0.98      0.99       892
           6       1.00      0.98      0.99       958
           7       1.00      0.98      0.99      1028
           8       0.98      0.99      0.99       974
           9       0.99      0.99      0.99      1009

    accuracy                           0.99     10000
   macro avg       0.99      0.99      0.99     10000
weighted avg       0.99      0.99      0.99     10000

📊 Actividad:

  • ¿Qué clases muestran mayor precisión y cuáles presentan errores?
  • ¿El modelo tiende a confundir alguna clase específica?
  • ¿Cómo interpretarías el valor de accuracy y la diferencia entre macro y weighted average?
  • ¿Qué importancia tiene el equilibrio entre precisión y recall en este tipo de tareas?
  • ¿Qué métricas destacarías para evaluar el modelo?
  • ¿Existe alguna clase con peor desempeño? ¿A qué se podría deber?
  • ¿Cómo se relaciona el desempeño con la complejidad visual del dígito?

5. Reflexión final¶

🧩 Actividad:

  • ¿Consideras que este modelo convolucional es adecuado para el problema?
  • ¿Qué modificaciones propondrías para mejorar el rendimiento?
  • ¿Cómo se compara esta arquitectura con una red neuronal multicapa (MLP) tradicional?

⏱️ Tiempo estimado de desarrollo: 2 horas ✍️ Entrega: Informe ejecutivo con respuestas justificadas y discusión de las visualizaciones presentadas.

Opción 3 - Libre elección de dataset de series temporales y optimización de hiperparámetros con LSTM¶

En esta tarea, el estudiante podrá seleccionar un conjunto de datos de series temporales (univariadas o multivariadas) para aplicar un modelo basado en redes LSTM (Long Short-Term Memory).

  • Si no dispone de un dataset, se recomienda utilizar alguno de acceso público, como:

    • AirPassengers (número de pasajeros aéreos, univariada).
    • Electricity Load Dataset (demanda de energía).
    • Weather Dataset (variables climáticas multivariadas).
  • El trabajo se desarrollará en Google Colab, asistido por Gemini AI, en modalidad:

    • high-code → escribir el código completo, o
    • no-code → apoyarse en Gemini para generar automáticamente bloques de código y luego adaptarlos.

📌 1. Cargar y explorar los datos¶

  • Subir el archivo CSV/Excel o importar el dataset desde una librería pública.
  • Visualizar la serie temporal para identificar patrones de tendencia, estacionalidad, anomalías o ruido.
  • Revisar valores faltantes y realizar un preprocesamiento inicial.

⚙️ 2. Preparar el conjunto de datos¶

  • Definir la variable objetivo (y) → el valor o vector futuro que se quiere predecir.
  • Generar ventanas temporales (ejemplo: usar los últimos n pasos de la serie para predecir el siguiente).
  • Dividir en entrenamiento y prueba respetando el orden temporal (no aleatorio).
  • Normalizar los datos (ejemplo: MinMaxScaler) para estabilizar el aprendizaje del LSTM.

🤖 3. Seleccionar modelo y definir hiperparámetros¶

  • Construir un modelo LSTM básico con al menos:

    • Una capa recurrente LSTM.
    • Una capa densa de salida para entregar la predicción.
  • Definir un espacio de búsqueda de hiperparámetros, por ejemplo:

    • Longitud de la ventana temporal (timesteps).
    • Número de neuronas en la capa LSTM.
    • Número de capas ocultas.
    • Función de activación.
    • Tamaño de batch y número de épocas.

📊 4. Optimización y evaluación¶

  • Aplicar validación temporal (ej. TimeSeriesSplit) o un conjunto de validación separado.
  • Reportar los mejores hiperparámetros encontrados.
  • Evaluar el modelo con métricas adecuadas:

    • MAE (Error absoluto medio).
    • RMSE (Raíz del error cuadrático medio).
    • MAPE (Error porcentual absoluto medio).
  • Visualizar resultados:

    • Curva de valores reales vs. predichos.
    • Gráfico del error en el tiempo.

✅ Recomendaciones finales¶

  • Comentar cada bloque de código generado o modificado.
  • Documentar brevemente:

    • ¿Por qué se eligió ese dataset?
    • ¿Qué hiperparámetros resultaron más relevantes?
    • ¿Qué métricas destacan del modelo entrenado?
    • ¿Qué posibles mejoras se implementarían en una segunda iteración?

Opción 4 – Libre elección de dataset de series temporales en KNIME (LSTM)¶

En esta tarea, el estudiante podrá seleccionar un dataset de series temporales (univariada o multivariada) y construir un flujo en KNIME para entrenar un modelo LSTM.

  • Si no dispone de un dataset propio, se recomienda utilizar alguno de acceso público, por ejemplo:

    • AirPassengers (serie univariada de pasajeros aéreos).
    • Weather Dataset (serie multivariada con temperatura, humedad, viento, etc.).
  • La consigna es plantear un problema de predicción de series temporales, distinto a los datasets ya usados en clase.

📌 1. Importación de datos¶

  • Usar File Reader o Excel Reader para cargar el dataset.
  • Verificar nombres de columnas y tipos de datos con Data Explorer.
  • En caso de series temporales multivariadas, asegurarse de que la columna de fecha/tiempo esté correctamente definida como índice.

⚙️ 2. Preprocesamiento¶

  • Escalar las variables con Normalizer (especialmente importante para LSTM).
  • Crear ventanas temporales con el nodo Lag Column (ejemplo: usar los últimos n valores como entrada para predecir el siguiente).
  • Dividir en entrenamiento y prueba con el nodo Partitioning, respetando el orden temporal (no aleatorio).

🤖 3. Modelado con LSTM¶

  • Utilizar el nodo Keras Network Learner para construir una red con al menos:

    • Una capa LSTM Layer.
    • Una capa Dense Layer de salida (un valor si es univariada, varios si es multivariada).
  • Conectar el modelo al nodo Keras Network Executor para el entrenamiento.
  • Opcional: probar distintas configuraciones (número de unidades LSTM, número de capas, tamaño de ventana, número de épocas).

📊 4. Evaluación¶

  • Comparar predicciones y valores reales con Numeric Scorer (MAE, RMSE, R²).
  • Visualizar con:

    • Line Plot para ver serie real vs. predicha.
    • Scatter Plot de valores reales vs. valores estimados.

✅ Recomendaciones finales¶

  • Documentar el flujo de KNIME con Annotation Nodes explicando cada bloque.
  • Guardar capturas del flujo completo y de los principales resultados (gráficos, métricas).
  • Reflexionar brevemente:

    • ¿Qué ventana temporal se usó y por qué?
    • ¿Qué tan bien capturó el modelo la tendencia/estacionalidad?
    • ¿Qué posibles mejoras implementarías en una segunda iteración?