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:
@@ -34,6 +34,11 @@ Se seleccionaron tres soluciones OCR de código abierto representativas del esta
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
**Imágenes Docker disponibles en el registro del proyecto:**
|
||||
- PaddleOCR: `seryus.ddns.net/unir/paddle-ocr-gpu`, `seryus.ddns.net/unir/paddle-ocr-cpu`
|
||||
- EasyOCR: `seryus.ddns.net/unir/easyocr-gpu`
|
||||
- DocTR: `seryus.ddns.net/unir/doctr-gpu`
|
||||
|
||||
### Criterios de Éxito
|
||||
|
||||
Los criterios establecidos para evaluar las soluciones fueron:
|
||||
@@ -65,121 +70,25 @@ Se utilizó el documento "Instrucciones para la redacción y elaboración del TF
|
||||
|
||||
#### Proceso de Conversión
|
||||
|
||||
La conversión del PDF a imágenes se realizó mediante PyMuPDF (fitz):
|
||||
|
||||
```python
|
||||
import fitz # PyMuPDF
|
||||
|
||||
def pdf_to_images(pdf_path, output_dir, dpi=300):
|
||||
doc = fitz.open(pdf_path)
|
||||
for page_num, page in enumerate(doc):
|
||||
# Matriz de transformación para 300 DPI
|
||||
mat = fitz.Matrix(dpi/72, dpi/72)
|
||||
pix = page.get_pixmap(matrix=mat)
|
||||
pix.save(f"{output_dir}/page_{page_num:04d}.png")
|
||||
```
|
||||
|
||||
La resolución de 300 DPI fue seleccionada como estándar para OCR de documentos, proporcionando suficiente detalle para caracteres pequeños sin generar archivos excesivamente grandes.
|
||||
La conversión del PDF a imágenes se realizó mediante PyMuPDF (fitz) a 300 DPI, resolución estándar para OCR que proporciona suficiente detalle para caracteres pequeños sin generar archivos excesivamente grandes. La implementación está disponible en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A).
|
||||
|
||||
#### Extracción del Ground Truth
|
||||
|
||||
El texto de referencia se extrajo directamente del PDF mediante PyMuPDF:
|
||||
|
||||
```python
|
||||
def extract_text(pdf_path):
|
||||
doc = fitz.open(pdf_path)
|
||||
text = ""
|
||||
for page in doc:
|
||||
blocks = page.get_text("dict")["blocks"]
|
||||
for block in blocks:
|
||||
if "lines" in block:
|
||||
for line in block["lines"]:
|
||||
for span in line["spans"]:
|
||||
text += span["text"]
|
||||
text += "\n"
|
||||
return text
|
||||
```
|
||||
|
||||
Esta aproximación preserva la estructura de líneas del documento original, aunque puede introducir errores en layouts muy complejos (tablas anidadas, texto en columnas).
|
||||
El texto de referencia se extrajo directamente del PDF mediante PyMuPDF, preservando la estructura de líneas del documento original. Esta aproximación puede introducir errores en layouts muy complejos (tablas anidadas, texto en columnas). La implementación está disponible en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A).
|
||||
|
||||
#### Configuración de los Modelos
|
||||
|
||||
Según el código en `ocr_benchmark_notebook.ipynb`:
|
||||
La configuración de cada modelo se detalla en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A):
|
||||
|
||||
**EasyOCR**:
|
||||
```python
|
||||
import easyocr
|
||||
- **EasyOCR**: Configurado con soporte para español e inglés, permitiendo reconocer palabras en ambos idiomas que puedan aparecer en documentos académicos (referencias, términos técnicos).
|
||||
|
||||
easyocr_reader = easyocr.Reader(['es', 'en']) # Spanish and English
|
||||
results = easyocr_reader.readtext(image_path)
|
||||
text = ' '.join([r[1] for r in results])
|
||||
```
|
||||
- **PaddleOCR (PP-OCRv5)**: Se utilizaron los modelos "server" (PP-OCRv5_server_det y PP-OCRv5_server_rec) que ofrecen mayor precisión a costa de mayor tiempo de inferencia. La versión utilizada fue PaddleOCR 3.2.0.
|
||||
|
||||
La configuración incluye soporte para español e inglés, permitiendo reconocer palabras en ambos idiomas que puedan aparecer en documentos académicos (referencias, términos técnicos).
|
||||
|
||||
**PaddleOCR (PP-OCRv5)**:
|
||||
```python
|
||||
from paddleocr import PaddleOCR
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
result = paddleocr_model.predict(image_path)
|
||||
text = '\n'.join([line['rec_texts'][0] for line in result[0]['rec_res']])
|
||||
```
|
||||
|
||||
Se utilizaron los modelos "server" que ofrecen mayor precisión a costa de mayor tiempo de inferencia. La versión utilizada fue PaddleOCR 3.2.0.
|
||||
|
||||
**DocTR**:
|
||||
```python
|
||||
from doctr.models import ocr_predictor
|
||||
|
||||
doctr_model = ocr_predictor(
|
||||
det_arch="db_resnet50",
|
||||
reco_arch="sar_resnet31",
|
||||
pretrained=True
|
||||
)
|
||||
|
||||
result = doctr_model([image])
|
||||
text = result.render()
|
||||
```
|
||||
|
||||
Se seleccionaron las arquitecturas db_resnet50 para detección y sar_resnet31 para reconocimiento, representando una configuración de alta precisión.
|
||||
- **DocTR**: Se seleccionaron las arquitecturas db_resnet50 para detección y sar_resnet31 para reconocimiento, representando una configuración de alta precisión.
|
||||
|
||||
#### Métricas de Evaluación
|
||||
|
||||
Se utilizó la biblioteca `jiwer` para calcular CER y WER de manera estandarizada:
|
||||
|
||||
```python
|
||||
from jiwer import wer, cer
|
||||
|
||||
def evaluate_text(reference, prediction):
|
||||
"""
|
||||
Calcula métricas de error entre texto de referencia y predicción.
|
||||
|
||||
Args:
|
||||
reference: Texto ground truth
|
||||
prediction: Texto predicho por el OCR
|
||||
|
||||
Returns:
|
||||
dict con WER y CER
|
||||
"""
|
||||
# Normalización básica
|
||||
ref_clean = reference.lower().strip()
|
||||
pred_clean = prediction.lower().strip()
|
||||
|
||||
return {
|
||||
'WER': wer(ref_clean, pred_clean),
|
||||
'CER': cer(ref_clean, pred_clean)
|
||||
}
|
||||
```
|
||||
|
||||
La normalización a minúsculas y eliminación de espacios extremos asegura una comparación justa que no penaliza diferencias de capitalización.
|
||||
Se utilizó la biblioteca `jiwer` para calcular CER y WER de manera estandarizada. La normalización a minúsculas y eliminación de espacios extremos asegura una comparación justa que no penaliza diferencias de capitalización. La implementación está disponible en `src/ocr_benchmark_notebook.ipynb` (ver Anexo A).
|
||||
|
||||
### Resultados del Benchmark
|
||||
|
||||
@@ -322,7 +231,7 @@ Esta sección ha presentado:
|
||||
|
||||
### 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`.
|
||||
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 [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py) con la librería de utilidades [`src/raytune_ocr.py`](https://github.com/seryus/MastersThesis/blob/main/src/raytune_ocr.py), y los resultados se almacenaron en [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results).
|
||||
|
||||
La optimización de hiperparámetros representa una alternativa al fine-tuning tradicional que no requiere:
|
||||
- Acceso a GPU dedicada
|
||||
@@ -339,59 +248,68 @@ El experimento se ejecutó en el siguiente entorno:
|
||||
|
||||
| Componente | Versión/Especificación |
|
||||
|------------|------------------------|
|
||||
| Sistema operativo | Windows 10/11 |
|
||||
| Python | 3.11.9 |
|
||||
| Sistema operativo | Ubuntu 24.04.3 LTS |
|
||||
| Python | 3.12.3 |
|
||||
| PaddlePaddle | 3.2.2 |
|
||||
| PaddleOCR | 3.3.2 |
|
||||
| Ray | 2.52.1 |
|
||||
| Optuna | 4.6.0 |
|
||||
| CPU | Intel Core (multinúcleo) |
|
||||
| RAM | 16 GB |
|
||||
| GPU | No disponible (ejecución CPU) |
|
||||
| Optuna | 4.7.0 |
|
||||
| CPU | AMD Ryzen 7 5800H |
|
||||
| RAM | 16 GB DDR4 |
|
||||
| GPU | NVIDIA RTX 3060 Laptop (5.66 GB VRAM) |
|
||||
|
||||
*Fuente: Outputs del notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`.*
|
||||
*Fuente: Configuración del entorno de ejecución. Resultados en `src/results/` generados por `src/run_tuning.py`.*
|
||||
|
||||
#### Arquitectura de Ejecución
|
||||
|
||||
Debido a incompatibilidades entre Ray y PaddleOCR cuando se ejecutan en el mismo proceso, se implementó una arquitectura basada en subprocesos:
|
||||
La arquitectura basada en contenedores Docker es fundamental para este proyecto debido a los conflictos de dependencias inherentes entre los diferentes componentes:
|
||||
|
||||
- **Conflictos entre motores OCR**: PaddleOCR, DocTR y EasyOCR tienen dependencias mutuamente incompatibles (diferentes versiones de PyTorch/PaddlePaddle, OpenCV, etc.)
|
||||
- **Incompatibilidades CUDA/cuDNN**: Cada motor OCR requiere versiones específicas de CUDA y cuDNN que no pueden coexistir en un mismo entorno virtual
|
||||
- **Aislamiento de Ray Tune**: Ray Tune tiene sus propias dependencias que pueden entrar en conflicto con las librerías de inferencia OCR
|
||||
|
||||
Esta arquitectura containerizada permite ejecutar cada componente en su entorno aislado óptimo, comunicándose via API REST:
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: "Arquitectura de ejecución con subprocesos"
|
||||
title: "Arquitectura de ejecución con Docker Compose"
|
||||
---
|
||||
flowchart LR
|
||||
A["Ray Tune (proceso principal)"]
|
||||
subgraph Docker["Docker Compose"]
|
||||
A["RayTune Container"]
|
||||
B["OCR Service Container"]
|
||||
end
|
||||
|
||||
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"]
|
||||
A -->|"HTTP POST /evaluate"| B
|
||||
B -->|"JSON {CER, WER, TIME}"| A
|
||||
A -.->|"Health check /health"| B
|
||||
```
|
||||
|
||||
El script `src/paddle_ocr_tuning.py` actúa como wrapper que:
|
||||
1. Recibe hiperparámetros por línea de comandos
|
||||
2. Inicializa PaddleOCR con la configuración especificada
|
||||
3. Evalúa sobre el dataset
|
||||
4. Retorna métricas en formato JSON
|
||||
La arquitectura containerizada (`src/docker-compose.tuning.*.yml`) ofrece:
|
||||
1. Aislamiento de dependencias entre Ray Tune y los motores OCR
|
||||
2. Health checks automáticos para asegurar disponibilidad del servicio
|
||||
3. Comunicación via API REST (endpoints `/health` y `/evaluate`)
|
||||
4. Soporte para GPU mediante nvidia-docker
|
||||
|
||||
```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 con GPU
|
||||
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
|
||||
```
|
||||
|
||||
Salida:
|
||||
Respuesta del servicio OCR:
|
||||
```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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -411,54 +329,11 @@ Para la fase de optimización se extendió el dataset:
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
La clase `ImageTextDataset` en `src/dataset_manager.py` gestiona la carga de pares imagen-texto:
|
||||
|
||||
```python
|
||||
class ImageTextDataset:
|
||||
def __init__(self, root):
|
||||
"""
|
||||
Carga pares (imagen, texto) de carpetas pareadas.
|
||||
|
||||
Estructura esperada:
|
||||
root/
|
||||
0/
|
||||
img/
|
||||
page_0001.png
|
||||
txt/
|
||||
page_0001.txt
|
||||
"""
|
||||
self.pairs = []
|
||||
for doc_folder in sorted(os.listdir(root)):
|
||||
img_folder = os.path.join(root, doc_folder, 'img')
|
||||
txt_folder = os.path.join(root, doc_folder, 'txt')
|
||||
# Cargar pares...
|
||||
|
||||
def __getitem__(self, idx):
|
||||
img_path, txt_path = self.pairs[idx]
|
||||
return PIL.Image.open(img_path), open(txt_path).read()
|
||||
```
|
||||
La clase `ImageTextDataset` gestiona la carga de pares imagen-texto desde la estructura de carpetas pareadas. La implementación está disponible en el repositorio (ver Anexo A).
|
||||
|
||||
#### Espacio de Búsqueda
|
||||
|
||||
El espacio de búsqueda se definió considerando los hiperparámetros más relevantes identificados en la documentación de PaddleOCR:
|
||||
|
||||
```python
|
||||
from ray import tune
|
||||
from ray.tune.search.optuna import OptunaSearch
|
||||
|
||||
search_space = {
|
||||
# Parámetros booleanos
|
||||
"use_doc_orientation_classify": tune.choice([True, False]),
|
||||
"use_doc_unwarping": tune.choice([True, False]),
|
||||
"textline_orientation": tune.choice([True, False]),
|
||||
|
||||
# Parámetros continuos (umbrales)
|
||||
"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),
|
||||
}
|
||||
```
|
||||
El espacio de búsqueda se definió considerando los hiperparámetros más relevantes identificados en la documentación de PaddleOCR, utilizando `tune.choice()` para parámetros booleanos y `tune.uniform()` para umbrales continuos. La implementación está disponible en `src/raytune/raytune_ocr.py` (ver Anexo A).
|
||||
|
||||
**Tabla 17.** *Descripción detallada del espacio de búsqueda.*
|
||||
|
||||
@@ -484,23 +359,7 @@ search_space = {
|
||||
|
||||
#### 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
|
||||
)
|
||||
```
|
||||
Se configuró Ray Tune con OptunaSearch como algoritmo de búsqueda, optimizando CER en 64 trials con 2 ejecuciones concurrentes. La implementación está disponible en `src/raytune/raytune_ocr.py` (ver Anexo A).
|
||||
|
||||
**Tabla 18.** *Parámetros de configuración de Ray Tune.*
|
||||
|
||||
@@ -613,7 +472,7 @@ Configuración óptima:
|
||||
| text_det_unclip_ratio | 0.0 | 1.5 | -1.5 (fijado) |
|
||||
| text_rec_score_thresh | **0.6350** | 0.5 | +0.135 |
|
||||
|
||||
*Fuente: Análisis del notebook.*
|
||||
*Fuente: Análisis de [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results) generados por [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py).*
|
||||
|
||||
#### Análisis de Correlación
|
||||
|
||||
@@ -628,7 +487,7 @@ Se calculó la correlación de Pearson entre los parámetros continuos y las mé
|
||||
| `text_rec_score_thresh` | -0.161 | Correlación débil negativa |
|
||||
| `text_det_unclip_ratio` | NaN | Varianza cero (valor fijo) |
|
||||
|
||||
*Fuente: Análisis del notebook.*
|
||||
*Fuente: Análisis de [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results) generados por [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py).*
|
||||
|
||||
**Tabla 24.** *Correlación de parámetros con WER.*
|
||||
|
||||
@@ -638,7 +497,7 @@ Se calculó la correlación de Pearson entre los parámetros continuos y las mé
|
||||
| `text_det_box_thresh` | +0.227 | Correlación débil positiva |
|
||||
| `text_rec_score_thresh` | -0.173 | Correlación débil negativa |
|
||||
|
||||
*Fuente: Análisis del notebook.*
|
||||
*Fuente: Análisis de [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results) generados por [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py).*
|
||||
|
||||
**Hallazgo clave**: El parámetro `text_det_thresh` muestra la correlación más fuerte (-0.52 con ambas métricas), indicando que valores más altos de este umbral tienden a reducir el error. Este umbral controla qué píxeles se consideran "texto" en el mapa de probabilidad del detector.
|
||||
|
||||
@@ -653,7 +512,7 @@ El parámetro booleano `textline_orientation` demostró tener el mayor impacto e
|
||||
| True | 3.76% | 7.12% | 12.73% | 32 |
|
||||
| False | 12.40% | 14.93% | 21.71% | 32 |
|
||||
|
||||
*Fuente: Análisis del notebook.*
|
||||
*Fuente: Análisis de [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results) generados por [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py).*
|
||||
|
||||
**Interpretación:**
|
||||
|
||||
@@ -706,33 +565,7 @@ Los trials con CER muy alto (>20%) presentaron patrones específicos:
|
||||
|
||||
#### Evaluación sobre Dataset Completo
|
||||
|
||||
La configuración óptima identificada se evaluó sobre el dataset completo de 24 páginas, comparando con la configuración baseline:
|
||||
|
||||
**Configuración Baseline:**
|
||||
```python
|
||||
baseline_config = {
|
||||
"textline_orientation": False, # Valor por defecto
|
||||
"use_doc_orientation_classify": False,
|
||||
"use_doc_unwarping": False,
|
||||
"text_det_thresh": 0.3, # Valor por defecto
|
||||
"text_det_box_thresh": 0.6, # Valor por defecto
|
||||
"text_det_unclip_ratio": 1.5, # Valor por defecto
|
||||
"text_rec_score_thresh": 0.5, # Valor por defecto
|
||||
}
|
||||
```
|
||||
|
||||
**Configuración Optimizada:**
|
||||
```python
|
||||
optimized_config = {
|
||||
"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,
|
||||
}
|
||||
```
|
||||
La configuración óptima identificada se evaluó sobre el dataset completo de 24 páginas, comparando con la configuración baseline (valores por defecto de PaddleOCR). Los parámetros optimizados más relevantes fueron: `textline_orientation=True`, `text_det_thresh=0.4690`, `text_det_box_thresh=0.5412`, y `text_rec_score_thresh=0.6350`.
|
||||
|
||||
**Tabla 27.** *Comparación baseline vs optimizado (24 páginas).*
|
||||
|
||||
@@ -741,7 +574,7 @@ optimized_config = {
|
||||
| PaddleOCR (Baseline) | 7.78% | 92.22% | 14.94% | 85.06% |
|
||||
| PaddleOCR-HyperAdjust | **1.49%** | **98.51%** | **7.62%** | **92.38%** |
|
||||
|
||||
*Fuente: Ejecución final en notebook `src/paddle_ocr_fine_tune_unir_raytune.ipynb`.*
|
||||
*Fuente: Validación final. Código en [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py), resultados en [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results).*
|
||||
|
||||
#### Métricas de Mejora
|
||||
|
||||
@@ -759,15 +592,16 @@ optimized_config = {
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: "Comparación Baseline vs Optimizado (24 páginas)"
|
||||
title: "Reducción de errores: Baseline vs Optimizado"
|
||||
---
|
||||
xychart-beta
|
||||
x-axis ["CER", "WER"]
|
||||
x-axis ["CER Baseline", "CER Optimizado", "WER Baseline", "WER Optimizado"]
|
||||
y-axis "Tasa de error (%)" 0 --> 16
|
||||
bar "Baseline" [7.78, 14.94]
|
||||
bar "Optimizado" [1.49, 7.62]
|
||||
bar [7.78, 1.49, 14.94, 7.62]
|
||||
```
|
||||
|
||||
*Leyenda: CER = Character Error Rate, WER = Word Error Rate. Baseline = configuración por defecto de PaddleOCR. Optimizado = configuración encontrada por Ray Tune.*
|
||||
|
||||
#### Impacto Práctico
|
||||
|
||||
**En un documento típico de 10,000 caracteres:**
|
||||
@@ -808,7 +642,7 @@ xychart-beta
|
||||
|
||||
Esta sección ha presentado:
|
||||
|
||||
1. **Configuración del experimento**: Arquitectura de subprocesos, dataset extendido, espacio de búsqueda de 7 dimensiones
|
||||
1. **Configuración del experimento**: Arquitectura Docker Compose, dataset extendido, espacio de búsqueda de 7 dimensiones
|
||||
|
||||
2. **Resultados estadísticos**:
|
||||
- CER medio: 5.25% (std: 11.03%)
|
||||
@@ -823,9 +657,9 @@ Esta sección ha presentado:
|
||||
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
|
||||
- [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py): Script principal de optimización
|
||||
- [`src/raytune_ocr.py`](https://github.com/seryus/MastersThesis/blob/main/src/raytune_ocr.py): Librería de utilidades Ray Tune
|
||||
- [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results): Resultados CSV de los trials
|
||||
|
||||
## Discusión y análisis de resultados
|
||||
|
||||
@@ -1002,24 +836,18 @@ Para documentos PDF digitales como los evaluados, estos módulos son innecesario
|
||||
|
||||
Para documentos académicos en español similares a los evaluados:
|
||||
|
||||
**Configuración recomendada:**
|
||||
```python
|
||||
config_recomendada = {
|
||||
# OBLIGATORIO
|
||||
"textline_orientation": True,
|
||||
**Tabla 31.** *Configuración recomendada para PaddleOCR.*
|
||||
|
||||
# RECOMENDADO
|
||||
"text_det_thresh": 0.45, # Rango: 0.4-0.5
|
||||
"text_rec_score_thresh": 0.6, # Rango: 0.5-0.7
|
||||
| Parámetro | Valor | Prioridad | Justificación |
|
||||
|-----------|-------|-----------|---------------|
|
||||
| `textline_orientation` | True | Obligatorio | Reduce CER en 69.7% |
|
||||
| `text_det_thresh` | 0.45 (rango: 0.4-0.5) | Recomendado | Correlación fuerte con CER |
|
||||
| `text_rec_score_thresh` | 0.6 (rango: 0.5-0.7) | Recomendado | Filtra reconocimientos poco confiables |
|
||||
| `text_det_box_thresh` | 0.55 (rango: 0.5-0.6) | Opcional | Impacto moderado |
|
||||
| `use_doc_orientation_classify` | False | No recomendado | Innecesario para PDFs digitales |
|
||||
| `use_doc_unwarping` | False | No recomendado | Innecesario para PDFs digitales |
|
||||
|
||||
# OPCIONAL
|
||||
"text_det_box_thresh": 0.55, # Rango: 0.5-0.6
|
||||
|
||||
# NO RECOMENDADO para PDFs digitales
|
||||
"use_doc_orientation_classify": False,
|
||||
"use_doc_unwarping": False,
|
||||
}
|
||||
```
|
||||
*Fuente: Análisis de resultados de optimización.*
|
||||
|
||||
#### Cuándo Aplicar Esta Metodología
|
||||
|
||||
@@ -1066,5 +894,74 @@ Este capítulo ha presentado el desarrollo completo de la contribución:
|
||||
**Resultado principal**: Se logró alcanzar el objetivo de CER < 2% mediante optimización de hiperparámetros, sin requerir fine-tuning ni recursos GPU.
|
||||
|
||||
**Fuentes de datos:**
|
||||
- `src/raytune_paddle_subproc_results_20251207_192320.csv`: Resultados de 64 trials
|
||||
- `src/paddle_ocr_fine_tune_unir_raytune.ipynb`: Notebook principal del experimento
|
||||
- [`src/run_tuning.py`](https://github.com/seryus/MastersThesis/blob/main/src/run_tuning.py): Script principal de optimización
|
||||
- [`src/results/`](https://github.com/seryus/MastersThesis/tree/main/src/results): Resultados CSV de los trials
|
||||
|
||||
**Imágenes Docker:**
|
||||
- `seryus.ddns.net/unir/paddle-ocr-gpu`: PaddleOCR con soporte GPU
|
||||
- `seryus.ddns.net/unir/easyocr-gpu`: EasyOCR con soporte GPU
|
||||
- `seryus.ddns.net/unir/doctr-gpu`: DocTR con soporte GPU
|
||||
|
||||
### Validación con Aceleración GPU
|
||||
|
||||
Para evaluar la viabilidad práctica del enfoque optimizado en escenarios de producción, se realizó una validación adicional utilizando aceleración GPU. Esta fase complementa los experimentos en CPU presentados anteriormente y demuestra la aplicabilidad del método cuando se dispone de hardware con capacidad de procesamiento paralelo.
|
||||
|
||||
#### Configuración del Entorno GPU
|
||||
|
||||
**Tabla 36.** *Especificaciones del entorno de validación GPU.*
|
||||
|
||||
| Componente | Especificación |
|
||||
|------------|----------------|
|
||||
| GPU | NVIDIA GeForce RTX 3060 Laptop |
|
||||
| VRAM | 5.66 GB |
|
||||
| CUDA | 12.4 |
|
||||
| Sistema Operativo | Ubuntu 24.04.3 LTS |
|
||||
| Kernel | 6.14.0-37-generic |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
El entorno de validación representa hardware de consumo típico para desarrollo de aplicaciones de machine learning, permitiendo evaluar el rendimiento en condiciones realistas de despliegue.
|
||||
|
||||
#### Comparación CPU vs GPU
|
||||
|
||||
Se evaluó el tiempo de procesamiento utilizando la configuración optimizada identificada en la fase anterior, comparando el rendimiento entre CPU y GPU.
|
||||
|
||||
**Tabla 37.** *Rendimiento comparativo CPU vs GPU.*
|
||||
|
||||
| Métrica | CPU | GPU (RTX 3060) | Factor de Aceleración |
|
||||
|---------|-----|----------------|----------------------|
|
||||
| Tiempo/Página | 69.4s | 0.55s | **126x** |
|
||||
| Dataset completo (45 páginas) | ~52 min | ~25 seg | **126x** |
|
||||
|
||||
*Fuente: Elaboración propia a partir de experimentos.*
|
||||
|
||||
La aceleración de 126x obtenida con GPU transforma la aplicabilidad práctica del sistema. Mientras que el procesamiento en CPU limita el uso a escenarios de procesamiento por lotes sin restricciones de tiempo, la velocidad con GPU habilita casos de uso interactivos y de tiempo real.
|
||||
|
||||
#### Comparación de Modelos PaddleOCR
|
||||
|
||||
PaddleOCR ofrece dos variantes de modelos: Mobile (optimizados para dispositivos con recursos limitados) y Server (mayor precisión a costa de mayor consumo de memoria). Se evaluó la viabilidad de ambas variantes en el hardware disponible.
|
||||
|
||||
**Tabla 38.** *Comparación de modelos Mobile vs Server en RTX 3060.*
|
||||
|
||||
| Modelo | VRAM Requerida | Resultado | Recomendación |
|
||||
|--------|----------------|-----------|---------------|
|
||||
| PP-OCRv5 Mobile | 0.06 GB | Funciona correctamente | ✓ Recomendado |
|
||||
| PP-OCRv5 Server | 5.3 GB | OOM en página 2 | ✗ Requiere >8 GB VRAM |
|
||||
|
||||
*Fuente: Elaboración propia.*
|
||||
|
||||
Los modelos Server, a pesar de ofrecer potencialmente mayor precisión, resultan inviables en hardware con VRAM limitada (≤6 GB) debido a errores de memoria (Out of Memory). Los modelos Mobile, con un consumo de memoria 88 veces menor, funcionan de manera estable y ofrecen rendimiento suficiente para el caso de uso evaluado.
|
||||
|
||||
#### Conclusiones de la Validación GPU
|
||||
|
||||
La validación con aceleración GPU permite extraer las siguientes conclusiones:
|
||||
|
||||
1. **Aceleración significativa**: La GPU proporciona una aceleración de 126x sobre CPU, haciendo viable el procesamiento en tiempo real para aplicaciones interactivas.
|
||||
|
||||
2. **Modelos Mobile recomendados**: Para hardware con VRAM limitada (≤6 GB), los modelos Mobile de PP-OCRv5 ofrecen el mejor balance entre precisión y recursos, funcionando de manera estable sin errores de memoria.
|
||||
|
||||
3. **Viabilidad práctica**: Con GPU, el procesamiento de un documento completo (45 páginas) toma menos de 30 segundos, validando la aplicabilidad en entornos de producción donde el tiempo de respuesta es crítico.
|
||||
|
||||
4. **Escalabilidad**: La arquitectura de microservicios dockerizados utilizada para la validación GPU facilita el despliegue horizontal, permitiendo escalar el procesamiento según demanda.
|
||||
|
||||
Esta validación demuestra que la configuración optimizada mediante Ray Tune no solo mejora la precisión (CER: 7.78% → 1.49%) sino que, combinada con aceleración GPU, resulta prácticamente aplicable en escenarios de producción real.
|
||||
|
||||
Reference in New Issue
Block a user