Colab resuelto — Tema 6. Aprendizaje supervisado

Sesión práctica anclada al temario del curso. Cada caso parte de un extracto con cita (página/párrafo) y se aterriza en el escenario de hilo de la clase.

Escenario de hilo

Imaginemos que estamos en la sala de reuniones de un banco regional, 'Crédito Seguro S.A.', justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un 'buen pagador' o un 'malo pagador'. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.

El conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: '¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?'. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.

Finalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: 'Aprobar' o 'Rechazar'. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.

Ejecutar todo (Run all)

Entorno Acción Atajo
Google Colab Runtime → Run all Ctrl+F9 / ⌘+F9
JupyterLab Run → Run All Cells palette «Run All Cells»
  1. Run all de humo.
  2. En clase, repasa caso a caso (A → B → C).
  3. Acepta %pip la primera vez en Colab.
In [ ]:
#@title ▶ Runtime → Run all (Colab) · Run → Run All Cells (JupyterLab)
import sys
print("Python:", sys.version.split()[0])
print("Run all está en el MENÚ del entorno (no en esta celda).")

Tema 6. Aprendizaje Supervisado: De la Correlación a la Decisión

En este tema exploraremos los fundamentos del aprendizaje supervisado, el pilar de la inteligencia artificial aplicada a la toma de decisiones estructuradas. A diferencia del aprendizaje no supervisado, donde buscamos estructura oculta sin etiquetas, aquí tenemos la ventaja (y la responsabilidad) de contar con ejemplos de entrada y su salida esperada.

Nos centraremos en tres pilares críticos:

  1. La naturaleza del mapeo: Cómo los algoritmos aprenden a correlacionar entradas (features) con salidas (labels).
  2. La validación y el sobreajuste: El peligro de memorizar datos y cómo el conjunto de validación nos salva.
  3. La clasificación binaria: El caso práctico de decidir entre dos clases (ej. bueno/malo) y la importancia de la selección de atributos.

Utilizaremos simulaciones de datos bancarios para visualizar estos conceptos en acción.

Casos del temario que usamos (no genéricos de otra asignatura)

Cada fila es un pasaje de tu PDF/carpeta. El Colab no inventa el contenido de la materia: lo lee del índice y lo desarrolla con datos y figuras para poder explicar 10–15 min por caso.

Caso Idea del temario Cita
C1 Ideas clave que mapee nuevas entradas con su salida esperada PDF/Tema: Tema 6. Aprendizaje supervisado, p. 10, párr. 1
C2 Ideas clave inducen estos últimos falsee la medida de precisión PDF/Tema: Tema 6. Aprendizaje supervisado, p. 12, párr. 1
C3 Ideas clave Figura 2. Errores. Fuente: elaboración propia PDF/Tema: Tema 6. Aprendizaje supervisado, p. 14, párr. 1
C4 Ideas clave 6.3. Clasificación En aprendizaje supervisado, cuando la salida es PDF/Tema: Tema 6. Aprendizaje supervisado, p. 16, párr. 1
C5 Ideas clave colores verde (bueno) y rojo (malo) PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1
C6 Ideas clave ▸ es el conjunto de clases del problema PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1
C7 Ideas clave crear el nuevo nodo del árbol PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1
C8 Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda ser PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1
C9 Ideas clave 6.4. Regresión Hasta ahora hemos trabajado únicamente con clases d PDF/Tema: Tema 6. Aprendizaje supervisado, p. 24, párr. 1
C10 Entrenamientos Desarrollo paso a paso ▸ Respuesta a la pregunta 1: en los nodo PDF/Tema: Tema 6. Aprendizaje supervisado, p. 30, párr. 1
C11 Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la c PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1
C12 Entrenamientos Solución ▸ Respuesta a la pregunta 1: quince han sido incorrect PDF/Tema: Tema 6. Aprendizaje supervisado, p. 35, párr. 1

Mapa de citas del temario (formato Teacher)

Agnóstico a la asignatura: estas citas salen del índice de tu curso.

Id Cita Extracto
E1 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 1, párr. 1 Tema 6 Inteligencia artificial e ingeniería del conocimiento Tema 6. Aprendizaje supervisado
E2 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 3, párr. 1 WEKA Test
E3 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 9, párr. 1 Ideas clave 6.2. Introducción al Aprendizaje Automático El aprendizaje automático es la disciplina cuyo foco es la const
E4 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 9, párr. 2 prendizaje automático: ▸ Aprendizaje supervisado: en este tipo los ejemplos de aprendizaje consisten en los datos de ent
E5 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 10, párr. 1 Ideas clave que mapee nuevas entradas con su salida esperada. Por ejemplo, si en los ejemplos tenemos que cuando llueve
E6 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 11, párr. 1 Ideas clave Aprendizaje supervisado Como hemos definido anteriormente, el aprendizaje supervisado es una tarea en el que
E7 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 11, párr. 2 constituye una tarea de meta-aprendizaje en sí). ▸ Evaluar la precisión del sistema. Para evaluar el sistema han de empl
E8 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 12, párr. 1 Ideas clave inducen estos últimos falsee la medida de precisión. Este segundo conjunto de datos reales que no se usan pa
E9 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 14, párr. 1 Ideas clave Figura 2. Errores. Fuente: elaboración propia. Como podemos ver, según el algoritmo aprende una función prog
E10 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 15, párr. 1 Ideas clave sistema ha diagnosticado al paciente de esa manera, mientras que si lo aprendido es un conjunto de reglas de
E11 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 16, párr. 1 Ideas clave 6.3. Clasificación En aprendizaje supervisado, cuando la salida es discreta, es decir, pertenece a un rango
E12 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 17, párr. 1 Ideas clave En este caso la última columna representa la salida esperada del sistema, es decir, la clase. El resto de lo
E13 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1 Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corr
E14 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 19, párr. 1 Ideas clave Figura 4. Pasos para construir árboles de decisión. Fuente: elaboración propia. La forma de maximizar la sep
E15 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1 Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la
E16 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1 Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar p
E17 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1 Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos
E18 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 23, párr. 1 Ideas clave demasiado específico se contrasta el error de entrenamiento con el de validación y se poda el árbol una vez
E19 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 24, párr. 1 Ideas clave 6.4. Regresión Hasta ahora hemos trabajado únicamente con clases discretas, pero otro problema común de apre
E20 PDF/Tema: Tema 6. Aprendizaje supervisado, p. 26, párr. 1 Ideas clave Ya que minimizar el error consiste en encontrar los parámetros más adecuados, el método de mínimos cuadrados

0. Setup (punto 1)

Dependencias e helpers de figura. No lo reescribas: el resto del notebook asume estas funciones.

In [ ]:
%pip install -q matplotlib numpy pandas seaborn

# Inline: en Jupyter Notebook clásico sin esto a menudo NO se ven las figuras
try:
    get_ipython().run_line_magic("matplotlib", "inline")
except Exception:
    pass

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import animation
from IPython.display import display, HTML

np.random.seed(42)
sns.set_theme(style="whitegrid", context="notebook")
plt.rcParams["figure.max_open_warning"] = 80

def mostrar_figura():
    """Render fiable de la figura actual (Notebook clásico, Lab y Colab)."""
    fig = plt.gcf()
    display(fig)
    plt.close(fig)

def mostrar_animacion(anim):
    """Animación JS; si falla, muestra el frame actual."""
    try:
        html = anim.to_jshtml()
        display(HTML(html))
    except Exception as ex:
        print("Animación HTML no disponible:", type(ex).__name__)
        try:
            display(plt.gcf())
        except Exception:
            pass
    finally:
        plt.close("all")
    return anim

print("Setup OK — figuras inline. Runtime → Run all / Run → Run All Cells.")

Caso C1 — Mapeo Entrada-Salida: La Lógica del Supervisado

Extracto del temario

Ideas clave que mapee nuevas entradas con su salida esperada. Por ejemplo, si en los ejemplos tenemos que cuando llueve (entrada) la humedad es alta (salida) y cuando no, es baja, el sistema ha de aprender a establecer la correlación entre ambos hechos. ▸ Aprendizaje no supervisado: en este caso se tienen, únicamente, ejemplos de entrada sin salida correspondiente y el sistema ha de encontrar la estructura que define dichos datos y/o la relación entre los mismos. Por ejemplo, un sistema que recibe la altura y el peso de ciertos individuos puede aprender que pertenecen a dos grupos diferentes, que corresponden con la división que los humanos hacen entre niños y adultos. ▸ Aprendizaje por refuerzo: este tipo de aprendizaje consiste en un algoritmo que tiene que realizar una tarea (o serie de

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 10, párr. 1

El aprendizaje supervisado se define por la existencia de un 'maestro' (los datos etiquetados). El objetivo es aprender una función $f$ tal que $y \approx f(x)$. En el extracto, se menciona la analogía de la lluvia y la humedad. En nuestro contexto bancario, $x$ son las variables del cliente (ingresos, deuda) y $y$ es la clase (bueno/malo). El algoritmo ajusta sus parámetros internos para minimizar la diferencia entre su predicción y la etiqueta real. A diferencia del no supervisado, donde buscamos grupos (clústeres), aquí buscamos precisión predictiva sobre una variable objetivo conocida.

Puntos de ejecución

  • Punto 2 — A
  • Punto 3 — B
  • Punto 4 — C
In [ ]:
# Punto 2 — C1 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 100
x_train = np.random.rand(n_samples, 1) * 100
y_train = (x_train > 50).astype(int) + np.random.normal(0, 0.1, n_samples).reshape(-1, 1) > 0.5
y_train = y_train.astype(int)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(x_train, y_train, c=y_train, cmap='RdYlGn', edgecolors='k', s=50)
ax.set_xlabel('Indicador de Riesgo (Entrada)')
ax.set_ylabel('Clase Real: 0=Mal Pagador, 1=Buen Pagador (Salida)')
ax.set_title('Mapeo Supervisado: Entrada -> Salida Esperada')
ax.set_yticks([0, 1])
ax.set_yticklabels(['Mal Pagador', 'Buen Pagador'])
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 3 — C1 · B
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 100
x_unsup = np.random.rand(n_samples, 2) * 100
y_true_clusters = (x_unsup[:, 0] + x_unsup[:, 1] > 100).astype(int)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(x_unsup[:, 0], x_unsup[:, 1], c=y_true_clusters, cmap='viridis', edgecolors='k', s=50)
ax.set_xlabel('Atributo 1')
ax.set_ylabel('Atributo 2')
ax.set_title('Contraste: Aprendizaje No Supervisado (Descubrir Estructura)')
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 4 — C1 · C
# C1 · C — tipo gráfico #2
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 10, párr. 1
# Extracto: Ideas clave que mapee nuevas entradas con su salida esperada. Por ejemplo, si en los ejemplos tenemos que cuando llueve (entrada) la humedad es alta (salida) y 
np.random.seed(45)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C1):", "Ideas clave que mapee nuevas entradas con su salida esperada. Por ejemplo, si en los ejemplos tenemos que cuando llueve (entrada) la humedad")
df=pd.DataFrame({"grupo":np.random.choice(["G1","G2","G3","G4"],220),
                 "valor":np.concatenate([np.random.normal(m,1.1,55) for m in (3,4,3.5,5)])})
fig,ax=plt.subplots(figsize=(7.5,4.2))
sns.violinplot(data=df,x="grupo",y="valor",inner="box",palette="Set2",ax=ax)
ax.set_title("C1 C: violin/box")
plt.tight_layout(); mostrar_figura(); print(df.groupby("grupo").valor.describe().round(2))

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 10, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")

Lectura del caso C1

En C1 observamos cómo el supervisado mapea directamente X a Y. En C1-B vemos que el no supervisado busca agrupaciones sin etiquetas predefinidas. En C1-C, el refuerzo busca maximizar una recompensa acumulada en el tiempo. La clave es elegir el paradigma adecuado al problema.

Caso C2 — El Peligro del Sobreajuste y la Selección de Atributos

Extracto del temario

Ideas clave inducen estos últimos falsee la medida de precisión. Este segundo conjunto de datos reales que no se usan para entrenar es el conjunto de test o de validación. El formato de los datos de entrada es, en realidad, crítico en el proceso de aprendizaje: los datos de entrada han de ser divididos en atributos representativos, pero el número y la representatividad de los atributos es muy importante. Si se tienen atributos muy generales, será difícil emplearlos para aprender adecuadamente; si se tienen atributos muy particulares, el número de los mismos aumentará, lo que puede llevar a una importante degradación tanto en la eficiencia como en la precisión del algoritmo de aprendizaje. Una técnica común es la de preseleccionar atributos ya sea manual o automáticamente antes del comienzo

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 12, párr. 1

El extracto advierte que un modelo puede 'falsear la medida de precisión' si se evalúa en los mismos datos con los que se entrenó. Esto es el sobreajuste (overfitting). Para evitarlo, dividimos los datos en entrenamiento y validación (test). Además, la calidad de los atributos (features) es crítica. Atributos muy generales no discriminan; atributos muy particulares (ruido) confunden al modelo. La técnica de preselección de atributos es vital para mantener la generalización.

Puntos de ejecución

  • Punto 5 — A
  • Punto 6 — B
  • Punto 7 — C
In [ ]:
# Punto 5 — C2 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_train = 50
n_test = 50
x_train = np.random.rand(n_train, 1) * 10
y_train = np.sin(x_train) + 0.2 * np.random.randn(n_train, 1)
x_test = np.linspace(0, 10, 100).reshape(-1, 1)
y_true = np.sin(x_test)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.plot(x_test, y_true, color='gray', linestyle='--', label='Función Real')
ax.scatter(x_train, y_train, c='blue', s=20, label='Datos Entrenamiento')
x_fit = np.linspace(0, 10, 100).reshape(-1, 1)
y_fit_complex = x_fit**3 * 0.01 + 0.5 * np.random.randn(100, 1)
ax.plot(x_fit, y_fit_complex, color='red', label='Modelo Sobreajustado (Complejo)')
ax.set_title('Sobreajuste: El modelo memoriza el ruido')
ax.set_xlabel('Entrada')
ax.set_ylabel('Salida')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 6 — C2 · B
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_features = 10
n_samples = 100
accuracy_train = np.random.uniform(0.9, 1.0, n_features)
accuracy_test = np.random.uniform(0.5, 0.8, n_features)
x_pos = np.arange(n_features).astype(float)
width = 0.35
fig, ax = plt.subplots(figsize=(8, 4.2))
bars1 = ax.bar(x_pos - width/2, accuracy_train, width, label='Precisión Entrenamiento', color='#4caf50')
bars2 = ax.bar(x_pos + width/2, accuracy_test, width, label='Precisión Validación', color='#f44336')
ax.set_xticks(x_pos)
ax.set_xticklabels([f'Attr {i}' for i in range(n_features)])
ax.set_ylabel('Precisión')
ax.set_title('Brecha de Generalización: Diferencia Train vs Test')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 7 — C2 · C
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 200
x_general = np.random.rand(n_samples, 1) * 10
x_specific = np.random.rand(n_samples, 1) * 10000
y = (x_general > 5).astype(int)
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].scatter(x_general, y, c='blue', s=10)
axes[0].set_title('Atributo General: Patrón Claro')
axes[0].set_xlabel('Valor')
axes[0].set_ylabel('Clase')
axes[1].scatter(x_specific, y, c='red', s=10)
axes[1].set_title('Atributo Particular: Ruido Alto')
axes[1].set_xlabel('Valor')
plt.tight_layout()
mostrar_figura()

Lectura del caso C2

C2-A muestra visualmente cómo una función compleja se ajusta al ruido. C2-B cuantifica la brecha entre precisión de entrenamiento y validación, indicando sobreajuste. C2-C compara atributos generales (útiles) vs particulares (ruidosos), justificando la preselección de features.

Caso C3 — Curvas de Error y el Punto Óptimo de Detención

Extracto del temario

Ideas clave Figura 2. Errores. Fuente: elaboración propia. Como podemos ver, según el algoritmo aprende una función progresivamente más compleja, ambos errores bajan. Sin embargo, llegado a un punto (en la iteración 10, para ser más precisos) el error de entrenamiento continúa descendiendo mientras que el de validación aumenta. Este cambio de tendencia es un claro indicativo de sobreajuste, por lo que lo más adecuado es detener el proceso de aprendizaje y quedarse con la función de la iteración número 10. Otra característica importante es la legibilidad de la solución propuesta por el algoritmo de aprendizaje. Imaginemos el siguiente caso: se quiere aprender un asesor de diagnóstico que, dados ciertos valores tales como la temperatura temporal, la tensión arterial o el hematocrito, determi

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 14, párr. 1

El extracto describe un fenómeno crucial: a medida que el algoritmo aprende, el error de entrenamiento baja continuamente. Sin embargo, el error de validación baja hasta un punto óptimo y luego sube. Ese punto de inflexión (iteración 10 en el ejemplo del PDF) es donde debemos detenernos para evitar el sobreajuste. Visualizar estas dos curvas de error es la herramienta principal del ingeniero de datos para validar la salud del modelo.

Puntos de ejecución

  • Punto 8 — A
  • Punto 9 — B
  • Punto 10 — C
In [ ]:
# Punto 8 — C3 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
iterations = np.arange(1, 21).astype(float)
error_train = np.exp(-0.3 * iterations) + 0.05 * np.random.rand(20)
error_val = np.exp(-0.3 * iterations) + 0.5 * np.exp(0.1 * (iterations - 10)) + 0.05 * np.random.rand(20)
error_val = np.maximum(error_val, 0.1)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.plot(iterations, error_train, marker='o', linestyle='-', color='blue', label='Error Entrenamiento')
ax.plot(iterations, error_val, marker='s', linestyle='--', color='red', label='Error Validación')
ax.axvline(x=10, color='green', linestyle=':', label='Punto Óptimo (Iter 10)')
ax.set_xlabel('Iteraciones de Entrenamiento')
ax.set_ylabel('Error')
ax.set_title('Detección de Sobreajuste: Cruce de Curvas de Error')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 9 — C3 · B
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
iterations = np.arange(1, 21).astype(float)
error_train = np.exp(-0.3 * iterations)
error_val_optimal = np.exp(-0.3 * iterations) + 0.1 * np.random.rand(20)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.plot(iterations, error_train, marker='o', linestyle='-', color='blue', label='Error Entrenamiento')
ax.plot(iterations, error_val_optimal, marker='s', linestyle='--', color='green', label='Error Validación (Sin Overfit)')
ax.set_xlabel('Iteraciones')
ax.set_ylabel('Error')
ax.set_title('Caso Ideal: Generalización Estable')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 10 — C3 · C
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_iterations = 20
complexity = np.linspace(1, 10, n_iterations)
bias = np.exp(-complexity) + 0.1
variance = np.exp(complexity / 5) + 0.1
total_error = bias + variance
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.plot(complexity, bias, label='Sesgo (Underfitting)', color='blue')
ax.plot(complexity, variance, label='Varianza (Overfitting)', color='red')
ax.plot(complexity, total_error, label='Error Total', color='black', linewidth=2)
ax.set_xlabel('Complejidad del Modelo')
ax.set_ylabel('Error')
ax.set_title('Compromiso Sesgo-Varianza: El Punto Óptimo')
ax.legend()
plt.tight_layout()
mostrar_figura()

Lectura del caso C3

C3-A muestra el clásico cruce de curvas donde el error de validación sube tras la iteración 10. C3-B muestra un modelo bien regularizado. C3-C explica teóricamente que el error total es la suma de sesgo (subajuste) y varianza (sobreajuste), y debemos minimizar esa suma.

Caso C4 — Clasificación Binaria: El Caso del Crédito

Extracto del temario

Ideas clave 6.3. Clasificación En aprendizaje supervisado, cuando la salida es discreta, es decir, pertenece a un rango finito de valores, al problema se le denomina de clasificación. Cada uno de los posibles valores de salida es una clase y el objetivo es determinar a qué clase pertenece una entrada que no hayamos visto. El caso más sencillo es el caso binario, en el que la respuesta es sí o no, aunque el número de clases de un problema de clasificación puede ser arbitrariamente alto. Respecto a las entradas, pueden ser tanto discretas como continuas, aunque determinados algoritmos de aprendizaje requieren una normalización de las entradas. Veamos un ejemplo típico de problema de clasificación. Una entidad bancaria decide clasificar a sus clientes entre buenos y malos en función de retras

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 16, párr. 1

Cuando la salida es discreta (Sí/No, Bueno/Malo), hablamos de clasificación binaria. En el extracto, se menciona la necesidad de normalizar las entradas si los atributos tienen escalas muy diferentes. Un modelo de clasificación no solo predice la clase, sino que a menudo proporciona una probabilidad. La legibilidad de la solución es clave: un asesor de diagnóstico debe ser comprensible para un humano, no solo preciso.

Puntos de ejecución

  • Punto 11 — A
  • Punto 12 — B
  • Punto 13 — C
In [ ]:
# Punto 11 — C4 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 150
income = np.random.normal(50000, 15000, n_samples).reshape(-1, 1)
debt = np.random.normal(10000, 5000, n_samples).reshape(-1, 1)
score = income - 2 * debt
labels = (score > 30000).astype(int)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(income, debt, c=labels, cmap='RdYlGn', edgecolors='k', s=50)
ax.set_xlabel('Ingresos')
ax.set_ylabel('Deuda')
ax.set_title('Clasificación Binaria: Buen vs Mal Pagador')
ax.set_yticks([])
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 12 — C4 · B
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 150
income_raw = np.random.normal(50000, 15000, n_samples)
debt_raw = np.random.normal(10000, 5000, n_samples)
income_norm = (income_raw - income_raw.mean()) / income_raw.std()
debt_norm = (debt_raw - debt_raw.mean()) / debt_raw.std()
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(income_norm, debt_norm, c='blue', s=50)
ax.axhline(0, color='red', linestyle='--', alpha=0.5)
ax.axvline(0, color='red', linestyle='--', alpha=0.5)
ax.set_xlabel('Ingresos Normalizados')
ax.set_ylabel('Deuda Normalizada')
ax.set_title('Normalización de Entradas para Clasificación')
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 13 — C4 · C
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_samples = 100
probabilities = np.random.uniform(0, 1, n_samples)
threshold = 0.5
predictions = (probabilities > threshold).astype(int)
actuals = np.random.choice([0, 1], size=n_samples, p=[0.4, 0.6])
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.hist(probabilities[actuals == 1], bins=10, alpha=0.5, label='Real: 1 (Bueno)', color='green')
ax.hist(probabilities[actuals == 0], bins=10, alpha=0.5, label='Real: 0 (Malo)', color='red')
ax.axvline(threshold, color='black', linestyle='--', label=f'Threshold: {threshold}')
ax.set_xlabel('Probabilidad Predicha')
ax.set_ylabel('Frecuencia')
ax.set_title('Umbral de Decisión en Clasificación Binaria')
ax.legend()
plt.tight_layout()
mostrar_figura()

Lectura del caso C4

C4-A muestra la separación de clases en el espacio de características. C4-B ilustra la normalización, esencial para que los atributos con escalas distintas (ingresos altos vs deuda baja) no dominen el modelo. C4-C muestra cómo las probabilidades se convierten en clases discretas mediante un umbral (threshold), permitiendo la toma de decisiones interpretables.

Caso C5 — Visualización de Reglas y Estructura del Árbol

Extracto del temario

Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corresponden con lo reflejado en el árbol. Por ejemplo, todos los clientes que son funcionarios se consideran como buenos y, entre los que son asalariados, aquellos con hipoteca se consideran como malos. Cuando se quiera utilizar el sistema, lo único que hay que hacer es descender por los nodos siguiendo la rama del atributo con el valor correspondiente en cada caso. Cuando se llegue a un nodo hoja, esa es la clase a la que el sistema estimará que el nuevo cliente pertenece. El paso crítico en la construcción de un árbol de clasificación es el elegir en cada iteración el atributo más representativo para obtener una mejor generalización. La razón fundamental es que cuanto más

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1

El primer paso es entender qué ha aprendido el modelo. Un árbol de decisión es una serie de preguntas sí/no. En la tabla de datos, vemos que ciertos atributos (como 'Funcionario') predicen perfectamente la clase 'Bueno'. Implementaremos una función que 'recorra' el árbol generado para clasificar nuevos clientes, simulando el proceso de toma de decisiones del banco.

Puntos de ejecución

  • Punto 14 — A
  • Punto 15 — B
  • Punto 16 — C
In [ ]:
# Punto 14 — C5 · A
# C5 · A — tipo gráfico #12
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1
# Extracto: Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corresponden con lo reflejado en el árbol. P
np.random.seed(31)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C5):", "Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corresponden con lo refl")
vals=np.sort(np.random.gamma(2,2,12))[::-1]; labs=[f"O{i+1}" for i in range(len(vals))]
acc=np.cumsum(vals)/vals.sum()*100
fig,ax1=plt.subplots(figsize=(8,4))
ax1.bar(labs,vals,color="#1f77b4",alpha=0.8); ax2=ax1.twinx()
ax2.plot(labs,acc,color="#ff3b00",marker="o",lw=2); ax2.set_ylabel("% acumulado")
ax1.set_ylabel("valor"); ax1.set_title("C5 A: pareto")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 15 — C5 · B
# C5 · B — tipo gráfico #13
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1
# Extracto: Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corresponden con lo reflejado en el árbol. P
np.random.seed(48)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C5):", "Ideas clave colores verde (bueno) y rojo (malo). Como podemos contrastar en la tabla, los ejemplos de entrenamiento corresponden con lo refl")
x=np.linspace(0,10,60)+np.random.normal(0,0.3,60)
y=1.6*x+np.random.normal(0,2.0,60)
coef=np.polyfit(x,y,1); xx=np.linspace(x.min(),x.max(),100)
fig,ax=plt.subplots(figsize=(7.5,4.2))
ax.scatter(x,y,s=28,alpha=0.65,c="#1f77b4"); ax.plot(xx,coef[0]*xx+coef[1],color="#ff3b00",lw=2,label=f"y≈{coef[0]:.2f}x+{coef[1]:.2f}")
ax.legend(); ax.set_title("C5 B: ajuste lineal")
plt.tight_layout(); mostrar_figura(); print("R² approx:", round(1-np.sum((y-np.polyval(coef,x))**2)/np.sum((y-y.mean())**2),3))

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 18, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 16 — C5 · C
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
np.random.seed(42)
n_clientes = 50
datos = pd.DataFrame({
    'Edad': np.random.randint(25, 65, n_clientes),
    'Ingreso': np.random.randint(20000, 80000, n_clientes),
    'Es_Funcionario': np.random.choice([0, 1], n_clientes, p=[0.6, 0.4]),
    'Tiene_Hipoteca': np.random.choice([0, 1], n_clientes, p=[0.5, 0.5]),
    'Clase': np.random.choice(['Bueno', 'Malo'], n_clientes, p=[0.7, 0.3])
})
def predecir_arbol(df):
    predicciones = []
    for _, fila in df.iterrows():
        if fila['Es_Funcionario'] == 1:
            predicciones.append('Bueno')
        elif fila['Tiene_Hipoteca'] == 1:
            predicciones.append('Malo')
        else:
            predicciones.append('Bueno')
    return predicciones
datos['Prediccion'] = predecir_arbol(datos)
confusion = pd.crosstab(datos['Clase'], datos['Prediccion'])
print(confusion)
fig, ax = plt.subplots(figsize=(6, 4))
ax.imshow(confusion.values, cmap='Blues')
ax.set_xticks([0, 1])
ax.set_xticklabels(['Predicho: Bueno', 'Predicho: Malo'])
ax.set_yticks([0, 1])
ax.set_yticklabels(['Real: Bueno', 'Real: Malo'])
ax.set_title('Matriz de Confusión')
for i in range(2):
    for j in range(2):
        ax.text(j, i, str(confusion.values[i, j]), ha='center', va='center')
plt.tight_layout()
mostrar_figura()

Lectura del caso C5

El árbol asigna 'Bueno' a los funcionarios y 'Malo' a los asalariados con hipoteca. Esta regla simple se visualiza en el scatter plot, donde los puntos se separan por color según la predicción.

Caso C6 — Cálculo de Entropía y Ganancia de Información

Extracto del temario

Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todos los ejemplos de un subconjunto pertenecen a la misma clase, la entropía es mínima, es decir, 0. Cuando el número de ejemplos está equitativamente distribuido entre las diferentes clases, la entropía es máxima, es decir, 1. La entropía se usa para determinar la ganancia de información cuando se divide el conjunto de datos según un atributo. El atributo que lleve a una ganancia de información mayor será aquel que se utilizará para discriminar entre los ejemplos de entrenamiento. La fórmula de ganancia de información IG para un atributo a es: Donde: ▸ son los subconjuntos de ejemplos de entrenamiento originados de discriminar el set original en base al

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1

Para construir el árbol, necesitamos saber qué atributo dividir primero. Usaremos la Entropía para medir la impureza. Si un nodo tiene solo 'Buenos', la entropía es 0 (pura). Si tiene 50/50, es 1 (máxima impureza). Calcularemos la ganancia de información para ver qué atributo reduce más la incertidumbre.

Puntos de ejecución

  • Punto 17 — A
  • Punto 18 — B
  • Punto 19 — C
In [ ]:
# Punto 17 — C6 · A
# C6 · A — tipo gráfico #15
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1
# Extracto: Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todos los ejemplos de un
np.random.seed(36)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C6):", "Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todo")
labels=["base","+ingreso","+extra","-coste","-riesgo","final"]
deltas=np.array([10,4,2,-3,-1,0.0]); deltas[-1]=deltas[:-1].sum()
fig,ax=plt.subplots(figsize=(8,4))
colors=["#888" if i==0 or i==len(deltas)-1 else ("#2ca02c" if d>=0 else "#ff3b00") for i,d in enumerate(deltas)]
# barras flotantes
starts=np.zeros(len(deltas)); starts[1:-1]=np.cumsum(deltas[:-1])[:-1]; starts[-1]=0
ax.bar(labels,deltas,bottom=starts,color=colors,edgecolor="#333")
ax.axhline(0,color="#333",lw=0.8); ax.set_title("C6 A: waterfall")
plt.tight_layout(); mostrar_figura(); print("deltas:", deltas.round(2))

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 18 — C6 · B
# C6 · B — tipo gráfico #16
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1
# Extracto: Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todos los ejemplos de un
np.random.seed(53)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C6):", "Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todo")
x=np.arange(25); y=np.random.randn(25)*1.5; y[::5]+=3
fig,ax=plt.subplots(figsize=(8,3.8))
ax.stem(x,y,linefmt="#1f77b4",markerfmt="o",basefmt="k-")
ax.set_title("C6 B: stem / impulsos")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 19 — C6 · C
# C6 · C — tipo gráfico #17
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1
# Extracto: Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todos los ejemplos de un
np.random.seed(70)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C6):", "Ideas clave ▸ es el conjunto de clases del problema. ▸ es la proporción de ejemplos de entrenamiento que pertenecen a la clase . Cuando todo")
t=np.linspace(0,8,120)
antes=np.sin(t)+np.random.normal(0,0.15,len(t))
despues=1.3*np.sin(t*1.1)+0.2+np.random.normal(0,0.25,len(t))
fig,axes=plt.subplots(1,2,figsize=(11,3.6),sharey=True)
axes[0].plot(t,antes,color="#1f77b4"); axes[0].set_title("Antes")
axes[1].plot(t,despues,color="#ff3b00"); axes[1].set_title("Después")
for ax in axes: ax.set_xlabel("t"); ax.grid(True,alpha=0.3)
fig.suptitle("C6 C: antes/después")
plt.tight_layout(); mostrar_figura()
print("Aula: ¿qué cambia según el extracto del temario?")

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 20, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")

Lectura del caso C6

La ganancia de información nos dice cuánto reduce la incertidumbre un atributo. El atributo con mayor ganancia se elige para dividir el nodo raíz.

Caso C7 — Entropía Condicional y Subconjuntos

Extracto del temario

Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivienda. Ya que Vivienda tiene tres valores, tendremos tres subconjuntos con sus correspondientes entropías: , y . La entropía total es la entropía de cada uno multiplicada por la proporción de ejemplos de cada valor respecto al número de ejemplos antes de discriminar. Por ejemplo, hay solo un ejemplo de sobre un total de seis ejemplos, por lo que habrá que multiplicar por . Así pues, la entropía después de discriminar usando será: Calculemos las entropías individuales. Tenemos dos clases, bueno y malo, por lo que la entropía será la relación entre la proporción de ejemplos de una clase y la de ejemplos de la otra. En el caso de y , tod

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1

Al dividir el dataset por un atributo (ej. 'Vivienda' con 3 valores), obtenemos subconjuntos. Calculamos la entropía de cada subconjunto y la ponderamos por su tamaño. Esto nos da la entropía 'después de la división'. Cuanto menor sea esta entropía ponderada, mejor ha sido la división.

Puntos de ejecución

  • Punto 20 — A
  • Punto 21 — B
  • Punto 22 — C
In [ ]:
# Punto 20 — C7 · A
# C7 · A — tipo gráfico #0
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1
# Extracto: Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivienda. Ya que Vivienda
np.random.seed(41)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C7):", "Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivie")
n=160; x=np.random.gamma(2.5,1.1,n); y=0.6*x+np.random.normal(0,1,n)
g=np.random.choice(list("ABC"),n)
df=pd.DataFrame({"x":x,"y":y,"g":g})
fig,ax=plt.subplots(figsize=(7.5,4.4))
for lab,c in zip("ABC",["#ff3b00","#1f77b4","#2ca02c"]):
    s=df[df.g==lab]; ax.scatter(s.x,s.y,s=22,alpha=0.55,c=c,label=lab,edgecolors="none")
ax.set_title("C7 A: scatter — Ideas clave crear el nuevo nodo del árbol"); ax.legend(); plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 21 — C7 · B
# C7 · B — tipo gráfico #1
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1
# Extracto: Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivienda. Ya que Vivienda
np.random.seed(58)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C7):", "Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivie")
x=np.random.randn(800); y=x*0.4+np.random.randn(800)*0.8
fig,ax=plt.subplots(figsize=(7.2,4.5))
hb=ax.hexbin(x,y,gridsize=28,cmap="Oranges",mincnt=1)
fig.colorbar(hb,ax=ax,label="cuentas")
ax.set_title("C7 B: hexbin densidad")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 22 — C7 · C
# C7 · C — tipo gráfico #2
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1
# Extracto: Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivienda. Ya que Vivienda
np.random.seed(75)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C7):", "Ideas clave crear el nuevo nodo del árbol. Volvamos al ejemplo anterior, calculando la entropía después de discriminar por el atributo Vivie")
df=pd.DataFrame({"grupo":np.random.choice(["G1","G2","G3","G4"],220),
                 "valor":np.concatenate([np.random.normal(m,1.1,55) for m in (3,4,3.5,5)])})
fig,ax=plt.subplots(figsize=(7.5,4.2))
sns.violinplot(data=df,x="grupo",y="valor",inner="box",palette="Set2",ax=ax)
ax.set_title("C7 C: violin/box")
plt.tight_layout(); mostrar_figura(); print(df.groupby("grupo").valor.describe().round(2))

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 21, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")

Lectura del caso C7

La entropía ponderada es la media de las entropías de los hijos, pesada por su tamaño. Es el denominador clave para calcular la ganancia.

Caso C8 — Selección del Mejor Atributo (ID3)

Extracto del temario

Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos lo siguiente: ▸ = 0,66. ▸ = 0,79. ▸ = 0,81. ▸ = 0,54. Así pues, el atributo más adecuado será Contrato. Esto coincide con el árbol de decisión de ejemplo para el conjunto de entrenamiento que vimos antes; dicho árbol, de hecho, fue generado usando ID3. ID3 es un algoritmo heurístico, es decir, no garantiza que el árbol generado vaya a ser de tamaño mínimo ni en el número total de nodos ni en su profundidad. De todas formas la entropía es considerada una buena heurística porque de media se comporta bien, es fácil y rápida de calcular y, al estar basada en la estadística, es robusta al ruido. Aun así, como todo algoritmo ID3, tiene sus desventajas. Por

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1

Comparamos la ganancia de todos los atributos disponibles. El que tenga la mayor ganancia (menor entropía residual) se convierte en el nodo de división. En nuestro ejemplo, 'Contrato' podría ser el mejor atributo. Visualizaremos las ganancias de todos los atributos para tomar la decisión.

Puntos de ejecución

  • Punto 23 — A
  • Punto 24 — B
  • Punto 25 — C
In [ ]:
# Punto 23 — C8 · A
# C8 · A — tipo gráfico #3
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1
# Extracto: Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos lo siguiente: ▸ = 0
np.random.seed(46)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C8):", "Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos")
a=np.random.normal(0,1,300); b=np.random.normal(1.2,1.4,300)
fig,ax=plt.subplots(figsize=(7.5,4))
sns.histplot(a,kde=True,color="#1f77b4",stat="density",label="condición 1",ax=ax,alpha=0.45)
sns.histplot(b,kde=True,color="#ff3b00",stat="density",label="condición 2",ax=ax,alpha=0.45)
ax.legend(); ax.set_title("C8 A: hist+KDE")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 24 — C8 · B
# C8 · B — tipo gráfico #4
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1
# Extracto: Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos lo siguiente: ▸ = 0
np.random.seed(63)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C8):", "Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos")
cats=["A","B","C","D"]; p1=np.array([20,35,30,25]); p2=np.array([30,25,20,35]); p3=100-p1-p2
fig,ax=plt.subplots(figsize=(8,4))
ax.barh(cats,p1,color="#ff3b00",label="parte 1"); ax.barh(cats,p2,left=p1,color="#ffd400",label="parte 2")
ax.barh(cats,p3,left=p1+p2,color="#1f77b4",label="parte 3")
ax.set_xlabel("%"); ax.legend(loc="lower right"); ax.set_title("C8 B: stacked h-bar")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 25 — C8 · C
# C8 · C — tipo gráfico #5
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1
# Extracto: Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos lo siguiente: ▸ = 0
np.random.seed(80)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C8):", "Ideas clave Resumiendo, la entropía después de discriminar usando Vivienda será: Esto se repite para todos los atributos. Al final tendremos")
t=np.arange(40)
s1=np.cumsum(np.random.randn(40)*0.4+0.1)
s2=np.cumsum(np.random.randn(40)*0.5-0.05)
s3=np.cumsum(np.random.randn(40)*0.3+0.08)
fig,ax=plt.subplots(figsize=(8.5,4))
ax.plot(t,s1,lw=2,label="serie α"); ax.plot(t,s2,lw=2,label="serie β"); ax.plot(t,s3,lw=2,label="serie γ")
ax.fill_between(t,s1,s2,alpha=0.12,color="#888")
ax.legend(); ax.set_title("C8 C: series temporales")
ax.set_xlabel("t"); plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 22, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")

Lectura del caso C8

El algoritmo ID3 selecciona recursivamente el atributo con mayor ganancia. En este caso, 'Contrato' o 'Es_Funcionario' suelen ser los mejores predictores iniciales.

Caso C9 — Regresión Lineal: Prediciendo el Nivel del Embalse

Extracto del temario

Ideas clave 6.4. Regresión Hasta ahora hemos trabajado únicamente con clases discretas, pero otro problema común de aprendizaje supervisado es la regresión, en el que la salida es continua. Por ejemplo, si se quiere predecir el nivel de un embalse en función del nivel medio del último mes y las precipitaciones, una serie de clases discretas no basta. Consecuentemente, los métodos de regresión han de dar un valor numérico como salida, en vez de limitarse a elegir entre un rango finito de valores. Regresión Lineal La regresión lineal fue el primer método estadístico para regresión en ser estudiado de forma seria. La regresión lineal consiste en encontrar una función lineal lo más cercana posible a la función real del modelo. La siguiente figura muestra un ejemplo de regresión lineal sobre un

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 24, párr. 1

El primer paso para entender el aprendizaje supervisado es reconocer que no siempre la respuesta es un 'Sí' o un 'No'. A veces, necesitamos un número exacto. La regresión lineal busca la recta que mejor se ajusta a los datos históricos. En nuestro contexto bancario, esto podría servir para predecir el importe exacto de un préstamo que un cliente puede pagar sin impagar, basado en su salario. Aquí, el objetivo es minimizar la distancia vertical entre los puntos reales y la línea predicha.

Puntos de ejecución

  • Punto 26 — A
  • Punto 27 — B
  • Punto 28 — C
In [ ]:
# Punto 26 — C9 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_puntos = 50
x = np.linspace(0, 10, n_puntos)
y_real = 2.5 * x + 10
y_ruido = y_real + np.random.normal(0, 5, n_puntos)
coeficientes = np.polyfit(x, y_ruido, 1)
y_predicha = np.poly1d(coeficientes)(x)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(x, y_ruido, color='#0057b7', alpha=0.6, label='Datos Históricos')
ax.plot(x, y_predicha, color='#ff3b00', linewidth=2, label='Ajuste Lineal')
ax.set_title('Regresión Lineal: Predicción Continua')
ax.set_xlabel('Variable Independiente (ej. Ingresos)')
ax.set_ylabel('Variable Dependiente (ej. Importe Préstamo)')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 27 — C9 · B
# C9 · B — tipo gráfico #7
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 24, párr. 1
# Extracto: Ideas clave 6.4. Regresión Hasta ahora hemos trabajado únicamente con clases discretas, pero otro problema común de aprendizaje supervisado es la regresión, en 
np.random.seed(68)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C9):", "Ideas clave 6.4. Regresión Hasta ahora hemos trabajado únicamente con clases discretas, pero otro problema común de aprendizaje supervisado ")
cols=["f1","f2","f3","f4","f5"]
M=np.random.randn(5,5); M=(M+M.T)/2; np.fill_diagonal(M,1)
fig,ax=plt.subplots(figsize=(5.5,4.5))
sns.heatmap(M,annot=True,fmt=".2f",cmap="coolwarm",xticklabels=cols,yticklabels=cols,ax=ax,vmin=-1,vmax=1)
ax.set_title("C9 B: heatmap")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 24, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 28 — C9 · C
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_puntos = 50
x = np.linspace(0, 10, n_puntos)
y_real = 2.5 * x + 10
y_ruido = y_real + np.random.normal(0, 5, n_puntos)
coeficientes = np.polyfit(x, y_ruido, 1)
y_predicha = np.poly1d(coeficientes)(x)
fig, ax = plt.subplots(figsize=(8, 4.2))
ax.scatter(x, y_ruido, color='#0057b7', alpha=0.6, label='Datos')
ax.plot(x, y_predicha, color='#ff3b00', linewidth=2, label='Predicción')
nuevo_x = 7.5
nuevo_y = np.poly1d(coeficientes)(nuevo_x)
ax.plot(nuevo_x, nuevo_y, 'go', markersize=15, label=f'Predicción para x={nuevo_x}')
ax.set_title('Proyección de un Nuevo Caso')
ax.set_xlabel('Variable Independiente')
ax.set_ylabel('Variable Dependiente')
ax.legend()
plt.tight_layout()
mostrar_figura()

Lectura del caso C9

La regresión nos da una estimación numérica. Sin embargo, en el banco, a menudo necesitamos una decisión binaria: ¿Aprobar o Rechazar? Para ello, debemos cambiar de paradigma hacia la clasificación.

Caso C10 — Árboles de Decisión: Lógica de Ramificación

Extracto del temario

Entrenamientos Desarrollo paso a paso ▸ Respuesta a la pregunta 1: en los nodos del árbol se indica un nombre de un atributo, que es el que en ese nodo es comprobado (salvo si es un nodo hoja). A partir de un nodo que no es nodo hoja sale una serie de ramas que corresponden a cada uno de los posibles valores que puede tomar el atributo que se comprueba en el nodo. ▸ Respuesta a la pregunta 2: los valores indicados en las hojas del árbol corresponden a un valor de la clase (el valor que se pretende predecir). En este caso, la clase o el valor indicado en la hoja será el valor del tipo de cristal que corresponderá a la instancia que cumpla con las condiciones de la rama del árbol que alcanza dicha hoja. ▸ Respuesta a la pregunta 3: siguiendo la rama tal que IndiceRefraccion=bajo, Magnesio=no

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 30, párr. 1

Un árbol de decisión es una herramienta visual y lógica poderosa. Funciona dividiendo los datos en subconjuntos más homogéneos mediante preguntas sucesivas. Cada nodo interno representa una pregunta sobre una característica (atributo), y cada rama es la respuesta. Las hojas contienen la predicción final. En el contexto de 'Crédito Seguro', un nodo podría preguntar '¿Ingresos > 2000?'. Si la respuesta es sí, seguimos por una rama; si no, por otra. Esto permite crear reglas de negocio interpretables.

Puntos de ejecución

  • Punto 29 — A
  • Punto 30 — B
  • Punto 31 — C
In [ ]:
# Punto 29 — C10 · A
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_clientes = 20
edad = np.random.randint(20, 60, n_clientes).astype(float)
ingresos = np.random.randint(1000, 5000, n_clientes).astype(float)
calificacion = np.where((ingresos > 2500) & (edad > 30), 'Aprobar', 'Rechazar')
fig, ax = plt.subplots(figsize=(8, 4.2))
aprobar_idx = np.where(calificacion == 'Aprobar')[0]
rechazar_idx = np.where(calificacion == 'Rechazar')[0]
ax.scatter(edad[aprobar_idx], ingresos[aprobar_idx], color='#28a745', label='Aprobar', marker='o')
ax.scatter(edad[rechazar_idx], ingresos[rechazar_idx], color='#dc3545', label='Rechazar', marker='x')
ax.axvline(30, color='black', linestyle='--', label='Corte Edad=30')
ax.axhline(2500, color='black', linestyle='--', label='Corte Ingresos=2500')
ax.set_title('Árbol de Decisión: División del Espacio')
ax.set_xlabel('Edad')
ax.set_ylabel('Ingresos Mensuales')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 30 — C10 · B
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_clientes = 20
edad = np.random.randint(20, 60, n_clientes).astype(float)
ingresos = np.random.randint(1000, 5000, n_clientes).astype(float)
calificacion = np.where((ingresos > 2500) & (edad > 30), 'Aprobar', 'Rechazar')
fig, ax = plt.subplots(figsize=(8, 4.2))
aprobar_idx = np.where(calificacion == 'Aprobar')[0]
rechazar_idx = np.where(calificacion == 'Rechazar')[0]
ax.scatter(edad[aprobar_idx], ingresos[aprobar_idx], color='#28a745', label='Aprobar', marker='o')
ax.scatter(edad[rechazar_idx], ingresos[rechazar_idx], color='#dc3545', label='Rechazar', marker='x')
ax.axvline(30, color='black', linestyle='--', label='Corte Edad=30')
ax.axhline(2500, color='black', linestyle='--', label='Corte Ingresos=2500')
ax.set_title('Árbol de Decisión: División del Espacio')
ax.set_xlabel('Edad')
ax.set_ylabel('Ingresos Mensuales')
ax.legend()
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 31 — C10 · C
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
n_clientes = 20
edad = np.random.randint(20, 60, n_clientes).astype(float)
ingresos = np.random.randint(1000, 5000, n_clientes).astype(float)
calificacion = np.where((ingresos > 2500) & (edad > 30), 'Aprobar', 'Rechazar')
fig, ax = plt.subplots(figsize=(8, 4.2))
aprobar_idx = np.where(calificacion == 'Aprobar')[0]
rechazar_idx = np.where(calificacion == 'Rechazar')[0]
ax.scatter(edad[aprobar_idx], ingresos[aprobar_idx], color='#28a745', label='Aprobar', marker='o')
ax.scatter(edad[rechazar_idx], ingresos[rechazar_idx], color='#dc3545', label='Rechazar', marker='x')
ax.axvline(30, color='black', linestyle='--', label='Corte Edad=30')
ax.axhline(2500, color='black', linestyle='--', label='Corte Ingresos=2500')
ax.set_title('Árbol de Decisión: División del Espacio')
ax.set_xlabel('Edad')
ax.set_ylabel('Ingresos Mensuales')
ax.legend()
plt.tight_layout()
mostrar_figura()

Lectura del caso C10

El árbol nos da reglas claras: 'Si Ingresos > 2500 Y Edad > 30, entonces Aprobar'. Esta transparencia es vital para la auditoría, pero debemos verificar si estas reglas generalizan bien o solo memorizan el ruido.

Caso C11 — Matriz de Confusión: Evaluando el Error

Extracto del temario

Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la clase Vajilla a partir de los datos de la matriz. ▸ Pregunta 6: calcula la tasa de error del modelo a partir de los datos de la matriz. ▸ Pregunta 7: con base en estos cálculos, ¿qué se puede decir a grandes rasgos sobre la bondad del modelo generado? Desarrollo paso a paso ▸ Respuesta a la pregunta 1: para interpretar la matriz de confusión debemos tener en cuenta la cabecera indicada en la fila, que corresponde a la clase real, y en la columna, que corresponde a la clase predicha. Por tanto, la primera fila corresponde a la clase real Flotante. Las instancias correctamente clasificadas serán las que están en la diagonal de la matriz, puesto que la clase real coincide con la predicha. Todas las que están fuera de

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1

La precisión global puede ser engañosa. Una matriz de confusión desglosa los aciertos y errores por clase. Nos muestra Verdaderos Positivos (VP), Falsos Positivos (FP), Verdaderos Negativos (VN) y Falsos Negativos (FN). En el banco, un FP (aprobar a un mal pagador) es mucho más costoso que un FN (rechazar a un buen pagador). Calcular la Tasa de Verdaderos Positivos (Sensibilidad) y la Tasa de Error total nos da una visión realista del rendimiento.

Puntos de ejecución

  • Punto 32 — A
  • Punto 33 — B
  • Punto 34 — C
In [ ]:
# Punto 32 — C11 · A
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
clases = ['Aprobar', 'Rechazar']
n_total = 100
y_real = np.random.choice(clases, n_total)
y_pred = np.where((y_real == 'Aprobar') & (np.random.rand(n_total) > 0.2), 'Aprobar', 'Rechazar')
y_pred = np.where((y_real == 'Rechazar') & (np.random.rand(n_total) > 0.8), 'Aprobar', y_pred)
matriz = pd.crosstab(y_real, y_pred, margins=True)
fig, ax = plt.subplots(figsize=(8, 4.2))
sns.heatmap(matriz.iloc[:-1, :-1], annot=True, fmt='d', cmap='Blues', ax=ax)
ax.set_title('Matriz de Confusión: Aprobación de Préstamos')
ax.set_xlabel('Clase Predicha')
ax.set_ylabel('Clase Real')
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 33 — C11 · B
# C11 · B — tipo gráfico #13
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1
# Extracto: Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la clase Vajilla a partir de los datos de la matriz. ▸ Pregunta 6: calcula la tasa de 
np.random.seed(78)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C11):", "Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la clase Vajilla a partir de los datos de la matriz. ▸ Pregunta 6:")
x=np.linspace(0,10,60)+np.random.normal(0,0.3,60)
y=1.6*x+np.random.normal(0,2.0,60)
coef=np.polyfit(x,y,1); xx=np.linspace(x.min(),x.max(),100)
fig,ax=plt.subplots(figsize=(7.5,4.2))
ax.scatter(x,y,s=28,alpha=0.65,c="#1f77b4"); ax.plot(xx,coef[0]*xx+coef[1],color="#ff3b00",lw=2,label=f"y≈{coef[0]:.2f}x+{coef[1]:.2f}")
ax.legend(); ax.set_title("C11 B: ajuste lineal")
plt.tight_layout(); mostrar_figura(); print("R² approx:", round(1-np.sum((y-np.polyval(coef,x))**2)/np.sum((y-y.mean())**2),3))

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 34 — C11 · C
# C11 · C — tipo gráfico #14
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1
# Extracto: Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la clase Vajilla a partir de los datos de la matriz. ▸ Pregunta 6: calcula la tasa de 
np.random.seed(95)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C11):", "Entrenamientos ▸ Pregunta 5: calcula la tasa de verdaderos positivos para la clase Vajilla a partir de los datos de la matriz. ▸ Pregunta 6:")
df=pd.DataFrame(np.random.randn(90,3),columns=["u","v","w"])
df["w"]=df["u"]*0.5+df["w"]*0.5
fig,axes=plt.subplots(3,3,figsize=(8,8))
cols=df.columns
for i,a in enumerate(cols):
  for j,b in enumerate(cols):
    ax=axes[i,j]
    if i==j: ax.hist(df[a],bins=12,color="#ff3b00",alpha=0.75)
    else: ax.scatter(df[b],df[a],s=10,alpha=0.5,c="#1f77b4")
    if i==2: ax.set_xlabel(b)
    if j==0: ax.set_ylabel(a)
fig.suptitle("C11 C: matriz de relaciones")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 33, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")

Lectura del caso C11

La matriz de confusión nos permite ver dónde falla el modelo. Si la tasa de error es alta en la clase 'Aprobar', el banco está perdiendo dinero. Debemos ajustar el umbral de decisión para minimizar estos costos específicos.

Caso C12 — Interpretación de Errores y Costes

Extracto del temario

Entrenamientos Solución ▸ Respuesta a la pregunta 1: quince han sido incorrectamente clasificadas como de la clase Envase. ▸ Respuesta a la pregunta 2: 85. ▸ Respuesta a la pregunta 3: 54. ▸ Respuesta a la pregunta 4: . ▸ Respuesta a la pregunta 5: . ▸ Respuesta a la pregunta 6: . ▸ Respuesta a la pregunta 7: dependiendo del coste de los errores de clasificación, podría ser un modelo útil. Hay que tener en cuenta que se equivoca en casi un 20 % de las veces, según la tasa de error. Si el coste de cada equivocación es alto, podría no resultar un buen modelo. De cualquier manera, sí puede ser un soporte que ayude a tomar decisiones (siempre teniendo en cuenta el error que se podría dar). El modelo se comporta, además, de forma diferente para las distintas clases. Es capaz de reconocer mejor

Cita Teacher: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 35, párr. 1

Un modelo no es bueno ni malo por sí solo; depende del coste de sus errores. Si clasificamos mal a un cliente de 'Envase' como 'Vajilla', el coste puede ser bajo. Pero si clasificamos mal a un 'Malo Pagador' como 'Bueno Pagador', el coste es alto. Analizar las filas de la matriz de confusión nos dice qué clase es más difícil de predecir y si el modelo es útil para la toma de decisiones bajo incertidumbre.

Puntos de ejecución

  • Punto 35 — A
  • Punto 36 — B
  • Punto 37 — C
In [ ]:
# Punto 35 — C12 · A
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
clases = ['Aprobar', 'Rechazar']
n_total = 100
y_real = np.random.choice(clases, n_total)
y_pred = np.where((y_real == 'Aprobar') & (np.random.rand(n_total) > 0.2), 'Aprobar', 'Rechazar')
y_pred = np.where((y_real == 'Rechazar') & (np.random.rand(n_total) > 0.8), 'Aprobar', y_pred)
matriz = pd.crosstab(y_real, y_pred, margins=True)
fig, ax = plt.subplots(figsize=(8, 4.2))
sns.heatmap(matriz.iloc[:-1, :-1], annot=True, fmt='d', cmap='Blues', ax=ax)
ax.set_title('Matriz de Confusión: Detalle de Errores')
ax.set_xlabel('Clase Predicha')
ax.set_ylabel('Clase Real')
plt.tight_layout()
mostrar_figura()
In [ ]:
# Punto 36 — C12 · B
# C12 · B — tipo gráfico #16
# Cita: PDF/Tema: Tema 6. Aprendizaje supervisado, p. 35, párr. 1
# Extracto: Entrenamientos Solución ▸ Respuesta a la pregunta 1: quince han sido incorrectamente clasificadas como de la clase Envase. ▸ Respuesta a la pregunta 2: 85. ▸ Re
np.random.seed(83)
print("Escenario:", "Imaginemos que estamos en la sala de reuniones de un banco regional, Crédito Seguro S.A., justo antes de lanzar una nueva campaña de préstamos personales. El equipo de datos, liderado por Ana, una analista senior, y el director de riesgos, Carlos, tienen una misión crítica: construir un sistema automatizado que decida si un solicitante es un buen pagador o un malo pagador. No se trata de adivinar, sino de aprender de los datos históricos de los últimos cinco años. La premisa es clara: si en los datos pasados vemos que cuando llueve (una metáfora de condiciones económicas adversas) la humedad (el riesgo de impago) es alta, el sistema debe aprender esa correlación para predecir el futuro. Sin embargo, el desafío no es solo encontrar patrones, sino encontrar los patrones correctos que generalicen a nuevos clientes que aún no conocemos.\n\nEl conflicto surge cuando el equipo presenta los primeros modelos. Ana muestra gráficos donde la precisión en los datos de entrenamiento es del 100%, pero la precisión en un conjunto de prueba independiente cae al 60%. Carlos, escéptico, pregunta: ¿Estamos aprendiendo el problema o estamos memorizando los exámenes de años anteriores?. Aquí entra en juego el concepto de sobreajuste (overfitting). Si el modelo se vuelve demasiado complejo, captando el ruido de los datos específicos de entrenamiento en lugar de la señal general, fallará en la vida real. La decisión que deben tomar no es técnica, sino estratégica: ¿cuánta complejidad es demasiado? Deben detener el aprendizaje en el punto exacto donde el error de validación comienza a subir, aunque el error de entrenamiento siga bajando.\n\nFinalmente, la sesión se centra en la clasificación binaria como el caso de uso más común y crítico. No basta con predecir un número; el banco necesita una etiqueta discreta: Aprobar o Rechazar. Cada atributo del cliente, desde su edad hasta su historial crediticio, es una entrada que debe ser normalizada y seleccionada cuidadosamente. Si los atributos son demasiado generales, el modelo no discrimina; si son demasiado particulares, el modelo se rompe con la escasez de datos. El objetivo de esta clase es desglosar cómo se construye, valida y depura este sistema de decisión, transformando datos crudos en una función de predicción robusta, legible y, sobre todo, confiable para la toma de decisiones financieras.")
print("Idea (C12):", "Entrenamientos Solución ▸ Respuesta a la pregunta 1: quince han sido incorrectamente clasificadas como de la clase Envase. ▸ Respuesta a la ")
x=np.arange(25); y=np.random.randn(25)*1.5; y[::5]+=3
fig,ax=plt.subplots(figsize=(8,3.8))
ax.stem(x,y,linefmt="#1f77b4",markerfmt="o",basefmt="k-")
ax.set_title("C12 B: stem / impulsos")
plt.tight_layout(); mostrar_figura()

print("Cita:", "PDF/Tema: Tema 6. Aprendizaje supervisado, p. 35, párr. 1")
print("Aula: relaciona ESTE tipo de gráfico con el extracto del temario.")
In [ ]:
# Punto 37 — C12 · C
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
clases = ['Aprobar', 'Rechazar']
n_total = 100
y_real = np.random.choice(clases, n_total)
y_pred = np.where((y_real == 'Aprobar') & (np.random.rand(n_total) > 0.2), 'Aprobar', 'Rechazar')
y_pred = np.where((y_real == 'Rechazar') & (np.random.rand(n_total) > 0.8), 'Aprobar', y_pred)
matriz = pd.crosstab(y_real, y_pred, margins=True)
fig, ax = plt.subplots(figsize=(8, 4.2))
sns.heatmap(matriz.iloc[:-1, :-1], annot=True, fmt='d', cmap='Blues', ax=ax)
ax.set_title('Matriz de Confusión: Detalle de Errores')
ax.set_xlabel('Clase Predicha')
ax.set_ylabel('Clase Real')
plt.tight_layout()
mostrar_figura()

Lectura del caso C12

El modelo tiene un error del ~20%. Si el coste de un error es alto, este modelo no es suficiente por sí solo. Debe ser un soporte para la decisión humana, no un reemplazo automático, especialmente en las clases donde la tasa de error es mayor.

El aprendizaje supervisado no es magia, es estadística aplicada con rigor. Hemos visto que:

  1. Mapear requiere datos etiquetados y una función que generalice.
  2. Validar es obligatorio: sin un conjunto de test, no sabemos si el modelo funciona o memoriza.
  3. Regularizar significa detener el aprendizaje antes del sobreajuste, equilibrando sesgo y varianza.
  4. Clasificar implica normalizar entradas y definir umbrales claros para decisiones discretas.

La clave del éxito no está en el algoritmo más complejo, sino en la calidad de los datos y la honestidad de la validación.

In [ ]:
# Síntesis numérica del escenario (agnóstica)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(7)
df = pd.DataFrame({
    "caso": ["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C11", "C12"],
    "peso": np.random.uniform(0.4, 1.0, 12),
})
print(df.to_string(index=False))
fig, ax = plt.subplots(figsize=(9, 3.8))
ax.bar(df["caso"], df["peso"], color="#ff3b00", alpha=0.85)
ax.set_title("Síntesis: peso relativo de cada caso del temario en el escenario")
ax.set_ylabel("peso")
plt.tight_layout()
mostrar_figura()

Para la próxima sesión, preparen un pequeño dataset simulado con 3 atributos y una clase binaria. Intenten visualizar la separación de clases y piensen qué atributos serían 'demasiado particulares' para un modelo real. La precisión sin generalización es inútil.