links regeneration
Some checks failed
build_docker / essential (push) Successful in 0s
build_docker / build_paddle_ocr (push) Successful in 5m30s
build_docker / build_paddle_ocr_gpu (push) Successful in 22m0s
build_docker / build_easyocr (push) Successful in 18m14s
build_docker / build_doctr_gpu (push) Has been cancelled
build_docker / build_raytune (push) Has been cancelled
build_docker / build_easyocr_gpu (push) Has started running
build_docker / build_doctr (push) Has been cancelled
Some checks failed
build_docker / essential (push) Successful in 0s
build_docker / build_paddle_ocr (push) Successful in 5m30s
build_docker / build_paddle_ocr_gpu (push) Successful in 22m0s
build_docker / build_easyocr (push) Successful in 18m14s
build_docker / build_doctr_gpu (push) Has been cancelled
build_docker / build_raytune (push) Has been cancelled
build_docker / build_easyocr_gpu (push) Has started running
build_docker / build_doctr (push) Has been cancelled
This commit is contained in:
@@ -16,6 +16,10 @@ DOCS_DIR = os.path.join(BASE_DIR, 'docs')
|
||||
# Global counters for tables and figures
|
||||
table_counter = 0
|
||||
figure_counter = 0
|
||||
anexo_table_counter = 0
|
||||
anexo_figure_counter = 0
|
||||
# Global sequential counter for figure filenames (figura_1.png, figura_2.png, etc.)
|
||||
global_figure_index = 0
|
||||
|
||||
def read_file(path):
|
||||
try:
|
||||
@@ -99,7 +103,7 @@ def extract_figure_title_from_mermaid(lines, current_index):
|
||||
|
||||
def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
"""Convert markdown content to HTML blocks with template styles."""
|
||||
global table_counter, figure_counter
|
||||
global table_counter, figure_counter, anexo_table_counter, anexo_figure_counter, global_figure_index
|
||||
|
||||
html_blocks = []
|
||||
lines = md_content.split('\n')
|
||||
@@ -115,7 +119,17 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
|
||||
# Mermaid diagram - convert to figure with actual image
|
||||
if line.strip().startswith('```mermaid'):
|
||||
# Always increment global index for sequential filenames
|
||||
global_figure_index += 1
|
||||
|
||||
# Use Anexo-specific counter with "A" prefix for display, or global counter
|
||||
if is_anexo:
|
||||
anexo_figure_counter += 1
|
||||
fig_num = f"A{anexo_figure_counter}" # Display number: A1, A2, A3...
|
||||
else:
|
||||
figure_counter += 1
|
||||
fig_num = str(figure_counter) # Display number: 1, 2, 3...
|
||||
|
||||
mermaid_lines = []
|
||||
i += 1
|
||||
while i < len(lines) and not lines[i].strip() == '```':
|
||||
@@ -132,18 +146,22 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
if title_match:
|
||||
fig_title = title_match.group(1).strip()
|
||||
else:
|
||||
fig_title = f"Diagrama {figure_counter}"
|
||||
fig_title = f"Diagrama {fig_num}"
|
||||
|
||||
# Check if the generated PNG exists
|
||||
fig_file = f'figures/figura_{figure_counter}.png'
|
||||
# Use global sequential index for filename (figura_1.png, figura_2.png, etc.)
|
||||
fig_file = f'figures/figura_{global_figure_index}.png'
|
||||
fig_path = os.path.join(BASE_DIR, 'thesis_output', fig_file)
|
||||
|
||||
# Create figure with MsoCaption class and proper Word SEQ field for cross-reference
|
||||
# Format: "Figura X." in bold, title in italic (per UNIR guidelines)
|
||||
# Word TOC looks for text with Caption style - anchor must be outside main caption text
|
||||
bookmark_id = f"_Ref_Fig{figure_counter}"
|
||||
bookmark_id = f"_Ref_Fig{fig_num}"
|
||||
# mso-pagination:keep-with-next ensures caption stays with figure image (correct MSO property)
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="text-align:center;mso-pagination:keep-with-next"><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>''')
|
||||
# For Anexo figures, use static text (no SEQ field) to prevent Word from overwriting A1, A2...
|
||||
if is_anexo:
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="text-align:center;mso-pagination:keep-with-next"><b><span lang=ES style="font-size:12.0pt;line-height:150%">Figura {fig_num}.</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>''')
|
||||
else:
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="text-align:center;mso-pagination:keep-with-next"><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]-->{fig_num}<!--[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):
|
||||
# Read actual image dimensions and scale to fit page width
|
||||
@@ -216,7 +234,8 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
# Headers - ## becomes h2, ### becomes h3
|
||||
if line.startswith('####'):
|
||||
text = line.lstrip('#').strip()
|
||||
html_blocks.append(f'<h4><span lang=ES>{text}</span></h4>')
|
||||
# Apply consistent styling like h2/h3, disable numbering for h4
|
||||
html_blocks.append(f'<h4 style="mso-list:none"><span lang=ES style="text-transform:none">{text}</span></h4>')
|
||||
i += 1
|
||||
continue
|
||||
elif line.startswith('###'):
|
||||
@@ -246,7 +265,13 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
|
||||
# Table - check for table title pattern first
|
||||
if '|' in line and i + 1 < len(lines) and '---' in lines[i + 1]:
|
||||
# Use Anexo-specific counter with "A" prefix, or global counter
|
||||
if is_anexo:
|
||||
anexo_table_counter += 1
|
||||
table_num = f"A{anexo_table_counter}"
|
||||
else:
|
||||
table_counter += 1
|
||||
table_num = str(table_counter)
|
||||
|
||||
# Check if previous line has table title (e.g., **Tabla 1.** *Title*)
|
||||
table_title = None
|
||||
@@ -281,7 +306,7 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
# Add table title with MsoCaption class and proper Word SEQ field for cross-reference
|
||||
# Format: "Tabla X." in bold, title in italic (per UNIR guidelines)
|
||||
# Word TOC looks for text with Caption style - anchor must be outside main caption text
|
||||
bookmark_id = f"_Ref_Tab{table_counter}"
|
||||
bookmark_id = f"_Ref_Tab{table_num}"
|
||||
if table_title:
|
||||
# Remove any "Tabla X." or "Tabla AX." pattern from the title
|
||||
clean_title = re.sub(r'^Tabla\s+[A-Z]?\d+\.\s*', '', table_title).strip()
|
||||
@@ -291,7 +316,11 @@ def parse_md_to_html_blocks(md_content, is_anexo=False):
|
||||
else:
|
||||
clean_title = "Tabla de datos."
|
||||
# mso-pagination:keep-with-next ensures caption stays with table (correct MSO property)
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="mso-pagination:keep-with-next"><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>''')
|
||||
# For Anexo tables, use static text (no SEQ field) to prevent Word from overwriting A1, A2...
|
||||
if is_anexo:
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="mso-pagination:keep-with-next"><b><span lang=ES style="font-size:12.0pt;line-height:150%">Tabla {table_num}.</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>''')
|
||||
else:
|
||||
html_blocks.append(f'''<a name="{bookmark_id}"></a><p class=MsoCaption style="mso-pagination:keep-with-next"><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_num}<!--[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)
|
||||
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\'">'
|
||||
@@ -445,25 +474,25 @@ def extract_resumen_parts(resumen_content):
|
||||
spanish_keywords = ''
|
||||
if '**Palabras clave:**' in spanish_part:
|
||||
text_part, kw_part = spanish_part.split('**Palabras clave:**')
|
||||
spanish_text = text_part.replace('# Resumen', '').strip()
|
||||
spanish_keywords = kw_part.strip()
|
||||
spanish_text = md_to_html_para(text_part.replace('# Resumen', '').strip())
|
||||
spanish_keywords = md_to_html_para(kw_part.strip())
|
||||
else:
|
||||
spanish_text = spanish_part.replace('# Resumen', '').strip()
|
||||
spanish_text = md_to_html_para(spanish_part.replace('# Resumen', '').strip())
|
||||
|
||||
# Extract English content
|
||||
english_text = ''
|
||||
english_keywords = ''
|
||||
if '**Keywords:**' in english_part:
|
||||
text_part, kw_part = english_part.split('**Keywords:**')
|
||||
english_text = text_part.replace('# Abstract', '').strip()
|
||||
english_keywords = kw_part.strip()
|
||||
english_text = md_to_html_para(text_part.replace('# Abstract', '').strip())
|
||||
english_keywords = md_to_html_para(kw_part.strip())
|
||||
else:
|
||||
english_text = english_part.replace('# Abstract', '').strip()
|
||||
english_text = md_to_html_para(english_part.replace('# Abstract', '').strip())
|
||||
|
||||
return spanish_text, spanish_keywords, english_text, english_keywords
|
||||
|
||||
def main():
|
||||
global table_counter, figure_counter
|
||||
global table_counter, figure_counter, anexo_table_counter, anexo_figure_counter
|
||||
|
||||
print("Reading template...")
|
||||
html_content = read_file(TEMPLATE_INPUT)
|
||||
@@ -692,7 +721,7 @@ def main():
|
||||
insert_point.insert_after(new_elem)
|
||||
print(f" ✓ Replaced content")
|
||||
|
||||
print(f"\nSummary: {table_counter} tables, {figure_counter} figures processed")
|
||||
print(f"\nSummary: {table_counter} tables + {anexo_table_counter} Anexo tables, {figure_counter} figures + {anexo_figure_counter} Anexo figures processed")
|
||||
|
||||
print("Saving modified template...")
|
||||
output_html = str(soup)
|
||||
|
||||
@@ -579,9 +579,7 @@ Fuente: Elaboración propia.
|
||||
|
||||
La optimización de hiperparámetros para documentos académicos en español representa una contribución original de este trabajo, abordando un nicho no explorado en la literatura.
|
||||
|
||||
## Conclusiones del capítulo
|
||||
|
||||
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, como PaddleOCR, EasyOCR y 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.
|
||||
En síntesis, 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, como PaddleOCR, EasyOCR y 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.
|
||||
|
||||
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, como umbrales de detección, opciones de preprocesamiento y filtros de confianza, que pueden marcar la diferencia entre un sistema usable y uno que requiere corrección manual extensiva.
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ Para las tareas específicas de este proyecto, los costos estimados en cloud ser
|
||||
|
||||
| Tarea | Tiempo GPU | Costo AWS | Costo Colab Pro |
|
||||
|-------|------------|-----------|-----------------|
|
||||
| Ajuste hiperparámetros (64×3 trials) | ~3 horas | ~$1.58 | ~$3.90 |
|
||||
| Ajuste hiperparámetros (64x3 trials) | ~3 horas | ~$1.58 | ~$3.90 |
|
||||
| Evaluación completa (45 páginas) | ~5 min | ~$0.04 | ~$0.11 |
|
||||
| Desarrollo y depuración (20 horas/mes) | 20 horas | ~$10.52 | ~$26.00 |
|
||||
Fuente: Elaboración propia a partir de precios públicos. Ver Anexo A, sección de fuentes de precios cloud (enero 2026).
|
||||
|
||||
@@ -269,7 +269,7 @@ flowchart LR
|
||||
A -.->|"Health check /health"| B
|
||||
```
|
||||
|
||||
La arquitectura containerizada [`src/docker-compose.tuning.paddle.yml)`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.paddle.yml))))), [`src/docker-compose.tuning.doctr.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.doctr.yml), [`src/docker-compose.tuning.easyocr.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.easyocr.yml), [`src/docker-compose.tuning.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.yml)ofrece:
|
||||
La arquitectura containerizada [`src/docker-compose.tuning.paddle.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.paddle.yml), [`src/docker-compose.tuning.doctr.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.doctr.yml), [`src/docker-compose.tuning.easyocr.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.easyocr.yml), [`src/docker-compose.tuning.yml`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/docker-compose.tuning.yml) ofrece:
|
||||
1. Aislamiento de dependencias entre Ray Tune y los motores OCR
|
||||
2. Health checks automáticos para asegurar disponibilidad del servicio
|
||||
3. Comunicación via API REST (endpoints `/health` y `/evaluate`)
|
||||
@@ -582,7 +582,7 @@ El experimento se ejecutó exitosamente con los siguientes resultados globales:
|
||||
| Trials fallidos | 0 |
|
||||
| Tiempo total (CPU) | 6.2 horas |
|
||||
| Tiempo medio por trial (CPU) | 347.6 segundos |
|
||||
| Páginas procesadas | 320 (64 trials × 5 páginas) |
|
||||
| Páginas procesadas | 320 (64 trials x 5 páginas) |
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv).
|
||||
|
||||
#### Estadísticas Descriptivas
|
||||
@@ -822,7 +822,7 @@ Fuente: [`docs/metrics/metrics_paddle.md`](https://seryus.ddns.net/unir/MastersT
|
||||
| Valor optimizado | 7.72% | 11.40% |
|
||||
| Mejora absoluta | -1.13 pp | -1.65 pp |
|
||||
| Reducción relativa del error | **12.8%** | **12.6%** |
|
||||
| Factor de mejora | 1.15× | 1.14× |
|
||||
| Factor de mejora | 1.15x | 1.14x |
|
||||
| **Mejor trial (5 páginas)** | **0.79%** | **7.78%** |
|
||||
Fuente: [`docs/metrics/metrics_paddle.md`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/docs/metrics/metrics_paddle.md).
|
||||
|
||||
@@ -872,7 +872,7 @@ Observaciones:
|
||||
|
||||
1. El tiempo por página (~0.84 segundos) corresponde a ejecución con GPU (RTX 3060).
|
||||
2. La variabilidad del tiempo es moderada (std = 0.53 s/página), con algunos trials más lentos debido a configuraciones con módulos de preprocesamiento activos.
|
||||
3. En comparación, la ejecución en CPU requiere ~69 segundos/página (82× más lento), lo que justifica el uso de GPU para optimización y producción.
|
||||
3. En comparación, la ejecución en CPU requiere ~69 segundos/página (82x más lento), lo que justifica el uso de GPU para optimización y producción.
|
||||
|
||||
### Síntesis de la Optimización
|
||||
|
||||
@@ -1114,7 +1114,7 @@ Fuente: [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryu
|
||||
|
||||
La optimización de hiperparámetros es recomendable cuando:
|
||||
|
||||
1. **GPU disponible**: Acelera significativamente la exploración del espacio de hiperparámetros (82× más rápido que CPU).
|
||||
1. **GPU disponible**: Acelera significativamente la exploración del espacio de hiperparámetros (82x más rápido que CPU).
|
||||
|
||||
2. **Modelo preentrenado adecuado**: El modelo ya soporta el idioma objetivo (como PaddleOCR para español).
|
||||
|
||||
@@ -1142,7 +1142,7 @@ A lo largo de este capítulo se ha desarrollado el proceso completo de evaluaci
|
||||
|
||||
Los resultados cuantifican tanto los logros como las limitaciones del enfoque. El mejor trial individual alcanzó un CER de 0.79%, cumpliendo holgadamente el objetivo de CER < 2%. Sin embargo, la validación sobre el dataset completo de 45 páginas reveló un CER de 7.72%, lo que representa una mejora del 12.8% respecto al baseline (8.85%) pero evidencia sobreajuste al subconjunto de optimización. Esta observación es valiosa: indica que futuros trabajos deberían emplear subconjuntos de optimización más representativos o aplicar técnicas de regularización.
|
||||
|
||||
Desde el punto de vista práctico, la infraestructura dockerizada desarrollada y la aceleración GPU (82× más rápida que CPU) demuestran la viabilidad de esta metodología tanto para experimentación como para despliegue en producción.
|
||||
Desde el punto de vista práctico, la infraestructura dockerizada desarrollada y la aceleración GPU (82x más rápida que CPU) demuestran la viabilidad de esta metodología tanto para experimentación como para despliegue en producción.
|
||||
|
||||
Fuente:
|
||||
- [`src/run_tuning.py`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/run_tuning.py) - Script principal de optimización
|
||||
@@ -1192,7 +1192,7 @@ Se comparó el tiempo de procesamiento entre CPU y GPU utilizando los datos de [
|
||||
|---------|-----|----------------|----------------------|
|
||||
| Tiempo/Página (promedio) | 69.4s | 0.84s | **82x** |
|
||||
| Dataset completo (45 páginas) | ~52 min | ~38 seg | **82x** |
|
||||
| 64 trials × 5 páginas | 6.2 horas | ~5.0 min | **75x** |
|
||||
| 64 trials x 5 páginas | 6.2 horas | ~5.0 min | **75x** |
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv), [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/raytune_paddle_results_20260119_122609.csv).
|
||||
|
||||
**Figura 20.** *Tiempo de procesamiento: CPU vs GPU (segundos/página).*
|
||||
@@ -1218,9 +1218,9 @@ xychart-beta
|
||||
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv), [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/raytune_paddle_results_20260119_122609.csv).
|
||||
|
||||
Leyenda: Aceleración de **82×** con GPU. El procesamiento de una página pasa de 69.4s (CPU) a 0.84s (GPU).
|
||||
Leyenda: Aceleración de **82x** con GPU. El procesamiento de una página pasa de 69.4s (CPU) a 0.84s (GPU).
|
||||
|
||||
La aceleración de 82× obtenida con GPU transforma la viabilidad del enfoque:
|
||||
La aceleración de 82x obtenida con GPU transforma la viabilidad del enfoque:
|
||||
- **Optimización en CPU (6.2 horas)**: Viable pero lento para iteraciones rápidas
|
||||
- **Optimización en GPU (~5.0 minutos)**: Permite explorar más configuraciones y realizar múltiples experimentos
|
||||
- **Producción con GPU (0.84s/página)**: Habilita procesamiento en tiempo real
|
||||
@@ -1239,16 +1239,4 @@ Fuente: [`docs/metrics/metrics.md`](https://seryus.ddns.net/unir/MastersThesis/s
|
||||
|
||||
Los modelos Server, a pesar de ofrecer potencialmente mayor precisión, resultan inviables en hardware con VRAM limitada (≤6 GB) debido a errores de memoria (Out of Memory). Los modelos Mobile, con un consumo de memoria 88 veces menor, funcionan de manera estable y ofrecen rendimiento suficiente para el caso de uso evaluado.
|
||||
|
||||
#### Conclusiones de la Validación GPU
|
||||
|
||||
La validación con aceleración GPU permite extraer las siguientes conclusiones:
|
||||
|
||||
1. **Aceleración significativa**: La GPU proporciona una aceleración de 82× sobre CPU, haciendo viable el procesamiento en tiempo real para aplicaciones interactivas.
|
||||
|
||||
2. **Modelos Mobile recomendados**: Para hardware con VRAM limitada (≤6 GB), los modelos Mobile de PP-OCRv5 ofrecen el mejor balance entre precisión y recursos, funcionando de manera estable sin errores de memoria.
|
||||
|
||||
3. **Viabilidad práctica**: Con GPU, el procesamiento de un documento completo (45 páginas) toma ~38 segundos, validando la aplicabilidad en entornos de producción donde el tiempo de respuesta es crítico.
|
||||
|
||||
4. **Escalabilidad**: La arquitectura de microservicios dockerizados utilizada para la validación GPU facilita el despliegue horizontal, permitiendo escalar el procesamiento según demanda.
|
||||
|
||||
Esta validación demuestra que la configuración optimizada mediante Ray Tune mejora la precisión (CER: 8.85% → 7.72% en dataset completo, 0.79% en mejor trial individual) y, combinada con aceleración GPU, resulta prácticamente aplicable en escenarios de producción real.
|
||||
La validación con aceleración GPU demuestra que la configuración optimizada mediante Ray Tune mejora la precisión (CER: 8.85% → 7.72% en dataset completo, 0.79% en mejor trial individual) y, combinada con la aceleración de 82x proporcionada por GPU, resulta prácticamente aplicable en escenarios de producción real. Las conclusiones derivadas de esta validación se presentan en el Capítulo 5.
|
||||
|
||||
@@ -47,6 +47,10 @@ Otro hallazgo relevante es la innecesariedad de ciertos módulos para documentos
|
||||
|
||||
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.
|
||||
|
||||
Respecto a la validación con aceleración GPU, la GPU proporciona una aceleración de 82x sobre CPU, haciendo viable el procesamiento en tiempo real para aplicaciones interactivas. Con GPU, el procesamiento de un documento completo (45 páginas) toma aproximadamente 38 segundos, validando la aplicabilidad en entornos de producción donde el tiempo de respuesta es crítico. Para hardware con VRAM limitada (≤6 GB), los modelos Mobile de PP-OCRv5 ofrecen el mejor balance entre precisión y recursos, funcionando de manera estable sin errores de memoria, mientras que los modelos Server resultan inviables debido a errores Out of Memory. Además, la arquitectura de microservicios dockerizados utilizada facilita el despliegue horizontal, permitiendo escalar el procesamiento según demanda.
|
||||
|
||||
Fuente: [`docs/metrics/metrics.md`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/docs/metrics/metrics.md).
|
||||
|
||||
### Contribuciones del Trabajo
|
||||
|
||||
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.
|
||||
@@ -65,7 +69,7 @@ El tamaño del corpus constituye otra limitación relevante. Con 45 páginas, el
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
Por último, aunque la GPU RTX 3060 utilizada proporcionó una aceleración de 82x 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.
|
||||
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv), [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/raytune_paddle_results_20260119_122609.csv).
|
||||
|
||||
@@ -101,6 +105,6 @@ En síntesis, este trabajo ha demostrado que la optimización de hiperparámetro
|
||||
|
||||
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.
|
||||
|
||||
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 horas en uno de minutos, haciendo viable la exploración exhaustiva de espacios de hiperparámetros con hardware de consumo.
|
||||
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 82x proporcionada por GPU transforma lo que sería un experimento de horas en uno de minutos, 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.
|
||||
|
||||
@@ -46,27 +46,11 @@ flowchart TB
|
||||
end
|
||||
```
|
||||
|
||||
**Tabla A1.** *Descripción de directorios principales.*
|
||||
|
||||
| Directorio | Contenido |
|
||||
|------------|-----------|
|
||||
| [`docs/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/docs/)| Capítulos del TFM en Markdown (estructura UNIR) |
|
||||
| [`docs/metrics/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/docs/metrics/)| Métricas de rendimiento por servicio OCR |
|
||||
| [`src/paddle_ocr/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/paddle_ocr/)| Servicio PaddleOCR dockerizado |
|
||||
| [`src/doctr_service/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/doctr_service/)| Servicio DocTR dockerizado |
|
||||
| [`src/easyocr_service/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/easyocr_service/)| Servicio EasyOCR dockerizado |
|
||||
| [`src/raytune/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune/)| Scripts de optimización Ray Tune |
|
||||
| [`src/results/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/)| CSVs con resultados de 64 trials por servicio |
|
||||
| [`src/results/correlations/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/correlations/)| Correlaciones de hiperparámetros por servicio |
|
||||
| [`thesis_output/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/thesis_output/)| Documento TFM generado + figuras PNG |
|
||||
| [`instructions/`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/instructions/)| Plantilla e instrucciones UNIR oficiales |
|
||||
Fuente: [Repositorio del proyecto](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/).
|
||||
|
||||
## A.3 Requisitos de Software
|
||||
|
||||
### Sistema de Desarrollo
|
||||
|
||||
**Tabla A2.** *Especificaciones del sistema de desarrollo.*
|
||||
**Tabla A1.** *Especificaciones del sistema de desarrollo.*
|
||||
|
||||
| Componente | Especificación |
|
||||
|------------|----------------|
|
||||
@@ -79,9 +63,7 @@ Fuente: [`docs/metrics/metrics.md`](https://seryus.ddns.net/unir/MastersThesis/s
|
||||
|
||||
### Dependencias
|
||||
|
||||
### Dependencias
|
||||
|
||||
**Tabla A3.** *Dependencias del proyecto.*
|
||||
**Tabla A2.** *Dependencias del proyecto.*
|
||||
|
||||
| Componente | Versión |
|
||||
|------------|---------|
|
||||
@@ -97,8 +79,6 @@ Fuente: [`src/paddle_ocr/requirements.txt`](https://seryus.ddns.net/unir/Masters
|
||||
|
||||
## A.4 Instrucciones de Ejecución de Servicios OCR
|
||||
|
||||
## A.4 Instrucciones de Ejecución de Servicios OCR
|
||||
|
||||
### PaddleOCR (Puerto 8002)
|
||||
|
||||
**Imágenes Docker:**
|
||||
@@ -117,7 +97,7 @@ docker compose -f docker-compose.cpu-registry.yml up -d
|
||||
|
||||
### DocTR (Puerto 8003)
|
||||
|
||||
**Imagen Docker:** `seryus.ddns.net/unir/doctr-gpu`(https://seryus.ddns.net/unir/-/packages/container/doctr-gpu/latest)
|
||||
**Imagen Docker:** [`seryus.ddns.net/unir/doctr-gpu`](https://seryus.ddns.net/unir/-/packages/container/doctr-gpu/latest)
|
||||
|
||||
```bash
|
||||
cd src/doctr_service
|
||||
@@ -130,7 +110,7 @@ docker compose up -d
|
||||
|
||||
> **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)
|
||||
**Imagen Docker:** [`seryus.ddns.net/unir/easyocr-gpu`](https://seryus.ddns.net/unir/-/packages/container/easyocr-gpu/latest)
|
||||
|
||||
```bash
|
||||
cd src/easyocr_service
|
||||
@@ -206,7 +186,7 @@ analyze_results(results, prefix='raytune_paddle', config_keys=PADDLE_OCR_CONFIG_
|
||||
|
||||
### Servicios y Puertos
|
||||
|
||||
**Tabla A4.** *Servicios Docker y puertos.*
|
||||
**Tabla A3.** *Servicios Docker y puertos.*
|
||||
|
||||
| Servicio | Puerto | Script de Ajuste | Nota |
|
||||
|----------|--------|------------------|------|
|
||||
@@ -223,7 +203,7 @@ Esta sección presenta los resultados completos de las evaluaciones comparativas
|
||||
|
||||
### Comparativa General de Servicios
|
||||
|
||||
**Tabla A5.** *Comparativa de servicios OCR en dataset de 45 páginas (GPU RTX 3060).*
|
||||
**Tabla A4.** *Comparativa de servicios OCR en dataset de 45 páginas (GPU RTX 3060).*
|
||||
|
||||
| Servicio | CER | WER | Tiempo/Página | Tiempo Total | VRAM |
|
||||
|----------|-----|-----|---------------|--------------|------|
|
||||
@@ -238,7 +218,7 @@ Fuente: [`docs/metrics/metrics_paddle.md`](https://seryus.ddns.net/unir/MastersT
|
||||
|
||||
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.*
|
||||
**Tabla A5.** *Resultados del ajuste de hiperparámetros por servicio.*
|
||||
|
||||
| Servicio | CER Base | CER Ajustado | Mejora | Mejor Trial (5 páginas) |
|
||||
|----------|----------|--------------|--------|-------------------------|
|
||||
@@ -251,7 +231,7 @@ Fuente: [`docs/metrics/metrics_paddle.md`](https://seryus.ddns.net/unir/MastersT
|
||||
|
||||
### Distribución de trials por rango de CER (PaddleOCR)
|
||||
|
||||
**Tabla A7.** *Distribución de trials por rango de CER.*
|
||||
**Tabla A6.** *Distribución de trials por rango de CER.*
|
||||
|
||||
| Rango CER | Número de trials | Porcentaje |
|
||||
|-----------|------------------|------------|
|
||||
@@ -307,7 +287,7 @@ La siguiente configuración logró el mejor rendimiento en el ajuste de hiperpar
|
||||
|
||||
### Rendimiento CPU vs GPU
|
||||
|
||||
**Tabla A8.** *Comparación de rendimiento CPU vs GPU (PaddleOCR).*
|
||||
**Tabla A7.** *Comparación de rendimiento CPU vs GPU (PaddleOCR).*
|
||||
|
||||
| Métrica | CPU | GPU (RTX 3060) | Aceleración |
|
||||
|---------|-----|----------------|-------------|
|
||||
@@ -336,11 +316,11 @@ xychart-beta
|
||||
bar [69.4, 0.84]
|
||||
```
|
||||
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv) y [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/raytune_paddle_results_20260119_122609.csv). Leyenda: Aceleración de **82×** con GPU. El procesamiento de una página pasa de 69.4s (CPU) a 0.84s (GPU).
|
||||
Fuente: [`src/raytune_paddle_subproc_results_20251207_192320.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/raytune_paddle_subproc_results_20251207_192320.csv) y [`src/results/raytune_paddle_results_20260119_122609.csv`](https://seryus.ddns.net/unir/MastersThesis/src/branch/main/src/results/raytune_paddle_results_20260119_122609.csv). Leyenda: Aceleración de **82x** con GPU. El procesamiento de una página pasa de 69.4s (CPU) a 0.84s (GPU).
|
||||
|
||||
### Análisis de Errores por Servicio
|
||||
|
||||
**Tabla A9.** *Tipos de errores identificados por servicio OCR.*
|
||||
**Tabla A8.** *Tipos de errores identificados por servicio OCR.*
|
||||
|
||||
| Servicio | Fortalezas | Debilidades | ¿Fine-tuning recomendado? |
|
||||
|----------|------------|-------------|---------------------------|
|
||||
@@ -353,7 +333,7 @@ Fuente: Análisis manual del debugset. Elaboración propia.
|
||||
|
||||
Los resultados crudos de los 64 trials por servicio están disponibles en el repositorio:
|
||||
|
||||
**Tabla A10.** *Ubicación de archivos de resultados.*
|
||||
**Tabla A9.** *Ubicación de archivos de resultados.*
|
||||
|
||||
| Servicio | Archivo CSV |
|
||||
|----------|-------------|
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
| Tarea | Tiempo GPU | Costo AWS | Costo Colab Pro |
|
||||
|-------|------------|-----------|-----------------|
|
||||
| Ajuste hiperparámetros (64×3 trials) | ~3 horas | ~$1.58 | ~$3.90 |
|
||||
| Ajuste hiperparámetros (64x3 trials) | ~3 horas | ~$1.58 | ~$3.90 |
|
||||
| Evaluación completa (45 páginas) | ~5 min | ~$0.04 | ~$0.11 |
|
||||
| Desarrollo/debug (20 horas/mes) | 20 horas | ~$10.52 | ~$26.00 |
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Usamos solo 5 páginas (páginas 5-10) para el ajuste de hiperparámetros porque:
|
||||
|
||||
1. **Velocidad**: 64 pruebas × 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
1. **Velocidad**: 64 pruebas x 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
2. **Eficiencia de recursos**: Cada prueba toma ~2-20 segundos en GPU
|
||||
|
||||
**Riesgo de Sobreajuste**: El ajuste de hiperparámetros en un subconjunto pequeño PUEDE causar sobreajuste. Nuestros resultados confirman esto:
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Usamos solo 5 páginas (páginas 5-10) para el ajuste de hiperparámetros porque:
|
||||
|
||||
1. **Velocidad**: 64 pruebas × 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
1. **Velocidad**: 64 pruebas x 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
2. **Eficiencia de recursos**: Cada prueba toma ~10-20 segundos en GPU
|
||||
|
||||
**Riesgo de Sobreajuste**: El ajuste de hiperparámetros en un subconjunto pequeño PUEDE causar sobreajuste. Nuestros resultados confirman esto:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
Usamos solo 5 páginas (páginas 5-10) para el ajuste de hiperparámetros porque:
|
||||
|
||||
1. **Velocidad**: 64 pruebas × 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
1. **Velocidad**: 64 pruebas x 5 páginas = 320 evaluaciones de página. Con 45 páginas, serían 2,880 evaluaciones (~9x más tiempo)
|
||||
2. **Eficiencia de recursos**: Cada prueba toma ~3-10 segundos en GPU; el dataset completo tomaría ~1 hora por prueba en CPU
|
||||
|
||||
**Riesgo de Sobreajuste**: El ajuste de hiperparámetros en un subconjunto pequeño PUEDE causar sobreajuste. Nuestros resultados confirman esto:
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user