
Proyecto Laennec — Sesión 6: escuchar sonidos concretos, y todo el camino recorrido
En las cinco sesiones anteriores hemos medido nuestros modelos con números: exactitud, matriz de confusión, macro avg, weighted avg, validación cruzada. Hoy, en la última sesión del proyecto, cambiamos de perspectiva por completo: en vez de un porcentaje, vamos a coger sonidos concretos, escucharlos con nuestros propios oídos —como haría cualquier médico antes de tener un algoritmo al lado— y comprobar después qué dice el modelo de cada uno.
Nota práctica antes de empezar: si retomáis esta sesión otro día y el kernel se ha reiniciado, necesitaréis volver a tener disponibles carpeta_datos, la función extraer_caracteristicas de la Sesión 2, y los modelos arbol y bosque ya entrenados (Sesiones 2 y 4). Con un dataset tan pequeño como este, reentrenarlos de nuevo lleva solo unos segundos, así que no hace falta ningún truco especial de rendimiento — basta con volver a ejecutar esas celdas en orden.
Vuestro turno primero: escuchad antes de preguntar al modelo
Igual que en la Sesión 1 escuchasteis un latido normal y uno con murmullo uno junto al otro, hoy vamos a elegir tres sonidos —uno de cada clase— y escucharlos con calma antes de decir nada sobre lo que hace el modelo.
import glob
from IPython.display import Audio
# Elegimos un sonido de cada clase, distinto de los que ya escuchamos en la Sesión 1
sonido_normal = glob.glob(carpeta_datos + "set_b/normal_*.wav")[-1]
sonido_murmullo = glob.glob(carpeta_datos + "set_b/murmur_*.wav")[-1]
sonido_extrasistole = glob.glob(carpeta_datos + "set_b/extrastole_*.wav")[-1]
Escuchad los tres, uno detrás de otro, y no sigáis leyendo hasta haber apuntado en un papel qué os parece cada uno:
Audio(sonido_normal)
Audio(sonido_murmullo)
Audio(sonido_extrasistole)
[COMPLETAR EN CLASE: para cada uno de los tres sonidos, escribid si os parece normal, murmullo o extrasístole, antes de seguir. No hace falta que acertéis los tres — lo interesante es fijarse en cuál os cuesta más decidir]

Pidiendo la predicción al modelo
Con vuestras respuestas ya escritas, convertimos estos tres sonidos en números —igual que en la Sesión 2— y se los pasamos al Random Forest de la Sesión 4:
sonidos_elegidos = [sonido_normal, sonido_murmullo, sonido_extrasistole]
caracteristicas_elegidas = [extraer_caracteristicas(ruta) for ruta in sonidos_elegidos]
predicciones_elegidas = bosque.predict(caracteristicas_elegidas)
print(predicciones_elegidas)
Y, como aprendimos en la Sesión 4, podemos pedirle también con cuánta seguridad ha votado cada clase, no solo el resultado final:
probabilidades_elegidas = bosque.predict_proba(caracteristicas_elegidas)
print("Clases:", bosque.classes_)
print(probabilidades_elegidas)
Si para algún sonido los votos están muy repartidos entre dos clases, es la versión del bosque de “dudar” — igual que puede que hayáis dudado vosotros al escuchar alguno de los tres.

[COMPLETAR CON VUESTROS DATOS REALES: predicciones del bosque para los 3 sonidos = ___]
Si el bosque os predice “normal” para los tres sonidos, incluidos el murmullo y la extrasístole, no habéis hecho nada mal. Es la misma historia que ya vimos en la Sesión 4, llevada a su consecuencia más extrema: un Random Forest entrenado sin ningún ajuste especial para las clases minoritarias, cuando duda, tiende a apostar por la clase mayoritaria — aquí, normal. Podéis comprobarlo con datos, no solo de memoria, mirando cuántas veces predice cada clase el bosque sobre todo el conjunto de prueba:
import pandas as pd
predicciones_prueba = bosque.predict(X_prueba)
print(pd.Series(predicciones_prueba).value_counts())
Si extrasistole aparece cero veces (o casi) en ese recuento, confirma lo que ya intuíais: el modelo casi nunca se atreve a predecir la clase con menos ejemplos, por muy segura que estuviera “en teoría” de una extrasístole real cuando la vio en el conjunto de prueba de la Sesión 4. Es exactamente la razón por la que insistimos tanto, desde la Sesión 3, en mirar el macro avg y no solo la exactitud global: un modelo que casi siempre dice “normal” puede lucir una exactitud decente —acierta casi siempre con la clase mayoritaria— y aun así fallar de forma sistemática con las otras dos. Hoy, con solo tres sonidos concretos, esa limitación se nota de una forma mucho más directa que en ninguna tabla de números.
¿Acertasteis vosotros? ¿Acertó el modelo?
En este caso sabemos la clase real de cada sonido porque los elegimos nosotros mismos de cada carpeta:
clases_reales = ["normal", "murmullo", "extrasistole"]
print(clases_reales)
Comparad tres cosas para cada sonido: vuestra respuesta a oído, la predicción exacta del bosque, y la clase real. Prestad especial atención al sonido de extrasístole: es, con diferencia, el más importante de los tres — es la clase que más nos ha costado reconocer bien durante todo el proyecto, desde la Sesión 3.
[COMPLETAR EN CLASE: ¿acertasteis a oído con los tres? ¿Acertó el bosque? ¿Coincidió alguna vez vuestro error con el del modelo, o fallasteis en sonidos distintos?]

Una honestidad rápida sobre este ejercicio: no podemos garantizar al cien por cien que estos tres sonidos concretos formaran parte del conjunto de prueba de la Sesión 2 y no del de entrenamiento — al construir la tabla de características no guardamos ninguna columna con el nombre del archivo original, así que, una vez calculados los 13 MFCC, perdimos el rastro hasta el .wav de origen. Para lo que queremos comprobar hoy (si el modelo reconoce bien los tres tipos de sonido, con nosotros escuchando en paralelo) no es grave. Pero es una lección práctica real, útil para cualquier proyecto de datos futuro: conviene guardar siempre un identificador o el nombre de archivo junto a cada fila de una tabla, precisamente para poder rastrear cualquier resultado de vuelta hasta su origen.
Todo el camino recorrido
Empezamos este proyecto con una confesión, no con una pregunta de examen: después de terminar Taussig, José Luis reconoció que el proyecto que de verdad quería hacer desde el principio era este, el de los sonidos del corazón. Y empezamos con una pregunta real: ¿puede un modelo entrenado con grabaciones clínicas reales aprender a distinguir un latido normal de uno con un soplo o una extrasístole, algo que a los propios médicos les cuesta años de práctica?
Repasemos el camino, sesión por sesión:
- Sesión 1: conocimos el dataset —656 grabaciones reales de un ensayo clínico hospitalario— y a René Laennec, el médico que inventó el estetoscopio enrollando un cuaderno de papel. Escuchamos, por primera vez en toda la familia de proyectos, sonido real en el cuaderno, y descubrimos que la columna
fnamedel CSV no coincidía con los nombres reales de los archivos. - Sesión 2: aprendimos a convertir cada sonido en 13 números fijos con MFCC, sin importar cuánto durara el archivo, y entrenamos nuestro primer árbol de decisión — con una herramienta nueva,
train_test_splitconstratify=y, necesaria porque la extrasístole apenas tenía 46 ejemplos. - Sesión 3: descubrimos, con una matriz de confusión 3×3, que el desequilibrio entre clases también nos pasaba factura aquí, igual que en Taussig — y que la clase con menos datos no siempre coincide con la clase médicamente más grave.
- Sesión 4: pasamos del árbol al Random Forest, y descubrimos en qué coeficiente MFCC concreto se fijaba el bosque para distinguir un timbre de otro — el equivalente, para audio, de lo que en Taussig fue “en qué instante del latido”.
- Sesión 5: comprobamos con validación cruzada si podíamos fiarnos de nuestros resultados, y aprendimos a leer con cautela un modelo entrenado con una clase de apenas 46 ejemplos.
- Sesión 6 (hoy): escuchamos sonidos concretos con nuestros propios oídos, antes de preguntarle nada al modelo — el mismo gesto, en el fondo, que hizo Laennec en 1816 con su cilindro de papel.
Una respuesta honesta a la pregunta con la que empezamos
¿Hemos construido un ayudante de diagnóstico listo para un hospital? No. Nuestro modelo es un ejercicio educativo, entrenado con poco más de 400 sonidos etiquetados y sin ninguna validación clínica. Pero sí hemos tocado, con herramientas reales de ciencia de datos, el mismo principio que hace doscientos años empezó con un cuaderno de papel enrollado: que escuchar mejor —ya sea con un oído entrenado o con un puñado de coeficientes MFCC— puede ayudar a detectar antes un problema de corazón. Laennec no tenía datos ni Random Forest, solo curiosidad y un tubo de papel. Nosotros hemos tenido ambas cosas, y con eso hemos llegado un poco más lejos en la misma dirección que él empezó a abrir.



