# Optimización de Hiperparámetros OCR con Ray Tune para Documentos Académicos en Español **Trabajo Fin de Máster (TFM) – Máster Universitario en Inteligencia Artificial** **Líneas:** Percepción computacional · Aprendizaje automático **Autor:** Sergio Jiménez Jiménez · **UNIR** · **Año:** 2025 > Optimización sistemática de hiperparámetros de **PaddleOCR (PP-OCRv5)** mediante **Ray Tune** con **Optuna** para mejorar el reconocimiento óptico de caracteres en documentos académicos en español. --- ## Objetivo Optimizar el rendimiento de PaddleOCR para documentos académicos en español mediante ajuste de hiperparámetros, alcanzando un **CER inferior al 2%** sin requerir fine-tuning del modelo. **Resultado alcanzado:** - **Mejor trial (5 páginas):** CER = **0.79%** ✓ objetivo cumplido - **Dataset completo (45 páginas):** CER = **7.72%** (mejora del 12.8% respecto a baseline) --- ## Resultados Principales **Tabla.** *Comparación de métricas OCR entre configuración baseline y optimizada (GPU).* | Modelo | CER | Precisión Caracteres | WER | Precisión Palabras | |--------|-----|---------------------|-----|-------------------| | PaddleOCR (Baseline) | 8.85% | 91.15% | 13.05% | 86.95% | | **PaddleOCR-HyperAdjust (dataset)** | **7.72%** | **92.28%** | **11.40%** | **88.60%** | | **PaddleOCR-HyperAdjust (mejor trial)** | **0.79%** | **99.21%** | **7.78%** | **92.22%** | *Fuente: [`src/results/raytune_paddle_results_20260119_122609.csv`](src/results/raytune_paddle_results_20260119_122609.csv)* **Mejora obtenida (dataset completo):** Reducción del CER en un **12.8%** ### Configuración Óptima Encontrada (GPU) ```python config_optimizada = { "textline_orientation": True, # CRÍTICO para layouts complejos "use_doc_orientation_classify": True, # Mejora orientación de documento "use_doc_unwarping": False, "text_det_thresh": 0.0462, # Correlación -0.52 con CER "text_det_box_thresh": 0.4862, "text_det_unclip_ratio": 0.0, "text_rec_score_thresh": 0.5658, } ``` --- ## Metodología ### Pipeline de Trabajo ``` PDF (académico UNIR) └─► Conversión a imagen (PyMuPDF, 300 DPI) └─► Extracción de ground truth └─► OCR con PaddleOCR (PP-OCRv5) └─► Evaluación (CER, WER con jiwer) └─► Optimización (Ray Tune + Optuna) ``` ### Experimento de Optimización **Tabla.** *Parámetros de configuración del experimento Ray Tune.* | Parámetro | Valor | |-----------|-------| | Número de trials | 64 | | Algoritmo de búsqueda | OptunaSearch (TPE) | | Métrica objetivo | CER (minimizar) | | Trials concurrentes | 2 | | Tiempo total | ~1.5 horas (GPU RTX 3060) | *Fuente: Elaboración propia.* --- ## Estructura del Repositorio ```mermaid flowchart TB subgraph root["MastersThesis/"] direction TB subgraph docs["docs/ - Capítulos TFM"] d0["00-07 chapters (.md)"] subgraph metrics["metrics/"] m1["metrics_paddle.md"] m2["metrics_doctr.md"] m3["metrics_easyocr.md"] end end subgraph src["src/ - Código fuente"] subgraph paddle["paddle_ocr/"] p1["paddle_ocr_tuning_rest.py"] p2["Dockerfile.gpu/cpu"] end subgraph doctr["doctr_service/"] dt1["doctr_tuning_rest.py"] end subgraph easy["easyocr_service/"] e1["easyocr_tuning_rest.py"] end subgraph ray["raytune/"] r1["raytune_ocr.py"] r2["run_tuning.py"] end results["results/*.csv"] dataset["dataset/"] end subgraph thesis["thesis_output/"] htm["plantilla_individual.htm"] figs["figures/figura_1-11.png"] end subgraph inst["instructions/"] i1["instrucciones.pdf"] i2["plantilla_individual.htm"] end scripts["apply_content.py
generate_mermaid_figures.py"] config["claude.md
README.md"] end ``` **Descripción de directorios principales:** | Directorio | Contenido | |------------|-----------| | `docs/` | Capítulos del TFM en Markdown (estructura UNIR) | | `docs/metrics/` | Métricas de rendimiento por servicio OCR | | `src/paddle_ocr/` | Servicio PaddleOCR dockerizado | | `src/doctr_service/` | Servicio DocTR dockerizado | | `src/easyocr_service/` | Servicio EasyOCR dockerizado | | `src/raytune/` | Scripts de optimización Ray Tune | | `src/results/` | CSVs con resultados de 64 trials por servicio | | `thesis_output/` | Documento TFM generado + figuras PNG | | `instructions/` | Plantilla e instrucciones UNIR oficiales | --- ## Hallazgos Clave 1. **`textline_orientation=True` es crítico**: Para documentos con layouts mixtos (tablas, encabezados), la clasificación de orientación de línea es esencial. 2. **`use_doc_orientation_classify=True` mejora resultados**: En la configuración GPU, la clasificación de orientación del documento demostró impacto positivo. 3. **Umbral `text_det_thresh` importante**: Correlación -0.52 con CER. En GPU, el valor óptimo fue 0.0462. Valores < 0.01 causan fallos catastróficos (CER >40%). 4. **`use_doc_unwarping` innecesario para PDFs digitales**: La corrección de deformación no mejora el rendimiento en documentos académicos digitales. --- ## Rendimiento GPU Los experimentos principales se ejecutaron con aceleración GPU para maximizar la eficiencia de la exploración de hiperparámetros. **Tabla.** *Comparación de rendimiento CPU vs GPU.* | Métrica | CPU | GPU (RTX 3060) | Aceleración | |---------|-----|----------------|-------------| | Tiempo/Página | 69.4s | 0.84s | **82x** | | Dataset completo (45 páginas) | ~52 min | ~38 seg | **82x** | | 64 trials completos | ~6.4 horas | ~1.5 horas | **4.3x** | *Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](src/raytune_paddle_subproc_results_20251207_192320.csv) (CPU) y [`src/results/raytune_paddle_results_20260119_122609.csv`](src/results/raytune_paddle_results_20260119_122609.csv) (GPU).* ### Recomendación de Modelos **Tabla.** *Comparación de modelos PaddleOCR en RTX 3060.* | Modelo | VRAM | Recomendación | |--------|------|---------------| | **PP-OCRv5 Mobile** | 0.06 GB | ✓ Recomendado | | PP-OCRv5 Server | 5.3 GB | ✗ Causa OOM en RTX 3060 | *Fuente: Elaboración propia.* **Conclusión:** Para hardware con VRAM limitada (≤6 GB), los modelos Mobile ofrecen el mejor balance entre precisión y recursos. La aceleración GPU (82×) hace viable la exploración exhaustiva de hiperparámetros y el procesamiento en tiempo real. --- ## Requisitos **Tabla.** *Dependencias principales del proyecto y versiones utilizadas.* | Componente | Versión | |------------|---------| | Python | 3.12.3 | | PaddlePaddle | 3.2.2 | | PaddleOCR | 3.3.2 | | Ray | 2.52.1 | | Optuna | 4.7.0 | | jiwer | (para métricas CER/WER) | | PyMuPDF | (para conversión PDF) | *Fuente: Elaboración propia.* --- ## Uso ### Preparar dataset ```bash # Ejecutar prepare_dataset.ipynb para convertir PDF a imágenes y extraer ground truth jupyter notebook src/prepare_dataset.ipynb ``` ### Ejecutar optimización ```bash # Ejecutar el notebook principal de Ray Tune jupyter notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb ``` ### Evaluación individual ```bash python src/paddle_ocr_tuning.py \ --pdf-folder ./dataset \ --textline-orientation True \ --text-det-thresh 0.469 \ --text-det-box-thresh 0.541 \ --text-rec-score-thresh 0.635 ``` --- ## Fuentes de Datos - **Dataset**: 2 documentos UNIR (45 páginas total): Instrucciones TFE (24 pág.) + Plantilla TFE (21 pág.) - **Resultados GPU (PRINCIPAL)**: [`src/results/raytune_paddle_results_20260119_122609.csv`](src/results/raytune_paddle_results_20260119_122609.csv) - 64 trials de optimización con GPU - **Resultados CPU (referencia de tiempo)**: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](src/raytune_paddle_subproc_results_20251207_192320.csv) - Para comparación de rendimiento CPU vs GPU --- ## Trabajo Pendiente para Completar el TFM ### Contexto: Hardware Este trabajo adoptó la estrategia de **optimización de hiperparámetros** en lugar de **fine-tuning** debido a que el fine-tuning de modelos OCR requiere datasets etiquetados extensos y tiempos de entrenamiento prohibitivos. **Hardware utilizado:** - **Optimización (GPU)**: Los 64 trials de Ray Tune se ejecutaron con GPU RTX 3060 (~0.84s/página, ~1.5 horas total) - **Referencia CPU**: Se midió el tiempo en CPU para comparación (~69s/página) La optimización de hiperparámetros demostró ser una **alternativa viable** al fine-tuning. El mejor trial alcanzó un CER de 0.79%, mientras que la validación sobre el dataset completo logró una mejora del 12.8%. ### Tareas Pendientes #### Obligatorias para Entrega - [ ] **Revisión final del documento**: Abrir en Word, actualizar índices (Ctrl+A → F9), ajustar figuras, guardar como .docx - [ ] **Crear presentación**: Preparar slides para la defensa del TFM #### Opcionales (Mejoras Futuras) - [ ] **Validación cruzada**: Evaluar configuración en otros documentos (facturas, formularios) - [ ] **Explorar `text_det_unclip_ratio`**: Parámetro fijado en 0.0, podría mejorar resultados - [ ] **Comparativa con fine-tuning**: Cuantificar brecha vs fine-tuning real - [ ] **Herramienta de configuración automática**: Auto-detectar configuración óptima por documento - [ ] **Benchmark público para español**: Facilitar comparación de soluciones OCR #### Completadas - [x] **Estructura docs/ según plantilla UNIR** - [x] **Diagramas Mermaid**: 8+ figuras generadas - [x] **Documento TFM unificado**: Script `apply_content.py` - [x] **Optimización con GPU**: RTX 3060 - 82× más rápido (0.84s/página) - [x] **Infraestructura Docker**: 5 imágenes (PaddleOCR, EasyOCR, DocTR, RayTune) ### Dataset El dataset contiene **45 páginas** de 2 documentos UNIR: - `src/dataset/0/`: Instrucciones TFE (24 páginas) - `src/dataset/1/`: Plantilla TFE (21 páginas) #### Formato Hugging Face El dataset está disponible en formato Hugging Face en `src/dataset_hf/`: ``` src/dataset_hf/ ├── README.md # Dataset card ├── metadata.jsonl # Metadata (image_path, text, doc_id, page_num) └── data/ # 45 imágenes PNG ``` #### Generar/Regenerar Dataset ```bash # Convertir de formato original a HF source .venv/bin/activate python src/dataset_formatting/convert_to_hf_dataset.py # Upload a Gitea packages (requiere GITEA_TOKEN) ./src/dataset_formatting/upload-dataset.sh $GITEA_TOKEN ``` #### Descargar Dataset ```bash # Desde Gitea packages curl -O https://seryus.ddns.net/api/packages/unir/generic/ocr-dataset-spanish/1.0.0/dataset-1.0.0.tar.gz tar -xzf dataset-1.0.0.tar.gz -C src/dataset_hf/ ``` --- ## Licencia Este proyecto es parte de un Trabajo Fin de Máster académico. --- ## Referencias - [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) - [EasyOCR](https://github.com/JaidedAI/EasyOCR) - [DocTR](https://github.com/mindee/doctr) - [Ray Tune](https://docs.ray.io/en/latest/tune/index.html) - [Optuna](https://optuna.org/) - [jiwer](https://github.com/jitsi/jiwer) - [PyMuPDF](https://pymupdf.readthedocs.io/)