CoolFace
Modelpublic

Jesusrodriguezf90/lgbm-diabetes-early-detection

sourceHugging Faceotherupdated 4mo agoView on Hugging Face
0likes
Model Card

LightGBM — Detección Temprana de Riesgo de Diabetes

Modelo de clasificación binaria para detección temprana de riesgo de diabetes desarrollado como Trabajo de Fin de Máster (TFM) en el Máster en Data Science de KSchool (2025–2026).

Pipeline sklearn completo: preprocesamiento determinista + ColumnTransformer + clasificador LightGBM, entrenado sobre 257.709 observaciones clínicas autorreportadas con 22 variables del cuestionario BRFSS 2015 (CDC).

Repositorio: TFM — GitHub Demo interactiva: diabetes-risk-demo — HF Spaces


Métricas

Resultados de validación cruzada estratificada (5 folds) sobre el conjunto de entrenamiento:

ModeloROC-AUC (CV media)PRC-AUC (CV media)ROC-AUC (CV std)
Random Forest0.8360.3780.0018
XGBoost0.8370.3840.0022
LightGBM ✓0.8390.3910.0017

Resultados sobre el conjunto de test (threshold=0.4733, F2-score óptimo en validación):

MétricaValor
ROC-AUC0.839
PRC-AUC0.391
Recall0.813
Precision0.256
LightGBM se seleccionó como modelo final por ofrecer el mejor equilibrio entre ROC-AUC, PRC-AUC y recall en un contexto clínico desbalanceado. El threshold de 0.4733 maximiza el F2-score en validación (β=2), priorizando el recall sobre la precisión — en cribado clínico un falso negativo tiene un coste sanitario mucho mayor que un falso positivo.

Matriz de confusión (test, threshold=0.4733)

Predicho: No riesgoPredicho: Riesgo
Real: No riesgo32.444 (TN)13.420 (FP)
Real: Riesgo1.063 (FN)4.615 (TP)

Uso

python
import sys
import types
import numpy as np
import pandas as pd
import joblib
from huggingface_hub import hf_hub_download

# 1. Registrar el módulo src — necesario para deserializar el pipeline
#    El pkl fue serializado con src.preprocessing.preprocessing_pipeline

BINARY_VARS = [
    "BPMEDS", "BLOODCHO", "HAVARTH3", "QLACTLM2", "USEEQUIP",
    "BLIND", "DECIDE", "DIFFWALK", "DIFFALON", "DIFFDRES",
    "SMOKE100", "ADDEPEV2", "SEX",
]
CATEGORICAL_NOMINAL = ["BPHIGH4", "_RACE"]

def boosting_deterministic_preproc(X_input):
    X = X_input.copy()
    X = X.replace(-1, np.nan)
    for col in BINARY_VARS:
        if col in X.columns:
            X[col] = (X[col] == 1).astype(int)
    for col in CATEGORICAL_NOMINAL:
        if col in X.columns:
            X[col] = X[col].astype("category")
    return X

def cap_outliers_numeric(X_input, numeric_vars):
    X = X_input.copy()
    for col in numeric_vars:
        low = np.nanpercentile(X[col], 1)
        high = np.nanpercentile(X[col], 99)
        X[col] = X[col].clip(low, high)
    return X

src_mod = types.ModuleType("src")
preprocessing_mod = types.ModuleType("src.preprocessing")
pipeline_mod = types.ModuleType("src.preprocessing.preprocessing_pipeline")
pipeline_mod.boosting_deterministic_preproc = boosting_deterministic_preproc
pipeline_mod.cap_outliers_numeric = cap_outliers_numeric
src_mod.preprocessing = preprocessing_mod
preprocessing_mod.preprocessing_pipeline = pipeline_mod
sys.modules.setdefault("src", src_mod)
sys.modules.setdefault("src.preprocessing", preprocessing_mod)
sys.modules.setdefault("src.preprocessing.preprocessing_pipeline", pipeline_mod)

# 2. Descargar y cargar el pipeline
ruta = hf_hub_download(
    repo_id="Jesusrodriguezf90/lgbm-diabetes-early-detection",
    filename="lgbm_diabetes_pipeline.pkl"
)
pipeline = joblib.load(ruta)

# 3. Preparar datos de entrada
#    X debe ser un DataFrame con las 22 variables del BRFSS 2015
#    en su codificación original (valores enteros según el codebook del CDC)
X = pd.DataFrame([{
    "GENHLTH": 3, "BPHIGH4": 3, "BPMEDS": 2, "BLOODCHO": 1,
    "HAVARTH3": 2, "ADDEPEV2": 2, "SEX": 1, "QLACTLM2": 2,
    "USEEQUIP": 2, "BLIND": 2, "DECIDE": 2, "DIFFWALK": 2,
    "DIFFDRES": 2, "DIFFALON": 2, "SMOKE100": 2, "EXEROFT1": 3.0,
    "_RACE": 1, "_AGEG5YR": 7, "_BMI5CAT": 2,
    "_FRUTSUM": 1.0, "_VEGESUM": 2.0, "_PACAT1": 2,
}])

# 4. Inferencia con threshold dinámico
proba = pipeline.predict_proba(X)[0][1]
threshold = 0.4733  # threshold por defecto — ajustable según contexto asistencial
decision = "Realizar prueba HbA1c" if proba >= threshold else "No realizar prueba HbA1c"

print(f"Probabilidad estimada de riesgo: {proba * 100:.1f}%")
print(f"Decisión (threshold={threshold}): {decision}")

Arquitectura y entrenamiento

Pipeline sklearn

El pipeline encapsula todas las transformaciones para garantizar ausencia de data leakage:

StepComponenteDescripción
1FunctionTransformerPreprocesamiento determinista: reemplaza -1 por NaN, normaliza binarias a 0/1, fuerza tipo category en nominales
2ColumnTransformerImputación (moda / mediana) + capping de outliers (P1-P99) + encoding nativo para boosting
3LGBMClassifierClasificador final con codificación nativa de categóricas

Selección de threshold

El threshold óptimo se determina maximizando el F2-score (β=2) sobre la curva Precision–Recall del conjunto de validación. Con β=2, el recall tiene cuatro veces más peso que la precisión — refleja el coste clínico asimétrico donde un falso negativo (diabetes no detectada) genera un coste estimado de ~2.817€/paciente/año, frente a ~30€ de una prueba HbA1c innecesaria.

El pipeline soporta threshold dinámico (rango 0.10–0.90) para que el profesional sanitario pueda ajustar la sensibilidad según la capacidad asistencial disponible.

Parámetros de entrenamiento

ParámetroValor
DatasetBRFSS 2015 (CDC)
Observaciones257.709
Variables de entrada22 (clínicas y demográficas)
Split60% train / 20% val / 20% test — estratificado
Tamaño conjunto test51.542 individuos
Validación cruzada5 folds estratificados sobre train
Desbalance clase positivaTratado con class_weight en LightGBM
Threshold por defecto0.4733 (F2-score óptimo en validación)
random_state42
HardwareGoogle Colab (CPU)

Interpretabilidad

El modelo incluye análisis de interpretabilidad con Feature Importance y SHAP (SHapley Additive exPlanations), que permite explicar tanto el comportamiento global del modelo como predicciones individuales.

Las variables con mayor influencia sobre el riesgo de diabetes identificadas por el modelo:

VariableImportanciaInterpretación clínica
_VEGESUM1143Total porciones de vegetales diarias
_FRUTSUM917Total porciones de frutas diarias
_AGEG5YR712Edad en grupos de 5 años
EXEROFT1617Frecuencia de ejercicio semanal
GENHLTH477Estado general de salud autorreportado
_BMI5CAT358Categoría de IMC

La demo interactiva incluye un gráfico SHAP waterfall individual que explica en tiempo real qué variables aumentaron o redujeron el riesgo para cada predicción concreta.


Limitaciones

  • —Entrenado sobre datos del BRFSS 2015 (población estadounidense) — puede no generalizar directamente a otras poblaciones sin recalibración
  • —Precision baja (0.256) con threshold=0.4733 — diseño deliberado para maximizar recall en cribado; genera falsos positivos asumibles dado el bajo coste de la prueba HbA1c confirmatoria
  • —Las 22 variables son autorreportadas — sujetas a sesgo de respuesta del encuestado
  • —El modelo es un apoyo al cribado y no reemplaza el diagnóstico médico; la decisión clínica final corresponde siempre al profesional sanitario
  • —Sin datos de seguimiento longitudinal — no predice progresión ni complicaciones

Dataset

BRFSS 2015 — Behavioral Risk Factor Surveillance System Centers for Disease Control and Prevention (CDC), Estados Unidos 🔗 CDC BRFSS 2015

  • —257.709 observaciones clínicas autorreportadas
  • —22 variables de entrada (hábitos de vida, condiciones médicas, datos demográficos)
  • —Variable objetivo: DIABETE3 — riesgo de diabetes (binaria: 1=sí, 3=no en codificación original CDC)
  • —Dataset procesado disponible en: Jesusrodriguezf90/brfss2015-diabetes-detection

Autor

Jesús Rodríguez Fernández — Data Scientist 🔗 LinkedIn · GitHub · HF Profile


Licencia

Uso no comercial. Dataset BRFSS 2015 de dominio público (CDC). Ver términos de uso del CDC para redistribución de datos derivados.