Predicción de pCR en BreastDCEDL

Pesos del modelo final de ML_PrediccionpCR. A partir de una resonancia de mama con contraste (DCE-MRI) tomada antes de la quimioterapia, el modelo estima la probabilidad de pCR, es decir, de que tras el tratamiento no quede tumor invasivo.

Uso educativo, sin validez clínica.

Qué es

  • CNN propia, entrenada desde cero, sin nada preentrenado: 3 bloques convolucionales de 8, 16 y 32 filtros. Trabaja a 128 px dentro de la red y tiene 18.329 parámetros.
  • Conjunto de 5 redes, una por fold de validación cruzada. La probabilidad de un corte es la media de las 5 sigmoides.
  • Umbral 0,3635, fijado en validación (pCR si la probabilidad es > 0,3635).
  • Entrada: un corte de 3 fases del contraste (PRE, EARLY, LATE, que no son RGB), cada una un PNG en gris de 256×256 dividido entre 255. La forma es (N, 3, 256, 256), float32, en [0, 1]. El resto del preprocesado (la reducción a 128 px) va dentro de la red.
  • Salida de cada red: un logit; la sigmoide da p(pCR).

Uso previsto y no previsto

  • Previsto: docencia e investigación. Sirve para estudiar el problema, reproducir los resultados y probar la web.
  • No previsto: cualquier uso clínico. No sirve para diagnosticar ni para decidir tratamientos, y no es un dispositivo médico. Un buen resultado retrospectivo no demostraría seguridad ni utilidad clínica, y este, además, no supera al azar en test.

Datos y partición

  • Dataset: BreastDCEDL (Fridman et al., 2025, arXiv:2506.12190). Está construido a partir de las colecciones públicas I-SPY1, I-SPY2 y Duke Breast Cancer MRI y tiene licencia CC BY-NC 4.0. Estos pesos derivan de él y se publican con la misma licencia, para uso no comercial y conservando la atribución.
  • Tamaño: 1.273 pacientes y 12.703 cortes; el 70,6 % son pCR=0.
    • Train: 1.097 pacientes (10.945 cortes).
    • Test: 176 pacientes (1.758 cortes).
  • Partición por paciente: ningún corte de una paciente aparece a la vez en entrenamiento y validación (5 folds) ni en train y test.
  • Test usado una sola vez, al final, con un plan fijado antes (pesos y su SHA-256, umbral y agregación). Nada se ajustó con él.

Resultados

  • Validación (5 folds): AUC medio de todas las épocas, 0,551 ± 0,011.
  • Test (evaluado una sola vez, por paciente, con la probabilidad media de sus cortes):
Métrica Valor
AUC 0,544 [IC 95 %: 0,457-0,629]
Sensibilidad 0,038
Especificidad 0,935

Matriz de confusión (176 pacientes):

Predicho pCR Predicho no pCR
pCR real VP 2 FN 51
No pCR real FP 8 VN 115

Los intervalos son bootstrap de pacientes (2.000 remuestreos). Fridman et al. 2025 obtienen 0,72 en el mismo test con un modelo preentrenado, así que no es comparable con una CNN desde cero. El detalle está en docs/decisiones.md.

Limitaciones

  • No se distingue del azar en test: el IC 95 % del AUC incluye 0,5. Con el umbral elegido, detecta 2 de las 53 pCR.
  • Un corte frente a un umbral por paciente: el umbral se eligió con la media de los cortes de cada paciente (unos 10). Aplicado a un solo corte, como en la web, la decisión es menos fiable.
  • EARLY saturado: en la zona que más realza, más de la mitad de los píxeles están a 255 en EARLY en el 63 % de los cortes de train. La magnitud del realce no está en la imagen. Es una limitación de los PNG de 8 bits del dataset, no de este modelo.
  • Diferencias entre cohortes: las tres cohortes se procesaron de forma distinta. En test, el AUC por cohorte va de 0,351 (I-SPY1, 35 pacientes) a 0,650 (Duke, 42).
  • TF32 frente a FP32: las cifras oficiales se calcularon en GPU con TF32, el valor por defecto de PyTorch. En FP32, como calculan la web y src.inferencia, las probabilidades cambian hasta ~7e-4.

Cómo cargarlos

La arquitectura está en el repositorio de GitHub (src/models/cnn.py). Con el repositorio clonado, desde su raíz:

import torch
from huggingface_hub import hf_hub_download
from src.models.cnn import cargar

REPO_HF = "Valdi183/ML_PrediccionpCR"
NOMBRES = ["it6_3bloques_f0", "it6_3bloques_f1", "it8_3bloques_f2",
           "it8_3bloques_f3", "it8_3bloques_f4"]
UMBRAL = 0.363489137

# cargar() usa torch.load(..., weights_only=True) y devuelve la red en modo evaluación
redes = [cargar(hf_hub_download(REPO_HF, f"{n}.pt"))[0] for n in NOMBRES]

x = torch.rand(1, 3, 256, 256)  # PRE, EARLY, LATE en [0, 1]
with torch.no_grad():
    prob = torch.stack([torch.sigmoid(r(x)) for r in redes]).mean().item()
print(prob, "pCR" if prob > UMBRAL else "no pCR")

Desde PNG reales: python -m src.inferencia --pre X_PRE.png --early X_EARLY.png --late X_LATE.png valida la entrada y comprueba el SHA-256 de cada peso.

Ficheros

Fichero Contenido SHA-256
it6_3bloques_f0.pt red del fold 0 f1eb794abdee19ae3c8308727741a1d3db2b53c27e8112b1d241d6728e671862
it6_3bloques_f1.pt red del fold 1 0c62d2e98b46ae493758c1670dbd56fcfd683d7e6f75074de00e02ff52e3a563
it8_3bloques_f2.pt red del fold 2 b58239fd676a4d9050524933589dd80fb3f56d178e5f6dec5e3b56df4f5e29c8
it8_3bloques_f3.pt red del fold 3 3c3826e3f1d07d3254b7ddf6a068c94e1ee24e791f04d981d38c9242afd47145
it8_3bloques_f4.pt red del fold 4 e2d184a2ea3275a958630c1481be64dd3c9d751ed8c20e8e0e1d97d4db7ff1f3
conjunto.onnx las 5 redes en un solo grafo (opset 17); devuelve prob (media) y por_modelo b6779db9769e1c62f61032dfec4c67215e862a0a4696fcd266f141382853413d

La fuente de verdad de los hashes de los .pt es results/test/plan.json; la del ONNX, web/modelo.json.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Paper for Valdi183/ML_PrediccionpCR