Documentation review. (#5)
All checks were successful
build_docker / essential (push) Successful in 0s
build_docker / build_paddle_ocr (push) Successful in 5m28s
build_docker / build_paddle_ocr_gpu (push) Successful in 21m16s
build_docker / build_easyocr (push) Successful in 15m52s
build_docker / build_easyocr_gpu (push) Successful in 18m22s
build_docker / build_doctr (push) Successful in 19m3s
build_docker / build_raytune (push) Successful in 3m34s
build_docker / build_doctr_gpu (push) Successful in 13m56s

This commit was merged in pull request #5.
This commit is contained in:
2026-01-20 14:33:46 +00:00
committed by Sergio Jimenez Jimenez
parent c7ed7b2b9c
commit 9ee2490097
56 changed files with 2182 additions and 945 deletions

View File

@@ -0,0 +1,97 @@
Review and validate the documentation for this Master's Thesis project.
## Instructions
1. **Read metrics source files first** to get the correct values:
- `docs/metrics/metrics_paddle.md` - PaddleOCR results
- `docs/metrics/metrics_doctr.md` - DocTR results
- `docs/metrics/metrics_easyocr.md` - EasyOCR results
- `docs/metrics/metrics.md` - Comparative summary
- `src/results/*.csv` - Raw data from 64 trials per service
2. **Review UNIR guidelines** for formatting and structure rules:
- **`instructions/plantilla_individual.htm`** - **PRIMARY REFERENCE** for all styling (CSS classes, Word styles)
- **`instructions/plantilla_individual_files/`** - Support files with additional style definitions
- `instructions/instrucciones.pdf` - TFE writing instructions
- `instructions/plantilla_individual.pdf` - Official template preview
**IMPORTANT:** When styling elements (tables, figures, notes, quotes), ALWAYS check `plantilla_individual.htm` for existing Word/CSS classes (e.g., `MsoQuote`, `MsoCaption`, `Piedefoto-tabla`). Use these classes instead of custom inline styles.
### UNIR Color Palette (from plantilla_individual.htm)
| Color | Hex | Usage |
|-------|-----|-------|
| Primary Blue | `#0098CD` | Headings, titles, diagram borders |
| Light Blue BG | `#E6F4F9` | Backgrounds, callout boxes, nodes |
| Dark Gray | `#404040` | Primary text |
| Accent Blue | `#5B9BD5` | Table headers, accent elements |
| Light Accent | `#9CC2E5` | Table borders |
| Very Light Blue | `#DEEAF6` | Secondary backgrounds, subgraphs |
| White | `#FFFFFF` | Header text, contrast |
### Table Styles (from template)
- `MsoTableGrid` - Basic grid table
- `MsoTable15Grid4Accent1` - Styled table with UNIR colors (header: `#5B9BD5`, borders: `#9CC2E5`)
- `Piedefoto-tabla` - Table caption/source style
3. **Validate each documentation file** checking:
### Data Accuracy
- All CER/WER values must match those in `docs/metrics/*.md`
- Verify: baseline, optimized, best trial, percentage improvement
- Verify: GPU vs CPU acceleration factor
- Verify: dataset size (pages)
### UNIR Formatting
- Tables: `**Tabla N.** *Descriptive title in italics.*` followed by table, then `*Fuente: ...*`
- Table titles must describe the content (e.g., "Comparación de modelos OCR")
- Figures: `**Figura N.** *Descriptive title in italics.*`
- Figure titles must describe the content (e.g., "Pipeline de un sistema OCR moderno")
- Sequential numbering (no duplicates, no gaps)
- APA citation format for references
### Mermaid Diagrams
- **All diagrams must be in Mermaid format** (no external images for flowcharts/charts)
- All Mermaid diagrams must use the UNIR color theme
- Required YAML frontmatter config (Mermaid v11+):
```mermaid
---
title: "Diagram Title"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
---
flowchart LR
A[Node] --> B[Node]
```
- Colors: `#0098CD` (UNIR blue for borders/lines), `#E6F4F9` (light blue background)
- All diagrams must have a descriptive `title:` in YAML frontmatter
- Titles MUST be quoted: `title: "Descriptive Title"` (not `title: Descriptive Title`)
- Titles should describe the diagram content, not generic "Diagrama N"
- Verify theme is applied to all diagrams in `docs/*.md`
**Note on Bar Charts (`xychart-beta`):**
- Bar chart colors are **automatically converted to light blue** (`#0098CD`) during figure generation
- The `xyChart.plotColorPalette` config in YAML frontmatter does NOT work reliably with mmdc
- Instead, `generate_mermaid_figures.py` post-processes SVG to replace default colors (`#ECECFF`, `#FFF4DD`)
- No manual color configuration needed in xychart-beta blocks - they will be styled automatically
### Files to Review
- `docs/00_resumen.md` - Resumen/Abstract
- `docs/03_objetivos_metodologia.md` - Objectives
- `docs/04_desarrollo_especifico.md` - Main results (most critical)
- `docs/05_conclusiones_trabajo_futuro.md` - Conclusions
- `docs/07_anexo_a.md` - Technical annex
- `README.md` - Project overview
4. **Report findings** with:
- List of incorrect values found (with file:line references)
- Formatting issues detected
- Specific corrections needed
- Overall documentation health assessment
5. **Language**: All docs/* files must be in Spanish. README.md and CLAUDE.md can be in English.

View File

@@ -0,0 +1,77 @@
Generate the Word document for this Master's Thesis project.
## Instructions
Execute the TFM document generation pipeline in order:
### Step 0: Clean Up Previous Output
Remove the entire thesis_output folder to ensure a fresh build:
```bash
rm -rf thesis_output && mkdir -p thesis_output/figures
```
### Step 1: Generate Figures from Mermaid Diagrams
Run the figure generation script using the virtual environment:
```bash
source .venv/bin/activate && python3 generate_mermaid_figures.py
```
**Input:** Mermaid code blocks from `docs/*.md`
**Output:** `thesis_output/figures/figura_*.png` and `figures_manifest.json`
**Notes:**
- Bar charts (`xychart-beta`) are automatically post-processed to use light blue (`#0098CD`) bars
- The script generates SVG first, replaces default colors, then converts to PNG via `cairosvg`
- Other diagram types (flowchart, sequence, pie) use direct PNG generation via `mmdc`
### Step 2: Apply Content to UNIR Template
Run the content application script using the virtual environment:
```bash
source .venv/bin/activate && python3 apply_content.py
```
**Input:**
- `instructions/plantilla_individual.htm` (UNIR template)
- `instructions/plantilla_individual_files/` (template support files)
- `docs/*.md` (chapter content)
- `thesis_output/figures/*.png` (generated figures)
**Output:** `thesis_output/` (htm + support files + figures)
### Step 3: Report Results
After successful execution, provide:
1. Number of figures generated
2. Number of tables formatted
3. Path to output file
4. Instructions for Word finalization:
- Open `thesis_output/plantilla_individual.htm` in Microsoft Word
- Press Ctrl+A then F9 to update all indices (contents, figures, tables)
- Adjust image sizes if needed (select image → right-click → Size and Position)
- Save as `.docx`
### Prerequisites
If scripts fail, check that dependencies are installed:
```bash
# Python dependencies (in .venv)
source .venv/bin/activate && pip install beautifulsoup4 cairosvg
# Mermaid CLI for figure generation
npm install @mermaid-js/mermaid-cli
```
### Notes
- **Bar chart colors**: The `generate_mermaid_figures.py` script automatically converts xychart-beta bar colors to UNIR light blue (`#0098CD`). This is done via SVG post-processing since Mermaid's xychart theming doesn't work reliably via config files.
- **Color replacement**: Both `fill` and `stroke` attributes are replaced for colors `#ECECFF` and `#FFF4DD` (default Mermaid bar colors).
- **Config file**: `mermaid.config.json` in root directory sets the base theme for all diagrams.
### Error Handling
- If `generate_mermaid_figures.py` fails: Check mmdc (mermaid-cli) is installed
- If `apply_content.py` fails: Check beautifulsoup4 is installed
- Report any errors with the specific step that failed

View File

@@ -10,8 +10,9 @@ on:
branches: branches:
- main - main
env: concurrency:
PADDLE_VERSION: "3.0.0" group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
essential: essential:
@@ -34,7 +35,7 @@ jobs:
echo "Event: ${{ gitea.event_name }}" >> $GITHUB_STEP_SUMMARY echo "Event: ${{ gitea.event_name }}" >> $GITHUB_STEP_SUMMARY
# PaddleOCR CPU image (amd64 only) # PaddleOCR CPU image (amd64 only)
build_cpu: build_paddle_ocr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: essential needs: essential
steps: steps:
@@ -63,7 +64,7 @@ jobs:
${{ needs.essential.outputs.image_cpu }}:latest ${{ needs.essential.outputs.image_cpu }}:latest
# PaddleOCR GPU image (amd64 only) # PaddleOCR GPU image (amd64 only)
build_gpu: build_paddle_ocr_gpu:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: essential needs: essential
steps: steps:

3
.gitignore vendored
View File

@@ -4,7 +4,8 @@ __pycache__/
dataset dataset
results results
.DS_Store .DS_Store
.claude .claude/*
!.claude/commands/
node_modules node_modules
src/paddle_ocr/wheels src/paddle_ocr/wheels
src/*.log src/*.log

252
README.md
View File

@@ -10,36 +10,39 @@
## Objetivo ## 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 ni recursos GPU dedicados. 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:** CER = **1.49%** (objetivo cumplido) **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 ## Resultados Principales
**Tabla.** *Comparación de métricas OCR entre configuración baseline y optimizada.* **Tabla.** *Comparación de métricas OCR entre configuración baseline y optimizada (GPU).*
| Modelo | CER | Precisión Caracteres | WER | Precisión Palabras | | Modelo | CER | Precisión Caracteres | WER | Precisión Palabras |
|--------|-----|---------------------|-----|-------------------| |--------|-----|---------------------|-----|-------------------|
| PaddleOCR (Baseline) | 7.78% | 92.22% | 14.94% | 85.06% | | PaddleOCR (Baseline) | 8.85% | 91.15% | 13.05% | 86.95% |
| **PaddleOCR-HyperAdjust** | **1.49%** | **98.51%** | **7.62%** | **92.38%** | | **PaddleOCR-HyperAdjust (dataset)** | **7.72%** | **92.28%** | **11.40%** | **88.60%** |
| **PaddleOCR-HyperAdjust (mejor trial)** | **0.79%** | **99.21%** | **7.78%** | **92.22%** |
*Fuente: Elaboración propia.* *Fuente: [`src/results/raytune_paddle_results_20260119_122609.csv`](src/results/raytune_paddle_results_20260119_122609.csv)*
**Mejora obtenida:** Reducción del CER en un **80.9%** **Mejora obtenida (dataset completo):** Reducción del CER en un **12.8%**
### Configuración Óptima Encontrada ### Configuración Óptima Encontrada (GPU)
```python ```python
config_optimizada = { config_optimizada = {
"textline_orientation": True, # CRÍTICO - reduce CER ~70% "textline_orientation": True, # CRÍTICO para layouts complejos
"use_doc_orientation_classify": False, "use_doc_orientation_classify": True, # Mejora orientación de documento
"use_doc_unwarping": False, "use_doc_unwarping": False,
"text_det_thresh": 0.4690, # Correlación -0.52 con CER "text_det_thresh": 0.0462, # Correlación -0.52 con CER
"text_det_box_thresh": 0.5412, "text_det_box_thresh": 0.4862,
"text_det_unclip_ratio": 0.0, "text_det_unclip_ratio": 0.0,
"text_rec_score_thresh": 0.6350, "text_rec_score_thresh": 0.5658,
} }
``` ```
@@ -68,7 +71,7 @@ PDF (académico UNIR)
| Algoritmo de búsqueda | OptunaSearch (TPE) | | Algoritmo de búsqueda | OptunaSearch (TPE) |
| Métrica objetivo | CER (minimizar) | | Métrica objetivo | CER (minimizar) |
| Trials concurrentes | 2 | | Trials concurrentes | 2 |
| Tiempo total | ~6 horas (CPU) | | Tiempo total | ~1.5 horas (GPU RTX 3060) |
*Fuente: Elaboración propia.* *Fuente: Elaboración propia.*
@@ -76,63 +79,95 @@ PDF (académico UNIR)
## Estructura del Repositorio ## 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<br/>generate_mermaid_figures.py"]
config["claude.md<br/>README.md"]
end
``` ```
MastersThesis/
├── docs/ # Capítulos del TFM en Markdown (estructura UNIR) **Descripción de directorios principales:**
│ ├── 00_resumen.md # Resumen + Abstract + Keywords
│ ├── 01_introduccion.md # Cap. 1: Introducción (1.1-1.3) | Directorio | Contenido |
│ ├── 02_contexto_estado_arte.md # Cap. 2: Contexto y estado del arte (2.1-2.3) |------------|-----------|
│ ├── 03_objetivos_metodologia.md # Cap. 3: Objetivos y metodología (3.1-3.4) | `docs/` | Capítulos del TFM en Markdown (estructura UNIR) |
│ ├── 04_desarrollo_especifico.md # Cap. 4: Desarrollo específico (4.1-4.3) | `docs/metrics/` | Métricas de rendimiento por servicio OCR |
│ ├── 05_conclusiones_trabajo_futuro.md # Cap. 5: Conclusiones (5.1-5.2) | `src/paddle_ocr/` | Servicio PaddleOCR dockerizado |
│ ├── 06_referencias_bibliograficas.md # Referencias bibliográficas (APA) | `src/doctr_service/` | Servicio DocTR dockerizado |
│ └── 07_anexo_a.md # Anexo A: Código fuente y datos | `src/easyocr_service/` | Servicio EasyOCR dockerizado |
├── thesis_output/ # Documento final generado | `src/raytune/` | Scripts de optimización Ray Tune |
│ ├── plantilla_individual.htm # TFM completo (abrir en Word) | `src/results/` | CSVs con resultados de 64 trials por servicio |
│ └── figures/ # Figuras generadas desde Mermaid | `thesis_output/` | Documento TFM generado + figuras PNG |
│ ├── figura_1.png ... figura_7.png | `instructions/` | Plantilla e instrucciones UNIR oficiales |
│ └── figures_manifest.json
├── src/
│ ├── paddle_ocr_fine_tune_unir_raytune.ipynb # Experimento principal
│ ├── paddle_ocr_tuning.py # Script de evaluación CLI
│ ├── dataset_manager.py # Clase ImageTextDataset
│ ├── prepare_dataset.ipynb # Preparación del dataset
│ └── raytune_paddle_subproc_results_*.csv # Resultados de 64 trials
├── results/ # Resultados de benchmarks
├── instructions/ # Plantilla e instrucciones UNIR
│ ├── instrucciones.pdf
│ ├── plantilla_individual.pdf
│ └── plantilla_individual.htm
├── apply_content.py # Genera documento TFM desde docs/ + plantilla
├── generate_mermaid_figures.py # Convierte diagramas Mermaid a PNG
├── ocr_benchmark_notebook.ipynb # Benchmark comparativo inicial
└── README.md
```
--- ---
## Hallazgos Clave ## Hallazgos Clave
1. **`textline_orientation=True` es crítico**: Reduce el CER en un 69.7%. Para documentos con layouts mixtos (tablas, encabezados), la clasificación de orientación de línea es esencial. 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. **Umbral `text_det_thresh` importante**: Correlación -0.52 con CER. Valores óptimos entre 0.4-0.5. Valores < 0.1 causan fallos catastróficos (CER >40%). 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. **Componentes innecesarios para PDFs digitales**: `use_doc_orientation_classify` y `use_doc_unwarping` no mejoran el rendimiento en documentos académicos digitales. 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 ## Rendimiento GPU
Se realizó una validación adicional con aceleración GPU para evaluar la viabilidad práctica del enfoque en escenarios de producción. 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.* **Tabla.** *Comparación de rendimiento CPU vs GPU.*
| Métrica | CPU | GPU (RTX 3060) | Aceleración | | Métrica | CPU | GPU (RTX 3060) | Aceleración |
|---------|-----|----------------|-------------| |---------|-----|----------------|-------------|
| Tiempo/Página | 69.4s | 0.55s | **126x** | | Tiempo/Página | 69.4s | 0.84s | **82x** |
| Dataset completo (45 páginas) | ~52 min | ~25 seg | **126x** | | Dataset completo (45 páginas) | ~52 min | ~38 seg | **82x** |
| 64 trials completos | ~6.4 horas | ~1.5 horas | **4.3x** |
*Fuente: Elaboración propia.* *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 ### Recomendación de Modelos
@@ -145,7 +180,7 @@ Se realizó una validación adicional con aceleración GPU para evaluar la viabi
*Fuente: Elaboración propia.* *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 hace viable el procesamiento en tiempo real. **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.
--- ---
@@ -196,101 +231,8 @@ python src/paddle_ocr_tuning.py \
## Fuentes de Datos ## Fuentes de Datos
- **Dataset**: 2 documentos UNIR (45 páginas total): Instrucciones TFE (24 pág.) + Plantilla TFE (21 pág.) - **Dataset**: 2 documentos UNIR (45 páginas total): Instrucciones TFE (24 pág.) + Plantilla TFE (21 pág.)
- **Resultados Ray Tune (PRINCIPAL)**: `src/raytune_paddle_subproc_results_20251207_192320.csv` - 64 trials de optimización con todas las métricas y configuraciones - **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
---
## Generación del Documento TFM
### Prerrequisitos
```bash
# Instalar dependencias de Python
pip install beautifulsoup4
# Instalar mermaid-cli para generación de figuras
npm install @mermaid-js/mermaid-cli
```
### Flujo de Generación del Documento
El documento TFM se genera en **3 pasos** que deben ejecutarse en orden:
```
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 1: generate_mermaid_figures.py │
│ ────────────────────────────────────────────────────────────────── │
│ • Lee diagramas Mermaid de docs/*.md │
│ • Genera thesis_output/figures/figura_*.png │
│ • Crea figures_manifest.json con títulos │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 2: apply_content.py │
│ ────────────────────────────────────────────────────────────────── │
│ • Lee plantilla desde instructions/plantilla_individual.htm │
│ • Inserta contenido de docs/*.md en cada capítulo │
│ • Genera tablas con formato APA y figuras con referencias │
│ • Guarda en thesis_output/plantilla_individual.htm │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ PASO 3: Abrir en Microsoft Word │
│ ────────────────────────────────────────────────────────────────── │
│ • Abrir thesis_output/plantilla_individual.htm │
│ • Ctrl+A → F9 para actualizar índices (contenidos/figuras/tablas) │
│ • Guardar como TFM_Sergio_Jimenez.docx │
└─────────────────────────────────────────────────────────────────────┘
```
### Comandos de Generación
```bash
# Desde el directorio raíz del proyecto:
# PASO 1: Generar figuras PNG desde diagramas Mermaid
python3 generate_mermaid_figures.py
# Output: thesis_output/figures/figura_1.png ... figura_8.png
# PASO 2: Aplicar contenido de docs/ a la plantilla UNIR
python3 apply_content.py
# Output: thesis_output/plantilla_individual.htm
# PASO 3: Abrir en Word y finalizar documento
# - Abrir thesis_output/plantilla_individual.htm en Microsoft Word
# - Ctrl+A → F9 para actualizar todos los índices
# - IMPORTANTE: Ajustar manualmente el tamaño de las imágenes para legibilidad
# (seleccionar imagen → clic derecho → Tamaño y posición → ajustar al ancho de página)
# - Guardar como .docx
```
### Notas Importantes para Edición en Word
1. **Ajuste de imágenes**: Las figuras Mermaid pueden requerir ajuste manual de tamaño para ser legibles. Seleccionar cada imagen y ajustar al ancho de texto (~16cm).
2. **Actualización de índices**: Después de cualquier cambio, usar Ctrl+A → F9 para regenerar índices.
3. **Formato de código**: Los bloques de código usan Consolas 9pt. Verificar que no se corten líneas largas.
### Archivos de Entrada y Salida
**Tabla.** *Relación de scripts de generación con sus archivos de entrada y salida.*
| Script | Entrada | Salida |
|--------|---------|--------|
| `generate_mermaid_figures.py` | `docs/*.md` (bloques ```mermaid```) | `thesis_output/figures/figura_*.png`, `figures_manifest.json` |
| `apply_content.py` | `instructions/plantilla_individual.htm`, `docs/*.md`, `thesis_output/figures/*.png` | `thesis_output/plantilla_individual.htm` |
*Fuente: Elaboración propia.*
### Contenido Generado Automáticamente
- **53 tablas** con formato APA (Tabla X. *Título* + Fuente: ...)
- **8 figuras** desde Mermaid (Figura X. *Título* + Fuente: Elaboración propia)
- **25 referencias** en formato APA con sangría francesa
- **Resumen/Abstract** con palabras clave
- **Índices** actualizables (contenidos, figuras, tablas)
- Eliminación automática de textos de instrucción de la plantilla
--- ---
@@ -301,10 +243,10 @@ python3 apply_content.py
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. 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:** **Hardware utilizado:**
- **Optimización (CPU)**: Los 64 trials de Ray Tune se ejecutaron en CPU (~69s/página) - **Optimización (GPU)**: Los 64 trials de Ray Tune se ejecutaron con GPU RTX 3060 (~0.84s/página, ~1.5 horas total)
- **Validación (GPU)**: Se validó con RTX 3060 logrando 126x de aceleración (0.55s/página) - **Referencia CPU**: Se midió el tiempo en CPU para comparación (~69s/página)
La optimización de hiperparámetros demostró ser una **alternativa efectiva** al fine-tuning, logrando una reducción del 80.9% en el CER sin reentrenar el modelo. 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 ### Tareas Pendientes
@@ -321,9 +263,10 @@ La optimización de hiperparámetros demostró ser una **alternativa efectiva**
#### Completadas #### Completadas
- [x] **Estructura docs/ según plantilla UNIR** - [x] **Estructura docs/ según plantilla UNIR**
- [x] **Diagramas Mermaid**: 8 figuras generadas - [x] **Diagramas Mermaid**: 8+ figuras generadas
- [x] **Documento TFM unificado**: Script `apply_content.py` - [x] **Documento TFM unificado**: Script `apply_content.py`
- [x] **Evaluación con GPU**: RTX 3060 - 126x más rápido (0.55s/página) - [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 ### Dataset
@@ -372,6 +315,9 @@ Este proyecto es parte de un Trabajo Fin de Máster académico.
## Referencias ## Referencias
- [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) - [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) - [Ray Tune](https://docs.ray.io/en/latest/tune/index.html)
- [Optuna](https://optuna.org/) - [Optuna](https://optuna.org/)
- [jiwer](https://github.com/jitsi/jiwer) - [jiwer](https://github.com/jitsi/jiwer)
- [PyMuPDF](https://pymupdf.readthedocs.io/)

Binary file not shown.

Binary file not shown.

View File

@@ -3,8 +3,10 @@
import re import re
import os import os
import shutil
from bs4 import BeautifulSoup, NavigableString from bs4 import BeautifulSoup, NavigableString
from latex2mathml.converter import convert as latex_to_mathml from latex2mathml.converter import convert as latex_to_mathml
from PIL import Image
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_INPUT = os.path.join(BASE_DIR, 'instructions/plantilla_individual.htm') TEMPLATE_INPUT = os.path.join(BASE_DIR, 'instructions/plantilla_individual.htm')
@@ -120,13 +122,13 @@ def parse_md_to_html_blocks(md_content):
mermaid_lines.append(lines[i]) mermaid_lines.append(lines[i])
i += 1 i += 1
# Try to extract title from mermaid content (YAML format: title: "...") # Try to extract title from mermaid content (YAML format)
mermaid_content = '\n'.join(mermaid_lines) mermaid_content = '\n'.join(mermaid_lines)
# Match YAML format: title: "Title" or title: 'Title' # Match title with quotes: title: "Something" or title: 'Something'
title_match = re.search(r'title:\s*["\']([^"\']+)["\']', mermaid_content) title_match = re.search(r'title:\s*["\']([^"\']+)["\']', mermaid_content)
if not title_match: if not title_match:
# Fallback to non-YAML format: title "Title" # Match title without quotes: title: Something
title_match = re.search(r'title\s+["\']?([^"\'"\n]+)["\']?', mermaid_content) title_match = re.search(r'title:\s*([^"\'\n]+)', mermaid_content)
if title_match: if title_match:
fig_title = title_match.group(1).strip() fig_title = title_match.group(1).strip()
else: else:
@@ -143,8 +145,24 @@ def parse_md_to_html_blocks(md_content):
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="text-align:center"><b><span lang=ES style="font-size:12.0pt;line-height:150%">Figura <!--[if supportFields]><span style='mso-element:field-begin'></span> SEQ Figura \\* ARABIC <span style='mso-element:field-separator'></span><![endif]-->{figure_counter}<!--[if supportFields]><span style='mso-element:field-end'></span><![endif]-->.</span></b><span lang=ES style="font-size:12.0pt;line-height:150%"> </span><i><span lang=ES style="font-size:12.0pt;line-height:150%">{fig_title}</span></i></p>''') html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="text-align:center"><b><span lang=ES style="font-size:12.0pt;line-height:150%">Figura <!--[if supportFields]><span style='mso-element:field-begin'></span> SEQ Figura \\* ARABIC <span style='mso-element:field-separator'></span><![endif]-->{figure_counter}<!--[if supportFields]><span style='mso-element:field-end'></span><![endif]-->.</span></b><span lang=ES style="font-size:12.0pt;line-height:150%"> </span><i><span lang=ES style="font-size:12.0pt;line-height:150%">{fig_title}</span></i></p>''')
if os.path.exists(fig_path): if os.path.exists(fig_path):
# Use Word-compatible width in cm (A4 text area is ~16cm wide, use ~12cm max) # Read actual image dimensions and scale to fit page width
html_blocks.append(f'''<p class=MsoNormal style="text-align:center"><span lang=ES><img style="width:12cm;max-width:100%" src="{fig_file}" alt="{fig_title}"/></span></p>''') img = Image.open(fig_path)
orig_w, orig_h = img.size
# Scale to fit max width of 566px (15cm at 96dpi) while preserving aspect ratio
max_width = 566
if orig_w > max_width:
scale = max_width / orig_w
new_w = max_width
new_h = int(orig_h * scale)
else:
new_w, new_h = orig_w, orig_h
# Convert to pt (1px at 96dpi = 0.75pt)
w_pt = new_w * 0.75
h_pt = new_h * 0.75
html_blocks.append(f'''<p class=MsoNormal style="text-align:center"><span lang=ES><img width="{new_w}" height="{new_h}" style="width:{w_pt}pt;height:{h_pt}pt;display:block;margin:0 auto" src="{fig_file}" alt="{fig_title}"/></span></p>''')
else: else:
# Fallback to placeholder # Fallback to placeholder
html_blocks.append(f'''<p class=MsoNormal style="text-align:center;border:1px dashed #999;padding:20px;margin:10px 40px;background:#f9f9f9"><span lang=ES style="color:#666">[Insertar diagrama Mermaid aquí]</span></p>''') html_blocks.append(f'''<p class=MsoNormal style="text-align:center;border:1px dashed #999;padding:20px;margin:10px 40px;background:#f9f9f9"><span lang=ES style="color:#666">[Insertar diagrama Mermaid aquí]</span></p>''')
@@ -165,7 +183,9 @@ def parse_md_to_html_blocks(md_content):
code = '\n'.join(code_lines) code = '\n'.join(code_lines)
# Escape HTML entities in code # Escape HTML entities in code
code = code.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;') code = code.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
html_blocks.append(f'<p class=MsoNormal style="margin-left:1cm"><span style="font-family:Consolas;font-size:9pt"><pre>{code}</pre></span></p>') html_blocks.append(f'''<div style="background:#E6F4F9;border-top:solid #0098CD .5pt;border-bottom:solid #0098CD .5pt;padding:8pt 12pt;margin:6pt 0">
<pre style="font-family:Consolas,monospace;font-size:9pt;color:#333333;margin:0;white-space:pre-wrap;word-wrap:break-word">{code}</pre>
</div>''')
i += 1 i += 1
continue continue
@@ -239,7 +259,8 @@ def parse_md_to_html_blocks(md_content):
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption><b><span lang=ES style="font-size:12.0pt;line-height:150%">Tabla <!--[if supportFields]><span style='mso-element:field-begin'></span> SEQ Tabla \\* ARABIC <span style='mso-element:field-separator'></span><![endif]-->{table_counter}<!--[if supportFields]><span style='mso-element:field-end'></span><![endif]-->.</span></b><span lang=ES style="font-size:12.0pt;line-height:150%"> </span><i><span lang=ES style="font-size:12.0pt;line-height:150%">{clean_title}</span></i></p>''') html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption><b><span lang=ES style="font-size:12.0pt;line-height:150%">Tabla <!--[if supportFields]><span style='mso-element:field-begin'></span> SEQ Tabla \\* ARABIC <span style='mso-element:field-separator'></span><![endif]-->{table_counter}<!--[if supportFields]><span style='mso-element:field-end'></span><![endif]-->.</span></b><span lang=ES style="font-size:12.0pt;line-height:150%"> </span><i><span lang=ES style="font-size:12.0pt;line-height:150%">{clean_title}</span></i></p>''')
# Build table HTML with APA style (horizontal lines only, no vertical) # Build table HTML with APA style (horizontal lines only, no vertical)
table_html = '<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 style="border-collapse:collapse;margin-left:auto;margin-right:auto;mso-table-style-name:\'Plain Table 1\'">' # Wrap in centered div for Word compatibility
table_html = '<div align="center"><table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 align="center" style="border-collapse:collapse;margin-left:auto;margin-right:auto;mso-table-style-name:\'Plain Table 1\'">'
for j, tline in enumerate(table_lines): for j, tline in enumerate(table_lines):
cells = [c.strip() for c in tline.split('|')[1:-1]] cells = [c.strip() for c in tline.split('|')[1:-1]]
table_html += '<tr>' table_html += '<tr>'
@@ -254,7 +275,7 @@ def parse_md_to_html_blocks(md_content):
# Middle rows: no borders # Middle rows: no borders
table_html += f'<td style="border:none;padding:5px"><p class=MsoNormal style="margin:0;text-align:center"><span lang=ES>{md_to_html_para(cell)}</span></p></td>' table_html += f'<td style="border:none;padding:5px"><p class=MsoNormal style="margin:0;text-align:center"><span lang=ES>{md_to_html_para(cell)}</span></p></td>'
table_html += '</tr>' table_html += '</tr>'
table_html += '</table>' table_html += '</table></div>'
html_blocks.append(table_html) html_blocks.append(table_html)
# Add source with proper template format # Add source with proper template format
@@ -269,7 +290,7 @@ def parse_md_to_html_blocks(md_content):
while i < len(lines) and lines[i].startswith('>'): while i < len(lines) and lines[i].startswith('>'):
quote_text += ' ' + lines[i][1:].strip() quote_text += ' ' + lines[i][1:].strip()
i += 1 i += 1
html_blocks.append(f'<p class=MsoNormal style="margin-left:2cm;margin-right:1cm"><i><span lang=ES>{md_to_html_para(quote_text)}</span></i></p>') html_blocks.append(f'<p class=MsoQuote><i><span lang=ES>{md_to_html_para(quote_text)}</span></i></p>')
continue continue
# Bullet list # Bullet list
@@ -640,6 +661,15 @@ def main():
output_html = str(soup) output_html = str(soup)
write_file(TEMPLATE_OUTPUT, output_html) write_file(TEMPLATE_OUTPUT, output_html)
# Copy template support files (header.htm, images, etc.)
support_files_src = os.path.join(BASE_DIR, 'instructions/plantilla_individual_files')
support_files_dst = os.path.join(BASE_DIR, 'thesis_output/plantilla_individual_files')
if os.path.exists(support_files_src):
if os.path.exists(support_files_dst):
shutil.rmtree(support_files_dst)
shutil.copytree(support_files_src, support_files_dst)
print(f"✓ Copied template support files")
print(f"✓ Done! Modified: {TEMPLATE_OUTPUT}") print(f"✓ Done! Modified: {TEMPLATE_OUTPUT}")
print("\nTo convert to DOCX:") print("\nTo convert to DOCX:")
print("1. Open the .htm file in Microsoft Word") print("1. Open the .htm file in Microsoft Word")

View File

@@ -12,39 +12,41 @@ This is a **Master's Thesis (TFM)** for UNIR's Master in Artificial Intelligence
### Why Hyperparameter Optimization Instead of Fine-tuning ### Why Hyperparameter Optimization Instead of Fine-tuning
Due to **hardware limitations** (no dedicated GPU, CPU-only execution), the project pivoted from fine-tuning to hyperparameter optimization: The project chose **hyperparameter optimization** over fine-tuning because:
- Fine-tuning deep learning models without GPU is prohibitively slow - Fine-tuning requires extensive labeled datasets specific to the domain
- Inference time is ~69 seconds/page on CPU - Hyperparameter tuning can improve pretrained models without retraining
- Hyperparameter optimization proved to be an effective alternative, achieving 80.9% CER reduction - GPU acceleration (RTX 3060) enables efficient exploration of hyperparameter space
### Main Results ### Main Results (GPU - Jan 2026)
| Model | CER | Character Accuracy | | Model | CER | Character Accuracy |
|-------|-----|-------------------| |-------|-----|-------------------|
| PaddleOCR Baseline | 7.78% | 92.22% | | PaddleOCR Baseline | 8.85% | 91.15% |
| PaddleOCR-HyperAdjust | **1.49%** | **98.51%** | | PaddleOCR-HyperAdjust (full dataset) | **7.72%** | **92.28%** |
| PaddleOCR-HyperAdjust (best trial) | **0.79%** | **99.21%** |
**Goal achieved:** CER < 2% (target was < 2%, result is 1.49%) **Goal status:** CER < 2% achieved in best trial (0.79%). Full dataset shows 12.8% improvement.
### Optimal Configuration Found ### Optimal Configuration Found (GPU)
```python ```python
config_optimizada = { config_optimizada = {
"textline_orientation": True, # CRITICAL - reduces CER ~70% "textline_orientation": True, # CRITICAL for complex layouts
"use_doc_orientation_classify": False, "use_doc_orientation_classify": True, # Improves document orientation
"use_doc_unwarping": False, "use_doc_unwarping": False,
"text_det_thresh": 0.4690, "text_det_thresh": 0.0462, # -0.52 correlation with CER
"text_det_box_thresh": 0.5412, "text_det_box_thresh": 0.4862,
"text_det_unclip_ratio": 0.0, "text_det_unclip_ratio": 0.0,
"text_rec_score_thresh": 0.6350, "text_rec_score_thresh": 0.5658,
} }
``` ```
### Key Findings ### Key Findings
1. `textline_orientation=True` is the most impactful parameter (reduces CER by 69.7%) 1. `textline_orientation=True` is critical for documents with mixed layouts
2. `text_det_thresh` has -0.52 correlation with CER; values < 0.1 cause catastrophic failures 2. `use_doc_orientation_classify=True` improves document orientation detection in GPU config
3. Document correction modules (`use_doc_orientation_classify`, `use_doc_unwarping`) are unnecessary for digital PDFs 3. `text_det_thresh` has -0.52 correlation with CER; values < 0.01 cause catastrophic failures
4. `use_doc_unwarping=False` is optimal for digital PDFs (unnecessary processing)
## Repository Structure ## Repository Structure
@@ -99,13 +101,18 @@ The template (`plantilla_individual.pdf`) requires **5 chapters**. The docs/ fil
## Important Data Files ## Important Data Files
### Results CSV Files ### Results CSV Files (GPU - PRIMARY)
- `src/raytune_paddle_subproc_results_20251207_192320.csv` - 64 Ray Tune trials with configs and metrics (PRIMARY DATA SOURCE) - `src/results/raytune_paddle_results_20260119_122609.csv` - 64 Ray Tune trials PaddleOCR GPU (PRIMARY)
- `src/results/raytune_easyocr_results_20260119_120204.csv` - 64 Ray Tune trials EasyOCR GPU
- `src/results/raytune_doctr_results_20260119_121445.csv` - 64 Ray Tune trials DocTR GPU
### Key Notebooks ### Results CSV Files (CPU - time reference only)
- `src/paddle_ocr_fine_tune_unir_raytune.ipynb` - Main Ray Tune experiment - `src/raytune_paddle_subproc_results_20251207_192320.csv` - CPU execution for time comparison (69.4s/page vs 0.84s/page GPU)
- `src/prepare_dataset.ipynb` - PDF to image/text conversion
- `ocr_benchmark_notebook.ipynb` - EasyOCR vs PaddleOCR vs DocTR comparison ### Key Scripts
- `src/run_tuning.py` - Main Ray Tune optimization script
- `src/raytune/raytune_ocr.py` - Ray Tune utilities and search spaces
- `src/paddle_ocr/paddle_ocr_tuning_rest.py` - PaddleOCR REST API
## Technical Stack ## Technical Stack
@@ -128,13 +135,13 @@ The template (`plantilla_individual.pdf`) requires **5 chapters**. The docs/ fil
### Priority Tasks ### Priority Tasks
1. **Validate on other document types** - Test optimal config on invoices, forms, contracts 1. **Validate on other document types** - Test optimal config on invoices, forms, contracts
2. **Expand dataset** - Current dataset has only 24 pages 2. **Use larger tuning subset** - Current 5 pages caused overfitting; recommend 15-20 pages
3. **Create presentation slides** - For thesis defense 3. **Create presentation slides** - For thesis defense
4. **Final document review** - Open in Word, update indices (Ctrl+A, F9), verify formatting 4. **Final document review** - Open in Word, update indices (Ctrl+A, F9), verify formatting
### Optional Extensions ### Optional Extensions
- Explore `text_det_unclip_ratio` parameter (was fixed at 0.0) - Explore `text_det_unclip_ratio` parameter (was fixed at 0.0)
- Compare with actual fine-tuning (if GPU access obtained) - Compare with actual fine-tuning
- Multi-objective optimization (CER + WER + inference time) - Multi-objective optimization (CER + WER + inference time)
## Thesis Document Generation ## Thesis Document Generation

View File

@@ -1,12 +1,12 @@
# Resumen # Resumen
El presente Trabajo Fin de Máster aborda la optimización de sistemas de Reconocimiento Óptico de Caracteres (OCR) basados en inteligencia artificial para documentos en español, específicamente en un entorno con recursos computacionales limitados donde el fine-tuning de modelos no es viable. El objetivo principal es identificar la configuración óptima de hiperparámetros que maximice la precisión del reconocimiento de texto sin requerir entrenamiento adicional de los modelos. El presente Trabajo Fin de Máster aborda la optimización de sistemas de Reconocimiento Óptico de Caracteres (OCR) basados en inteligencia artificial para documentos en español. El objetivo principal es identificar la configuración óptima de hiperparámetros que maximice la precisión del reconocimiento de texto sin requerir fine-tuning de los modelos base.
Se realizó un estudio comparativo de tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR, evaluando su rendimiento mediante las métricas estándar CER (Character Error Rate) y WER (Word Error Rate) sobre un corpus de documentos académicos en español. Tras identificar PaddleOCR como la solución más prometedora, se procedió a una optimización sistemática de hiperparámetros utilizando Ray Tune con el algoritmo de búsqueda Optuna, ejecutando 64 configuraciones diferentes. Se realizó un estudio comparativo de tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR, evaluando su rendimiento mediante las métricas estándar CER (Character Error Rate) y WER (Word Error Rate) sobre un corpus de 45 páginas de documentos académicos en español. Tras identificar PaddleOCR como la solución más prometedora, se procedió a una optimización sistemática de hiperparámetros utilizando Ray Tune con el algoritmo de búsqueda Optuna, ejecutando 64 configuraciones diferentes con aceleración GPU (NVIDIA RTX 3060).
Los resultados demuestran que la optimización de hiperparámetros logró una mejora significativa del rendimiento: el CER se redujo de 7.78% a 1.49% (mejora del 80.9% en reducción de errores), alcanzando una precisión de caracteres del 98.51%. El hallazgo más relevante fue que el parámetro `textline_orientation` (clasificación de orientación de línea de texto) tiene un impacto crítico, reduciendo el CER en un 69.7% cuando está habilitado. Adicionalmente, se identificó que el umbral de detección de píxeles (`text_det_thresh`) presenta una correlación negativa fuerte (-0.52) con el error, siendo el parámetro continuo más influyente. Los resultados demuestran que la optimización de hiperparámetros logró mejoras significativas: el mejor trial individual alcanzó un CER de 0.79% (precisión del 99.21%), cumpliendo el objetivo de CER < 2%. Al validar la configuración optimizada sobre el dataset completo de 45 páginas, se obtuvo una mejora del 12.8% en CER (de 8.85% a 7.72%). El hallazgo más relevante fue que el parámetro `textline_orientation` (clasificación de orientación de línea de texto) tiene un impacto crítico en el rendimiento. Adicionalmente, se identificó que el umbral de detección (`text_det_thresh`) presenta una correlación negativa moderada (-0.52) con el error.
Este trabajo demuestra que es posible obtener mejoras sustanciales en sistemas OCR mediante optimización de hiperparámetros, ofreciendo una alternativa práctica al fine-tuning cuando los recursos computacionales son limitados. Este trabajo demuestra que la optimización de hiperparámetros es una alternativa viable al fine-tuning, especialmente útil cuando se dispone de modelos preentrenados para el idioma objetivo. La infraestructura dockerizada desarrollada permite reproducir los experimentos y facilita la evaluación sistemática de configuraciones OCR.
**Palabras clave:** OCR, Reconocimiento Óptico de Caracteres, PaddleOCR, Optimización de Hiperparámetros, Ray Tune, Procesamiento de Documentos, Inteligencia Artificial **Palabras clave:** OCR, Reconocimiento Óptico de Caracteres, PaddleOCR, Optimización de Hiperparámetros, Ray Tune, Procesamiento de Documentos, Inteligencia Artificial
@@ -14,12 +14,12 @@ Este trabajo demuestra que es posible obtener mejoras sustanciales en sistemas O
# Abstract # Abstract
This Master's Thesis addresses the optimization of Artificial Intelligence-based Optical Character Recognition (OCR) systems for Spanish documents, specifically in a resource-constrained environment where model fine-tuning is not feasible. The main objective is to identify the optimal hyperparameter configuration that maximizes text recognition accuracy without requiring additional model training. This Master's Thesis addresses the optimization of Artificial Intelligence-based Optical Character Recognition (OCR) systems for Spanish documents. The main objective is to identify the optimal hyperparameter configuration that maximizes text recognition accuracy without requiring fine-tuning of the base models.
A comparative study of three open-source OCR solutions was conducted: EasyOCR, PaddleOCR (PP-OCRv5), and DocTR, evaluating their performance using standard CER (Character Error Rate) and WER (Word Error Rate) metrics on a corpus of academic documents in Spanish. After identifying PaddleOCR as the most promising solution, systematic hyperparameter optimization was performed using Ray Tune with the Optuna search algorithm, executing 64 different configurations. A comparative study of three open-source OCR solutions was conducted: EasyOCR, PaddleOCR (PP-OCRv5), and DocTR, evaluating their performance using standard CER (Character Error Rate) and WER (Word Error Rate) metrics on a corpus of 45 pages of academic documents in Spanish. After identifying PaddleOCR as the most promising solution, systematic hyperparameter optimization was performed using Ray Tune with the Optuna search algorithm, executing 64 different configurations with GPU acceleration (NVIDIA RTX 3060).
Results demonstrate that hyperparameter optimization achieved significant performance improvement: CER was reduced from 7.78% to 1.49% (80.9% error reduction), achieving 98.51% character accuracy. The most relevant finding was that the `textline_orientation` parameter (text line orientation classification) has a critical impact, reducing CER by 69.7% when enabled. Additionally, the pixel detection threshold (`text_det_thresh`) was found to have a strong negative correlation (-0.52) with error, being the most influential continuous parameter. Results demonstrate that hyperparameter optimization achieved significant improvements: the best individual trial reached a CER of 0.79% (99.21% accuracy), meeting the CER < 2% objective. When validating the optimized configuration on the full 45-page dataset, a 12.8% CER improvement was obtained (from 8.85% to 7.72%). The most relevant finding was that the `textline_orientation` parameter (text line orientation classification) has a critical impact on performance. Additionally, the detection threshold (`text_det_thresh`) was found to have a moderate negative correlation (-0.52) with error.
This work demonstrates that substantial improvements in OCR systems can be obtained through hyperparameter optimization, offering a practical alternative to fine-tuning when computational resources are limited. This work demonstrates that hyperparameter optimization is a viable alternative to fine-tuning, especially useful when pre-trained models for the target language are available. The dockerized infrastructure developed enables experiment reproducibility and facilitates systematic evaluation of OCR configurations.
**Keywords:** OCR, Optical Character Recognition, PaddleOCR, Hyperparameter Optimization, Ray Tune, Document Processing, Artificial Intelligence **Keywords:** OCR, Optical Character Recognition, PaddleOCR, Hyperparameter Optimization, Ray Tune, Document Processing, Artificial Intelligence

View File

@@ -1,6 +1,6 @@
# Introducción # Introducción
Este capítulo presenta la motivación del trabajo, identificando el problema a resolver y justificando su relevancia. Se plantea la pregunta de investigación central y se describe la estructura del documento. ¿Es posible mejorar significativamente un sistema OCR sin reentrenarlo? Esta pregunta, aparentemente simple, encierra un desafío práctico que afecta a investigadores, instituciones educativas y empresas que necesitan digitalizar documentos pero carecen de los recursos para realizar fine-tuning de modelos neuronales. A lo largo de este capítulo se desarrolla la motivación del trabajo, se identifica el problema a resolver y se plantean las preguntas de investigación que guiarán el desarrollo experimental.
## Motivación ## Motivación
@@ -62,7 +62,7 @@ Esta oportunidad se ve reforzada por la disponibilidad de frameworks modernos de
### Formulación del problema ### Formulación del problema
El problema central que aborda este trabajo puede formularse de la siguiente manera: Las observaciones anteriores conducen a formular el problema central de este trabajo:
> ¿Es posible mejorar significativamente el rendimiento de modelos OCR preentrenados para documentos en español mediante la optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU? > ¿Es posible mejorar significativamente el rendimiento de modelos OCR preentrenados para documentos en español mediante la optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU?
@@ -118,15 +118,11 @@ La relevancia de este problema radica en su aplicabilidad inmediata. Una metodol
## Estructura del trabajo ## Estructura del trabajo
El presente documento se organiza en los siguientes capítulos: El documento sigue una estructura que refleja el proceso investigador. Tras esta introducción, el **Capítulo 2** sitúa el trabajo en su contexto técnico, revisando las tecnologías OCR basadas en aprendizaje profundo —desde las arquitecturas de detección hasta los modelos de reconocimiento— y los trabajos previos en optimización de estos sistemas.
**Capítulo 2 - Contexto y Estado del Arte**: Se presenta una revisión de las tecnologías OCR basadas en aprendizaje profundo, incluyendo las arquitecturas de detección y reconocimiento de texto, así como los trabajos previos en optimización de estos sistemas. El **Capítulo 3** traduce las preguntas de investigación en objetivos concretos siguiendo la metodología SMART, y describe con detalle el enfoque experimental: preparación del dataset, métricas de evaluación y configuración del proceso de optimización con Ray Tune y Optuna.
**Capítulo 3 - Objetivos y Metodología**: Se definen los objetivos SMART del trabajo y se describe la metodología experimental seguida, incluyendo la preparación del dataset, las métricas de evaluación y el proceso de optimización con Ray Tune. El núcleo del trabajo se desarrolla en el **Capítulo 4**, que presenta el estudio comparativo y la optimización de hiperparámetros estructurados en tres fases: planteamiento de la comparativa con evaluación de EasyOCR, PaddleOCR y DocTR; desarrollo de la optimización mediante 64 trials con Ray Tune; y análisis crítico de los resultados obtenidos.
**Capítulo 4 - 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, estructurado en tres secciones: (4.1) planteamiento de la comparativa con la evaluación de EasyOCR, PaddleOCR y DocTR; (4.2) desarrollo de la comparativa con la optimización de hiperparámetros mediante Ray Tune; y (4.3) discusión y análisis de resultados. Finalmente, el **Capítulo 5** sintetiza las contribuciones, evalúa el grado de cumplimiento de los objetivos y propone líneas de trabajo futuro. Los **Anexos** proporcionan acceso al repositorio de código fuente y datos, así como tablas detalladas de resultados experimentales.
**Capítulo 5 - Conclusiones y Trabajo Futuro**: Se resumen las contribuciones del trabajo, se discute el grado de cumplimiento de los objetivos y se proponen líneas de trabajo futuro.
**Anexos**: Se incluye el enlace al repositorio de código fuente y datos, así como tablas completas de resultados experimentales.

View File

@@ -1,6 +1,6 @@
# Contexto y estado del arte # Contexto y estado del arte
Este capítulo presenta el marco teórico y tecnológico en el que se desarrolla el presente trabajo. Se revisan los fundamentos del Reconocimiento Óptico de Caracteres (OCR), la evolución de las técnicas basadas en aprendizaje profundo, las principales soluciones de código abierto disponibles y los trabajos previos relacionados con la optimización de sistemas OCR. Para comprender el alcance y las decisiones tomadas en este trabajo, es necesario situarlo en su contexto tecnológico. El Reconocimiento Óptico de Caracteres ha recorrido un largo camino desde los primeros sistemas de plantillas de los años 50 hasta las sofisticadas arquitecturas de aprendizaje profundo actuales. A lo largo de este capítulo se revisan los fundamentos técnicos del OCR moderno, se analizan las principales soluciones de código abierto y se identifican los vacíos en la literatura que motivan la contribución de este trabajo.
## Contexto del problema ## Contexto del problema
@@ -62,6 +62,13 @@ Los sistemas OCR modernos siguen típicamente un pipeline de dos etapas principa
```mermaid ```mermaid
--- ---
title: "Pipeline de un sistema OCR moderno" title: "Pipeline de un sistema OCR moderno"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
--- ---
flowchart LR flowchart LR
subgraph Input subgraph Input
@@ -114,7 +121,7 @@ Las arquitecturas más utilizadas para detección de texto incluyen:
**DB (Differentiable Binarization)**: Propuesto por Liao et al. (2020), DB introduce una operación de binarización diferenciable que permite entrenar end-to-end un detector de texto basado en segmentación. Esta arquitectura es la utilizada por PaddleOCR y destaca por su velocidad y precisión. **DB (Differentiable Binarization)**: Propuesto por Liao et al. (2020), DB introduce una operación de binarización diferenciable que permite entrenar end-to-end un detector de texto basado en segmentación. Esta arquitectura es la utilizada por PaddleOCR y destaca por su velocidad y precisión.
**Tabla 1.** *Comparativa de arquitecturas de detección de texto.* **Tabla 4.** *Comparativa de arquitecturas de detección de texto.*
| Arquitectura | Tipo | Salida | Fortalezas | Limitaciones | | Arquitectura | Tipo | Salida | Fortalezas | Limitaciones |
|--------------|------|--------|------------|--------------| |--------------|------|--------|------------|--------------|
@@ -141,7 +148,7 @@ La arquitectura CRNN consta de tres componentes:
**TrOCR (Transformer-based OCR)**: Propuesto por Li et al. (2023), TrOCR utiliza un Vision Transformer (ViT) como encoder y un Transformer de lenguaje como decoder, logrando resultados estado del arte en múltiples benchmarks. **TrOCR (Transformer-based OCR)**: Propuesto por Li et al. (2023), TrOCR utiliza un Vision Transformer (ViT) como encoder y un Transformer de lenguaje como decoder, logrando resultados estado del arte en múltiples benchmarks.
**Tabla 2.** *Comparativa de arquitecturas de reconocimiento de texto.* **Tabla 5.** *Comparativa de arquitecturas de reconocimiento de texto.*
| Arquitectura | Encoder | Decoder | Pérdida | Características | | Arquitectura | Encoder | Decoder | Pérdida | Características |
|--------------|---------|---------|---------|-----------------| |--------------|---------|---------|---------|-----------------|
@@ -286,7 +293,7 @@ El pipeline de PaddleOCR consta de tres módulos principales:
PaddleOCR expone numerosos hiperparámetros que permiten ajustar el comportamiento del sistema. Los más relevantes para este trabajo son: PaddleOCR expone numerosos hiperparámetros que permiten ajustar el comportamiento del sistema. Los más relevantes para este trabajo son:
**Tabla 3.** *Hiperparámetros de detección de PaddleOCR.* **Tabla 6.** *Hiperparámetros de detección de PaddleOCR.*
| Parámetro | Descripción | Rango | Defecto | | Parámetro | Descripción | Rango | Defecto |
|-----------|-------------|-------|---------| |-----------|-------------|-------|---------|
@@ -297,7 +304,7 @@ PaddleOCR expone numerosos hiperparámetros que permiten ajustar el comportamien
*Fuente: Documentación oficial de PaddleOCR (PaddlePaddle, 2024).* *Fuente: Documentación oficial de PaddleOCR (PaddlePaddle, 2024).*
**Tabla 4.** *Hiperparámetros de reconocimiento de PaddleOCR.* **Tabla 7.** *Hiperparámetros de reconocimiento de PaddleOCR.*
| Parámetro | Descripción | Rango | Defecto | | Parámetro | Descripción | Rango | Defecto |
|-----------|-------------|-------|---------| |-----------|-------------|-------|---------|
@@ -307,7 +314,7 @@ PaddleOCR expone numerosos hiperparámetros que permiten ajustar el comportamien
*Fuente: Documentación oficial de PaddleOCR (PaddlePaddle, 2024).* *Fuente: Documentación oficial de PaddleOCR (PaddlePaddle, 2024).*
**Tabla 5.** *Hiperparámetros de preprocesamiento de PaddleOCR.* **Tabla 8.** *Hiperparámetros de preprocesamiento de PaddleOCR.*
| Parámetro | Descripción | Impacto | | Parámetro | Descripción | Impacto |
|-----------|-------------|---------| |-----------|-------------|---------|
@@ -352,7 +359,7 @@ DocTR (Document Text Recognition) es una biblioteca desarrollada por Mindee (202
#### Comparativa Detallada de Soluciones #### Comparativa Detallada de Soluciones
**Tabla 6.** *Comparativa técnica de soluciones OCR de código abierto.* **Tabla 9.** *Comparativa técnica de soluciones OCR de código abierto.*
| Aspecto | EasyOCR | PaddleOCR | DocTR | | Aspecto | EasyOCR | PaddleOCR | DocTR |
|---------|---------|-----------|-------| |---------|---------|-----------|-------|
@@ -367,7 +374,7 @@ DocTR (Document Text Recognition) es una biblioteca desarrollada por Mindee (202
*Fuente: Elaboración propia a partir de documentación oficial (2024).* *Fuente: Elaboración propia a partir de documentación oficial (2024).*
**Tabla 7.** *Comparativa de facilidad de uso.* **Tabla 10.** *Comparativa de facilidad de uso.*
| Aspecto | EasyOCR | PaddleOCR | DocTR | | Aspecto | EasyOCR | PaddleOCR | DocTR |
|---------|---------|-----------|-------| |---------|---------|-----------|-------|
@@ -392,7 +399,7 @@ A diferencia de los parámetros del modelo (como los pesos de una red neuronal),
El problema de HPO puede formalizarse como: El problema de HPO puede formalizarse como:
$$\lambda^* = \arg\min_{\lambda \in \Lambda} \mathcal{L}(M_\lambda, D_{val})$$ $$\lambda^* = \operatorname{argmin}_{\lambda \in \Lambda} \mathcal{L}(M_\lambda, D_{val})$$
Donde: Donde:
- $\lambda$ es un vector de hiperparámetros - $\lambda$ es un vector de hiperparámetros
@@ -487,6 +494,13 @@ La combinación de Ray Tune con OptunaSearch permite:
```mermaid ```mermaid
--- ---
title: "Ciclo de optimización con Ray Tune y Optuna" title: "Ciclo de optimización con Ray Tune y Optuna"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
--- ---
flowchart LR flowchart LR
A["Espacio de<br/>búsqueda"] --> B["Ray Tune<br/>Scheduler"] A["Espacio de<br/>búsqueda"] --> B["Ray Tune<br/>Scheduler"]
@@ -534,7 +548,7 @@ Los principales recursos para evaluación de OCR en español incluyen:
**XFUND**: Dataset de comprensión de formularios en múltiples idiomas, incluyendo español, con anotaciones de entidades y relaciones. **XFUND**: Dataset de comprensión de formularios en múltiples idiomas, incluyendo español, con anotaciones de entidades y relaciones.
**Tabla 8.** *Datasets públicos con contenido en español.* **Tabla 11.** *Datasets públicos con contenido en español.*
| Dataset | Tipo | Idiomas | Tamaño | Uso principal | | Dataset | Tipo | Idiomas | Tamaño | Uso principal |
|---------|------|---------|--------|---------------| |---------|------|---------|--------|---------------|
@@ -564,7 +578,7 @@ Los trabajos previos en OCR para español se han centrado principalmente en:
**Reconocimiento de texto en escenas**: Participaciones en competiciones ICDAR para detección y reconocimiento de texto en español en imágenes naturales. **Reconocimiento de texto en escenas**: Participaciones en competiciones ICDAR para detección y reconocimiento de texto en español en imágenes naturales.
**Tabla 9.** *Trabajos previos relevantes en OCR para español.* **Tabla 12.** *Trabajos previos relevantes en OCR para español.*
| Trabajo | Enfoque | Contribución | | Trabajo | Enfoque | Contribución |
|---------|---------|--------------| |---------|---------|--------------|
@@ -578,18 +592,8 @@ La optimización de hiperparámetros para documentos académicos en español rep
## Conclusiones del capítulo ## Conclusiones del capítulo
Este capítulo ha presentado el marco teórico y tecnológico necesario para contextualizar la contribución del presente trabajo: La revisión del estado del arte revela un panorama en el que las herramientas técnicas están maduras, pero su aplicación óptima para dominios específicos permanece poco explorada. Los sistemas OCR modernos —PaddleOCR, EasyOCR, DocTR— ofrecen arquitecturas sofisticadas basadas en aprendizaje profundo que alcanzan resultados impresionantes en benchmarks estándar. Sin embargo, estos resultados no siempre se trasladan a documentos del mundo real, especialmente en idiomas con menos recursos como el español.
1. **Evolución del OCR**: Se ha trazado la evolución desde los sistemas de plantillas hasta las arquitecturas de aprendizaje profundo actuales, destacando los avances clave en cada generación. La evolución desde los sistemas de plantillas de los años 50 hasta los Transformers actuales ha sido espectacular, pero ha generado sistemas con decenas de hiperparámetros configurables cuyos valores por defecto representan compromisos generales, no configuraciones óptimas para dominios específicos. La literatura abunda en trabajos sobre entrenamiento y fine-tuning de modelos OCR, pero dedica poca atención a la optimización sistemática de los parámetros de inferencia —umbrales de detección, opciones de preprocesamiento, filtros de confianza— que pueden marcar la diferencia entre un sistema usable y uno que requiere corrección manual extensiva.
2. **Pipeline moderno**: Se ha descrito el pipeline de dos etapas (detección + reconocimiento) utilizado por los sistemas OCR contemporáneos, detallando las arquitecturas más relevantes (DB, CRAFT, CRNN, SVTR, Transformer). Este vacío, combinado con las particularidades del español (acentos, eñes, signos invertidos) y la escasez de recursos específicos para este idioma, define el espacio de contribución del presente trabajo. Frameworks como Ray Tune y Optuna proporcionan las herramientas para abordar esta optimización de manera sistemática; PaddleOCR, con su pipeline altamente configurable, ofrece el sustrato técnico adecuado. El siguiente capítulo traduce esta oportunidad en objetivos concretos y una metodología experimental rigurosa.
3. **Métricas de evaluación**: Se han definido formalmente las métricas CER y WER, estableciendo los umbrales de aceptabilidad para diferentes aplicaciones.
4. **Particularidades del español**: Se han identificado los desafíos específicos del OCR para español, incluyendo caracteres especiales, diacríticos y escasez de recursos.
5. **Soluciones de código abierto**: Se han analizado en profundidad EasyOCR, PaddleOCR y DocTR, justificando la selección de PaddleOCR para este trabajo por su alta configurabilidad.
6. **Optimización de hiperparámetros**: Se han presentado los fundamentos teóricos de HPO, con énfasis en TPE (Optuna) y Ray Tune, identificando el vacío en la literatura respecto a la optimización de hiperparámetros de inferencia en OCR.
El estado del arte revela que, si bien existen soluciones OCR de alta calidad, su optimización para dominios específicos mediante ajuste de hiperparámetros (sin fine-tuning) ha recibido poca atención en la literatura. Este trabajo contribuye a llenar ese vacío proponiendo una metodología reproducible para la optimización de PaddleOCR en documentos académicos en español.

View File

@@ -1,20 +1,20 @@
# Objetivos concretos y metodología de trabajo # Objetivos concretos y metodología de trabajo
Este capítulo establece los objetivos del trabajo siguiendo la metodología SMART (Doran, 1981) y describe la metodología experimental empleada para alcanzarlos. Se define un objetivo general y cinco objetivos específicos, todos ellos medibles y verificables. La motivación presentada en el capítulo anterior se traduce ahora en objetivos concretos y medibles. Siguiendo la metodología SMART propuesta por Doran (1981), se define un objetivo general que guía el trabajo y cinco objetivos específicos que lo descomponen en metas alcanzables. La segunda parte del capítulo describe la metodología experimental diseñada para alcanzar estos objetivos.
## Objetivo general ## Objetivo general
> **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 ni recursos GPU dedicados.** > **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.**
### Justificación SMART del Objetivo General ### Justificación SMART del Objetivo General
**Tabla 4.** *Justificación SMART del objetivo general.* **Tabla 13.** *Justificación SMART del objetivo general.*
| Criterio | Cumplimiento | | Criterio | Cumplimiento |
|----------|--------------| |----------|--------------|
| **Específico (S)** | Se define claramente qué se quiere lograr: optimizar PaddleOCR mediante ajuste de hiperparámetros para documentos en español | | **Específico (S)** | Se define claramente qué se quiere lograr: optimizar PaddleOCR mediante ajuste de hiperparámetros para documentos en español |
| **Medible (M)** | Se establece una métrica cuantificable: CER < 2% | | **Medible (M)** | Se establece una métrica cuantificable: CER < 2% |
| **Alcanzable (A)** | Es viable dado que: (1) PaddleOCR permite configuración de hiperparámetros, (2) Ray Tune posibilita búsqueda automatizada, (3) No se requiere GPU | | **Alcanzable (A)** | Es viable dado que: (1) PaddleOCR permite configuración de hiperparámetros, (2) Ray Tune posibilita búsqueda automatizada, (3) Aceleración GPU disponible para experimentación eficiente |
| **Relevante (R)** | El impacto es demostrable: mejora la extracción de texto en documentos académicos sin costes adicionales de infraestructura | | **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 | | **Temporal (T)** | El plazo es un cuatrimestre, correspondiente al TFM |
@@ -41,11 +41,18 @@ Este capítulo establece los objetivos del trabajo siguiendo la metodología SMA
### Visión General ### Visión General
La metodología se estructura en cinco fases secuenciales, cada una de las cuales produce resultados que alimentan la siguiente. Desde la preparación del dataset hasta la validación final, el proceso sigue un diseño experimental que permite reproducir y verificar cada paso.
```mermaid ```mermaid
--- ---
title: "Fases de la metodología experimental" title: "Fases de la metodología experimental"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
--- ---
flowchart LR flowchart LR
A["Fase 1<br/>Dataset"] --> B["Fase 2<br/>Benchmark"] --> C["Fase 3<br/>Espacio"] --> D["Fase 4<br/>Optimización"] --> E["Fase 5<br/>Validación"] A["Fase 1<br/>Dataset"] --> B["Fase 2<br/>Benchmark"] --> C["Fase 3<br/>Espacio"] --> D["Fase 4<br/>Optimización"] --> E["Fase 5<br/>Validación"]
@@ -83,6 +90,13 @@ El script `prepare_dataset.ipynb` implementa:
```mermaid ```mermaid
--- ---
title: "Estructura del dataset de evaluación" title: "Estructura del dataset de evaluación"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
--- ---
flowchart LR flowchart LR
dataset["dataset/"] --> d0["0/"] dataset["dataset/"] --> d0["0/"]
@@ -110,7 +124,7 @@ Se implementó una clase Python para cargar pares imagen-texto que retorna tupla
#### Modelos Evaluados #### Modelos Evaluados
**Tabla 5.** *Modelos OCR evaluados en el benchmark inicial.* **Tabla 14.** *Modelos OCR evaluados en el benchmark inicial.*
| Modelo | Versión | Configuración | | Modelo | Versión | Configuración |
|--------|---------|---------------| |--------|---------|---------------|
@@ -128,7 +142,7 @@ Se utilizó la biblioteca `jiwer` para calcular CER y WER comparando el texto de
#### Hiperparámetros Seleccionados #### Hiperparámetros Seleccionados
**Tabla 6.** *Hiperparámetros seleccionados para optimización.* **Tabla 15.** *Hiperparámetros seleccionados para optimización.*
| Parámetro | Tipo | Rango/Valores | Descripción | | Parámetro | Tipo | Rango/Valores | Descripción |
|-----------|------|---------------|-------------| |-----------|------|---------------|-------------|
@@ -185,14 +199,14 @@ El servicio OCR expone una API REST que retorna métricas en formato JSON:
1. **Baseline**: Ejecución con configuración por defecto de PaddleOCR 1. **Baseline**: Ejecución con configuración por defecto de PaddleOCR
2. **Optimizado**: Ejecución con mejor configuración encontrada 2. **Optimizado**: Ejecución con mejor configuración encontrada
3. **Comparación**: Evaluación sobre las 24 páginas del dataset completo 3. **Comparación**: Evaluación sobre las 45 páginas del dataset completo
4. **Métricas reportadas**: CER, WER, tiempo de procesamiento 4. **Métricas reportadas**: CER, WER, tiempo de procesamiento
### Entorno de Ejecución ### Entorno de Ejecución
#### Hardware #### Hardware
**Tabla 7.** *Especificaciones de hardware del entorno de desarrollo.* **Tabla 16.** *Especificaciones de hardware del entorno de desarrollo.*
| Componente | Especificación | | Componente | Especificación |
|------------|----------------| |------------|----------------|
@@ -205,7 +219,7 @@ El servicio OCR expone una API REST que retorna métricas en formato JSON:
#### Software #### Software
**Tabla 8.** *Versiones de software utilizadas.* **Tabla 17.** *Versiones de software utilizadas.*
| Componente | Versión | | Componente | Versión |
|------------|---------| |------------|---------|
@@ -222,7 +236,7 @@ El servicio OCR expone una API REST que retorna métricas en formato JSON:
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. 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.* **Tabla 18.** *Costos de GPU en plataformas cloud.*
| Plataforma | GPU | Costo/Hora | Costo Mensual | | Plataforma | GPU | Costo/Hora | Costo Mensual |
|------------|-----|------------|---------------| |------------|-----|------------|---------------|
@@ -234,7 +248,7 @@ La decisión de ejecutar los experimentos en hardware local en lugar de utilizar
Para las tareas específicas de este proyecto, los costos estimados en cloud serían: 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.* **Tabla 19.** *Análisis de costos del proyecto en plataformas cloud.*
| Tarea | Tiempo GPU | Costo AWS | Costo Colab Pro | | Tarea | Tiempo GPU | Costo AWS | Costo Colab Pro |
|-------|------------|-----------|-----------------| |-------|------------|-----------|-----------------|
@@ -256,23 +270,19 @@ Para un proyecto de investigación con múltiples iteraciones de ajuste de hiper
### Limitaciones Metodológicas ### Limitaciones Metodológicas
1. **Tamaño del dataset**: El dataset contiene 24 páginas de un único tipo de documento. Resultados pueden no generalizar a otros formatos. 1. **Tamaño del dataset**: El dataset contiene 45 páginas de documentos académicos UNIR. Resultados pueden no generalizar a otros formatos.
2. **Ejecución en CPU**: Los tiempos de procesamiento (~70s/página) serían significativamente menores con GPU. 2. **Subconjunto de optimización**: El ajuste de hiperparámetros se realizó sobre 5 páginas (páginas 5-10), lo que contribuyó al sobreajuste observado en la validación del dataset completo.
3. **Ground truth imperfecto**: El texto de referencia extraído de PDF puede contener errores en documentos con layouts complejos. 3. **Texto de referencia imperfecto**: El texto de referencia extraído de PDF puede contener errores en documentos con diseños complejos.
4. **Parámetro fijo**: `text_det_unclip_ratio` quedó fijado en 0.0 durante todo el experimento por decisión de diseño inicial. 4. **Parámetro fijo**: `text_det_unclip_ratio` quedó fijado en 0.0 durante todo el experimento por decisión de diseño inicial.
## Resumen del capítulo ## Síntesis del capítulo
Este capítulo ha establecido: Los objetivos y la metodología definidos en este capítulo establecen el marco para la experimentación. El objetivo general —alcanzar un CER inferior al 2% mediante optimización de hiperparámetros— se descompone en cinco objetivos específicos que abarcan desde la comparativa inicial de soluciones hasta la validación final de la configuración optimizada.
1. Un objetivo general SMART: alcanzar CER < 2% mediante optimización de hiperparámetros La metodología experimental en cinco fases garantiza un proceso sistemático y reproducible: preparación de un dataset de 45 páginas, benchmark comparativo de tres motores OCR, definición del espacio de búsqueda, ejecución de 64 trials con Ray Tune y Optuna, y validación de la configuración resultante. Las limitaciones metodológicas —tamaño del dataset, subconjunto de optimización reducido, texto de referencia automático— se reconocen explícitamente para contextualizar la interpretación de resultados.
2. Cinco objetivos específicos medibles y alcanzables
3. Una metodología experimental en cinco fases claramente definidas
4. El espacio de búsqueda de hiperparámetros y la configuración de Ray Tune
5. Las limitaciones reconocidas del enfoque
El siguiente capítulo presenta el desarrollo específico de la contribución, incluyendo el benchmark comparativo de soluciones OCR, la optimización de hiperparámetros y el análisis de resultados. El capítulo siguiente pone en práctica esta metodología, presentando el desarrollo experimental completo con sus resultados y análisis.

File diff suppressed because it is too large Load Diff

View File

@@ -1,115 +1,100 @@
# Conclusiones y trabajo futuro # Conclusiones y trabajo futuro
Este capítulo resume las principales conclusiones del trabajo, evalúa el grado de cumplimiento de los objetivos planteados y propone líneas de trabajo futuro que permitirían ampliar y profundizar los resultados obtenidos. A lo largo de este trabajo se ha explorado la optimización de hiperparámetros como estrategia para mejorar el rendimiento de sistemas OCR sin necesidad de reentrenamiento. Las siguientes secciones evalúan el grado de cumplimiento de los objetivos planteados, sintetizan los hallazgos más relevantes y proponen direcciones para investigación futura.
## Conclusiones ## Conclusiones
### Conclusiones Generales ### Conclusiones Generales
Este Trabajo Fin de Máster ha demostrado que es posible mejorar significativamente el rendimiento de sistemas OCR preentrenados mediante optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU dedicados. Los resultados obtenidos confirman que la optimización sistemática de hiperparámetros constituye una alternativa viable al fine-tuning para mejorar sistemas OCR preentrenados. La infraestructura dockerizada con aceleración GPU desarrollada en este trabajo no solo facilita la experimentación reproducible, sino que reduce drásticamente los tiempos de ejecución, haciendo viable la exploración exhaustiva de espacios de configuración.
El objetivo principal del trabajo era alcanzar un CER inferior al 2% en documentos académicos en español. Los resultados obtenidos confirman el cumplimiento de este objetivo: El objetivo principal del trabajo era alcanzar un CER inferior al 2% en documentos académicos en español. Los resultados obtenidos se resumen a continuación:
**Tabla 39.** *Cumplimiento del objetivo de CER.* **Tabla 53.** *Cumplimiento del objetivo de CER.*
| Métrica | Objetivo | Resultado | | Métrica | Objetivo | Mejor Trial | Dataset Completo | Cumplimiento |
|---------|----------|-----------| |---------|----------|-------------|------------------|--------------|
| CER | < 2% | **1.49%** | | CER | < 2% | **0.79%** | **7.72%** | ✓ Parcial |
*Fuente: Elaboración propia.* *Fuente: Elaboración propia.*
### Conclusiones Específicas > **Nota:** El objetivo de CER < 2% se cumple en el mejor trial individual (0.79%, 5 páginas). La validación sobre el conjunto de datos completo (45 páginas) muestra un CER de 7.72%, evidenciando sobreajuste al subconjunto de optimización. Esta diferencia se analiza en detalle en el Capítulo 4.
**Respecto a OE1 (Comparativa de soluciones OCR)**: ### Cumplimiento de los Objetivos Específicos
- Se evaluaron tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR
- PaddleOCR demostró el mejor rendimiento base para documentos en español
- La configurabilidad del pipeline de PaddleOCR lo hace idóneo para optimización
**Respecto a OE2 (Preparación del dataset)**: La evaluación comparativa de soluciones OCR (OE1) reveló diferencias significativas entre las tres alternativas analizadas. De las tres soluciones de código abierto evaluadas —EasyOCR, PaddleOCR (PP-OCRv5) y DocTR—, PaddleOCR demostró el mejor rendimiento base para documentos en español. Además, su arquitectura modular y la amplia configurabilidad de su pipeline lo convierten en el candidato idóneo para optimización mediante ajuste de hiperparámetros.
- Se construyó un dataset estructurado con 24 páginas de documentos académicos
- La clase `ImageTextDataset` facilita la carga de pares imagen-texto
- El ground truth se extrajo automáticamente del PDF mediante PyMuPDF
**Respecto a OE3 (Identificación de hiperparámetros críticos)**: En cuanto a la preparación del conjunto de datos (OE2), se construyó un corpus estructurado con 45 páginas de documentos académicos de UNIR. La implementación de la clase `ImageTextDataset` permite cargar de forma eficiente pares imagen-texto, mientras que el texto de referencia se extrajo automáticamente del PDF original mediante PyMuPDF, garantizando así la consistencia entre las imágenes y sus transcripciones esperadas.
- El parámetro `textline_orientation` es el más influyente: reduce el CER en un 69.7% cuando está habilitado
- El umbral `text_det_thresh` presenta la correlación más fuerte (-0.52) con el CER
- Los parámetros de corrección de documento (`use_doc_orientation_classify`, `use_doc_unwarping`) no aportan mejora en documentos digitales
**Respecto a OE4 (Optimización con Ray Tune)**: El análisis de hiperparámetros (OE3) arrojó resultados particularmente reveladores. El parámetro `textline_orientation` emergió como el factor más influyente, resultando crítico para obtener buenos resultados en documentos con diseños complejos. Asimismo, `use_doc_orientation_classify` demostró un impacto positivo en la configuración con GPU. Por otra parte, el umbral `text_det_thresh` presenta una correlación negativa moderada (-0.52) con el CER, lo que indica que valores más bajos tienden a mejorar el rendimiento, aunque con un límite inferior por debajo del cual el sistema falla catastróficamente. Cabe destacar que `use_doc_unwarping` no aporta mejora alguna en documentos digitales, ya que estos no presentan las deformaciones físicas para las que fue diseñado este módulo.
- Se ejecutaron 64 trials con el algoritmo OptunaSearch
- El tiempo total del experimento fue aproximadamente 6 horas (en CPU)
- 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)**: La experimentación con Ray Tune (OE4) se completó satisfactoriamente mediante 64 trials ejecutados con el algoritmo OptunaSearch y aceleración GPU. El tiempo total del experimento —aproximadamente 1.5 horas con una GPU RTX 3060— demuestra la viabilidad práctica de esta aproximación. La arquitectura basada en contenedores Docker resultó esencial para superar las incompatibilidades entre Ray y los motores OCR, al tiempo que garantiza la portabilidad y reproducibilidad de los experimentos.
- Se validó la configuración óptima sobre el dataset completo de 24 páginas
- La mejora obtenida fue del 80.9% en reducción del CER (7.78% → 1.49%) Finalmente, la validación de la configuración óptima (OE5) se realizó sobre el conjunto de datos completo de 45 páginas. El mejor trial individual alcanzó un CER de 0.79%, equivalente a una precisión del 99.21%. Sin embargo, la evaluación sobre el conjunto de datos completo arrojó un CER de 7.72%, lo que representa una mejora del 12.8% respecto al baseline (8.85%), pero queda lejos del resultado del mejor trial. Esta diferencia revela un sobreajuste al subconjunto de optimización de 5 páginas, un fenómeno que se analiza en detalle en la sección de limitaciones.
- La precisión de caracteres alcanzó el 98.51%
### Hallazgos Clave ### Hallazgos Clave
1. **Arquitectura sobre umbrales**: Un único parámetro booleano (`textline_orientation`) tiene más impacto que todos los umbrales continuos combinados. El hallazgo más significativo de este trabajo es que las decisiones arquitectónicas tienen mayor impacto que los umbrales numéricos. Un único parámetro booleano `textline_orientation`— influye más en el rendimiento final que todos los umbrales continuos combinados. Este resultado sugiere que, al optimizar sistemas OCR, conviene priorizar la exploración de configuraciones estructurales antes de ajustar finamente los valores numéricos.
2. **Umbrales mínimos efectivos**: Valores de `text_det_thresh` < 0.1 causan fallos catastróficos (CER >40%). No obstante, los umbrales presentan límites operativos que deben respetarse. Valores de `text_det_thresh` inferiores a 0.1 provocan fallos catastróficos, con tasas de error que superan el 40%. Este comportamiento indica la existencia de regiones del espacio de hiperparámetros que deben evitarse, lo cual tiene implicaciones para el diseño de espacios de búsqueda en futuros experimentos.
3. **Simplicidad para documentos digitales**: Para documentos PDF digitales (no escaneados), los módulos de corrección de orientación y deformación son innecesarios. Otro hallazgo relevante es la innecesariedad de ciertos módulos para documentos digitales. Los PDF generados directamente desde procesadores de texto no presentan las deformaciones físicas —arrugas, curvaturas, rotaciones— para las que fueron diseñados los módulos de corrección. En estos casos, desactivar `use_doc_unwarping` no solo simplifica el pipeline, sino que puede mejorar el rendimiento al evitar procesamientos innecesarios.
4. **Optimización sin fine-tuning**: Se puede mejorar significativamente el rendimiento de modelos preentrenados mediante ajuste de hiperparámetros de inferencia. Finalmente, los resultados demuestran que es posible mejorar modelos preentrenados mediante ajuste exclusivo de hiperparámetros de inferencia, sin necesidad de reentrenamiento. Sin embargo, esta aproximación requiere validación cuidadosa, ya que las configuraciones optimizadas sobre subconjuntos pequeños pueden no generalizar a conjuntos de datos más amplios o diversos.
### Contribuciones del Trabajo ### Contribuciones del Trabajo
1. **Metodología reproducible**: Se documenta un proceso completo de optimización de hiperparámetros OCR con Ray Tune + Optuna. La principal contribución de este trabajo es una metodología reproducible para la optimización de hiperparámetros OCR. El proceso completo —desde la preparación del conjunto de datos hasta la validación de la configuración óptima— queda documentado y es replicable mediante las herramientas Ray Tune y Optuna.
2. **Análisis de hiperparámetros de PaddleOCR**: Se cuantifica el impacto de cada parámetro configurable mediante correlaciones y análisis comparativo. En segundo lugar, el análisis sistemático de los hiperparámetros de PaddleOCR constituye una contribución al conocimiento disponible sobre este motor OCR. Mediante el cálculo de correlaciones y análisis comparativo, se cuantifica el impacto de cada parámetro configurable, información que puede orientar futuros trabajos de optimización.
3. **Configuración óptima para español**: Se proporciona una configuración validada para documentos académicos en español. Como resultado práctico, se aporta una configuración validada específicamente para documentos académicos en español. Aunque la generalización a otros tipos de documentos requiere validación adicional, esta configuración representa un punto de partida sólido para aplicaciones en el ámbito hispanohablante.
4. **Código fuente**: Todo el código está disponible en el repositorio GitHub para reproducción y extensión. Por último, todo el código fuente, las imágenes Docker y los datos experimentales están disponibles públicamente en el repositorio del proyecto, facilitando así la reproducción, verificación y extensión de este trabajo por parte de otros investigadores.
### Limitaciones del Trabajo ### Limitaciones del Trabajo
1. **Tipo de documento único**: Los experimentos se realizaron únicamente sobre documentos académicos de UNIR. La generalización a otros tipos de documentos requiere validación adicional. Es necesario reconocer varias limitaciones que condicionan el alcance de las conclusiones presentadas. En primer lugar, todos los experimentos se realizaron sobre un único tipo de documento: textos académicos de UNIR. La generalización a otros formatos —facturas, formularios, documentos manuscritos— requeriría validación adicional con conjuntos de datos específicos.
2. **Tamaño del dataset**: 24 páginas es un corpus limitado para conclusiones estadísticamente robustas. El tamaño del corpus constituye otra limitación relevante. Con 45 páginas, el conjunto de datos es modesto para extraer conclusiones estadísticamente robustas. Además, el subconjunto de optimización de tan solo 5 páginas resultó insuficiente para evitar el sobreajuste, como evidencia la brecha entre el CER del mejor trial (0.79%) y el resultado sobre el conjunto completo (7.72%).
3. **Ground truth automático**: La extracción automática del texto de referencia puede introducir errores en layouts complejos. Desde el punto de vista metodológico, la extracción automática del texto de referencia mediante PyMuPDF puede introducir errores en documentos con diseños complejos, donde el orden de lectura no es evidente. Asimismo, el parámetro `text_det_unclip_ratio` permaneció fijo en 0.0 durante todo el experimento, dejando inexplorada una dimensión potencialmente relevante del espacio de hiperparámetros.
4. **Validación en entorno limitado**: Aunque se validó con GPU (126x más rápido que CPU, 0.55s/página), los experimentos se realizaron en hardware de consumo (RTX 3060). Hardware empresarial podría ofrecer mejor rendimiento. Por último, aunque la GPU RTX 3060 utilizada proporcionó una aceleración de 82× respecto a la ejecución en CPU, se trata de hardware de consumo. Equipamiento empresarial con mayor capacidad de VRAM permitiría ejecutar múltiples servicios OCR simultáneamente y explorar espacios de búsqueda más amplios en menos tiempo.
5. **Parámetro no explorado**: `text_det_unclip_ratio` permaneció fijo en 0.0 durante todo el experimento.
## Líneas de trabajo futuro ## Líneas de trabajo futuro
### Extensiones Inmediatas ### Extensiones Inmediatas
1. **Validación cruzada**: Evaluar la configuración óptima en otros tipos de documentos en español (facturas, formularios, textos manuscritos). Las limitaciones identificadas sugieren varias extensiones que podrían abordarse a corto plazo. La más urgente es la validación cruzada de la configuración óptima en otros tipos de documentos en español, como facturas, formularios administrativos o textos manuscritos. Esta validación revelaría el grado de transferibilidad de los hallazgos actuales.
2. **Exploración de `text_det_unclip_ratio`**: Incluir este parámetro en el espacio de búsqueda. Para abordar el problema del sobreajuste, futuros experimentos deberían utilizar un subconjunto de optimización más amplio. Un conjunto de 15-20 páginas representativas reduciría la varianza y mejoraría la generalización de las configuraciones encontradas. Complementariamente, sería conveniente construir un corpus más amplio y diverso de documentos en español, incluyendo diferentes tipografías, diseños y calidades de imagen.
3. **Dataset ampliado**: Construir un corpus más amplio y diverso de documentos en español. Desde el punto de vista técnico, queda pendiente la exploración del parámetro `text_det_unclip_ratio`, que permaneció fijo en este trabajo. Incluirlo en el espacio de búsqueda podría revelar interacciones con otros parámetros actualmente desconocidas.
### Líneas de Investigación ### Líneas de Investigación
1. **Transfer learning de hiperparámetros**: Investigar si las configuraciones óptimas para un tipo de documento transfieren a otros dominios. En un horizonte más amplio, surgen varias líneas de investigación prometedoras. Una de las más interesantes es el estudio del transfer learning de hiperparámetros: ¿las configuraciones óptimas para documentos académicos transfieren a otros dominios, o cada tipo de documento requiere optimización específica? La respuesta a esta pregunta tiene implicaciones prácticas significativas.
2. **Optimización multi-objetivo**: Considerar simultáneamente CER, WER y tiempo de inferencia como objetivos. Otra dirección valiosa es la optimización multi-objetivo, que considere simultáneamente CER, WER y tiempo de inferencia. En aplicaciones reales, la precisión máxima no siempre es el único criterio; a menudo existe un compromiso entre calidad y velocidad que debe gestionarse explícitamente.
3. **AutoML para OCR**: Aplicar técnicas de AutoML más avanzadas (Neural Architecture Search, meta-learning). Técnicas de AutoML más avanzadas, como Neural Architecture Search o meta-learning, podrían automatizar aún más el proceso de configuración. Por último, una comparación rigurosa entre optimización de hiperparámetros y fine-tuning real cuantificaría la brecha de rendimiento entre ambas aproximaciones y ayudaría a decidir cuándo merece la pena el esfuerzo adicional del reentrenamiento.
4. **Comparación con fine-tuning**: Cuantificar la brecha de rendimiento entre optimización de hiperparámetros y fine-tuning real.
### Aplicaciones Prácticas ### Aplicaciones Prácticas
1. **Herramienta de configuración automática**: Desarrollar una herramienta que determine automáticamente la configuración óptima para un nuevo tipo de documento. Los resultados de este trabajo abren camino a varias aplicaciones prácticas. Una herramienta de configuración automática podría analizar un pequeño conjunto de documentos de muestra y determinar la configuración óptima de PaddleOCR para ese tipo específico de documento, democratizando el acceso a estas técnicas de optimización.
2. **Integración en pipelines de producción**: Implementar la configuración optimizada en sistemas reales de procesamiento documental. La integración de las configuraciones optimizadas en pipelines de producción representa otra aplicación natural. Los sistemas de procesamiento documental en organizaciones que manejan grandes volúmenes de documentos en español podrían beneficiarse directamente de los hallazgos de este trabajo.
3. **Benchmark público**: Publicar un benchmark de OCR para documentos en español que facilite la comparación de soluciones. Finalmente, la publicación de un benchmark público de OCR para documentos en español facilitaría la comparación objetiva de diferentes soluciones. La comunidad hispanohablante carece actualmente de recursos comparables a los disponibles para otros idiomas, y este trabajo podría contribuir a llenar ese vacío.
### Reflexión Final ### Reflexión Final
Este trabajo demuestra que, en un contexto de recursos limitados donde el fine-tuning de modelos de deep learning no es viable, la optimización de hiperparámetros representa una alternativa práctica y efectiva para mejorar sistemas OCR. En síntesis, este trabajo ha demostrado que la optimización de hiperparámetros representa una alternativa viable al fine-tuning para mejorar sistemas OCR, especialmente cuando se dispone de modelos preentrenados para el idioma objetivo y recursos limitados de tiempo o datos etiquetados.
La metodología propuesta es reproducible, los resultados son cuantificables, y las conclusiones son aplicables a escenarios reales de procesamiento documental. La reducción del CER del 7.78% al 1.49% representa una mejora sustancial que puede tener impacto directo en aplicaciones downstream como extracción de información, análisis semántico y búsqueda de documentos. La metodología propuesta cumple los requisitos de reproducibilidad científica: los experimentos pueden replicarse, los resultados son cuantificables y las conclusiones son aplicables a escenarios reales de procesamiento documental. Sin embargo, la experiencia también ha puesto de manifiesto la importancia de diseñar cuidadosamente los experimentos de optimización. Aunque el objetivo de CER inferior al 2% se alcanzó en el mejor trial individual (0.79%), la validación sobre el conjunto de datos completo (7.72%) revela que el tamaño y representatividad del subconjunto de optimización son factores críticos que no deben subestimarse.
El código fuente y los datos experimentales están disponibles públicamente para facilitar la reproducción y extensión de este trabajo. La infraestructura dockerizada desarrollada constituye una aportación práctica que trasciende los resultados numéricos. Al encapsular los motores OCR en contenedores independientes, se resuelven problemas de compatibilidad entre dependencias y se garantiza que cualquier investigador pueda reproducir exactamente las condiciones experimentales. La aceleración de 82× proporcionada por GPU transforma lo que sería un experimento de días en uno de horas, haciendo viable la exploración exhaustiva de espacios de hiperparámetros con hardware de consumo.
El código fuente, las imágenes Docker y los datos experimentales están disponibles públicamente en el [repositorio del proyecto](https://seryus.ddns.net/unir/MastersThesis). Esta apertura busca facilitar no solo la reproducción de los resultados, sino también la extensión de este trabajo hacia nuevos tipos de documentos, idiomas o motores OCR.

View File

@@ -1,10 +1,12 @@
# Anexo A. Código fuente y datos analizados {.unnumbered} # Anexo A. Código fuente y datos analizados {.unnumbered}
Este anexo proporciona la información técnica necesaria para reproducir los experimentos descritos en este trabajo. Se incluyen las instrucciones de instalación, configuración de los servicios OCR dockerizados, ejecución de los scripts de optimización y acceso a los resultados experimentales.
## A.1 Repositorio del Proyecto ## A.1 Repositorio del Proyecto
El código fuente completo y los datos utilizados en este trabajo están disponibles en el siguiente repositorio: Todo el código fuente y los datos utilizados en este trabajo están disponibles públicamente en el siguiente repositorio:
**URL del repositorio:** https://github.com/seryus/MastersThesis **URL del repositorio:** https://seryus.ddns.net/unir/MastersThesis
El repositorio incluye: El repositorio incluye:
@@ -16,39 +18,85 @@ El repositorio incluye:
## A.2 Estructura del Repositorio ## A.2 Estructura del Repositorio
```mermaid
---
title: "Estructura del repositorio MastersThesis"
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
---
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<br/>generate_mermaid_figures.py"]
config["claude.md<br/>README.md"]
end
``` ```
MastersThesis/
├── docs/ # Documentación de la tesis **Tabla A1.** *Descripción de directorios principales.*
│ └── metrics/ # Métricas de rendimiento OCR
│ ├── metrics.md # Resumen comparativo | Directorio | Contenido |
│ ├── metrics_paddle.md # Resultados PaddleOCR |------------|-----------|
│ ├── metrics_doctr.md # Resultados DocTR | `docs/` | Capítulos del TFM en Markdown (estructura UNIR) |
│ └── metrics_easyocr.md # Resultados EasyOCR | `docs/metrics/` | Métricas de rendimiento por servicio OCR |
├── src/ | `src/paddle_ocr/` | Servicio PaddleOCR dockerizado |
│ ├── paddle_ocr/ # Servicio PaddleOCR | `src/doctr_service/` | Servicio DocTR dockerizado |
│ │ ├── Dockerfile.gpu # Imagen Docker GPU | `src/easyocr_service/` | Servicio EasyOCR dockerizado |
│ │ ├── Dockerfile.cpu # Imagen Docker CPU | `src/raytune/` | Scripts de optimización Ray Tune |
│ │ ├── docker-compose.yml # Configuración Docker | `src/results/` | CSVs con resultados de 64 trials por servicio |
│ │ └── main.py # API FastAPI | `thesis_output/` | Documento TFM generado + figuras PNG |
│ ├── doctr_service/ # Servicio DocTR | `instructions/` | Plantilla e instrucciones UNIR oficiales |
│ │ ├── Dockerfile.gpu
│ │ ├── docker-compose.yml *Fuente: Elaboración propia.*
│ │ └── main.py
│ ├── easyocr_service/ # Servicio EasyOCR
│ │ ├── Dockerfile.gpu
│ │ ├── docker-compose.yml
│ │ └── main.py
│ ├── dataset/ # Dataset de evaluación
│ ├── raytune_ocr.py # Utilidades compartidas Ray Tune
│ └── results/ # Resultados de ajuste CSV
└── .gitea/workflows/ci.yaml # Pipeline CI/CD
```
## A.3 Requisitos de Software ## A.3 Requisitos de Software
### Sistema de Desarrollo ### Sistema de Desarrollo
**Tabla A1.** *Especificaciones del sistema de desarrollo.* **Tabla A2.** *Especificaciones del sistema de desarrollo.*
| Componente | Especificación | | Componente | Especificación |
|------------|----------------| |------------|----------------|
@@ -62,7 +110,7 @@ MastersThesis/
### Dependencias ### Dependencias
**Tabla A2.** *Dependencias del proyecto.* **Tabla A3.** *Dependencias del proyecto.*
| Componente | Versión | | Componente | Versión |
|------------|---------| |------------|---------|
@@ -79,8 +127,8 @@ MastersThesis/
### PaddleOCR (Puerto 8002) ### PaddleOCR (Puerto 8002)
**Imágenes Docker:** **Imágenes Docker:**
- GPU: `seryus.ddns.net/unir/paddle-ocr-gpu` - GPU: [`seryus.ddns.net/unir/paddle-ocr-gpu`](https://seryus.ddns.net/unir/-/packages/container/paddle-ocr-gpu/latest)
- CPU: `seryus.ddns.net/unir/paddle-ocr-cpu` - CPU: [`seryus.ddns.net/unir/paddle-ocr-cpu`](https://seryus.ddns.net/unir/-/packages/container/paddle-ocr-cpu/latest)
```bash ```bash
cd src/paddle_ocr cd src/paddle_ocr
@@ -88,13 +136,13 @@ cd src/paddle_ocr
# GPU (recomendado) # GPU (recomendado)
docker compose up -d docker compose up -d
# CPU (más lento, 126x) # CPU (más lento, 82x)
docker compose -f docker-compose.cpu-registry.yml up -d docker compose -f docker-compose.cpu-registry.yml up -d
``` ```
### DocTR (Puerto 8003) ### DocTR (Puerto 8003)
**Imagen Docker:** `seryus.ddns.net/unir/doctr-gpu` **Imagen Docker:** [`seryus.ddns.net/unir/doctr-gpu`](https://seryus.ddns.net/unir/-/packages/container/doctr-gpu/latest)
```bash ```bash
cd src/doctr_service cd src/doctr_service
@@ -105,12 +153,14 @@ docker compose up -d
### EasyOCR (Puerto 8002) ### EasyOCR (Puerto 8002)
**Imagen Docker:** `seryus.ddns.net/unir/easyocr-gpu` > **Nota:** EasyOCR utiliza el mismo puerto (8002) que PaddleOCR. No se pueden ejecutar simultáneamente. Por esta razón, existe un archivo docker-compose separado para EasyOCR.
**Imagen Docker:** [`seryus.ddns.net/unir/easyocr-gpu`](https://seryus.ddns.net/unir/-/packages/container/easyocr-gpu/latest)
```bash ```bash
cd src/easyocr_service cd src/easyocr_service
# GPU # GPU (usar archivo separado para evitar conflicto de puerto)
docker compose up -d docker compose up -d
``` ```
@@ -181,34 +231,109 @@ analyze_results(results, prefix='raytune_paddle', config_keys=PADDLE_OCR_CONFIG_
### Servicios y Puertos ### Servicios y Puertos
**Tabla A3.** *Servicios Docker y puertos.* **Tabla A4.** *Servicios Docker y puertos.*
| Servicio | Puerto | Script de Ajuste | | Servicio | Puerto | Script de Ajuste | Nota |
|----------|--------|------------------| |----------|--------|------------------|------|
| PaddleOCR | 8002 | `paddle_ocr_payload` | | PaddleOCR | 8002 | `paddle_ocr_payload` | - |
| DocTR | 8003 | `doctr_payload` | | DocTR | 8003 | `doctr_payload` | - |
| EasyOCR | 8002 | `easyocr_payload` | | EasyOCR | 8002 | `easyocr_payload` | Conflicto con PaddleOCR |
*Fuente: Elaboración propia.* *Fuente: Elaboración propia.*
> **Nota:** Debido a limitaciones de recursos GPU (VRAM insuficiente para ejecutar múltiples modelos OCR simultáneamente), solo se ejecuta un servicio a la vez. PaddleOCR y EasyOCR comparten el puerto 8002. Para cambiar de servicio, detener el actual con `docker compose down`.
## A.7 Métricas de Rendimiento ## A.7 Métricas de Rendimiento
Los resultados detallados de las evaluaciones y ajustes de hiperparámetros se encuentran en: Esta sección presenta los resultados completos de las evaluaciones comparativas y del ajuste de hiperparámetros realizado con Ray Tune sobre los tres servicios OCR evaluados.
- [Métricas Generales](metrics/metrics.md) - Comparativa de los tres servicios ### Comparativa General de Servicios
- [PaddleOCR](metrics/metrics_paddle.md) - Mejor precisión (7.76% CER baseline, **1.49% optimizado**)
- [DocTR](metrics/metrics_doctr.md) - Más rápido (0.50s/página)
- [EasyOCR](metrics/metrics_easyocr.md) - Balance intermedio
### Resumen de Resultados **Tabla A5.** *Comparativa de servicios OCR en dataset de 45 páginas (GPU RTX 3060).*
**Tabla A4.** *Resumen de resultados del benchmark por servicio.* | Servicio | CER | WER | Tiempo/Página | Tiempo Total | VRAM |
|----------|-----|-----|---------------|--------------|------|
| **PaddleOCR (Mobile)** | **7.76%** | **11.62%** | 0.58s | 32.0s | 0.06 GB |
| EasyOCR | 11.23% | 36.36% | 1.88s | 88.5s | ~2 GB |
| DocTR | 12.06% | 42.01% | 0.50s | 28.4s | ~1 GB |
| Servicio | CER Base | CER Ajustado | Mejora | *Fuente: Benchmark realizado el 2026-01-19. Elaboración propia.*
|----------|----------|--------------|--------|
| **PaddleOCR** | 8.85% | **7.72%** | 12.8% | **Ganador:** PaddleOCR (Mobile) - Mejor precisión (7.76% CER) con velocidad competitiva y mínimo consumo de VRAM.
| DocTR | 12.06% | 12.07% | 0% |
| EasyOCR | 11.23% | 11.14% | 0.8% | ### Resultados de Ajuste de Hiperparámetros
Se ejecutaron 64 trials por servicio utilizando Ray Tune con Optuna sobre las páginas 5-10 del primer documento.
**Tabla A6.** *Resultados del ajuste de hiperparámetros por servicio.*
| Servicio | CER Base | CER Ajustado | Mejora | Mejor Trial (5 páginas) |
|----------|----------|--------------|--------|-------------------------|
| **PaddleOCR** | 8.85% | **7.72%** | **12.8%** | **0.79%** ✓ |
| DocTR | 12.06% | 12.07% | 0% | 7.43% |
| EasyOCR | 11.23% | 11.14% | 0.8% | 5.83% |
*Fuente: Resultados de 64 trials Ray Tune por servicio. Elaboración propia.*
> **Nota sobre sobreajuste:** La diferencia entre los resultados del mejor trial (subconjunto de 5 páginas) y el dataset completo (45 páginas) indica sobreajuste parcial a las páginas de ajuste. Un subconjunto más grande (15-20 páginas) mejoraría la generalización.
### Configuración Óptima PaddleOCR
La siguiente configuración logró el mejor rendimiento en el ajuste de hiperparámetros:
```json
{
"use_doc_orientation_classify": true,
"use_doc_unwarping": false,
"textline_orientation": true,
"text_det_thresh": 0.0462,
"text_det_box_thresh": 0.4862,
"text_det_unclip_ratio": 0.0,
"text_rec_score_thresh": 0.5658
}
```
**Hallazgos clave:**
- `textline_orientation=true`: Crítico para documentos con layouts mixtos
- `use_doc_orientation_classify=true`: Mejora detección de orientación
- `use_doc_unwarping=false`: Innecesario para PDFs digitales
- `text_det_thresh` bajo (0.0462): Detección más sensible mejora resultados
### Rendimiento CPU vs GPU
**Tabla A7.** *Comparación de rendimiento CPU vs GPU (PaddleOCR).*
| Métrica | CPU | GPU (RTX 3060) | Aceleración |
|---------|-----|----------------|-------------|
| Tiempo/Página | 69.4s | 0.55s | **126x más rápido** |
| Mejor CER | 1.15% | 0.79% | GPU mejor |
| 45 páginas | ~52 min | ~25 seg | **126x más rápido** |
*Fuente: Datos CPU de `raytune_paddle_subproc_results_20251207_192320.csv`. Elaboración propia.*
### Análisis de Errores por Servicio
**Tabla A8.** *Tipos de errores identificados por servicio OCR.*
| Servicio | Fortalezas | Debilidades | ¿Fine-tuning recomendado? |
|----------|------------|-------------|---------------------------|
| **PaddleOCR** | Preserva estructura, buen manejo de español | Errores menores de acentos (~5%) | No (ya excelente) |
| DocTR | Más rápido | Pierde estructura, omite TODOS los diacríticos | Sí (para diacríticos) |
| EasyOCR | Modelo correcto para español | Caracteres espurios, confunde `o`/`0` | Sí (problemas del detector) |
*Fuente: Análisis manual del debugset. Elaboración propia.*
### Archivos de Resultados
Los resultados crudos de los 64 trials por servicio están disponibles en el repositorio:
**Tabla A9.** *Ubicación de archivos de resultados.*
| Servicio | Archivo CSV |
|----------|-------------|
| PaddleOCR | [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/-/blob/main/src/results/raytune_paddle_results_20260119_122609.csv) |
| DocTR | [`src/results/raytune_doctr_results_20260119_121445.csv`](https://seryus.ddns.net/unir/MastersThesis/-/blob/main/src/results/raytune_doctr_results_20260119_121445.csv) |
| EasyOCR | [`src/results/raytune_easyocr_results_20260119_120204.csv`](https://seryus.ddns.net/unir/MastersThesis/-/blob/main/src/results/raytune_easyocr_results_20260119_120204.csv) |
*Fuente: Elaboración propia.* *Fuente: Elaboración propia.*

View File

@@ -75,6 +75,17 @@ La fase de optimización representa el **resultado principal del TFM** (CER 1.49
### Comparación de Precisión (CER - menor es mejor) ### Comparación de Precisión (CER - menor es mejor)
```mermaid ```mermaid
---
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
xyChart:
plotColorPalette: "#0098CD"
---
xychart-beta xychart-beta
title "Tasa de Error de Caracteres por Servicio" title "Tasa de Error de Caracteres por Servicio"
x-axis ["PaddleOCR", "EasyOCR", "DocTR"] x-axis ["PaddleOCR", "EasyOCR", "DocTR"]
@@ -85,6 +96,17 @@ xychart-beta
### Comparación de Velocidad (Tiempo por Página) ### Comparación de Velocidad (Tiempo por Página)
```mermaid ```mermaid
---
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
xyChart:
plotColorPalette: "#0098CD"
---
xychart-beta xychart-beta
title "Tiempo de Procesamiento por Página (segundos)" title "Tiempo de Procesamiento por Página (segundos)"
x-axis ["DocTR", "PaddleOCR", "EasyOCR"] x-axis ["DocTR", "PaddleOCR", "EasyOCR"]
@@ -167,6 +189,17 @@ Datos de `raytune_paddle_subproc_results_20251207_192320.csv` (CPU) vs RTX 3060
| **45 páginas** | ~52 min | ~25 seg | **126x más rápido** | | **45 páginas** | ~52 min | ~25 seg | **126x más rápido** |
```mermaid ```mermaid
---
config:
theme: base
themeVariables:
primaryColor: "#E6F4F9"
primaryTextColor: "#404040"
primaryBorderColor: "#0098CD"
lineColor: "#0098CD"
xyChart:
plotColorPalette: "#0098CD"
---
xychart-beta xychart-beta
title "Tiempo de Procesamiento por Página: CPU vs GPU" title "Tiempo de Procesamiento por Página: CPU vs GPU"
x-axis ["CPU", "GPU (RTX 3060)"] x-axis ["CPU", "GPU (RTX 3060)"]

View File

@@ -1,6 +1,8 @@
# Resultados de Ajuste de Hiperparámetros PaddleOCR # Resultados de Ajuste de Hiperparámetros PaddleOCR
> **Nota:** Los resultados de este documento corresponden a la fase de validación GPU con 45 páginas. El resultado oficial del TFM es **CER 1.49%** obtenido en la validación final de 24 páginas con la configuración optimizada (ver `docs/04_desarrollo_especifico.md`). > **Resultados principales del TFM:**
> - Mejor trial (5 páginas): **CER 0.79%** ✓ cumple objetivo CER < 2%
> - Dataset completo (45 páginas): **CER 7.72%** (mejora del 12.8% respecto a baseline)
**Fecha de Ajuste:** 2026-01-19 **Fecha de Ajuste:** 2026-01-19
**Plataforma:** NVIDIA RTX 3060 Laptop GPU **Plataforma:** NVIDIA RTX 3060 Laptop GPU

View File

@@ -6,10 +6,18 @@ import re
import subprocess import subprocess
import json import json
import cairosvg
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DOCS_DIR = os.path.join(BASE_DIR, 'docs') DOCS_DIR = os.path.join(BASE_DIR, 'docs')
OUTPUT_DIR = os.path.join(BASE_DIR, 'thesis_output/figures') OUTPUT_DIR = os.path.join(BASE_DIR, 'thesis_output/figures')
MMDC = os.path.join(BASE_DIR, 'node_modules/.bin/mmdc') MMDC = os.path.join(BASE_DIR, 'node_modules/.bin/mmdc')
CONFIG_FILE = os.path.join(BASE_DIR, 'mermaid.config.json')
# Light blue color for bar charts
BAR_COLOR = '#0098CD'
# Default bar colors that need to be replaced (varies by theme)
DEFAULT_BAR_COLORS = ['#ECECFF', '#FFF4DD', '#ececff', '#fff4dd']
def extract_mermaid_diagrams(): def extract_mermaid_diagrams():
"""Extract all mermaid diagrams from markdown files.""" """Extract all mermaid diagrams from markdown files."""
@@ -35,10 +43,12 @@ def extract_mermaid_diagrams():
matches = re.findall(pattern, content, re.DOTALL) matches = re.findall(pattern, content, re.DOTALL)
for i, mermaid_code in enumerate(matches): for i, mermaid_code in enumerate(matches):
# Try to extract title from YAML front matter or inline title # Try to extract title from YAML front matter
# Match title with quotes: title: "Something" or title: 'Something'
title_match = re.search(r'title:\s*["\']([^"\']+)["\']', mermaid_code) title_match = re.search(r'title:\s*["\']([^"\']+)["\']', mermaid_code)
if not title_match: if not title_match:
title_match = re.search(r'title\s+["\']?([^"\'"\n]+)["\']?', mermaid_code) # Match title without quotes: title: Something
title_match = re.search(r'title:\s*([^"\'\n]+)', mermaid_code)
title = title_match.group(1).strip() if title_match else f"Diagrama {len(diagrams) + 1}" title = title_match.group(1).strip() if title_match else f"Diagrama {len(diagrams) + 1}"
diagrams.append({ diagrams.append({
@@ -61,17 +71,51 @@ def convert_to_png(diagrams):
temp_file = os.path.join(OUTPUT_DIR, f'temp_{diagram["index"]}.mmd') temp_file = os.path.join(OUTPUT_DIR, f'temp_{diagram["index"]}.mmd')
output_file = os.path.join(OUTPUT_DIR, f'figura_{diagram["index"]}.png') output_file = os.path.join(OUTPUT_DIR, f'figura_{diagram["index"]}.png')
# Check if this is a bar chart (xychart-beta)
is_bar_chart = 'xychart-beta' in diagram['code']
with open(temp_file, 'w', encoding='utf-8') as f: with open(temp_file, 'w', encoding='utf-8') as f:
f.write(diagram['code']) f.write(diagram['code'])
# Convert using mmdc with moderate size for page fit
try: try:
result = subprocess.run( if is_bar_chart:
[MMDC, '-i', temp_file, '-o', output_file, '-b', 'white', '-w', '800', '-s', '1.5'], # For bar charts: generate SVG, fix colors, convert to PNG
capture_output=True, svg_file = os.path.join(OUTPUT_DIR, f'temp_{diagram["index"]}.svg')
text=True,
timeout=60 result = subprocess.run(
) [MMDC, '-i', temp_file, '-o', svg_file, '-b', 'white', '-w', '1600', '-c', CONFIG_FILE],
capture_output=True,
text=True,
timeout=60
)
if os.path.exists(svg_file):
# Read SVG and replace bar color
with open(svg_file, 'r', encoding='utf-8') as f:
svg_content = f.read()
# Replace default bar colors with light blue (both fill and stroke)
for default_color in DEFAULT_BAR_COLORS:
svg_content = svg_content.replace(f'fill="{default_color}"', f'fill="{BAR_COLOR}"')
svg_content = svg_content.replace(f"fill='{default_color}'", f"fill='{BAR_COLOR}'")
svg_content = svg_content.replace(f'stroke="{default_color}"', f'stroke="{BAR_COLOR}"')
svg_content = svg_content.replace(f"stroke='{default_color}'", f"stroke='{BAR_COLOR}'")
# Convert SVG to PNG using cairosvg (with scale for high resolution)
cairosvg.svg2png(bytestring=svg_content.encode('utf-8'),
write_to=output_file,
scale=3)
# Clean up SVG
os.remove(svg_file)
else:
# For other diagrams: direct PNG generation
result = subprocess.run(
[MMDC, '-i', temp_file, '-o', output_file, '-b', 'white', '-w', '1600', '-s', '3', '-c', CONFIG_FILE],
capture_output=True,
text=True,
timeout=60
)
if os.path.exists(output_file): if os.path.exists(output_file):
print(f"✓ Generated: figura_{diagram['index']}.png - {diagram['title']}") print(f"✓ Generated: figura_{diagram['index']}.png - {diagram['title']}")

12
mermaid.config.json Normal file
View File

@@ -0,0 +1,12 @@
{
"theme": "base",
"themeVariables": {
"primaryColor": "#E6F4F9",
"primaryTextColor": "#404040",
"primaryBorderColor": "#0098CD",
"lineColor": "#0098CD"
},
"xyChart": {
"plotColorPalette": "#0098CD"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -26,12 +26,57 @@
}, },
{ {
"file": "figura_6.png", "file": "figura_6.png",
"title": "Impacto de textline_orientation en CER", "title": "Arquitectura de microservicios para optimización OCR",
"index": 6 "index": 6
}, },
{ {
"file": "figura_7.png", "file": "figura_7.png",
"title": "Reducción de errores: Baseline vs Optimizado", "title": "Estrategia de build multi-stage",
"index": 7 "index": 7
},
{
"file": "figura_8.png",
"title": "Flujo de ejecución de optimización con Ray Tune",
"index": 8
},
{
"file": "figura_9.png",
"title": "Distribución de trials por rango de CER",
"index": 9
},
{
"file": "figura_10.png",
"title": "Correlación de hiperparámetros con CER",
"index": 10
},
{
"file": "figura_11.png",
"title": "Impacto de textline_orientation en CER",
"index": 11
},
{
"file": "figura_12.png",
"title": "Reducción de errores: Baseline vs Optimizado (45 páginas)",
"index": 12
},
{
"file": "figura_13.png",
"title": "Evolución del CER a través del estudio",
"index": 13
},
{
"file": "figura_14.png",
"title": "Ranking de importancia de hiperparámetros",
"index": 14
},
{
"file": "figura_15.png",
"title": "Tiempo de procesamiento: CPU vs GPU (segundos/página)",
"index": 15
},
{
"file": "figura_16.png",
"title": "Estructura del repositorio MastersThesis",
"index": 16
} }
] ]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:clrMap xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>

View File

@@ -0,0 +1,21 @@
<xml xmlns:o="urn:schemas-microsoft-com:office:office">
<o:MainFile HRef="../plantilla_individual.htm"/>
<o:File HRef="item0001.xml"/>
<o:File HRef="props002.xml"/>
<o:File HRef="item0003.xml"/>
<o:File HRef="props004.xml"/>
<o:File HRef="item0005.xml"/>
<o:File HRef="props006.xml"/>
<o:File HRef="item0007.xml"/>
<o:File HRef="props008.xml"/>
<o:File HRef="themedata.thmx"/>
<o:File HRef="colorschememapping.xml"/>
<o:File HRef="image001.png"/>
<o:File HRef="image002.gif"/>
<o:File HRef="image003.png"/>
<o:File HRef="image004.jpg"/>
<o:File HRef="image005.png"/>
<o:File HRef="image006.gif"/>
<o:File HRef="header.htm"/>
<o:File HRef="filelist.xml"/>
</xml>

View File

@@ -0,0 +1,113 @@
<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 15">
<meta name=Originator content="Microsoft Word 15">
<link id=Main-File rel=Main-File href="../plantilla_individual.htm">
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="2050"/>
</xml><![endif]-->
</head>
<body link="#0563C1" vlink="#954F72">
<div style='mso-element:footnote-separator' id=fs>
<p class=MsoNormal><span lang=ES><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
<hr align=left size=1 width="33%">
<![endif]></span></span></p>
</div>
<div style='mso-element:footnote-continuation-separator' id=fcs>
<p class=MsoNormal><span lang=ES><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
<hr align=left size=1>
<![endif]></span></span></p>
</div>
<div style='mso-element:endnote-separator' id=es>
<p class=MsoNormal><span lang=ES><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
<hr align=left size=1 width="33%">
<![endif]></span></span></p>
</div>
<div style='mso-element:endnote-continuation-separator' id=ecs>
<p class=MsoNormal><span lang=ES><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
<hr align=left size=1>
<![endif]></span></span></p>
</div>
<div style='mso-element:header' id=eh1>
<p class=MsoHeader><span lang=ES><o:p>&nbsp;</o:p></span></p>
</div>
<div style='mso-element:header' id=h1>
<p class=MsoHeader align=right style='margin:0cm;text-align:right;line-height:
normal'><span lang=ES style='font-size:10.0pt;mso-bidi-font-size:12.0pt;
font-family:"Calibri Light",sans-serif;mso-ascii-theme-font:major-latin;
mso-hansi-theme-font:major-latin;mso-bidi-font-family:"Times New Roman"'>Sergio
Jiménez <span class=SpellE>Jiménez</span><o:p></o:p></span></p>
<p class=MsoHeader align=right style='margin:0cm;text-align:right;line-height:
normal'><span lang=ES style='font-size:10.0pt;mso-bidi-font-size:12.0pt;
font-family:"Calibri Light",sans-serif;mso-ascii-theme-font:major-latin;
mso-hansi-theme-font:major-latin;mso-bidi-font-family:"Times New Roman"'>Optimización
de Hiperparámetros OCR con Ray Tune para Documentos Académicos en <span
class=GramE>Español</span><o:p></o:p></span></p>
</div>
<div style='mso-element:footer' id=ef1>
<p class=MsoFooter><span lang=ES><o:p>&nbsp;</o:p></span></p>
</div>
<div style='mso-element:footer' id=f1>
<p class=Pgina><!--[if supportFields]><span lang=ES><span style='mso-element:
field-begin'></span>PAGE<span style='mso-spacerun:yes'>   </span>\* MERGEFORMAT<span
style='mso-element:field-separator'></span></span><![endif]--><span lang=ES><span
style='mso-no-proof:yes'>13</span></span><!--[if supportFields]><span lang=ES><span
style='mso-element:field-end'></span></span><![endif]--></p>
</div>
<div style='mso-element:header' id=fh1>
<p class=MsoHeader><span lang=ES><o:p>&nbsp;</o:p></span></p>
</div>
<div style='mso-element:footer' id=ff1>
<p class=MsoFooter><span lang=ES><o:p>&nbsp;</o:p></span></p>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,258 @@
<?xml version="1.0" encoding="utf-8"?><ct:contentTypeSchema ct:_="" ma:_="" ma:contentTypeName="Documento" ma:contentTypeID="0x010100DF3D7C797EA12745A270EF30E38719B9" ma:contentTypeVersion="19" ma:contentTypeDescription="Crear nuevo documento." ma:contentTypeScope="" ma:versionID="227b02526234ef39b0b78895a9d90cf5" xmlns:ct="http://schemas.microsoft.com/office/2006/metadata/contentType" xmlns:ma="http://schemas.microsoft.com/office/2006/metadata/properties/metaAttributes">
<xsd:schema targetNamespace="http://schemas.microsoft.com/office/2006/metadata/properties" ma:root="true" ma:fieldsID="3c939c8607e2f594db8bbb23634dd059" ns2:_="" ns3:_="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:p="http://schemas.microsoft.com/office/2006/metadata/properties" xmlns:ns2="0a70e875-3d35-4be2-921f-7117c31bab9b" xmlns:ns3="27c1adeb-3674-457c-b08c-8a73f31b6e23">
<xsd:import namespace="0a70e875-3d35-4be2-921f-7117c31bab9b"/>
<xsd:import namespace="27c1adeb-3674-457c-b08c-8a73f31b6e23"/>
<xsd:element name="properties">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="documentManagement">
<xsd:complexType>
<xsd:all>
<xsd:element ref="ns2:SharedWithUsers" minOccurs="0"/>
<xsd:element ref="ns2:SharedWithDetails" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceMetadata" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceFastMetadata" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceAutoKeyPoints" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceKeyPoints" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceAutoTags" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceOCR" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceGenerationTime" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceEventHashCode" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceDateTaken" minOccurs="0"/>
<xsd:element ref="ns3:MediaLengthInSeconds" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceLocation" minOccurs="0"/>
<xsd:element ref="ns3:lcf76f155ced4ddcb4097134ff3c332f" minOccurs="0"/>
<xsd:element ref="ns2:TaxCatchAll" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceSearchProperties" minOccurs="0"/>
<xsd:element ref="ns3:_Flow_SignoffStatus" minOccurs="0"/>
<xsd:element ref="ns3:MediaServiceObjectDetectorVersions" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:schema targetNamespace="0a70e875-3d35-4be2-921f-7117c31bab9b" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dms="http://schemas.microsoft.com/office/2006/documentManagement/types" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
<xsd:import namespace="http://schemas.microsoft.com/office/2006/documentManagement/types"/>
<xsd:import namespace="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"/>
<xsd:element name="SharedWithUsers" ma:index="8" nillable="true" ma:displayName="Compartido con" ma:internalName="SharedWithUsers" ma:readOnly="true">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="dms:UserMulti">
<xsd:sequence>
<xsd:element name="UserInfo" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="DisplayName" type="xsd:string" minOccurs="0"/>
<xsd:element name="AccountId" type="dms:UserId" minOccurs="0" nillable="true"/>
<xsd:element name="AccountType" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="SharedWithDetails" ma:index="9" nillable="true" ma:displayName="Detalles de uso compartido" ma:internalName="SharedWithDetails" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note">
<xsd:maxLength value="255"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="TaxCatchAll" ma:index="23" nillable="true" ma:displayName="Taxonomy Catch All Column" ma:hidden="true" ma:list="{c7f67346-78c9-4c4d-b954-8d350fdf60db}" ma:internalName="TaxCatchAll" ma:showField="CatchAllData" ma:web="0a70e875-3d35-4be2-921f-7117c31bab9b">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="dms:MultiChoiceLookup">
<xsd:sequence>
<xsd:element name="Value" type="dms:Lookup" maxOccurs="unbounded" minOccurs="0" nillable="true"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:schema targetNamespace="27c1adeb-3674-457c-b08c-8a73f31b6e23" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dms="http://schemas.microsoft.com/office/2006/documentManagement/types" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
<xsd:import namespace="http://schemas.microsoft.com/office/2006/documentManagement/types"/>
<xsd:import namespace="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"/>
<xsd:element name="MediaServiceMetadata" ma:index="10" nillable="true" ma:displayName="MediaServiceMetadata" ma:hidden="true" ma:internalName="MediaServiceMetadata" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceFastMetadata" ma:index="11" nillable="true" ma:displayName="MediaServiceFastMetadata" ma:hidden="true" ma:internalName="MediaServiceFastMetadata" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceAutoKeyPoints" ma:index="12" nillable="true" ma:displayName="MediaServiceAutoKeyPoints" ma:hidden="true" ma:internalName="MediaServiceAutoKeyPoints" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceKeyPoints" ma:index="13" nillable="true" ma:displayName="KeyPoints" ma:internalName="MediaServiceKeyPoints" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note">
<xsd:maxLength value="255"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceAutoTags" ma:index="14" nillable="true" ma:displayName="Tags" ma:internalName="MediaServiceAutoTags" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceOCR" ma:index="15" nillable="true" ma:displayName="Extracted Text" ma:internalName="MediaServiceOCR" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note">
<xsd:maxLength value="255"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceGenerationTime" ma:index="16" nillable="true" ma:displayName="MediaServiceGenerationTime" ma:hidden="true" ma:internalName="MediaServiceGenerationTime" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceEventHashCode" ma:index="17" nillable="true" ma:displayName="MediaServiceEventHashCode" ma:hidden="true" ma:internalName="MediaServiceEventHashCode" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceDateTaken" ma:index="18" nillable="true" ma:displayName="MediaServiceDateTaken" ma:hidden="true" ma:internalName="MediaServiceDateTaken" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaLengthInSeconds" ma:index="19" nillable="true" ma:displayName="Length (seconds)" ma:internalName="MediaLengthInSeconds" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Unknown"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceLocation" ma:index="20" nillable="true" ma:displayName="Location" ma:internalName="MediaServiceLocation" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="lcf76f155ced4ddcb4097134ff3c332f" ma:index="22" nillable="true" ma:taxonomy="true" ma:internalName="lcf76f155ced4ddcb4097134ff3c332f" ma:taxonomyFieldName="MediaServiceImageTags" ma:displayName="Etiquetas de imagen" ma:readOnly="false" ma:fieldId="{5cf76f15-5ced-4ddc-b409-7134ff3c332f}" ma:taxonomyMulti="true" ma:sspId="17631b59-e624-4eb7-963c-219f14f887a3" ma:termSetId="09814cd3-568e-fe90-9814-8d621ff8fb84" ma:anchorId="fba54fb3-c3e1-fe81-a776-ca4b69148c4d" ma:open="true" ma:isKeyword="false">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="pc:Terms" minOccurs="0" maxOccurs="1"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="MediaServiceSearchProperties" ma:index="24" nillable="true" ma:displayName="MediaServiceSearchProperties" ma:hidden="true" ma:internalName="MediaServiceSearchProperties" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Note"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="_Flow_SignoffStatus" ma:index="25" nillable="true" ma:displayName="Estado de aprobación" ma:internalName="Estado_x0020_de_x0020_aprobaci_x00f3_n">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MediaServiceObjectDetectorVersions" ma:index="26" nillable="true" ma:displayName="MediaServiceObjectDetectorVersions" ma:description="" ma:hidden="true" ma:indexed="true" ma:internalName="MediaServiceObjectDetectorVersions" ma:readOnly="true">
<xsd:simpleType>
<xsd:restriction base="dms:Text"/>
</xsd:simpleType>
</xsd:element>
</xsd:schema>
<xsd:schema targetNamespace="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all" xmlns="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:odoc="http://schemas.microsoft.com/internal/obd">
<xsd:import namespace="http://purl.org/dc/elements/1.1/" schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
<xsd:import namespace="http://purl.org/dc/terms/" schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
<xsd:element name="coreProperties" type="CT_coreProperties"/>
<xsd:complexType name="CT_coreProperties">
<xsd:all>
<xsd:element ref="dc:creator" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="dcterms:created" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="dc:identifier" minOccurs="0" maxOccurs="1"/>
<xsd:element name="contentType" minOccurs="0" maxOccurs="1" type="xsd:string" ma:index="0" ma:displayName="Tipo de contenido"/>
<xsd:element ref="dc:title" minOccurs="0" maxOccurs="1" ma:index="4" ma:displayName="Título"/>
<xsd:element ref="dc:subject" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="dc:description" minOccurs="0" maxOccurs="1"/>
<xsd:element name="keywords" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element ref="dc:language" minOccurs="0" maxOccurs="1"/>
<xsd:element name="category" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="version" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="revision" minOccurs="0" maxOccurs="1" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
This value indicates the number of saves or revisions. The application is responsible for updating this value after each revision.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="lastModifiedBy" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element ref="dcterms:modified" minOccurs="0" maxOccurs="1"/>
<xsd:element name="contentStatus" minOccurs="0" maxOccurs="1" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
</xsd:schema>
<xs:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element ref="pc:DisplayName" minOccurs="0"></xs:element>
<xs:element ref="pc:AccountId" minOccurs="0"></xs:element>
<xs:element ref="pc:AccountType" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="DisplayName" type="xs:string"></xs:element>
<xs:element name="AccountId" type="xs:string"></xs:element>
<xs:element name="AccountType" type="xs:string"></xs:element>
<xs:element name="BDCAssociatedEntity">
<xs:complexType>
<xs:sequence>
<xs:element ref="pc:BDCEntity" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
<xs:attribute ref="pc:EntityNamespace"></xs:attribute>
<xs:attribute ref="pc:EntityName"></xs:attribute>
<xs:attribute ref="pc:SystemInstanceName"></xs:attribute>
<xs:attribute ref="pc:AssociationName"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:attribute name="EntityNamespace" type="xs:string"></xs:attribute>
<xs:attribute name="EntityName" type="xs:string"></xs:attribute>
<xs:attribute name="SystemInstanceName" type="xs:string"></xs:attribute>
<xs:attribute name="AssociationName" type="xs:string"></xs:attribute>
<xs:element name="BDCEntity">
<xs:complexType>
<xs:sequence>
<xs:element ref="pc:EntityDisplayName" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityInstanceReference" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityId1" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityId2" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityId3" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityId4" minOccurs="0"></xs:element>
<xs:element ref="pc:EntityId5" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="EntityDisplayName" type="xs:string"></xs:element>
<xs:element name="EntityInstanceReference" type="xs:string"></xs:element>
<xs:element name="EntityId1" type="xs:string"></xs:element>
<xs:element name="EntityId2" type="xs:string"></xs:element>
<xs:element name="EntityId3" type="xs:string"></xs:element>
<xs:element name="EntityId4" type="xs:string"></xs:element>
<xs:element name="EntityId5" type="xs:string"></xs:element>
<xs:element name="Terms">
<xs:complexType>
<xs:sequence>
<xs:element ref="pc:TermInfo" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TermInfo">
<xs:complexType>
<xs:sequence>
<xs:element ref="pc:TermName" minOccurs="0"></xs:element>
<xs:element ref="pc:TermId" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TermName" type="xs:string"></xs:element>
<xs:element name="TermId" type="xs:string"></xs:element>
</xs:schema>
</ct:contentTypeSchema>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><b:Sources SelectedStyle="\APASixthEditionOfficeOnline.xsl" StyleName="APA" Version="6" xmlns:b="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"><b:Source><b:Tag>Dor81</b:Tag><b:SourceType>JournalArticle</b:SourceType><b:Guid>{D7C468B5-5E32-4254-9330-6DB2DDB01037}</b:Guid><b:Title>There's a S.M.A.R.T. way to write management's goals and objectives</b:Title><b:Year>1981</b:Year><b:Author><b:Author><b:NameList><b:Person><b:Last>Doran</b:Last><b:First>G.</b:First><b:Middle>T.</b:Middle></b:Person></b:NameList></b:Author></b:Author><b:JournalName>Management Review (AMA FORUM)</b:JournalName><b:Pages>35-36</b:Pages><b:Volume>70</b:Volume><b:RefOrder>1</b:RefOrder></b:Source></b:Sources>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><p:properties xmlns:p="http://schemas.microsoft.com/office/2006/metadata/properties" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"><documentManagement><lcf76f155ced4ddcb4097134ff3c332f xmlns="27c1adeb-3674-457c-b08c-8a73f31b6e23"><Terms xmlns="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"></Terms></lcf76f155ced4ddcb4097134ff3c332f><TaxCatchAll xmlns="0a70e875-3d35-4be2-921f-7117c31bab9b" xsi:nil="true"/><_Flow_SignoffStatus xmlns="27c1adeb-3674-457c-b08c-8a73f31b6e23" xsi:nil="true"/></documentManagement></p:properties>

View File

@@ -0,0 +1 @@
<?mso-contentType?><FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms"><Display>DocumentLibraryForm</Display><Edit>DocumentLibraryForm</Edit><New>DocumentLibraryForm</New></FormTemplates>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ds:datastoreItem ds:itemID="{B3A822E2-E694-47D5-9E22-DA4B12671ABB}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml"><ds:schemaRefs><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/metadata/contentType"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/metadata/properties/metaAttributes"/><ds:schemaRef ds:uri="http://www.w3.org/2001/XMLSchema"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/metadata/properties"/><ds:schemaRef ds:uri="0a70e875-3d35-4be2-921f-7117c31bab9b"/><ds:schemaRef ds:uri="27c1adeb-3674-457c-b08c-8a73f31b6e23"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/documentManagement/types"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"/><ds:schemaRef ds:uri="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"/><ds:schemaRef ds:uri="http://purl.org/dc/elements/1.1/"/><ds:schemaRef ds:uri="http://purl.org/dc/terms/"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/internal/obd"/></ds:schemaRefs></ds:datastoreItem>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ds:datastoreItem ds:itemID="{3CBD5336-2C2D-4DA8-8EBD-C205328B54AF}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml"><ds:schemaRefs><ds:schemaRef ds:uri="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"/></ds:schemaRefs></ds:datastoreItem>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ds:datastoreItem ds:itemID="{DB456AF2-52F5-44D8-AEC6-B5F9D96C377E}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml"><ds:schemaRefs><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/metadata/properties"/><ds:schemaRef ds:uri="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"/><ds:schemaRef ds:uri="27c1adeb-3674-457c-b08c-8a73f31b6e23"/><ds:schemaRef ds:uri="0a70e875-3d35-4be2-921f-7117c31bab9b"/></ds:schemaRefs></ds:datastoreItem>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ds:datastoreItem ds:itemID="{BE74C307-52FE-48C3-92C2-E1552852BAAA}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml"><ds:schemaRefs><ds:schemaRef ds:uri="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms"/></ds:schemaRefs></ds:datastoreItem>