
Proyecto Taussig — Sesión 5: validación cruzada, y una pregunta incómoda sobre nuestros propios datos
Desde la Sesión 2 hemos trabajado siempre con la misma partición: mitbih_train.csv para entrenar, mitbih_test.csv para examinar. Con esa única partición hemos entrenado un árbol, calculado su exactitud, leído su matriz de confusión de 5×5 y comparado árbol contra Random Forest. Aquí, a diferencia de Javierre, no es un problema de pocos pacientes — tenemos más de 100.000 latidos. Pero eso no nos libra de la pregunta de fondo: ¿y si mitbih_test.csv en concreto nos está dando una imagen demasiado favorable (o demasiado dura) de nuestros modelos?
Cerramos esta parte del proyecto con la misma herramienta que ya usamos para cerrar CUTLER y Javierre: la validación cruzada.
Un examen no es suficiente, aunque tenga muchas preguntas
En CUTLER y Javierre, el riesgo era tener pocos pacientes de examen. Aquí el riesgo es distinto: mitbih_test.csv es un único conjunto fijo, publicado una sola vez por quien creó el dataset. Aunque tenga casi 22.000 latidos, sigue siendo un solo examen. La validación cruzada nos deja comprobar, usando solo los datos de entrenamiento (sin tocar mitbih_test.csv en ningún momento), si nuestros modelos se comportan de forma parecida sin importar qué latidos de entrenamiento les toquen para aprender y cuáles para el mini-examen interno.
Validación cruzada en 5 particiones (k-fold)
El procedimiento es el mismo que ya conocéis: se divide X_entrenamiento en 5 partes. Se entrena con 4 de esas partes y se examina con la que queda fuera; se repite 5 veces, cambiando cada vez cuál es la parte de examen. Al final tenemos 5 exactitudes distintas, y las promediamos.
from sklearn.model_selection import cross_val_score
# Validación cruzada de 5 particiones, con el árbol de la Sesión 2
puntuaciones_arbol = cross_val_score(arbol, X_entrenamiento, y_entrenamiento, cv=5)
print("Exactitudes del árbol en cada partición:", puntuaciones_arbol)
print(f"Exactitud media del árbol: {puntuaciones_arbol.mean():.2%}")
# Lo mismo con el Random Forest de la Sesión 4
puntuaciones_bosque = cross_val_score(bosque, X_entrenamiento, y_entrenamiento, cv=5)
print("Exactitudes del bosque en cada partición:", puntuaciones_bosque)
print(f"Exactitud media del bosque: {puntuaciones_bosque.mean():.2%}")
Con más de 87.000 latidos de entrenamiento y 100 árboles en el bosque, esta celda puede tardar varios minutos en ejecutarse — es buen momento para levantarse a por agua mientras el ordenador trabaja.
[COMPLETAR CON VUESTROS DATOS REALES: exactitudes del árbol en las 5 particiones = ___ | media = ___. Exactitudes del bosque = ___ | media = ___]

Cómo leer estos cinco números
Miradlos de dos formas. Primero, la media: es una exactitud más fiable que la de un único examen, porque es el promedio de cinco exámenes distintos con latidos distintos cada vez. Segundo, comparad las 5 exactitudes entre sí: si son muy parecidas, el modelo se comporta de forma estable; si alguna se aleja bastante de las demás, merece la pena mirar qué tenía de particular esa partición.
Comparad también la media de la validación cruzada con la exactitud que obtuvisteis en la Sesión 2 (árbol) y en la Sesión 4 (bosque) sobre mitbih_test.csv. Si los números se parecen, esa partición de examen no os favoreció ni os perjudicó de forma especial.
Una pregunta incómoda que no podemos responder del todo
Hay algo que hay que decir con honestidad, aunque no tengamos manera de comprobarlo con lo que tenemos: ni mitbih_train.csv ni mitbih_test.csv nos dicen de qué paciente viene cada latido. Los 109.446 latidos se cortaron de las grabaciones continuas de un número mucho menor de pacientes reales del Beth Israel Hospital, y distintos artículos científicos que han revisado este dataset tan usado señalan una limitación real: si latidos del mismo paciente terminan repartidos entre entrenamiento y examen (o entre distintas particiones de la validación cruzada), el modelo podría estar aprendiendo rasgos concretos de ese paciente en vez de rasgos generales de la arritmia — y eso haría que la exactitud pareciera mejor de lo que sería con un paciente completamente nuevo.
No es un fallo nuestro ni algo que podamos arreglar con el código de hoy — es una limitación del propio dataset que hereda toda la literatura científica que lo usa. Lo importante es no olvidarla: un modelo que “acierta mucho” en este examen concreto no es necesariamente un modelo listo para un hospital de verdad, con pacientes que nunca ha visto.
Próximo paso
Con esto sabemos si podemos fiarnos de los números que hemos visto hasta ahora, o si dependían en parte de qué latidos concretos cayeron en cada partición. En la última sesión del proyecto vamos a poner a los modelos a prueba de otra forma más directa: coger latidos concretos —incluida, si es posible, alguna arritmia ventricular real— y comprobar, uno a uno, si el modelo los reconoce.




