Files
MastersThesis/docs/04_desarrollo_especifico.md

567 lines
22 KiB
Markdown
Raw Normal View History

2025-12-16 00:53:27 +01:00
# Desarrollo específico de la contribución
Este capítulo presenta el desarrollo completo del estudio comparativo y la optimización de hiperparámetros de sistemas OCR. Se estructura según el tipo de trabajo "Comparativa de soluciones" establecido por las instrucciones de UNIR: planteamiento de la comparativa, desarrollo de la comparativa, y discusión y análisis de resultados.
## Planteamiento de la comparativa
### Introducción
Esta sección presenta los resultados del estudio comparativo realizado entre tres soluciones OCR de código abierto: EasyOCR, PaddleOCR y DocTR. Los experimentos fueron documentados en el notebook `ocr_benchmark_notebook.ipynb` del repositorio. El objetivo es identificar el modelo base más prometedor para la posterior fase de optimización de hiperparámetros.
### Configuración del Experimento
#### Dataset de Evaluación
Se utilizó el documento "Instrucciones para la redacción y elaboración del TFE" del Máster Universitario en Inteligencia Artificial de UNIR, ubicado en la carpeta `instructions/`.
**Tabla 3.** *Características del dataset de evaluación.*
| Característica | Valor |
|----------------|-------|
| Número de páginas evaluadas | 5 (páginas 1-5 en benchmark inicial) |
| Formato | PDF digital (no escaneado) |
| Idioma | Español |
| Resolución de conversión | 300 DPI |
*Fuente: Elaboración propia.*
#### Configuración de los Modelos
Según el código en `ocr_benchmark_notebook.ipynb`:
**EasyOCR**:
```python
easyocr_reader = easyocr.Reader(['es', 'en']) # Spanish and English
```
**PaddleOCR (PP-OCRv5)**:
```python
paddleocr_model = PaddleOCR(
text_detection_model_name="PP-OCRv5_server_det",
text_recognition_model_name="PP-OCRv5_server_rec",
use_doc_orientation_classify=False,
use_doc_unwarping=False,
use_textline_orientation=True,
)
```
Versión utilizada: PaddleOCR 3.2.0 (según output del notebook)
**DocTR**:
```python
doctr_model = ocr_predictor(det_arch="db_resnet50", reco_arch="sar_resnet31", pretrained=True)
```
#### Métricas de Evaluación
Se utilizó la biblioteca `jiwer` para calcular CER y WER:
```python
from jiwer import wer, cer
def evaluate_text(reference, prediction):
return {'WER': wer(reference, prediction), 'CER': cer(reference, prediction)}
```
### Resultados del Benchmark
#### Resultados de PaddleOCR (Configuración Baseline)
Durante el benchmark inicial se evaluó PaddleOCR con configuración por defecto en un subconjunto del dataset. Los resultados preliminares mostraron variabilidad significativa entre páginas, con CER entre 1.54% y 6.40% dependiendo de la complejidad del layout.
**Observaciones del benchmark inicial:**
- Las páginas con tablas y layouts complejos presentaron mayor error
- La página 8 (texto corrido) obtuvo el mejor resultado (CER ~1.5%)
- El promedio general se situó en CER ~5-6%
#### Comparativa de Modelos
Según la documentación del notebook `ocr_benchmark_notebook.ipynb`, los tres modelos evaluados representan diferentes paradigmas de OCR:
**Tabla 5.** *Comparativa de arquitecturas OCR evaluadas.*
| Modelo | Tipo | Componentes | Fortalezas Clave |
|--------|------|-------------|------------------|
| **EasyOCR** | End-to-end (det + rec) | DB + CRNN/Transformer | Ligero, fácil de usar, multilingüe |
| **PaddleOCR (PP-OCR)** | End-to-end (det + rec + cls) | DB + SRN/CRNN | Soporte multilingüe robusto, pipeline configurable |
| **DocTR** | End-to-end (det + rec) | DB/LinkNet + CRNN/SAR/VitSTR | Orientado a investigación, API limpia |
*Fuente: Documentación oficial de cada herramienta (JaidedAI, 2020; PaddlePaddle, 2024; Mindee, 2021).*
#### Ejemplo de Salida OCR
Del archivo CSV, un ejemplo de predicción de PaddleOCR para la página 8:
> "Escribe siempre al menos un párrafo de introducción en cada capítulo o apartado, explicando de qué vas a tratar en esa sección. Evita que aparezcan dos encabezados de nivel consecutivos sin ningún texto entre medias. [...] En esta titulacióon se cita de acuerdo con la normativa Apa."
**Errores observados en este ejemplo:**
- `titulacióon` en lugar de `titulación` (carácter duplicado)
- `Apa` en lugar de `APA` (capitalización)
### Justificación de la Selección de PaddleOCR
#### Criterios de Selección
Basándose en los resultados obtenidos y la documentación del benchmark:
1. **Rendimiento**: PaddleOCR obtuvo CER entre 1.54% y 6.40% en las páginas evaluadas
2. **Configurabilidad**: PaddleOCR ofrece múltiples hiperparámetros ajustables:
- Umbrales de detección (`text_det_thresh`, `text_det_box_thresh`)
- Umbral de reconocimiento (`text_rec_score_thresh`)
- Componentes opcionales (`use_textline_orientation`, `use_doc_orientation_classify`, `use_doc_unwarping`)
3. **Documentación oficial**: [PaddleOCR Documentation](https://www.paddleocr.ai/v3.0.0/en/version3.x/pipeline_usage/OCR.html)
#### Decisión
**Se selecciona PaddleOCR (PP-OCRv5)** para la fase de optimización debido a:
- Resultados iniciales prometedores (CER ~5%)
- Alta configurabilidad de hiperparámetros de inferencia
- Pipeline modular que permite experimentación
### Limitaciones del Benchmark
1. **Tamaño reducido**: Solo 5 páginas evaluadas en el benchmark comparativo inicial
2. **Único tipo de documento**: Documentos académicos de UNIR únicamente
3. **Ground truth**: El texto de referencia se extrajo automáticamente del PDF, lo cual puede introducir errores en layouts complejos
### Resumen de la Sección
Esta sección ha presentado:
1. La configuración del benchmark según `ocr_benchmark_notebook.ipynb`
2. Los resultados cuantitativos de PaddleOCR del archivo CSV de resultados
3. La justificación de la selección de PaddleOCR para optimización
**Fuentes de datos utilizadas:**
- `ocr_benchmark_notebook.ipynb`: Código del benchmark
- Documentación oficial de PaddleOCR
## Desarrollo de la comparativa: Optimización de hiperparámetros
### Introducción
Esta sección describe el proceso de optimización de hiperparámetros de PaddleOCR utilizando Ray Tune con el algoritmo de búsqueda Optuna. Los experimentos fueron implementados en el notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb` y los resultados se almacenaron en `src/raytune_paddle_subproc_results_20251207_192320.csv`.
### Configuración del Experimento
#### Entorno de Ejecución
Según los outputs del notebook:
**Tabla 6.** *Entorno de ejecución del experimento.*
| Componente | Versión/Especificación |
|------------|------------------------|
| Python | 3.11.9 |
| PaddlePaddle | 3.2.2 |
| PaddleOCR | 3.3.2 |
| Ray | 2.52.1 |
| GPU | No disponible (CPU only) |
*Fuente: Outputs del notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`.*
#### Dataset
Se utilizó un dataset estructurado en `src/dataset/` creado mediante el notebook `src/prepare_dataset.ipynb`:
- **Estructura**: Carpetas con subcarpetas `img/` y `txt/` pareadas
- **Páginas evaluadas por trial**: 5 (páginas 5-10 del documento)
- **Gestión de datos**: Clase `ImageTextDataset` en `src/dataset_manager.py`
#### Espacio de Búsqueda
Según el código del notebook, se definió el siguiente espacio de búsqueda:
```python
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]), # Fijado
"text_rec_score_thresh": tune.uniform(0.0, 0.7),
}
```
**Descripción de parámetros** (según documentación de PaddleOCR):
| Parámetro | Descripción |
|-----------|-------------|
| `use_doc_orientation_classify` | Clasificación de orientación del documento |
| `use_doc_unwarping` | Corrección de deformación del documento |
| `textline_orientation` | Clasificación de orientación de línea de texto |
| `text_det_thresh` | Umbral de detección de píxeles de texto |
| `text_det_box_thresh` | Umbral de caja de detección |
| `text_det_unclip_ratio` | Coeficiente de expansión (fijado en 0.0) |
| `text_rec_score_thresh` | Umbral de confianza de reconocimiento |
#### Configuración de Ray Tune
```python
tuner = tune.Tuner(
trainable_paddle_ocr,
tune_config=tune.TuneConfig(
metric="CER",
mode="min",
search_alg=OptunaSearch(),
num_samples=64,
max_concurrent_trials=2
),
run_config=air.RunConfig(verbose=2, log_to_file=False),
param_space=search_space
)
```
- **Métrica objetivo**: CER (minimizar)
- **Algoritmo de búsqueda**: Optuna (TPE - Tree-structured Parzen Estimator)
- **Número de trials**: 64
- **Trials concurrentes**: 2
### Resultados de la Optimización
#### Estadísticas Descriptivas
Del archivo CSV de resultados (`raytune_paddle_subproc_results_20251207_192320.csv`):
**Tabla 7.** *Estadísticas descriptivas de los 64 trials de Ray Tune.*
| Estadística | CER | WER | Tiempo (s) | Tiempo/Página (s) |
|-------------|-----|-----|------------|-------------------|
| **count** | 64 | 64 | 64 | 64 |
| **mean** | 5.25% | 14.28% | 347.61 | 69.42 |
| **std** | 11.03% | 10.75% | 7.88 | 1.57 |
| **min** | 1.15% | 9.89% | 320.97 | 64.10 |
| **25%** | 1.20% | 10.04% | 344.24 | 68.76 |
| **50%** | 1.23% | 10.20% | 346.42 | 69.19 |
| **75%** | 4.03% | 13.20% | 350.14 | 69.93 |
| **max** | 51.61% | 59.45% | 368.57 | 73.63 |
*Fuente: `src/raytune_paddle_subproc_results_20251207_192320.csv`.*
#### Mejor Configuración Encontrada
Según el análisis del notebook:
```
Best CER: 0.011535 (1.15%)
Best WER: 0.098902 (9.89%)
Configuración óptima:
textline_orientation: True
use_doc_orientation_classify: False
use_doc_unwarping: False
text_det_thresh: 0.4690
text_det_box_thresh: 0.5412
text_det_unclip_ratio: 0.0
text_rec_score_thresh: 0.6350
```
#### Análisis de Correlación
Correlación de Pearson entre parámetros y métricas de error (del notebook):
**Correlación con CER:**
| Parámetro | Correlación |
|-----------|-------------|
| CER | 1.000 |
| config/text_det_box_thresh | 0.226 |
| config/text_rec_score_thresh | -0.161 |
| **config/text_det_thresh** | **-0.523** |
| config/text_det_unclip_ratio | NaN |
**Correlación con WER:**
| Parámetro | Correlación |
|-----------|-------------|
| WER | 1.000 |
| config/text_det_box_thresh | 0.227 |
| config/text_rec_score_thresh | -0.173 |
| **config/text_det_thresh** | **-0.521** |
| config/text_det_unclip_ratio | NaN |
**Hallazgo clave**: El parámetro `text_det_thresh` muestra la correlación más fuerte (-0.52), indicando que valores más altos de este umbral tienden a reducir el error.
#### Impacto del Parámetro textline_orientation
Según el análisis del notebook, este parámetro booleano tiene el mayor impacto:
**Tabla 8.** *Impacto del parámetro textline_orientation en las métricas de error.*
| textline_orientation | CER Medio | WER Medio |
|---------------------|-----------|-----------|
| True | ~3.76% | ~12.73% |
| False | ~12.40% | ~21.71% |
*Fuente: Análisis del notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`.*
**Interpretación**:
El CER medio es ~3.3x menor con `textline_orientation=True` (3.76% vs 12.40%). Además, la varianza es mucho menor, lo que indica resultados más consistentes. Para documentos en español con layouts mixtos (tablas, encabezados, direcciones), la clasificación de orientación ayuda a PaddleOCR a ordenar correctamente las líneas de texto.
```mermaid
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#0098CD'}}}%%
xychart-beta
title "Impacto de textline_orientation en CER"
x-axis ["textline_orientation=False", "textline_orientation=True"]
y-axis "CER (%)" 0 --> 15
bar [12.40, 3.76]
```
*Figura 3. Comparación del CER medio según el valor del parámetro textline_orientation.*
#### Análisis de Fallos
Los trials con CER muy alto (>40%) se produjeron cuando:
- `text_det_thresh` < 0.1 (valores muy bajos)
- `textline_orientation = False`
Ejemplo de trial con fallo catastrófico:
- CER: 51.61%
- WER: 59.45%
- Configuración: `text_det_thresh=0.017`, `textline_orientation=True`
### Comparación Baseline vs Optimizado
#### Resultados sobre Dataset Completo (24 páginas)
Del análisis final del notebook ejecutando sobre las 24 páginas:
**Tabla 9.** *Comparación baseline vs configuración optimizada (24 páginas).*
| Modelo | CER | WER |
|--------|-----|-----|
| PaddleOCR (Baseline) | 7.78% | 14.94% |
| PaddleOCR-HyperAdjust | 1.49% | 7.62% |
*Fuente: Ejecución final en notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`.*
#### Métricas de Mejora
**Tabla 10.** *Análisis de la mejora obtenida.*
| Métrica | Baseline | Optimizado | Mejora Absoluta | Reducción Error |
|---------|----------|------------|-----------------|-----------------|
| CER | 7.78% | 1.49% | -6.29 pp | 80.9% |
| WER | 14.94% | 7.62% | -7.32 pp | 49.0% |
*Fuente: Elaboración propia a partir de los resultados experimentales.*
#### Interpretación (del notebook)
> "La optimización de hiperparámetros mejoró la precisión de caracteres de 92.2% a 98.5%, una ganancia de 6.3 puntos porcentuales. Aunque el baseline ya ofrecía resultados aceptables, la configuración optimizada reduce los errores residuales en un 80.9%."
```mermaid
%%{init: {'theme': 'base'}}%%
xychart-beta
title "Comparación Baseline vs Optimizado (24 páginas)"
x-axis ["CER", "WER"]
y-axis "Tasa de error (%)" 0 --> 16
bar "Baseline" [7.78, 14.94]
bar "Optimizado" [1.49, 7.62]
```
*Figura 4. Comparación de métricas de error entre configuración baseline y optimizada.*
**Impacto práctico**: En un documento de 10,000 caracteres:
- Baseline: ~778 caracteres con error
- Optimizado: ~149 caracteres con error
- Diferencia: ~629 caracteres menos con errores
### Tiempo de Ejecución
| Métrica | Valor |
|---------|-------|
| Tiempo total del experimento | ~6 horas (64 trials × ~6 min/trial) |
| Tiempo medio por trial | 367.72 segundos |
| Tiempo medio por página | 69.42 segundos |
| Total páginas procesadas | 64 trials × 5 páginas = 320 evaluaciones |
### Resumen de la Sección
Esta sección ha presentado:
1. **Configuración del experimento**: 64 trials con Ray Tune + Optuna sobre 7 hiperparámetros
2. **Resultados estadísticos**: CER medio 5.25%, CER mínimo 1.15%
3. **Hallazgos clave**:
- `textline_orientation=True` es crítico (reduce CER ~70%)
- `text_det_thresh` tiene correlación -0.52 con CER
- Valores bajos de `text_det_thresh` (<0.1) causan fallos catastróficos
4. **Mejora final**: CER reducido de 7.78% a 1.49% (reducción del 80.9%)
**Fuentes de datos:**
- `src/paddle_ocr_fine_tune_unir_raytune.ipynb`: Código del experimento
- `src/raytune_paddle_subproc_results_20251207_192320.csv`: Resultados de 64 trials
- `src/paddle_ocr_tuning.py`: Script de evaluación
## Discusión y análisis de resultados
### Introducción
Esta sección presenta un análisis consolidado de los resultados obtenidos en las fases de benchmark comparativo y optimización de hiperparámetros. Se discuten las implicaciones prácticas y se evalúa el cumplimiento de los objetivos planteados.
### Resumen de Resultados
#### Resultados del Benchmark Comparativo
En el benchmark inicial, PaddleOCR con configuración por defecto mostró variabilidad en el rendimiento según la complejidad de cada página, con CER promedio en torno al 5-6% y variaciones significativas entre páginas con layouts simples (~1.5%) y complejos (~6.4%).
#### Resultados de la Optimización con Ray Tune
Del archivo `src/raytune_paddle_subproc_results_20251207_192320.csv` (64 trials):
| Métrica | Valor |
|---------|-------|
| CER mínimo | 1.15% |
| CER medio | 5.25% |
| CER máximo | 51.61% |
| WER mínimo | 9.89% |
| WER medio | 14.28% |
| WER máximo | 59.45% |
#### Comparación Final (Dataset Completo - 24 páginas)
Resultados del notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`:
| Modelo | CER | Precisión Caracteres | WER | Precisión Palabras |
|--------|-----|---------------------|-----|-------------------|
| PaddleOCR (Baseline) | 7.78% | 92.22% | 14.94% | 85.06% |
| PaddleOCR-HyperAdjust | 1.49% | 98.51% | 7.62% | 92.38% |
### Análisis de Resultados
#### Mejora Obtenida
| Forma de Medición | Valor |
|-------------------|-------|
| Mejora en precisión de caracteres (absoluta) | +6.29 puntos porcentuales |
| Reducción del CER (relativa) | 80.9% |
| Mejora en precisión de palabras (absoluta) | +7.32 puntos porcentuales |
| Reducción del WER (relativa) | 49.0% |
| Precisión final de caracteres | 98.51% |
#### Impacto de Hiperparámetros Individuales
**Parámetro `textline_orientation`**
Este parámetro booleano demostró ser el más influyente:
| Valor | CER Medio | Impacto |
|-------|-----------|---------|
| True | ~3.76% | Rendimiento óptimo |
| False | ~12.40% | 3.3x peor |
**Reducción del CER**: 69.7% cuando se habilita la clasificación de orientación de línea.
**Parámetro `text_det_thresh`**
Correlación con CER: **-0.523** (la más fuerte de los parámetros continuos)
| Rango | Comportamiento |
|-------|----------------|
| < 0.1 | Fallos catastróficos (CER 40-50%) |
| 0.3 - 0.6 | Rendimiento óptimo |
| Valor óptimo | 0.4690 |
**Parámetros con menor impacto**
| Parámetro | Correlación con CER | Valor óptimo |
|-----------|---------------------|--------------|
| text_det_box_thresh | +0.226 | 0.5412 |
| text_rec_score_thresh | -0.161 | 0.6350 |
| use_doc_orientation_classify | - | False |
| use_doc_unwarping | - | False |
#### Configuración Óptima Final
```python
config_optimizada = {
"textline_orientation": True, # CRÍTICO
"use_doc_orientation_classify": False,
"use_doc_unwarping": False,
"text_det_thresh": 0.4690, # Correlación -0.52
"text_det_box_thresh": 0.5412,
"text_det_unclip_ratio": 0.0,
"text_rec_score_thresh": 0.6350,
}
```
### Discusión
#### Hallazgos Principales
1. **Importancia de la clasificación de orientación de línea**: El parámetro `textline_orientation=True` es el factor más determinante. Esto tiene sentido para documentos con layouts mixtos (tablas, encabezados, direcciones) donde el orden correcto de las líneas de texto es crucial.
2. **Umbral de detección crítico**: El parámetro `text_det_thresh` presenta un umbral mínimo efectivo (~0.1). Valores inferiores generan demasiados falsos positivos en la detección, corrompiendo el reconocimiento posterior.
3. **Componentes opcionales innecesarios**: Para documentos académicos digitales (no escaneados), los módulos de corrección de orientación de documento (`use_doc_orientation_classify`) y corrección de deformación (`use_doc_unwarping`) no aportan mejora e incluso pueden introducir overhead.
#### Interpretación de la Correlación Negativa
La correlación negativa de `text_det_thresh` (-0.52) con el CER indica que:
- Umbrales más altos filtran detecciones de baja confianza
- Esto reduce falsos positivos que generan texto erróneo
- El reconocimiento es más preciso con menos regiones pero más confiables
#### Limitaciones de los Resultados
1. **Generalización**: Los resultados se obtuvieron sobre documentos de un único tipo (instrucciones académicas UNIR). La configuración óptima puede variar para otros tipos de documentos.
2. **Ground truth automático**: El texto de referencia se extrajo programáticamente del PDF. En layouts complejos, esto puede introducir errores en la evaluación.
3. **Ejecución en CPU**: Los tiempos reportados (~69s/página) corresponden a ejecución en CPU. Con GPU, los tiempos serían significativamente menores.
4. **Parámetro fijo**: `text_det_unclip_ratio` permaneció fijo en 0.0 durante todo el experimento por decisión de diseño.
#### Comparación con Objetivos
| Objetivo | Meta | Resultado | Cumplimiento |
|----------|------|-----------|--------------|
| OE1: Comparar soluciones OCR | Evaluar EasyOCR, PaddleOCR, DocTR | PaddleOCR seleccionado | ✓ |
| OE2: Preparar dataset | Construir dataset estructurado | Dataset de 24 páginas | ✓ |
| OE3: Identificar hiperparámetros críticos | Analizar correlaciones | `textline_orientation` y `text_det_thresh` identificados | ✓ |
| OE4: Optimizar con Ray Tune | Mínimo 50 configuraciones | 64 trials ejecutados | ✓ |
| OE5: Validar configuración | Documentar mejora | CER 7.78% → 1.49% | ✓ |
| **Objetivo General** | CER < 2% | CER = 1.49% | ✓ |
### Implicaciones Prácticas
#### Recomendaciones de Configuración
Para documentos académicos en español similares a los evaluados:
1. **Obligatorio**: `use_textline_orientation=True`
2. **Recomendado**: `text_det_thresh` entre 0.4 y 0.5
3. **Opcional**: `text_det_box_thresh` ~0.5, `text_rec_score_thresh` >0.6
4. **No recomendado**: Habilitar `use_doc_orientation_classify` o `use_doc_unwarping` para documentos digitales
#### Impacto Cuantitativo
En un documento típico de 10,000 caracteres:
| Configuración | Errores estimados |
|---------------|-------------------|
| Baseline | ~778 caracteres |
| Optimizada | ~149 caracteres |
| **Reducción** | **629 caracteres menos con errores** |
#### Aplicabilidad
Esta metodología de optimización es aplicable cuando:
- No se dispone de recursos GPU para fine-tuning
- El modelo preentrenado ya tiene soporte para el idioma objetivo
- Se busca mejorar rendimiento sin reentrenar
### Resumen de la Sección
Esta sección ha presentado:
1. Los resultados consolidados del benchmark y la optimización
2. El análisis del impacto de cada hiperparámetro
3. La configuración óptima identificada
4. La discusión de limitaciones y aplicabilidad
5. El cumplimiento de los objetivos planteados
**Resultado principal**: Se logró reducir el CER del 7.78% al 1.49% (mejora del 80.9%) mediante optimización de hiperparámetros, cumpliendo el objetivo de alcanzar CER < 2%.
**Fuentes de datos:**
- `src/raytune_paddle_subproc_results_20251207_192320.csv`: Resultados de 64 trials de optimización
- `src/paddle_ocr_fine_tune_unir_raytune.ipynb`: Notebook principal del experimento