1. Resumen ejecutivo
1.1. Objetivo del proyecto
Doctor Maíz (corn-leaf-desease-project) es un sistema de clasificación de imágenes que, dada la fotografía de una hoja de maíz, identifica cuál de 9 condiciones presenta: enfermedades foliares, plagas o deficiencias nutricionales. El objetivo final es empaquetar el modelo ganador como un archivo TensorFlow Lite Int8 embebido en una app Android que funcione completamente offline.
El repositorio que documenta esta guía es el componente de Machine Learning del proyecto: la ingesta y limpieza de datos, la construcción de splits reproducibles, el entrenamiento y comparación de arquitecturas baseline, la evaluación y la explicabilidad post-hoc (LIME + Grad-CAM). La app Android y la exportación a TFLite todavía no están implementadas en este repo.
1.2. Problema que resuelve
| Dato del contexto | Implicación |
|---|---|
| El maíz es alimento crítico en El Salvador; la agricultura aporta el 5.6 % del PIB | Las pérdidas de cosecha tienen impacto social directo |
| El 82.1 % de los productores son pequeños agricultores con acceso limitado a asistencia técnica | No hay agrónomo disponible para diagnosticar |
| Enfermedades/plagas/deficiencias pueden destruir hasta el 70 % de una cosecha | El diagnóstico tardío es catastrófico |
| Zonas rurales sin conectividad | La solución no puede depender de la nube: debe correr en el dispositivo |
El diagnóstico actual depende de experiencia empírica del agricultor. El sistema busca reemplazar esa incertidumbre por un análisis objetivo, inmediato y gratuito en un teléfono de gama media.
1.3. Usuarios objetivo y casos de uso
- Usuario final: pequeño agricultor de subsistencia. Toma una foto de una hoja sospechosa con su teléfono y recibe un diagnóstico + orientación de tratamiento, sin internet.
- Equipo de ML (lectores de esta guía): entrena, evalúa y explica los modelos; mantiene el pipeline de datos.
- Restricción de despliegue clave: Android ≥ 4 GB RAM, gama de chip Snapdragon 6xx, modelo ≤ 20 MB e inferencia ≤ 300 ms/imagen. Esta restricción es la que justifica toda la selección de arquitecturas: solo redes ligeras y eficientes (MobileNet, ShuffleNet, EfficientNet-Lite, GhostNet, FastViT) son candidatas.
Casos de uso concretos que el repo soporta hoy:
- Reproducir splits de train/val/test deterministas a partir del dataset limpio.
- Entrenar y comparar varias arquitecturas ligeras rápidamente (pipeline de baselines).
- Evaluar con métricas por clase (macro-F1, matriz de confusión, reporte de clasificación).
- Explicar las predicciones (por qué el modelo dijo lo que dijo) con LIME y Grad-CAM.
- Predecir la clase de una imagen suelta desde la línea de comandos.
1.4. Las 9 clases
Definidas en config/dataset.yaml → dataset.classes (este orden es el orden canónico que fija los índices de clase):
| # | Clase (código) | Tipo | Traducción |
|---|---|---|---|
| 0 | common_rust | Enfermedad | Roya común |
| 1 | fall_armyworm | Plaga | Gusano cogollero |
| 2 | gray_leaf_spot | Enfermedad | Mancha gris |
| 3 | healthy | Sana | Hoja sana |
| 4 | lethal_necrosis | Enfermedad | Necrosis letal |
| 5 | nitrogen_deficiency | Deficiencia | Deficiencia de nitrógeno |
| 6 | northern_corn_leaf_blight | Enfermedad | Tizón foliar del norte |
| 7 | phosphorus_deficiency | Deficiencia | Deficiencia de fósforo |
| 8 | potassium_deficiency | Deficiencia | Deficiencia de potasio |
Estas clases no están balanceadas: healthy tiene ~8.7k imágenes mientras potassium_deficiency tiene ~266. Esa asimetría es un tema transversal en todo el proyecto (ver desbalance de clases).
1.5. Resultados actuales (baselines sobre 9 clases)
Tres arquitecturas entrenadas sobre el perfil baseline (9 clases, tope de 1500 imágenes/clase, 30 épocas, entrada 224×224, transfer learning). Métricas reales del conjunto de test (summary.json de cada run):
| Modelo | Test macro-F1 | Test accuracy | Test loss | Mejor época |
|---|---|---|---|---|
| EfficientNet-B0 | 0.9117 | 0.9514 | 0.229 | 26 |
| ShuffleNetV2-x1.0 | 0.9083 | 0.9541 | 0.197 | 26 |
| EfficientNet-Lite0 | 0.8905 | 0.9454 | 0.257 | 30 |
La meta del proyecto es macro-F1 ≥ 0.85, ya superada por los tres. EfficientNet-B0 lidera en macro-F1; ShuffleNetV2 es competitivo y más ligero (candidato fuerte para el despliegue móvil por tamaño/latencia).
¿Por qué macro-F1 y no accuracy?
Con clases desbalanceadas, la accuracy premia acertar la clase mayoritaria (healthy). El macro-F1 promedia el F1 de cada clase con el mismo peso, así que penaliza fuerte si el modelo ignora las clases minoritarias (las deficiencias nutricionales, que son las más difíciles y las que más importan al agricultor). Ver fundamentos: métricas.
1.6. Arquitectura general del sistema
El código se divide en dos grandes zonas:
src/— librería instalable (pip install -e .). Contiene toda la lógica reutilizable: carga de imágenes, dataset, splits, transforms, registro de modelos, utilidades de entrenamiento y explicabilidad. No tiene entrypoints; solo define componentes.scripts/— los entrypoints ejecutables que orquestan la librería: crear splits, entrenar, explicar, predecir, además de scripts de limpieza de datos y ejecución en la nube (Modal).
Sobre un mismo dataset limpio (clean/) conviven dos pipelines paralelos que comparten toda la infraestructura de datos y modelos:
Idea central que conviene interiorizar desde el principio: el pipeline de baselines (train_baselines.py) es Deep Learning completo y funcional, no un pipeline sklearn a pesar del nombre "baseline". Se llama así porque su propósito es comparar arquitecturas rápido y barato para elegir la mejor, no porque sea simple. El pipeline "principal" (train.py) comparte toda la infraestructura pero su loop de entrenamiento aún no está implementado (es un esqueleto con un TODO).
1.7. Flujo de extremo a extremo (resumen)
Cada uno de estos pasos se detalla en Flujo completo del sistema y se disecciona a nivel de código en Análisis detallado de código.
1.8. Restricciones y decisiones de diseño de alto nivel
| Restricción | Consecuencia de diseño |
|---|---|
| Debe correr offline en teléfonos de gama media | Solo arquitecturas ligeras; objetivo ≤ 20 MB y ≤ 300 ms |
| Dataset heterogéneo (8 fuentes, lab + campo) y desbalanceado | Deduplicación por hash, estratificación por clase+entorno, sampler balanceado |
| Proyecto académico reproducible | Semilla global fija (42), splits deterministas, versionado de runs por timestamp |
| Equipo pequeño que debe comparar muchas arquitecturas | Registry de modelos + pipeline de baselines desacoplado del pipeline principal |
| Necesidad de confianza/interpretabilidad (agrónomos, jurado) | Explicabilidad post-hoc obligatoria (LIME + Grad-CAM), desacoplada del entrenamiento |
Siguiente paso
Si quieres el mapa de "qué archivo hace qué", continúa con Mapa del repositorio. Si prefieres seguir el recorrido de una imagen a través del sistema, salta a Flujo completo del sistema.