5. Fundamentos teóricos
Esta sección conecta cada técnica presente en el proyecto con su fundamento. Para cada una: concepto, intuición, base matemática (cuando aplica), ventajas, desventajas y dónde aparece en el código. Pensada para que un desarrollador sin background de ML entienda por qué funciona, y para que un lector con ML pueda defenderlo.
5.1. Redes Neuronales Convolucionales (CNN)
Concepto. Una CNN es una red neuronal que procesa imágenes aplicando filtros convolucionales: pequeñas ventanas (p.ej. 3×3) que se deslizan por la imagen detectando patrones locales (bordes, texturas, y en capas profundas, formas complejas como lesiones).
Intuición. En vez de conectar cada píxel con cada neurona (inviable: una imagen 224×224×3 tiene 150k valores), la convolución comparte pesos espacialmente. El mismo detector de "borde verde-amarillo" se aplica en toda la imagen. Esto da dos propiedades: invariancia a la traslación (una lesión se detecta esté donde esté) y eficiencia de parámetros.
Matemática (una capa conv). Para una entrada
Ventajas: estado del arte en visión; jerarquía de features automática; eficiente en parámetros. Desventajas: requiere muchos datos y cómputo; menos interpretable que un modelo lineal; campo receptivo local (mitigado por profundidad). En el proyecto: las 8 arquitecturas de src/models/baselines/ son CNNs (FastViT es híbrido CNN+Transformer).
5.2. Transfer Learning
Concepto. En vez de entrenar una red desde cero (pesos aleatorios), se parte de una red preentrenada en ImageNet (1.2M imágenes, 1000 clases) y se reutiliza ese conocimiento, reemplazando solo la última capa para las 9 clases del proyecto.
Intuición. Las primeras capas de cualquier CNN aprenden features genéricas (bordes, texturas, colores) que sirven para cualquier tarea visual. Solo las últimas capas son específicas de la tarea. Reutilizar las genéricas ahorra datos y tiempo enormemente.
En el código: weights = EfficientNet_B0_Weights.DEFAULT + model.classifier[1] = nn.Linear(in_features, num_classes) (modelos). El backbone conserva pesos de ImageNet; la cabeza es nueva.
| Transfer learning | Desde cero | |
|---|---|---|
| Datos necesarios | Miles | Cientos de miles a millones |
| Tiempo de entrenamiento | Horas | Días/semanas |
| Precisión con dataset pequeño | Alta | Baja (sobreajusta) |
Por qué es la decisión correcta aquí: el dataset tiene ~25k imágenes, dos órdenes de magnitud menos que ImageNet. Sin transfer learning, redes de esta capacidad sobreajustarían. Ver ¿qué pasaría si entreno desde cero?.
5.3. Backpropagation y descenso de gradiente
Concepto. El entrenamiento ajusta los pesos para minimizar la pérdida. Backpropagation calcula, vía la regla de la cadena, el gradiente de la pérdida respecto a cada peso: cuánto y en qué dirección cambiar cada uno para reducir el error.
Intuición. Imagina la pérdida como un paisaje montañoso; el gradiente apunta cuesta arriba, así que damos un paso en dirección contraria (cuesta abajo) para bajar el error. El tamaño del paso es el learning rate.
En el código (_run_epoch): loss.backward() calcula los gradientes; optimizer.step() da el paso. optimizer.zero_grad() los resetea entre batches (si no, se acumularían). Ver entrenamiento.
5.4. Optimizadores: SGD, Adam, AdamW
El problema. ¿Cómo exactamente actualizar los pesos con el gradiente? Distintos optimizadores, distintos trade-offs.
| Optimizador | Idea | Ventaja | Desventaja |
|---|---|---|---|
| SGD (+momentum) | Paso fijo en dirección del gradiente (con inercia) | Generaliza muy bien; estándar en visión | Sensible al learning rate; converge lento |
| Adam | Learning rate adaptativo por parámetro (usa media y varianza de gradientes) | Converge rápido; robusto sin mucho tuning | Puede generalizar algo peor; mezcla mal el weight decay |
| AdamW | Adam con weight decay desacoplado de la actualización adaptativa | Lo mejor de Adam + regularización correcta | Un hiperparámetro más que ajustar |
El proyecto usa AdamW (torch.optim.AdamW, lr=1e-4, weight_decay=1e-4).
Por qué AdamW y no Adam: en Adam clásico, el weight decay se mezcla con el término adaptativo y su efecto se distorsiona. AdamW lo desacopla (lo aplica directo sobre los pesos), recuperando la regularización L2 "verdadera". Es la elección moderna estándar para fine-tuning de CNNs/Transformers. Por qué no SGD: SGD suele exigir un schedule de learning rate cuidadoso y más épocas; AdamW da buenos resultados con menos tuning, ideal para comparar muchas arquitecturas rápido. Ver decisiones técnicas.
Matemática (AdamW, simplificada). Mantiene momentos
5.5. Función de pérdida: Cross-Entropy
Concepto. Mide la distancia entre la distribución predicha (softmax de los logits) y la etiqueta real (one-hot). Para clasificación multiclase:
Intuición. Penaliza fuerte estar seguro y equivocado: si el modelo asigna probabilidad 0.01 a la clase correcta,
En el código: torch.nn.CrossEntropyLoss() — sin pesos por clase. Combina internamente log_softmax + NLLLoss, por eso el modelo devuelve logits crudos (no softmax). El balanceo lo hace el sampler, no la loss.
Alternativa relevante — Focal Loss: reduce el peso de los ejemplos fáciles para enfocarse en los difíciles (útil en desbalance extremo). El proyecto no la usa (elige balanceo por sampler), pero es la primera alternativa a considerar. Ver ¿qué pasaría si cambio la loss?.
5.6. Regularización: Weight Decay, Dropout, Batch Norm, Data Augmentation
Todas combaten el sobreajuste (memorizar el train en vez de generalizar).
- Weight Decay (L2). Penaliza pesos grandes → modelos más simples y suaves. En el proyecto:
weight_decay=1e-4en AdamW. - Dropout. Apaga aleatoriamente neuronas en entrenamiento → la red no depende de ninguna en particular. Presente dentro de las arquitecturas (EfficientNet lo trae); se apaga en
model.eval(). - Batch Normalization. Normaliza las activaciones de cada capa por batch → entrenamiento más estable y rápido, con efecto regularizador leve. Usa estadísticas del batch en train y acumuladas en eval — por eso
model.train()/model.eval()importan. Presente en todas las arquitecturas. - Data Augmentation. Genera variaciones sintéticas (flips, rotaciones, jitter) → más "datos" efectivos, más robustez. En el proyecto:
transforms.py, con la distinción crítica de preservar el hue en el pipeline estándar para no dañar el diagnóstico de deficiencias. Ver datos: transforms.
5.7. Early Stopping (implícito por checkpoint)
Concepto. Detener el entrenamiento (o quedarse con el mejor punto) antes de que el modelo empiece a sobreajustar.
En el proyecto: no hay parada temprana estricta (siempre corre 30 épocas), pero se guarda best.pth en la época de mejor val macro-F1 y ese es el que se evalúa/despliega. Es early stopping por selección de checkpoint: aunque las épocas finales sobreajusten, el modelo final es el mejor punto de validación.
5.8. Learning Rate Scheduling (no usado, pero relevante)
Reducir el learning rate durante el entrenamiento (p.ej. coseno, step decay) suele mejorar la convergencia final. El proyecto usa LR constante por simplicidad y comparabilidad entre baselines. Es la primera mejora candidata para el pipeline principal train.py. Ver ¿qué pasaría si...?.
5.9. Métricas: Accuracy, Precision, Recall, F1, Macro-F1
Con desbalance, la métrica es una decisión de diseño.
| Métrica | Fórmula | Qué mide |
|---|---|---|
| Accuracy | aciertos / total | Global; engaña con desbalance |
| Precision | TP / (TP+FP) | De lo que predije clase X, cuánto acerté |
| Recall | TP / (TP+FN) | De los X reales, cuántos detecté |
| F1 | Media armónica de P y R | |
| Macro-F1 | promedio simple de F1 por clase | Trata todas las clases por igual |
Por qué macro-F1 es la métrica principal: promedia el F1 de cada clase con el mismo peso, sin importar cuántas imágenes tenga. Así, ignorar potassium_deficiency (266 imágenes) penaliza tanto como ignorar healthy (8.7k). Con accuracy, el modelo podría alcanzar >90 % simplemente prediciendo bien las clases grandes. El código selecciona best.pth por macro-F1 de validación, precisamente por esto. Ver decisiones técnicas.
5.10. Matriz de confusión
Tabla clase-real × clase-predicha. La diagonal son aciertos; fuera de la diagonal, los errores específicos ("cuánto se confunde gray_leaf_spot con northern_corn_leaf_blight"). El proyecto la exporta a test_confusion_matrix.csv. Es la herramienta clave para el análisis cualitativo de errores.
5.11. Explicabilidad (XAI): LIME, Grad-CAM, y SHAP
LIME (Local Interpretable Model-agnostic Explanations)
Concepto. Explica una predicción individual aproximando el modelo (complejo) por un modelo lineal simple en la vecindad de esa imagen. Para imágenes: segmenta en superpíxeles, los enciende/apaga aleatoriamente (num_samples perturbaciones), observa cómo cambia la predicción, y ajusta una regresión que asigna un peso a cada superpíxel.
Ventajas: model-agnostic (funciona con cualquier clasificador); explica en el espacio visible de la imagen. Desventajas: costoso (miles de forwards por imagen); estocástico → puede ser inestable entre seeds (por eso existe lime_stability.py).
Grad-CAM (Gradient-weighted Class Activation Mapping)
Concepto. Usa los gradientes de la clase predicha respecto a la última capa convolucional para ponderar los mapas de activación → heatmap de "dónde miró" el modelo.
Ventajas: rápido (un backward); usa la estructura real de la red. Desventajas: solo CNNs con capa espacial; resolución gruesa (la de la última conv, ~7×7 upsampleado).
SHAP (mencionado, no implementado)
Basado en valores de Shapley (teoría de juegos): reparte la "contribución" de cada feature de forma teóricamente fundamentada. Más riguroso pero más costoso que LIME. El proyecto no lo usa; LIME + Grad-CAM cubren la necesidad. Si un jurado pregunta por SHAP, la respuesta es: "consideramos SHAP; para explicaciones visuales por superpíxel, LIME + Grad-CAM ofrecen mejor relación costo/claridad en nuestro caso; SHAP sería el siguiente paso para explicaciones tabulares o de atribución exacta".
5.12. Cuantización y Distillation (despliegue, pendientes)
- Cuantización (Int8). Convertir los pesos/activaciones de float32 a enteros de 8 bits. Reduce ~4× el tamaño y acelera la inferencia en CPU/móvil, a cambio de una pérdida pequeña de precisión. Es el paso de despliegue objetivo (TFLite Int8, ≤20 MB, ≤300 ms). Ver ¿qué pasaría si cuantizo?.
- Knowledge Distillation. Entrenar un modelo pequeño ("estudiante") para imitar a uno grande ("maestro"). Alternativa a la cuantización para reducir tamaño. No usado, pero mencionable como vía futura si la cuantización degrada demasiado.
Siguiente
Con la teoría en la mano, la Justificación de decisiones técnicas explica por qué se eligió cada opción concreta frente a sus alternativas.