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
evaluaciónmétricasoverfittingunderfittingconfusion-matrix

Evaluación del Rendimiento y Desafíos Comunes en Deep Learning

2 de octubre de 2025
7 min read
Por Alvaro Efren Bolaños Scalante
Evaluación del Rendimiento y Desafíos Comunes en Deep Learning
  • 5. Evaluación del Rendimiento y Desafíos Comunes
  • 🎯 Introducción
  • 📊 La Matriz de Confusión
  • Para Clasificación Binaria
  • Implementación en Python
  • 📈 Métricas Derivadas
  • 1. Precisión (Accuracy)
  • 2. Recall (Sensibilidad o Exhaustividad)
  • 3. Precisión (Precision)
  • 4. F1-Score
  • Reporte Completo de Clasificación
  • ⚠️ Desafíos Comunes: Subajuste y Sobreajuste
  • 🔻 Subajuste (Underfitting)
  • 1. Aumentar la Complejidad del Modelo
  • 🔺 Sobreajuste (Overfitting)
  • 1. Dropout
  • 2. Regularización L1/L2
  • 3. Early Stopping
  • 4. Data Augmentation
  • 🎯 Resumen de Estrategias
  • 🧪 Ejemplo Completo: Pipeline Anti-Overfitting
  • 🎓 Conclusión
  • Puntos Clave
  • 📚 Referencias

5. Evaluación del Rendimiento y Desafíos Comunes

🎯 Introducción

Aunque la precisión (accuracy) es una métrica intuitiva, no siempre es suficiente para una evaluación completa de un modelo. Además, durante el desarrollo de modelos, es común enfrentarse a desafíos como el sobreajuste y el subajuste, que deben ser identificados y gestionados adecuadamente.


📊 La Matriz de Confusión

Una herramienta más profunda para la evaluación es la Matriz de Confusión. Esta tabla visualiza el rendimiento de un algoritmo de clasificación, mostrando explícitamente cuándo una clase es confundida con otra.

Para Clasificación Binaria

Predicción PositivaPredicción Negativa
Observación PositivaVerdaderos Positivos (VP)Falsos Negativos (FN)
Observación NegativaFalsos Positivos (FP)Verdaderos Negativos (VN)

Componentes:

  • VP (True Positives): Casos positivos correctamente identificados
  • VN (True Negatives): Casos negativos correctamente identificados
  • FP (False Positives): Error Tipo I - predecir positivo cuando es negativo
  • FN (False Negatives): Error Tipo II - predecir negativo cuando es positivo

Implementación en Python

python
1from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
2import matplotlib.pyplot as plt
3import numpy as np
4
5# Obtener predicciones del modelo
6y_pred = model.predict(x_test)
7y_pred_classes = np.argmax(y_pred, axis=1)
8y_true = np.argmax(y_test, axis=1)
9
10# Calcular matriz de confusión
11cm = confusion_matrix(y_true, y_pred_classes)
12
13# Visualizar la matriz de confusión
14disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=range(10))
15disp.plot(cmap='Blues', values_format='d')
16plt.title('Matriz de Confusión - MNIST')
17plt.show()

📈 Métricas Derivadas

1. Precisión (Accuracy)

Mide la proporción de predicciones correctas sobre el total.

Fórmula:

1Accuracy = (VP + VN) / (VP + VN + FP + FN)

Limitación: No es adecuada para conjuntos de datos desbalanceados.

python
1from sklearn.metrics import accuracy_score
2
3accuracy = accuracy_score(y_true, y_pred_classes)
4print(f"Accuracy: {accuracy:.4f} ({accuracy*100:.2f}%)")

2. Recall (Sensibilidad o Exhaustividad)

Mide la proporción de positivos reales que fueron correctamente identificados.

Fórmula:

1Recall = VP / (VP + FN)

¿Cuándo es crucial?

  • 🏥 Detección de enfermedades: Es crítico no perder ningún caso positivo
  • 💳 Identificación de fraudes: Detectar todas las transacciones fraudulentas
  • 🍄 Clasificación de setas venenosas: No queremos clasificar erróneamente una seta venenosa como comestible
python
1from sklearn.metrics import recall_score
2
3recall = recall_score(y_true, y_pred_classes, average='weighted')
4print(f"Recall: {recall:.4f}")

3. Precisión (Precision)

Mide la proporción de predicciones positivas que fueron correctas.

Fórmula:

1Precision = VP / (VP + FP)

¿Cuándo es crucial?

  • 📧 Filtrado de spam: Minimizar que correos legítimos vayan a spam
  • 🎯 Recomendaciones de productos: Asegurar que las recomendaciones sean relevantes
python
1from sklearn.metrics import precision_score
2
3precision = precision_score(y_true, y_pred_classes, average='weighted')
4print(f"Precision: {precision:.4f}")

4. F1-Score

Media armónica entre Precision y Recall.

Fórmula:

1F1 = 2 · (Precision · Recall) / (Precision + Recall)
python
1from sklearn.metrics import f1_score
2
3f1 = f1_score(y_true, y_pred_classes, average='weighted')
4print(f"F1-Score: {f1:.4f}")

Reporte Completo de Clasificación

python
1from sklearn.metrics import classification_report
2
3report = classification_report(y_true, y_pred_classes, 
4                               target_names=[str(i) for i in range(10)],
5                               digits=4)
6print(report)

⚠️ Desafíos Comunes: Subajuste y Sobreajuste

🔻 Subajuste (Underfitting)

Definición: Ocurre cuando un modelo es demasiado simple para capturar la complejidad subyacente de los datos.

Características:

  • ❌ Alto error en datos de entrenamiento
  • ❌ Alto error en datos de validación/prueba
  • ❌ El modelo no aprende los patrones subyacentes

Código para detectar underfitting:

python
1def detectar_underfitting(history):
2    train_loss = history.history['loss'][-5:]
3    val_loss = history.history['val_loss'][-5:]
4    
5    avg_train_loss = np.mean(train_loss)
6    avg_val_loss = np.mean(val_loss)
7    
8    if avg_train_loss > 0.5 and avg_val_loss > 0.5:
9        print("⚠️ ALERTA: Posible UNDERFITTING detectado")
10        print(f"   - Error de entrenamiento: {avg_train_loss:.4f}")
11        print(f"   - Error de validación: {avg_val_loss:.4f}")
12        print("\n💡 Soluciones sugeridas:")
13        print("   1. Aumentar la complejidad del modelo")
14        print("   2. Añadir más capas o neuronas")
15        print("   3. Entrenar por más épocas")
16        return True
17    return False

Estrategias de solución:

1. Aumentar la Complejidad del Modelo

python
1# Modelo SIMPLE (propenso a underfitting)
2model_simple = Sequential([
3    Flatten(input_shape=(28, 28)),
4    Dense(32, activation='relu'),
5    Dense(10, activation='softmax')
6])
7
8# Modelo MÁS COMPLEJO (mejor capacidad)
9model_complejo = Sequential([
10    Flatten(input_shape=(28, 28)),
11    Dense(256, activation='relu'),
12    Dense(128, activation='relu'),
13    Dense(64, activation='relu'),
14    Dense(10, activation='softmax')
15])

🔺 Sobreajuste (Overfitting)

Definición: Ocurre cuando un modelo es demasiado complejo y "memoriza" los datos de entrenamiento.

Características:

  • ✅ Muy bajo error en datos de entrenamiento
  • ❌ Alto error en datos de validación/prueba
  • ⚠️ Gran brecha entre error de entrenamiento y validación

Código para detectar overfitting:

python
1def detectar_overfitting(history, threshold=0.1):
2    train_loss = history.history['loss'][-5:]
3    val_loss = history.history['val_loss'][-5:]
4    
5    avg_train_loss = np.mean(train_loss)
6    avg_val_loss = np.mean(val_loss)
7    
8    gap = avg_val_loss - avg_train_loss
9    
10    if gap > threshold:
11        print("⚠️ ALERTA: Posible OVERFITTING detectado")
12        print(f"   - Error de entrenamiento: {avg_train_loss:.4f}")
13        print(f"   - Error de validación: {avg_val_loss:.4f}")
14        print(f"   - Brecha: {gap:.4f}")
15        print("\n💡 Soluciones sugeridas:")
16        print("   1. Usar Dropout")
17        print("   2. Aplicar regularización L1/L2")
18        print("   3. Usar Early Stopping")
19        print("   4. Aumentar datos de entrenamiento")
20        return True
21    return False

Estrategias de solución:

1. Dropout

python
1from tensorflow.keras.layers import Dropout
2
3model = Sequential([
4    Flatten(input_shape=(28, 28)),
5    Dense(128, activation='relu'),
6    Dropout(0.5),  # Desactiva 50% de neuronas
7    Dense(64, activation='relu'),
8    Dropout(0.3),
9    Dense(10, activation='softmax')
10])

2. Regularización L1/L2

python
1from tensorflow.keras import regularizers
2
3model = Sequential([
4    Flatten(input_shape=(28, 28)),
5    Dense(128, activation='relu', 
6          kernel_regularizer=regularizers.l2(0.01)),
7    Dense(64, activation='relu',
8          kernel_regularizer=regularizers.l1(0.01)),
9    Dense(10, activation='softmax')
10])

3. Early Stopping

python
1from tensorflow.keras.callbacks import EarlyStopping
2
3early_stop = EarlyStopping(
4    monitor='val_loss',
5    patience=10,
6    restore_best_weights=True,
7    verbose=1
8)
9
10history = model.fit(
11    x_train, y_train,
12    epochs=100,
13    validation_split=0.2,
14    callbacks=[early_stop]
15)

4. Data Augmentation

python
1from tensorflow.keras.preprocessing.image import ImageDataGenerator
2
3datagen = ImageDataGenerator(
4    rotation_range=10,
5    width_shift_range=0.1,
6    height_shift_range=0.1,
7    zoom_range=0.1
8)
9
10history = model.fit(
11    datagen.flow(x_train, y_train, batch_size=32),
12    steps_per_epoch=len(x_train) // 32,
13    epochs=20,
14    validation_data=(x_test, y_test)
15)

🎯 Resumen de Estrategias

ProblemaSíntomaSoluciones
UnderfittingAlto error en train y testAumentar complejidad del modelo, Más capas/neuronas, Entrenar más épocas
OverfittingBajo error en train, Alto en testDropout, Regularización L1/L2, Early stopping, Data augmentation, Más datos

🧪 Ejemplo Completo: Pipeline Anti-Overfitting

python
1import numpy as np
2from tensorflow import keras
3from tensorflow.keras import Sequential
4from tensorflow.keras.layers import Dense, Flatten, Dropout
5from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
6from tensorflow.keras import regularizers
7
8# Cargar datos
9(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
10x_train, x_test = x_train / 255.0, x_test / 255.0
11y_train = keras.utils.to_categorical(y_train, 10)
12y_test = keras.utils.to_categorical(y_test, 10)
13
14# Modelo con técnicas anti-overfitting
15model = Sequential([
16    Flatten(input_shape=(28, 28)),
17    Dense(128, activation='relu',
18          kernel_regularizer=regularizers.l2(0.001)),
19    Dropout(0.5),
20    Dense(64, activation='relu',
21          kernel_regularizer=regularizers.l2(0.001)),
22    Dropout(0.3),
23    Dense(10, activation='softmax')
24])
25
26model.compile(
27    optimizer='adam',
28    loss='categorical_crossentropy',
29    metrics=['accuracy']
30)
31
32# Callbacks
33early_stop = EarlyStopping(
34    monitor='val_loss',
35    patience=10,
36    restore_best_weights=True
37)
38
39checkpoint = ModelCheckpoint(
40    'mejor_modelo.h5',
41    monitor='val_accuracy',
42    save_best_only=True
43)
44
45# Entrenar
46history = model.fit(
47    x_train, y_train,
48    epochs=100,
49    batch_size=32,
50    validation_split=0.2,
51    callbacks=[early_stop, checkpoint]
52)
53
54# Evaluar
55test_loss, test_acc = model.evaluate(x_test, y_test)
56print(f"\nPrecisión en test: {test_acc:.4f} ({test_acc*100:.2f}%)")

🎓 Conclusión

Hemos completado este recorrido por los fundamentos del Deep Learning:

  1. ✅ Fundamentos del ML: Paradigmas y conceptos básicos
  2. ✅ Redes Neuronales: Arquitectura y componentes
  3. ✅ Entrenamiento: Función de costo y backpropagation
  4. ✅ Implementación: Aplicación práctica con Keras
  5. ✅ Evaluación: Métricas avanzadas y solución de desafíos

Puntos Clave

🔹 Evaluación: Usa métricas múltiples, no solo accuracy 🔹 Underfitting: Aumenta complejidad, más features, más épocas 🔹 Overfitting: Dropout, regularización, early stopping 🔹 Balance: Busca el punto óptimo entre simplicidad y complejidad


📚 Referencias

  • Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep learning. MIT Press.
  • AWS. (s.f.). ¿En qué consiste el ajuste de hiperparámetros?
  • Ng, A. (2017). Neural Networks and Deep Learning. Coursera.

← Anterior: Blog 4: Aplicación Práctica con Keras

🏠 Inicio de la serie: Blog 1: Introducción al Machine Learning