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
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_ROOT2.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é es | Librería (paquete Python instalable) | Entrypoints ejecutables (CLI) |
| Contiene | Componentes reutilizables, clases, funciones puras | Orquestación: parseo de argumentos, main(), efectos secundarios |
| Se ejecuta directo | No (se importa) | Sí (python scripts/pipeline/...) |
| Ejemplo | CornDataset, MODEL_REGISTRY, GradCAM | train_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.py—CornDataset(untorch.utils.data.Dataset), la derivación de clases minoritarias y elWeightedRandomSampler.splitter.py— el algoritmo de partición estratificada porclase+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.py—MODEL_REGISTRY, una tabla nombre→fábrica (patrón registry).baselines/*.py— cada archivo registra 1-3 arquitecturas. Al importarsrc.modelsse ejecutan losregister(...)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— descargaclean/desde Hugging Face Hub (fallback a Google Drive).upload_to_hf.py— subeclean/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:
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 exploratorioRegla 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:
| Componente | Criticidad | Por qué |
|---|---|---|
config/dataset.yaml | 🔴 Crítica | Fuente ú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ítica | Corazón de la carga de datos y del balanceo de clases. |
scripts/pipeline/train_baselines.py | 🔴 Crítica | El único pipeline de entrenamiento funcional hoy. |
scripts/pipeline/create_splits.py | 🔴 Crítica | Determinismo y validez de los datos de entrenamiento. |
src/models/registry.py + baselines/ | 🟠 Alta | Define qué arquitecturas existen y cómo se construyen. |
src/training/common.py | 🟠 Alta | Versionado de runs y consistencia entre pipelines. |
src/explainability/* | 🟡 Media | Importante para confianza/defensa, pero no bloquea entrenar. |
scripts/cleanup/* | ⚪ Baja | Histórico, de un solo uso. |
scripts/modal/* | ⚪ Baja | Conveniencia (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.