Paddle ocr, easyicr and doctr gpu support. (#4)
All checks were successful
build_docker / essential (push) Successful in 0s
build_docker / build_cpu (push) Successful in 5m0s
build_docker / build_gpu (push) Successful in 22m55s
build_docker / build_easyocr (push) Successful in 18m47s
build_docker / build_easyocr_gpu (push) Successful in 19m0s
build_docker / build_raytune (push) Successful in 3m27s
build_docker / build_doctr (push) Successful in 19m42s
build_docker / build_doctr_gpu (push) Successful in 14m49s
All checks were successful
build_docker / essential (push) Successful in 0s
build_docker / build_cpu (push) Successful in 5m0s
build_docker / build_gpu (push) Successful in 22m55s
build_docker / build_easyocr (push) Successful in 18m47s
build_docker / build_easyocr_gpu (push) Successful in 19m0s
build_docker / build_raytune (push) Successful in 3m27s
build_docker / build_doctr (push) Successful in 19m42s
build_docker / build_doctr_gpu (push) Successful in 14m49s
This commit was merged in pull request #4.
This commit is contained in:
@@ -8,6 +8,8 @@ Este capítulo establece los objetivos del trabajo siguiendo la metodología SMA
|
||||
|
||||
### Justificación SMART del Objetivo General
|
||||
|
||||
**Tabla 4.** *Justificación SMART del objetivo general.*
|
||||
|
||||
| Criterio | Cumplimiento |
|
||||
|----------|--------------|
|
||||
| **Específico (S)** | Se define claramente qué se quiere lograr: optimizar PaddleOCR mediante ajuste de hiperparámetros para documentos en español |
|
||||
@@ -16,6 +18,8 @@ Este capítulo establece los objetivos del trabajo siguiendo la metodología SMA
|
||||
| **Relevante (R)** | El impacto es demostrable: mejora la extracción de texto en documentos académicos sin costes adicionales de infraestructura |
|
||||
| **Temporal (T)** | El plazo es un cuatrimestre, correspondiente al TFM |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
## Objetivos específicos
|
||||
|
||||
### OE1: Comparar soluciones OCR de código abierto
|
||||
@@ -100,45 +104,32 @@ flowchart LR
|
||||
|
||||
#### Clase ImageTextDataset
|
||||
|
||||
Se implementó una clase Python para cargar pares imagen-texto:
|
||||
|
||||
```python
|
||||
class ImageTextDataset:
|
||||
def __init__(self, root):
|
||||
# Carga pares (imagen, texto) de carpetas pareadas
|
||||
|
||||
def __getitem__(self, idx):
|
||||
# Retorna (PIL.Image, str)
|
||||
```
|
||||
Se implementó una clase Python para cargar pares imagen-texto que retorna tuplas (PIL.Image, str) desde carpetas pareadas. La implementación completa está disponible en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A).
|
||||
|
||||
### Fase 2: Benchmark Comparativo
|
||||
|
||||
#### Modelos Evaluados
|
||||
|
||||
**Tabla 5.** *Modelos OCR evaluados en el benchmark inicial.*
|
||||
|
||||
| Modelo | Versión | Configuración |
|
||||
|--------|---------|---------------|
|
||||
| EasyOCR | - | Idiomas: ['es', 'en'] |
|
||||
| PaddleOCR | PP-OCRv5 | Modelos server_det + server_rec |
|
||||
| DocTR | - | db_resnet50 + sar_resnet31 |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
#### Métricas de Evaluación
|
||||
|
||||
Se utilizó la biblioteca `jiwer` para calcular:
|
||||
|
||||
```python
|
||||
from jiwer import wer, cer
|
||||
|
||||
def evaluate_text(reference, prediction):
|
||||
return {
|
||||
'WER': wer(reference, prediction),
|
||||
'CER': cer(reference, prediction)
|
||||
}
|
||||
```
|
||||
Se utilizó la biblioteca `jiwer` para calcular CER y WER comparando el texto de referencia con la predicción del modelo OCR. La implementación está disponible en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A).
|
||||
|
||||
### Fase 3: Espacio de Búsqueda
|
||||
|
||||
#### Hiperparámetros Seleccionados
|
||||
|
||||
**Tabla 6.** *Hiperparámetros seleccionados para optimización.*
|
||||
|
||||
| Parámetro | Tipo | Rango/Valores | Descripción |
|
||||
|-----------|------|---------------|-------------|
|
||||
| `use_doc_orientation_classify` | Booleano | [True, False] | Clasificación de orientación del documento |
|
||||
@@ -149,76 +140,42 @@ def evaluate_text(reference, prediction):
|
||||
| `text_det_unclip_ratio` | Fijo | 0.0 | Coeficiente de expansión (fijado) |
|
||||
| `text_rec_score_thresh` | Continuo | [0.0, 0.7] | Umbral de confianza de reconocimiento |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
#### Configuración de Ray Tune
|
||||
|
||||
```python
|
||||
from ray import tune
|
||||
from ray.tune.search.optuna import OptunaSearch
|
||||
|
||||
search_space = {
|
||||
"use_doc_orientation_classify": tune.choice([True, False]),
|
||||
"use_doc_unwarping": tune.choice([True, False]),
|
||||
"textline_orientation": tune.choice([True, False]),
|
||||
"text_det_thresh": tune.uniform(0.0, 0.7),
|
||||
"text_det_box_thresh": tune.uniform(0.0, 0.7),
|
||||
"text_det_unclip_ratio": tune.choice([0.0]),
|
||||
"text_rec_score_thresh": tune.uniform(0.0, 0.7),
|
||||
}
|
||||
|
||||
tuner = tune.Tuner(
|
||||
trainable_paddle_ocr,
|
||||
tune_config=tune.TuneConfig(
|
||||
metric="CER",
|
||||
mode="min",
|
||||
search_alg=OptunaSearch(),
|
||||
num_samples=64,
|
||||
max_concurrent_trials=2
|
||||
)
|
||||
)
|
||||
```
|
||||
El espacio de búsqueda se definió utilizando `tune.choice()` para parámetros booleanos y `tune.uniform()` para parámetros continuos, con OptunaSearch como algoritmo de optimización configurado para minimizar CER en 64 trials. La implementación completa está disponible en `src/raytune/raytune_ocr.py` (ver Anexo A).
|
||||
|
||||
### Fase 4: Ejecución de Optimización
|
||||
|
||||
#### Arquitectura de Ejecución
|
||||
|
||||
Debido a incompatibilidades entre Ray y PaddleOCR en el mismo proceso, se implementó una arquitectura basada en subprocesos:
|
||||
Se implementó una arquitectura basada en contenedores Docker para aislar los servicios OCR y facilitar la reproducibilidad (ver sección 4.2.3 para detalles de la arquitectura).
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: "Arquitectura de ejecución con subprocesos"
|
||||
---
|
||||
flowchart LR
|
||||
A["Ray Tune (proceso principal)"]
|
||||
#### Ejecución con Docker Compose
|
||||
|
||||
A --> B["Subprocess 1: paddle_ocr_tuning.py --config"]
|
||||
B --> B_out["Retorna JSON con métricas"]
|
||||
|
||||
A --> C["Subprocess 2: paddle_ocr_tuning.py --config"]
|
||||
C --> C_out["Retorna JSON con métricas"]
|
||||
```
|
||||
|
||||
#### Script de Evaluación (paddle_ocr_tuning.py)
|
||||
|
||||
El script recibe hiperparámetros por línea de comandos:
|
||||
Los servicios se orquestan mediante Docker Compose (`src/docker-compose.tuning.*.yml`):
|
||||
|
||||
```bash
|
||||
python paddle_ocr_tuning.py \
|
||||
--pdf-folder ./dataset \
|
||||
--textline-orientation True \
|
||||
--text-det-box-thresh 0.5 \
|
||||
--text-det-thresh 0.4 \
|
||||
--text-rec-score-thresh 0.6
|
||||
# Iniciar servicio OCR
|
||||
docker compose -f docker-compose.tuning.doctr.yml up -d doctr-gpu
|
||||
|
||||
# Ejecutar optimización (64 trials)
|
||||
docker compose -f docker-compose.tuning.doctr.yml run raytune --service doctr --samples 64
|
||||
|
||||
# Detener servicios
|
||||
docker compose -f docker-compose.tuning.doctr.yml down
|
||||
```
|
||||
|
||||
Y retorna métricas en formato JSON:
|
||||
El servicio OCR expone una API REST que retorna métricas en formato JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"CER": 0.0125,
|
||||
"WER": 0.1040,
|
||||
"TIME": 331.09,
|
||||
"CER": 0.0149,
|
||||
"WER": 0.0762,
|
||||
"TIME": 15.8,
|
||||
"PAGES": 5,
|
||||
"TIME_PER_PAGE": 66.12
|
||||
"TIME_PER_PAGE": 3.16
|
||||
}
|
||||
```
|
||||
|
||||
@@ -235,23 +192,67 @@ Y retorna métricas en formato JSON:
|
||||
|
||||
#### Hardware
|
||||
|
||||
**Tabla 7.** *Especificaciones de hardware del entorno de desarrollo.*
|
||||
|
||||
| Componente | Especificación |
|
||||
|------------|----------------|
|
||||
| CPU | Intel Core (especificar modelo) |
|
||||
| RAM | 16 GB |
|
||||
| GPU | No disponible (ejecución en CPU) |
|
||||
| CPU | AMD Ryzen 7 5800H |
|
||||
| RAM | 16 GB DDR4 |
|
||||
| GPU | NVIDIA RTX 3060 Laptop (5.66 GB VRAM) |
|
||||
| Almacenamiento | SSD |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
#### Software
|
||||
|
||||
**Tabla 8.** *Versiones de software utilizadas.*
|
||||
|
||||
| Componente | Versión |
|
||||
|------------|---------|
|
||||
| Sistema Operativo | Windows 10/11 |
|
||||
| Python | 3.11.9 |
|
||||
| Sistema Operativo | Ubuntu 24.04.3 LTS |
|
||||
| Python | 3.12.3 |
|
||||
| PaddleOCR | 3.3.2 |
|
||||
| PaddlePaddle | 3.2.2 |
|
||||
| Ray | 2.52.1 |
|
||||
| Optuna | 4.6.0 |
|
||||
| Optuna | 4.7.0 |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
#### Justificación de Ejecución Local vs Cloud
|
||||
|
||||
La decisión de ejecutar los experimentos en hardware local en lugar de utilizar servicios cloud se fundamenta en un análisis de costos y beneficios operativos.
|
||||
|
||||
**Tabla 9.** *Costos de GPU en plataformas cloud.*
|
||||
|
||||
| Plataforma | GPU | Costo/Hora | Costo Mensual |
|
||||
|------------|-----|------------|---------------|
|
||||
| AWS EC2 g4dn.xlarge | NVIDIA T4 (16 GB) | $0.526 | ~$384 |
|
||||
| Google Colab Pro | T4/P100 | ~$1.30 | $10 + CU extras |
|
||||
| Google Colab Pro+ | T4/V100/A100 | ~$1.30 | $50 + CU extras |
|
||||
|
||||
*Fuente: Elaboración propia a partir de precios públicos de AWS y Google Cloud (enero 2026).*
|
||||
|
||||
Para las tareas específicas de este proyecto, los costos estimados en cloud serían:
|
||||
|
||||
**Tabla 10.** *Análisis de costos del proyecto en plataformas cloud.*
|
||||
|
||||
| Tarea | Tiempo GPU | Costo AWS | Costo Colab Pro |
|
||||
|-------|------------|-----------|-----------------|
|
||||
| Ajuste hiperparámetros (64×3 trials) | ~3 horas | ~$1.58 | ~$3.90 |
|
||||
| Evaluación completa (45 páginas) | ~5 min | ~$0.04 | ~$0.11 |
|
||||
| Desarrollo y depuración (20 horas/mes) | 20 horas | ~$10.52 | ~$26.00 |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
Las ventajas de la ejecución local incluyen:
|
||||
|
||||
1. **Costo cero de GPU**: La RTX 3060 ya está disponible en el equipo de desarrollo
|
||||
2. **Sin límites de tiempo**: AWS y Colab imponen timeouts de sesión que interrumpen experimentos largos
|
||||
3. **Acceso instantáneo**: Sin tiempo de aprovisionamiento de instancias cloud
|
||||
4. **Almacenamiento local**: Dataset y resultados en disco sin costos de transferencia
|
||||
5. **Iteración rápida**: Reinicio inmediato de contenedores Docker para depuración
|
||||
|
||||
Para un proyecto de investigación con múltiples iteraciones de ajuste de hiperparámetros, la ejecución local ahorra aproximadamente $50-100 mensuales comparado con servicios cloud, además de ofrecer mayor flexibilidad en la velocidad de iteración durante el desarrollo.
|
||||
|
||||
### Limitaciones Metodológicas
|
||||
|
||||
|
||||
Reference in New Issue
Block a user