CoolFace
Apppublic

danirodriguezz/image-classifier-resnet18

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
App README

<div align="center">

Image Classifier

Clasificación de imágenes en tiempo real con ResNet18 + FastAPI

Python PyTorch FastAPI Accuracy

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

ClasePrecisiónRecallF1-scoreMuestras val
airplane0.991.001.001 000
bicycle1.000.950.97100
car1.000.991.001 000
dog0.991.001.001 000
avg0.9950.9850.993 100
Accuracy de validación: 99.26 %

Stack tecnológico

CapaTecnología
ModeloResNet18 pre-entrenado (ImageNet) + fine-tuning
TrainingPyTorch · torchvision · scikit-learn
BackendFastAPI · Uvicorn
FrontendHTML + CSS + JavaScript vanilla
DatosCIFAR-10 + CIFAR-100 (descarga automática)

Instalación y uso

1. Preparar el entorno

bash
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.txt

2. Entrenar el modelo

bash
python train_pipeline.py

Descarga 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

bash
uvicorn api.main:app --reload --port 8000
URLDescripción
http://localhost:8000Interfaz web
http://localhost:8000/docsSwagger UI

4. Predecir desde la línea de comandos

bash
curl -X POST http://localhost:8000/predict \
  -F "file=@mi_imagen.jpg"
json
{
  "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

FaseÉpocasCapas entrenablesLR cabezaLR backbone
1 — warmup1–5Solo FC head1e-3—
2 — fine-tuning6–20Toda la red1e-31e-4

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

ClaseFuenteÍndice originalTrainVal
airplaneCIFAR-1005 0001 000
bicycleCIFAR-1008500100
carCIFAR-101 (automobile)5 0001 000
dogCIFAR-1055 0001 000

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