Información de la Tarea
- Estudiante: Andrés Cruz Chipol
- Curso: Aprendizaje Profundo
- Fecha de entrega: 16 de Junio, 2026
Descripción de la Tarea
Se deber realizar el clasificador de imagene de ocho formas utilizando transfering learning con EfficientNet, recortarla de la forma indicada, Aumentando las imagenes con el script Proporcionado.
Del Script EfficientNet-B0.py Como se muestra en la imagen, recortamos para que solo nos quede con bloques de hasta el bloque 7. Modificamos la ultima capa para que tenga la forma adecuada para poder entrenar nuestra red.
inverted_residual_setting = [ bneck_conf(1, 3, 1, 32, 16, 1), bneck_conf(6, 3, 2, 16, 24, 2), bneck_conf(6, 5, 2, 24, 40, 2), #<- 8 # bneck_conf(6, 3, 2, 40, 80, 3), # bneck_conf(6, 5, 1, 80, 112, 3), # bneck_conf(6, 5, 2, 112, 192, 4), bneck_conf(6, 3, 1, 40, 320, 1), # Block 7 adaptado (in:40 en lugar de 192) ] last_channUtilizamos entonces el script para instanfciar el codigo y realizar el transfer.py De acuerdo a la estructura que modificamos.
# Cargo la red originalmodelo1 = EfficientNet_B0.efficientnet_b0(weights=EfficientNet_B0.EfficientNet_B0_Weights.DEFAULT)modelo1.eval()
modelo2 = EfficientNet_B0.efficientnet_b0_modif()
# Copiamos los pesos de la primera capa (de tres canales a uno)w1 = modelo1.state_dict()['features.0.0.weight']w2 = modelo2.state_dict()['features.0.0.weight']
# En EfficientNet_B0, la primera capa tiene 32 filtrosi = 0while i < 32: f1 = w1[i, 0] f2 = w1[i, 1] f3 = w1[i, 2]
g = 0.2989 * f1 + 0.5870 * f2 + 0.1140 * f3 w2[i, 0].copy_(g)
i += 1
# Copiamos el resto de los pesos que sean compatiblesk = 0for i in modelo1.state_dict(): if i == 'features.0.0.weight': continue if i in modelo2.state_dict() and modelo1.state_dict()[i].shape == modelo2.state_dict()[i].shape: p1 = modelo1.state_dict()[i] p2 = modelo2.state_dict()[i] p2.copy_(p1) k += 1
modelo2.eval()torch.save(modelo2.state_dict(), 'efficientnet_b0_recortada.pth')Imprimi la red con torchinfo para visualizar que este correcta nuestra arquitectura.
=========================================================================================================Layer (type:depth-idx) Output Shape Param #=========================================================================================================EfficientNet_modif [32, 8] --├─Sequential: 1-1 [32, 1280, 28, 28] --│ └─Conv2dNormActivation: 2-1 [32, 32, 112, 112] --│ │ └─Conv2d: 3-1 [32, 32, 112, 112] 288│ │ └─BatchNorm2d: 3-2 [32, 32, 112, 112] 64│ │ └─SiLU: 3-3 [32, 32, 112, 112] --│ └─Sequential: 2-2 [32, 16, 112, 112] --│ │ └─MBConv: 3-4 [32, 16, 112, 112] 1,448│ └─Sequential: 2-3 [32, 24, 56, 56] --│ │ └─MBConv: 3-5 [32, 24, 56, 56] 6,004│ │ └─MBConv: 3-6 [32, 24, 56, 56] 10,710│ └─Sequential: 2-4 [32, 40, 28, 28] --│ │ └─MBConv: 3-7 [32, 40, 28, 28] 15,350│ │ └─MBConv: 3-8 [32, 40, 28, 28] 31,290│ └─Sequential: 2-5 [32, 320, 28, 28] --│ │ └─MBConv: 3-9 [32, 320, 28, 28] 95,210│ └─Conv2dNormActivation: 2-6 [32, 1280, 28, 28] --│ │ └─Conv2d: 3-10 [32, 1280, 28, 28] 409,600│ │ └─BatchNorm2d: 3-11 [32, 1280, 28, 28] 2,560│ │ └─SiLU: 3-12 [32, 1280, 28, 28] --├─AdaptiveAvgPool2d: 1-2 [32, 1280, 1, 1] --├─Sequential: 1-3 [32, 8] --│ └─Dropout: 2-7 [32, 1280] --│ └─Linear: 2-8 [32, 8] 10,248=========================================================================================================Total params: 582,772Trainable params: 582,772Non-trainable params: 0Total mult-adds (Units.GIGABYTES): 15.91=========================================================================================================Input size (MB): 6.42Forward/backward pass size (MB): 3172.97Params size (MB): 2.33Estimated Total Size (MB): 3181.73=========================================================================================================Data Augmentation
Para el entrenamiento de la red, se partió de una base de datos original compuesta por 480 imágenes distribuidas uniformemente en 8 clases (60 imágenes por clase).
Con el fin de evitar el problema de Fuga de Datos (Data Leakage) y asegurar una validación objetiva del modelo, el particionamiento de los datos se realizó antes de aplicar cualquier técnica de aumento, utilizando una proporción estándar de 80/20:
-
Conjunto de Prueba (Test - 20%): Se reservaron de forma aleatoria 12 imágenes originales por clase (96 imágenes en total). Este conjunto se mantuvo completamente intacto y sin alteraciones para garantizar que la red sea evaluada exclusivamente con datos que jamás haya visto durante el entrenamiento.
-
Conjunto de Entrenamiento (Train - 80%): Se tomaron las 48 imágenes restantes de cada clase. Para expandir la capacidad de generalización del modelo, a este conjunto se le aplicó un algoritmo de Data Augmentation generando 200 variaciones sintéticas por cada imagen. Las transformaciones aleatorias incluyeron:
- Volteo horizontal y vertical.
- Rotación aleatoria ($\pm 15$ grados).
- Escalado aleatorio (zoom entre 1.12x y 1.18x).
Conjunto de entrenamiento robusto de 77,184 imágenes y un conjunto de prueba puro de 96 imágenes.Los datos se estructuraron automáticamente en un formato de directorios por clases (ImageFolder) para facilitar su integración directa con los DataLoaders de PyTorch.
Entrenamiento
Se congelaron las capas base de la red (requires_grad = False). Solamente se descongelaron las últimas tres capas (el nuevo Bloque 7, la convolución final de proyección y el clasificador lineal de 8 clases).
| Parámetro | Valor Configurado |
|---|---|
| Optimizador | SGD con Nesterov |
| Tasa de Aprendizaje | 0.001 |
| Momentum | 0.95 |
| Función de Pérdida | CrossEntropyLoss |
| Tamaño de Lote (Batch) | 32 |
| Épocas (Epochs) | 10 |
Resultados
Se obtuvo un tiempo aprox de 10min en una Macbook air M4-16gb utilizando mps para las 10 epocas.
Guardamos el mejor modelo en cada iteracion si disminuía el gap entre train y test loss.
| Época | Precisión (Train) | Loss (Train) | Precisión (Test) | Loss (Test) |
|---|---|---|---|---|
| 1 | 98.4% | 0.053290 | 100.0% | 0.004266 |
| 2 | 99.9% | 0.006035 | 100.0% | 0.000834 |
| 3 | 99.9% | 0.003582 | 100.0% | 0.001451 |
| 4 | 100.0% | 0.002224 | 100.0% | 0.000762 |
| 5 | 100.0% | 0.001677 | 100.0% | 0.000673 |
| 6 | 100.0% | 0.001527 | 100.0% | 0.001297 |
| 7 | 100.0% | 0.001317 | 100.0% | 0.000828 |
| 8 | 100.0% | 0.001054 | 100.0% | 0.000385 |
| 9 | 100.0% | 0.000918 | 100.0% | 0.000261 |
| 10 | 100.0% | 0.000738 | 100.0% | 0.000363 |
Conclusión
La reducción estructural de EfficientNet-B0 (~582k parámetros) y el fine-tuning con prevención de data leakage resultaron en un modelo altamente eficiente. Se alcanzó un 100% de precisión en prueba (Loss 0.000261) sin sobreajuste, demostrando que es posible minimizar el costo computacional sin sacrificar rendimiento.