regen docs
Some checks failed
build_docker / build_cpu (pull_request) Has been cancelled
build_docker / build_gpu (pull_request) Has been cancelled
build_docker / build_easyocr (pull_request) Has been cancelled
build_docker / build_easyocr_gpu (pull_request) Has been cancelled
build_docker / build_raytune (pull_request) Has been cancelled
build_docker / build_doctr (pull_request) Has been cancelled
build_docker / essential (pull_request) Has been cancelled
build_docker / build_doctr_gpu (pull_request) Has been cancelled
Some checks failed
build_docker / build_cpu (pull_request) Has been cancelled
build_docker / build_gpu (pull_request) Has been cancelled
build_docker / build_easyocr (pull_request) Has been cancelled
build_docker / build_easyocr_gpu (pull_request) Has been cancelled
build_docker / build_raytune (pull_request) Has been cancelled
build_docker / build_doctr (pull_request) Has been cancelled
build_docker / essential (pull_request) Has been cancelled
build_docker / build_doctr_gpu (pull_request) Has been cancelled
This commit is contained in:
@@ -104,16 +104,7 @@ flowchart LR
|
|||||||
|
|
||||||
#### Clase ImageTextDataset
|
#### Clase ImageTextDataset
|
||||||
|
|
||||||
Se implementó una clase Python para cargar pares imagen-texto:
|
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).
|
||||||
|
|
||||||
```python
|
|
||||||
class ImageTextDataset:
|
|
||||||
def __init__(self, root):
|
|
||||||
# Carga pares (imagen, texto) de carpetas pareadas
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
|
||||||
# Retorna (PIL.Image, str)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 2: Benchmark Comparativo
|
### Fase 2: Benchmark Comparativo
|
||||||
|
|
||||||
@@ -131,17 +122,7 @@ class ImageTextDataset:
|
|||||||
|
|
||||||
#### Métricas de Evaluación
|
#### Métricas de Evaluación
|
||||||
|
|
||||||
Se utilizó la biblioteca `jiwer` para calcular:
|
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).
|
||||||
|
|
||||||
```python
|
|
||||||
from jiwer import wer, cer
|
|
||||||
|
|
||||||
def evaluate_text(reference, prediction):
|
|
||||||
return {
|
|
||||||
'WER': wer(reference, prediction),
|
|
||||||
'CER': cer(reference, prediction)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 3: Espacio de Búsqueda
|
### Fase 3: Espacio de Búsqueda
|
||||||
|
|
||||||
@@ -163,66 +144,45 @@ def evaluate_text(reference, prediction):
|
|||||||
|
|
||||||
#### Configuración de Ray Tune
|
#### Configuración de Ray Tune
|
||||||
|
|
||||||
```python
|
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).
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 4: Ejecución de Optimización
|
### Fase 4: Ejecución de Optimización
|
||||||
|
|
||||||
#### Arquitectura de Ejecució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:
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
---
|
---
|
||||||
title: "Arquitectura de ejecución con subprocesos"
|
title: "Arquitectura de ejecución con Docker Compose"
|
||||||
---
|
---
|
||||||
flowchart LR
|
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"]
|
A -->|"HTTP POST /evaluate"| B
|
||||||
B --> B_out["Retorna JSON con métricas"]
|
B -->|"JSON {CER, WER, TIME}"| A
|
||||||
|
A -.->|"Health check /health"| B
|
||||||
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)
|
#### Ejecución con Docker Compose
|
||||||
|
|
||||||
El script recibe hiperparámetros por línea de comandos:
|
Los servicios se orquestan mediante Docker Compose (`src/docker-compose.tuning.*.yml`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python paddle_ocr_tuning.py \
|
# Iniciar servicio OCR
|
||||||
--pdf-folder ./dataset \
|
docker compose -f docker-compose.tuning.doctr.yml up -d doctr-gpu
|
||||||
--textline-orientation True \
|
|
||||||
--text-det-box-thresh 0.5 \
|
# Ejecutar optimización (64 trials)
|
||||||
--text-det-thresh 0.4 \
|
docker compose -f docker-compose.tuning.doctr.yml run raytune --service doctr --samples 64
|
||||||
--text-rec-score-thresh 0.6
|
|
||||||
|
# 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
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,121 +70,25 @@ Se utilizó el documento "Instrucciones para la redacción y elaboración del TF
|
|||||||
|
|
||||||
#### Proceso de Conversión
|
#### Proceso de Conversión
|
||||||
|
|
||||||
La conversión del PDF a imágenes se realizó mediante PyMuPDF (fitz):
|
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).
|
||||||
|
|
||||||
```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.
|
|
||||||
|
|
||||||
#### Extracción del Ground Truth
|
#### Extracción del Ground Truth
|
||||||
|
|
||||||
El texto de referencia se extrajo directamente del PDF mediante PyMuPDF:
|
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).
|
||||||
|
|
||||||
```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).
|
|
||||||
|
|
||||||
#### Configuración de los Modelos
|
#### 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**:
|
- **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).
|
||||||
```python
|
|
||||||
import easyocr
|
|
||||||
|
|
||||||
easyocr_reader = easyocr.Reader(['es', 'en']) # Spanish and English
|
- **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.
|
||||||
results = easyocr_reader.readtext(image_path)
|
|
||||||
text = ' '.join([r[1] for r in results])
|
|
||||||
```
|
|
||||||
|
|
||||||
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).
|
- **DocTR**: Se seleccionaron las arquitecturas db_resnet50 para detección y sar_resnet31 para reconocimiento, representando una configuración de alta precisión.
|
||||||
|
|
||||||
**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.
|
|
||||||
|
|
||||||
#### Métricas de Evaluación
|
#### Métricas de Evaluación
|
||||||
|
|
||||||
Se utilizó la biblioteca `jiwer` para calcular CER y WER de manera estandarizada:
|
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).
|
||||||
|
|
||||||
```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.
|
|
||||||
|
|
||||||
### Resultados del Benchmark
|
### Resultados del Benchmark
|
||||||
|
|
||||||
@@ -358,38 +262,47 @@ El experimento se ejecutó en el siguiente entorno:
|
|||||||
|
|
||||||
#### Arquitectura de Ejecución
|
#### 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
|
```mermaid
|
||||||
---
|
---
|
||||||
title: "Arquitectura de ejecución con subprocesos"
|
title: "Arquitectura de ejecución con Docker Compose"
|
||||||
---
|
---
|
||||||
flowchart LR
|
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"]
|
A -->|"HTTP POST /evaluate"| B
|
||||||
B --> B_out["Retorna JSON con métricas"]
|
B -->|"JSON {CER, WER, TIME}"| A
|
||||||
|
A -.->|"Health check /health"| B
|
||||||
A --> C["Subprocess 2: paddle_ocr_tuning.py --config"]
|
|
||||||
C --> C_out["Retorna JSON con métricas"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
El script `src/paddle_ocr_tuning.py` actúa como wrapper que:
|
La arquitectura containerizada (`src/docker-compose.tuning.*.yml`) ofrece:
|
||||||
1. Recibe hiperparámetros por línea de comandos
|
1. Aislamiento de dependencias entre Ray Tune y los motores OCR
|
||||||
2. Inicializa PaddleOCR con la configuración especificada
|
2. Health checks automáticos para asegurar disponibilidad del servicio
|
||||||
3. Evalúa sobre el dataset
|
3. Comunicación via API REST (endpoints `/health` y `/evaluate`)
|
||||||
4. Retorna métricas en formato JSON
|
4. Soporte para GPU mediante nvidia-docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python paddle_ocr_tuning.py \
|
# Iniciar servicio OCR con GPU
|
||||||
--pdf-folder ./dataset \
|
docker compose -f docker-compose.tuning.doctr.yml up -d doctr-gpu
|
||||||
--textline-orientation True \
|
|
||||||
--text-det-box-thresh 0.5 \
|
# Ejecutar optimización (64 trials)
|
||||||
--text-det-thresh 0.4 \
|
docker compose -f docker-compose.tuning.doctr.yml run raytune --service doctr --samples 64
|
||||||
--text-rec-score-thresh 0.6
|
|
||||||
|
# Detener servicios
|
||||||
|
docker compose -f docker-compose.tuning.doctr.yml down
|
||||||
```
|
```
|
||||||
|
|
||||||
Salida:
|
Respuesta del servicio OCR:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"CER": 0.0125,
|
"CER": 0.0125,
|
||||||
@@ -416,54 +329,11 @@ Para la fase de optimización se extendió el dataset:
|
|||||||
|
|
||||||
*Fuente: Elaboración propia.*
|
*Fuente: Elaboración propia.*
|
||||||
|
|
||||||
La clase `ImageTextDataset` en `src/dataset_manager.py` gestiona la carga de pares imagen-texto:
|
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).
|
||||||
|
|
||||||
```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()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Espacio de Búsqueda
|
#### 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:
|
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).
|
||||||
|
|
||||||
```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),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tabla 17.** *Descripción detallada del espacio de búsqueda.*
|
**Tabla 17.** *Descripción detallada del espacio de búsqueda.*
|
||||||
|
|
||||||
@@ -489,23 +359,7 @@ search_space = {
|
|||||||
|
|
||||||
#### Configuración de Ray Tune
|
#### Configuración de Ray Tune
|
||||||
|
|
||||||
```python
|
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).
|
||||||
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
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tabla 18.** *Parámetros de configuración de Ray Tune.*
|
**Tabla 18.** *Parámetros de configuración de Ray Tune.*
|
||||||
|
|
||||||
@@ -711,33 +565,7 @@ Los trials con CER muy alto (>20%) presentaron patrones específicos:
|
|||||||
|
|
||||||
#### Evaluación sobre Dataset Completo
|
#### 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:
|
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`.
|
||||||
|
|
||||||
**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,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tabla 27.** *Comparación baseline vs optimizado (24 páginas).*
|
**Tabla 27.** *Comparación baseline vs optimizado (24 páginas).*
|
||||||
|
|
||||||
@@ -813,7 +641,7 @@ xychart-beta
|
|||||||
|
|
||||||
Esta sección ha presentado:
|
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**:
|
2. **Resultados estadísticos**:
|
||||||
- CER medio: 5.25% (std: 11.03%)
|
- CER medio: 5.25% (std: 11.03%)
|
||||||
@@ -1007,24 +835,18 @@ Para documentos PDF digitales como los evaluados, estos módulos son innecesario
|
|||||||
|
|
||||||
Para documentos académicos en español similares a los evaluados:
|
Para documentos académicos en español similares a los evaluados:
|
||||||
|
|
||||||
**Configuración recomendada:**
|
**Tabla 31.** *Configuración recomendada para PaddleOCR.*
|
||||||
```python
|
|
||||||
config_recomendada = {
|
|
||||||
# OBLIGATORIO
|
|
||||||
"textline_orientation": True,
|
|
||||||
|
|
||||||
# RECOMENDADO
|
| Parámetro | Valor | Prioridad | Justificación |
|
||||||
"text_det_thresh": 0.45, # Rango: 0.4-0.5
|
|-----------|-------|-----------|---------------|
|
||||||
"text_rec_score_thresh": 0.6, # Rango: 0.5-0.7
|
| `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
|
*Fuente: Análisis de resultados de optimización.*
|
||||||
"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,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Cuándo Aplicar Esta Metodología
|
#### Cuándo Aplicar Esta Metodología
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ El objetivo principal del trabajo era alcanzar un CER inferior al 2% en document
|
|||||||
**Respecto a OE4 (Optimización con Ray Tune)**:
|
**Respecto a OE4 (Optimización con Ray Tune)**:
|
||||||
- Se ejecutaron 64 trials con el algoritmo OptunaSearch
|
- Se ejecutaron 64 trials con el algoritmo OptunaSearch
|
||||||
- El tiempo total del experimento fue aproximadamente 6 horas (en CPU)
|
- El tiempo total del experimento fue aproximadamente 6 horas (en CPU)
|
||||||
- La arquitectura basada en subprocesos permitió superar incompatibilidades entre Ray y PaddleOCR
|
- La arquitectura basada en contenedores Docker permitió superar incompatibilidades entre Ray y los motores OCR, facilitando además la portabilidad y reproducibilidad
|
||||||
|
|
||||||
**Respecto a OE5 (Validación de la configuración)**:
|
**Respecto a OE5 (Validación de la configuración)**:
|
||||||
- Se validó la configuración óptima sobre el dataset completo de 24 páginas
|
- Se validó la configuración óptima sobre el dataset completo de 24 páginas
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user