danirodriguezz/image-classifier-resnet18
0
<div align="center">
Image Classifier
Clasificación de imágenes en tiempo real con ResNet18 + FastAPI
Sube una imagen y obtén predicciones con nivel de confianza para 4 clases: avión · bicicleta · coche · perro
</div>
Cómo funciona
Imagen subida
│
▼
POST /predict (FastAPI)
│
▼
PIL → Resize 224×224 → Normalización ImageNet
│
▼
ResNet18 fine-tuned (512 → 4 logits)
│
▼
Softmax → ordenado por confianza
│
▼
{ "top_class": "dog", "predictions": [...] }Resultados
Accuracy de validación: 99.26 %
Stack tecnológico
Instalación y uso
1. Preparar el entorno
git clone https://github.com/tu-usuario/End_to_End_Image_Clasifications.git
cd End_to_End_Image_Clasifications
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt2. Entrenar el modelo
python train_pipeline.pyDescarga CIFAR-10 y CIFAR-100 automáticamente, entrena durante 20 épocas y guarda los mejores pesos en models/.
~10 min en CPU · ~2 min en GPU
3. Arrancar el servidor
uvicorn api.main:app --reload --port 80004. Predecir desde la línea de comandos
curl -X POST http://localhost:8000/predict \
-F "file=@mi_imagen.jpg"{
"predictions": [
{ "class": "dog", "confidence": 0.9241 },
{ "class": "car", "confidence": 0.0432 },
{ "class": "bicycle", "confidence": 0.0201 },
{ "class": "airplane", "confidence": 0.0126 }
],
"top_class": "dog"
}Arquitectura del modelo
ResNet18 (ImageNet pre-trained)
├── Conv1 → BN → ReLU → MaxPool
├── Layer1-4 (residual blocks, congelados en fase 1)
└── FC: 512 → 4 ← cabeza nueva (siempre entrenable)Estrategia de entrenamiento en dos fases
La fase 1 estabiliza la nueva cabeza antes de propagar gradientes por el backbone, evitando destruir los features aprendidos de ImageNet.
Gestión del desbalance de clases
Bicycle tiene 10× menos muestras que el resto (500 vs 5 000):
- `WeightedRandomSampler` — oversampling de bicicleta en cada batch
- `CrossEntropyLoss(weight=[1, 10, 1, 1])` — mayor penalización por errores en bicicleta
Dataset
Los datos se descargan automáticamente en data/ la primera vez que se ejecuta el entrenamiento.
Estructura del proyecto
├── config.py # Hiperparámetros y rutas (fuente única de verdad)
├── train_pipeline.py # Punto de entrada del entrenamiento
├── requirements.txt
│
├── src/
│ ├── dataset.py # Filtrado y fusión de CIFAR-10 + CIFAR-100
│ ├── model.py # ResNet18 + helpers de fine-tuning
│ ├── train.py # Bucle de entrenamiento, evaluación y métricas
│ └── transforms.py # Augmentación (train) y preprocesado (val/infer)
│
├── api/
│ ├── main.py # FastAPI app, endpoints, CORS, static files
│ └── inference.py # Singleton del modelo + predict_bytes()
│
└── frontend/
├── index.html
├── style.css
└── app.js # Estado: idle → loading → result → idle