Skip to content

2. Mapa completo del repositorio

Esta sección es el "GPS" del proyecto: qué contiene cada carpeta, qué responsabilidad tiene, de qué depende y cómo se relaciona con las demás. El análisis línea-por-línea de los archivos vive en Análisis detallado de código; aquí importa la topología.

2.1. Árbol del proyecto

text
corn-leaf-desease-project/
├── config/
│   └── dataset.yaml          # ⭐ Config central: clases, target_size, seed, perfil baseline, LIME, Grad-CAM
├── src/                      # ⭐ Librería instalable (pip install -e .). SIN entrypoints.
│   ├── config.py             # Rutas (get_dataset_root/get_output_root) + set_global_seed
│   ├── data/
│   │   ├── loader.py         # ÚNICO punto de entrada a imagen: EXIF + RGB
│   │   ├── dataset.py        # CornDataset + minoritarias + WeightedRandomSampler
│   │   ├── splitter.py       # Split estratificado jerárquico (clase+entorno)
│   │   └── transforms.py     # Pipelines de augmentation (train/minority/val) via Factory
│   ├── models/
│   │   ├── registry.py       # MODEL_REGISTRY (patrón registry)
│   │   ├── input_sizes.py    # Resolución nativa por modelo (excepciones)
│   │   └── baselines/        # 8 arquitecturas registradas (efficientnet, mobilenet, ...)
│   ├── training/
│   │   └── common.py         # Utilidades compartidas train.py ↔ train_baselines.py
│   ├── explainability/
│   │   ├── gradcam.py        # Grad-CAM con hooks nativos de PyTorch
│   │   ├── visual_report.py  # Reporte visual LIME (3 paneles) + Grad-CAM (4º panel)
│   │   └── augmentation_preview.py  # Evidencia visual de las augmentations
│   ├── analysis/
│   │   └── dataset_summary.py # Conteo de imágenes por clase/entorno
│   └── cleanup/
│       └── find_duplicates.py
├── scripts/                  # ⭐ Entrypoints ejecutables
│   ├── pipeline/
│   │   ├── create_splits.py       # clean/ → splits CSV
│   │   ├── train_baselines.py     # ⭐ Pipeline funcional de DL (entrenamiento completo)
│   │   ├── train.py               # Pipeline principal (loop PENDIENTE)
│   │   ├── explain_lime.py        # Reporte visual LIME+Grad-CAM
│   │   ├── explain_report.py      # Fidelidad agregada + análisis de errores
│   │   └── predict.py             # Predicción de una imagen suelta
│   ├── checks/
│   │   ├── smoke_loader.py        # Smoke test del pipeline de carga
│   │   └── lime_stability.py      # Auditoría de estabilidad de LIME
│   ├── cleanup/                   # ~25 scripts de limpieza por clase (uso único)
│   ├── dataset/                   # Descarga/subida de clean/ (HF Hub, Google Drive)
│   ├── modal/                     # Entrenamiento/explicabilidad en GPU de Modal
│   └── download_datasets.sh       # Ingesta de fuentes crudas → raw/
├── config/dataset.yaml
├── notebooks/01_eda.ipynb    # Análisis exploratorio de datos
├── docs/es/                  # Documentación VitePress existente del proyecto
├── reports/firts-phase/      # Reporte LaTeX de la primera fase
├── outputs/                  # (gitignored) Artefactos generados: splits, runs, reportes
├── Makefile                  # Comandos frecuentes (detecta Windows/Linux)
├── pyproject.toml            # Metadatos del paquete + dependencias
├── CLAUDE.md / AGENTS.md     # Instrucciones para agentes de IA
├── README.md / LOCAL.md      # Documentación humana + setup local
└── .env                      # (gitignored) DATASET_ROOT, OUTPUT_ROOT

2.2. La dualidad src/ vs scripts/

Es la separación arquitectónica más importante del proyecto, y conviene entenderla antes que nada:

src/scripts/
Qué esLibrería (paquete Python instalable)Entrypoints ejecutables (CLI)
ContieneComponentes reutilizables, clases, funciones purasOrquestación: parseo de argumentos, main(), efectos secundarios
Se ejecuta directoNo (se importa)Sí (python scripts/pipeline/...)
EjemploCornDataset, MODEL_REGISTRY, GradCAMtrain_baselines.py, create_splits.py

Por qué esta separación (justificación): permite que la misma lógica de datos y modelos sea consumida por ambos pipelines (train.py y train_baselines.py), por los scripts de explicabilidad, por predict.py y por los tests, sin duplicar código. Si CornDataset viviera dentro de train_baselines.py, no podrías reutilizarlo en predict.py sin copiar/pegar. Es la aplicación directa del principio DRY y de separación de responsabilidades.

Habilitador técnico: el paquete se instala en modo editable (pip install -e ., ver pyproject.toml). Eso hace que from src.data.dataset import CornDataset resuelva desde cualquier directorio sin sys.path.append. La regla del proyecto es explícita: nunca usar sys.path.append (ver CLAUDE.md).

2.3. Carpetas de src/ en detalle

src/data/ — la capa de datos

Responsabilidad: transformar rutas de disco en tensores listos para el modelo, de forma reproducible y robusta.

  • loader.py — el único lugar autorizado para abrir una imagen. Aplica corrección EXIF y fuerza RGB. Regla del proyecto: nadie más lee imágenes con PIL directamente.
  • dataset.pyCornDataset (un torch.utils.data.Dataset), la derivación de clases minoritarias y el WeightedRandomSampler.
  • splitter.py — el algoritmo de partición estratificada por clase+entorno.
  • transforms.py — las tuberías de augmentation, organizadas con el patrón Factory.

Dependencias: loader.py no depende de nada del proyecto (solo PIL). dataset.py depende de loader.py y de config.py. transforms.py depende de config.py. Es una capa de bajo acoplamiento.

src/models/ — el catálogo de arquitecturas

Responsabilidad: dar un nombre-string ("efficientnet_b0") y devolver un nn.Module listo, con su cabeza de clasificación adaptada a las 9 clases.

  • registry.pyMODEL_REGISTRY, una tabla nombre→fábrica (patrón registry).
  • baselines/*.py — cada archivo registra 1-3 arquitecturas. Al importar src.models se ejecutan los register(...) y el registry queda poblado.
  • input_sizes.py — declara excepciones de resolución (EfficientNet-B4 → 380, FastViT-T8 → 256); el resto usa 224.

src/training/ — utilidades transversales de entrenamiento

Un único archivo, common.py, con lo que comparten train.py y train_baselines.py: resolución de nombres de modelo, semilla de workers, selección de dispositivo, generación de run_id, versionado de runs y lectura de metadatos de un run (load_run_metadata).

src/explainability/ — interpretabilidad post-hoc

Responsabilidad: explicar por qué el modelo predijo lo que predijo, sin acoplarse al entrenamiento (se corre después, sobre checkpoints ya guardados).

  • gradcam.py — Grad-CAM con hooks de PyTorch.
  • visual_report.py — arma el PNG de 3 (o 4) paneles con LIME + Grad-CAM.
  • augmentation_preview.py — evidencia visual de qué le hacen las augmentations a cada clase.

src/analysis/ y src/cleanup/

Utilidades de apoyo: dataset_summary.py cuenta imágenes por clase/entorno; find_duplicates.py ayuda en la deduplicación durante la fase de limpieza.

2.4. Carpetas de scripts/ en detalle

scripts/pipeline/ — el corazón operativo

Los 6 entrypoints que ejecutas día a día. Relación entre ellos:

scripts/cleanup/ — limpieza de datos (histórico)

~25 scripts pequeños, organizados por clase (common_rust/, gray_leaf_spot/, ...). Cada uno resolvió un problema puntual de una fuente cruda concreta: renombrar, mover, deduplicar, reordenar imágenes para consolidarlas en la estructura clean/<clase>/{lab,real}/. Son de un solo uso: ya cumplieron su función al construir clean/. No forman parte del pipeline de entrenamiento y no se vuelven a correr. Su valor hoy es de trazabilidad (documentan cómo se construyó cada clase).

scripts/dataset/ — hosting del dataset

  • download_dataset.py — descarga clean/ desde Hugging Face Hub (fallback a Google Drive).
  • upload_to_hf.py — sube clean/ al Hub.

scripts/modal/ — cómputo en la nube

Ejecuta los mismos pipelines en GPU de Modal. _common.py define la imagen Docker y los Volumes compartidos; train.py y explain.py son wrappers que invocan los scripts locales dentro del contenedor remoto. La CLI es idéntica a la local.

scripts/checks/ — verificación

  • smoke_loader.py — prueba rápida de que el pipeline de carga funciona.
  • lime_stability.py — auditoría manual de cuán estable es una explicación LIME.

2.5. outputs/ — todo lo que el sistema produce

outputs/ está gitignored y contiene exclusivamente artefactos regenerables:

text
outputs/
├── splits/
│   ├── seed_42/            # splits de las 9 clases completas
│   └── seed_42_baseline/   # splits del perfil baseline (cap 1500/clase)
├── baselines/
│   └── <modelo>/
│       ├── latest.json     # puntero al run más reciente
│       └── <run_id>/       # p.ej. 20260709_040040/
│           ├── best.pth            # mejor checkpoint (por val macro-F1)
│           ├── last.pth            # último checkpoint
│           ├── summary.json        # ⭐ metadatos del run (mapeo de clases, hiperparámetros, métricas de test)
│           ├── predictions.csv     # predicción + confianza por imagen de test
│           ├── train_history.csv   # métricas por época
│           ├── test_confusion_matrix.csv
│           ├── test_classification_report.csv
│           ├── augmentation_preview/  # grids PNG de augmentations
│           ├── lime_visual/           # reportes LIME de la muestra pequeña
│           ├── lime_report/           # reportes de la muestra amplia
│           └── explain_report/        # summary de fidelidad agregada
└── eda/                    # figuras del análisis exploratorio

Regla de oro (de CLAUDE.md): todo lo que el pipeline consume (dataset fuente) se accede vía get_dataset_root(); todo lo que produce vía get_output_root(). Nunca se hardcodean rutas. Ver Configuración y rutas.

2.6. Nivel de importancia de cada componente

Para priorizar el estudio, esta es la criticidad de cada pieza dentro del sistema:

ComponenteCriticidadPor qué
config/dataset.yaml🔴 CríticaFuente única de verdad de dominio. Un cambio aquí afecta todo.
src/data/loader.py🔴 CríticaÚnico punto de entrada a imagen; garantiza consistencia train/eval/inferencia.
src/data/dataset.py🔴 CríticaCorazón de la carga de datos y del balanceo de clases.
scripts/pipeline/train_baselines.py🔴 CríticaEl único pipeline de entrenamiento funcional hoy.
scripts/pipeline/create_splits.py🔴 CríticaDeterminismo y validez de los datos de entrenamiento.
src/models/registry.py + baselines/🟠 AltaDefine qué arquitecturas existen y cómo se construyen.
src/training/common.py🟠 AltaVersionado de runs y consistencia entre pipelines.
src/explainability/*🟡 MediaImportante para confianza/defensa, pero no bloquea entrenar.
scripts/cleanup/*⚪ BajaHistórico, de un solo uso.
scripts/modal/*⚪ BajaConveniencia (nube); no cambia la lógica.
scripts/pipeline/train.py⚪ Baja (hoy)Esqueleto; su loop está pendiente.

Siguiente paso

Con el mapa claro, el recorrido natural es seguir una imagen a través de todo el sistema: Flujo completo del sistema.