# ResNet50 Transfer Learning para Nocciola - Documentación

## 🚀 **Implementación Completa de ResNet50**

Este proyecto implementa transfer learning con ResNet50 para clasificación de fases fenológicas de nocciola, basado en la estructura exitosa de MobileNetV1.py pero optimizado específicamente para ResNet50.

## 📁 **Estructura de Archivos**

```
Code/Supervised_learning/
├── ResNET.py                  # Script principal ResNet50 ✅ NUEVO
├── train_resnet50.py         # Script facilitado de entrenamiento ✅ NUEVO
├── MobileNetV1.py            # Script MobileNetV2 (referencia exitosa)
└── README_ResNet50.md        # Esta documentación ✅ NUEVO
```

## 🔧 **Características Específicas de ResNet50**

### **Arquitectura Optimizada:**
```python
# Modelo base ResNet50
base_model = ResNet50(
    weights='imagenet',
    include_top=False,
    input_shape=(224, 224, 3)
)

# Capas personalizadas optimizadas para ResNet50
model = Sequential([
    base_model,
    GlobalAveragePooling2D(),
    BatchNormalization(),        # ✅ Importante para ResNet50
    Dropout(0.5),               # ✅ Dropout más alto
    Dense(256, activation='relu'), # ✅ Más neuronas
    BatchNormalization(),
    Dropout(0.3),
    Dense(num_classes, activation='softmax')
])
```

### **Optimizaciones Específicas:**

1. **Learning Rate Conservador:**
   - Inicial: `5e-4` (vs `1e-3` en MobileNet)
   - Fine-tuning: `1e-6` (muy bajo para estabilidad)

2. **Data Augmentation Reducido:**
   - Rotación: 15° (vs 20° en MobileNet)
   - Shifts/Zoom: 0.08 (vs 0.1 en MobileNet)
   - Más conservador para evitar overfitting

3. **Fine-tuning Selectivo:**
   - Solo últimas capas residuales (conv5_x)
   - Punto de corte: capa 140 (de 175 total)
   - Preserva features básicas, adapta características específicas

4. **Callbacks Adaptados:**
   - Paciencia EarlyStopping: 10 (vs 7 en MobileNet)
   - Más épocas de fine-tuning: 15 (vs 10)
   - Factor ReduceLR: 0.3 (más agresivo)

## 📊 **Comparación ResNet50 vs MobileNetV2**

| Característica | ResNet50 | MobileNetV2 |
|----------------|----------|-------------|
| **Parámetros** | ~25M | ~3.4M |
| **Memoria** | Alta | Baja |
| **Velocidad** | Lenta | Rápida |
| **Precisión** | Alta | Media-Alta |
| **Overfitting** | Más propenso | Menos propenso |
| **Dataset ideal** | Grande/Complejo | Pequeño/Mediano |

## 🎯 **Casos de Uso Recomendados**

### **Usar ResNet50 cuando:**
- ✅ Dataset tiene suficientes muestras (>1000)
- ✅ Patrones complejos en imágenes
- ✅ Precisión es más importante que velocidad
- ✅ Hardware robusto disponible
- ✅ Investigación/análisis detallado

### **Usar MobileNetV2 cuando:**
- ✅ Dataset pequeño (<500 muestras)
- ✅ Velocidad es importante
- ✅ Recursos limitados
- ✅ Producción/móvil
- ✅ Prototipado rápido

## 🚀 **Ejecución**

### **Opción 1: Script Facilitado (Recomendado)**
```bash
# Entrenar solo ResNet50
python train_resnet50.py --model resnet50 --epochs 25

# Comparar ambos modelos
python train_resnet50.py --model both --epochs 20

# Ver comparación detallada
python train_resnet50.py --compare
```

### **Opción 2: Ejecución Directa**
```bash
# ResNet50 básico
python ResNET.py --epochs 25 --force_split

# ResNet50 con dataset específico
python ResNET.py --csv_path "assignments.csv" --epochs 30
```

### **Parámetros Disponibles:**
- `--csv_path`: Ruta al CSV (default: assignments.csv)
- `--images_dir`: Directorio de imágenes
- `--output_dir`: Directorio de resultados (default: results_resnet50_faseV)
- `--epochs`: Épocas de entrenamiento (default: 25)
- `--force_split`: Recrear división de datos

## 📈 **Proceso de Entrenamiento ResNet50**

### **Fase 1: Entrenamiento Inicial**
1. Base model congelado (ImageNet weights)
2. Solo entrenar capas personalizadas
3. Learning rate conservador (5e-4)
4. Callbacks con paciencia aumentada

### **Fase 2: Fine-tuning Selectivo**
5. Descongelar solo conv5_x layers (últimas capas residuales)
6. Learning rate muy bajo (1e-6)
7. 15 épocas adicionales
8. Monitoreo estricto de overfitting

### **Evaluación Robusta:**
9. Manejo automático de clases desbalanceadas
10. Métricas específicas para ResNet50
11. Visualizaciones diferenciadas

## 📂 **Resultados Generados**

### **Modelos:**
- `best_resnet50_model.keras`: Mejor modelo durante entrenamiento
- `final_resnet50_model.keras`: Modelo final completo

### **Reportes:**
- `classification_report.txt`: Reporte detallado con marcador ResNet50
- `confusion_matrix.csv`: Matriz numérica

### **Visualizaciones:**
- `resnet50_training_history.png`: Gráficos de entrenamiento
- `resnet50_confusion_matrix.png`: Matriz visual
- `resnet50_prediction_examples.png`: Ejemplos de predicciones

### **Data Splits:**
- `train_split.csv`, `val_split.csv`, `test_split.csv`
- `class_indices.json`: Mapeo de clases

## ⚙️ **Configuración Técnica**

### **Requisitos del Sistema:**
- RAM: Mínimo 8GB (recomendado 16GB)
- GPU: Opcional pero muy recomendada
- Espacio: ~3GB para resultados completos

### **Dependencias:**
```bash
tensorflow>=2.8.0
scikit-learn
pandas
numpy
matplotlib
seaborn
```

### **Configuración Interna:**
```python
IMG_SIZE = (224, 224)    # Estándar ImageNet
BATCH_SIZE = 16          # Reducido para ResNet50
SPLIT = {'train': 0.7, 'val': 0.15, 'test': 0.15}
```

## 🔍 **Diferencias Implementadas vs MobileNet**

### **1. Arquitectura:**
- BatchNormalization adicional
- Dropout más agresivo (0.5 vs 0.3)
- Dense layer mayor (256 vs 128)

### **2. Entrenamiento:**
- Learning rates más conservadores
- Fine-tuning más selectivo
- Más épocas de fine-tuning

### **3. Data Augmentation:**
- Rotaciones menores (15° vs 20°)
- Shifts reducidos (0.08 vs 0.1)
- Menos agresivo para ResNet50

### **4. Callbacks:**
- Paciencia aumentada (10 vs 7)
- Factor ReduceLR más agresivo (0.3 vs 0.2)
- Monitoreo específico para ResNet

### **5. Outputs:**
- Nombres diferenciados (`resnet50_*`)
- Reportes marcados con modelo
- Métricas específicas

## 🎯 **Recomendaciones de Uso**

### **Para Dataset Nocciola Actual:**
Dado que el dataset es relativamente pequeño (~500 muestras):

1. **Primera opción:** MobileNetV2 (más adecuado)
2. **Segunda opción:** ResNet50 con regularización fuerte
3. **Comparación:** Entrenar ambos y comparar resultados

### **Comando Recomendado:**
```bash
# Comparar ambos modelos con pocas épocas
python train_resnet50.py --model both --epochs 15

# Analizar resultados y elegir el mejor
```

## 🚨 **Solución de Problemas**

### **Overfitting en ResNet50:**
- Reducir épocas de entrenamiento
- Aumentar dropout
- Usar dataset filtrado
- Más data augmentation

### **Underfitting:**
- Aumentar épocas
- Reducir regularización
- Learning rate más alto
- Descongelar más capas

### **Problemas de memoria:**
- Reducir BATCH_SIZE a 8 o 4
- Usar gradient checkpointing
- Cerrar otras aplicaciones

## 📊 **Interpretación de Resultados**

### **Métricas Esperadas:**
- **ResNet50:** Mayor precision, posible overfitting
- **MobileNetV2:** Más generalizable, menos overfitting

### **Comparación Visual:**
- Training curves más suaves en MobileNet
- Posible gap train/val en ResNet50
- Matriz de confusión similar o mejor en ResNet50

### **Decisión Final:**
Elegir modelo basado en:
1. Accuracy en test set
2. Diferencia train/validation
3. Requisitos de producción
4. Interpretabilidad de errores

---

## 🎉 **¡ResNet50 Implementado Exitosamente!**

El modelo ResNet50 está completamente implementado usando la misma estructura robusta que MobileNetV1.py, con optimizaciones específicas para ResNet50 y manejo automático de clases desbalanceadas.

**Para comenzar:** `python train_resnet50.py --model resnet50 --epochs 20`