From d67cbd4677ed057c4cbe31f8706dd5b6e4582073 Mon Sep 17 00:00:00 2001 From: Sergio Jimenez Jimenez Date: Mon, 19 Jan 2026 14:00:28 +0100 Subject: [PATCH] readme and hf dataset formater. --- .gitignore | 2 + README.md | 77 ++++++---- .../convert_to_hf_dataset.py | 138 ++++++++++++++++++ src/dataset_formatting/upload-dataset.sh | 63 ++++++++ 4 files changed, 252 insertions(+), 28 deletions(-) create mode 100755 src/dataset_formatting/convert_to_hf_dataset.py create mode 100755 src/dataset_formatting/upload-dataset.sh diff --git a/.gitignore b/.gitignore index 1eb7d2f..c2762ec 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ src/paddle_ocr/wheels src/*.log src/output_*.ipynb debugset/ + +src/dataset_hf/ diff --git a/README.md b/README.md index 3f43396..62bf3e4 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ python src/paddle_ocr_tuning.py \ ## Fuentes de Datos -- **Dataset**: Instrucciones para la elaboración del TFE (UNIR), 24 páginas +- **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 --- @@ -290,39 +290,60 @@ Este trabajo adoptó la estrategia de **optimización de hiperparámetros** en l 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. -### Tareas Completadas - -- [x] **Estructura docs/ según plantilla UNIR**: Todos los capítulos siguen numeración exacta (1.1, 1.2, etc.) -- [x] **Añadir diagramas Mermaid**: 7 diagramas añadidos (pipeline OCR, arquitectura Ray Tune, gráficos de comparación) -- [x] **Generar documento TFM unificado**: Script `apply_content.py` genera documento completo desde docs/ -- [x] **Convertir Mermaid a PNG**: Script `generate_mermaid_figures.py` genera figuras automáticamente - ### Tareas Pendientes -#### 1. Validación del Enfoque (Prioridad Alta) -- [ ] **Validación cruzada en otros documentos**: Evaluar la configuración óptima en otros tipos de documentos en español (facturas, formularios, contratos) para verificar generalización -- [ ] **Ampliar el dataset**: El dataset actual tiene solo 24 páginas. Construir un corpus más amplio y diverso (mínimo 100 páginas) -- [ ] **Validación del ground truth**: Revisar manualmente el texto de referencia extraído automáticamente para asegurar su exactitud - -#### 2. Experimentación Adicional (Prioridad Media) -- [ ] **Explorar `text_det_unclip_ratio`**: Este parámetro quedó fijado en 0.0. Incluirlo en el espacio de búsqueda podría mejorar resultados -- [ ] **Comparativa con fine-tuning** (si se obtiene acceso a GPU): Cuantificar la brecha de rendimiento entre optimización de hiperparámetros y fine-tuning real -- [x] **Evaluación con GPU**: Validado con RTX 3060 - 126x más rápido que CPU (0.55s/página vs 69.4s/página) - -#### 3. Documentación y Presentación (Prioridad Alta) +#### Obligatorias para Entrega +- [ ] **Revisión final del documento**: Abrir en Word, actualizar índices (Ctrl+A → F9), ajustar figuras, guardar como .docx - [ ] **Crear presentación**: Preparar slides para la defensa del TFM -- [ ] **Revisión final del documento**: Verificar formato, índices y contenido en Word -#### 4. Extensiones Futuras (Opcional) -- [ ] **Herramienta de configuración automática**: Desarrollar una herramienta que determine automáticamente la configuración óptima para un nuevo tipo de documento -- [ ] **Benchmark público para español**: Publicar un benchmark de OCR para documentos en español que facilite comparación de soluciones -- [ ] **Optimización multi-objetivo**: Considerar CER, WER y tiempo de inferencia simultáneamente +#### Opcionales (Mejoras Futuras) +- [ ] **Validación cruzada**: Evaluar configuración en otros documentos (facturas, formularios) +- [ ] **Explorar `text_det_unclip_ratio`**: Parámetro fijado en 0.0, podría mejorar resultados +- [ ] **Comparativa con fine-tuning**: Cuantificar brecha vs fine-tuning real +- [ ] **Herramienta de configuración automática**: Auto-detectar configuración óptima por documento +- [ ] **Benchmark público para español**: Facilitar comparación de soluciones OCR -### Recomendación de Próximos Pasos +#### Completadas +- [x] **Estructura docs/ según plantilla UNIR** +- [x] **Diagramas Mermaid**: 8 figuras generadas +- [x] **Documento TFM unificado**: Script `apply_content.py` +- [x] **Evaluación con GPU**: RTX 3060 - 126x más rápido (0.55s/página) -1. **Inmediato**: Abrir documento generado en Word, actualizar índices (Ctrl+A, F9), guardar como .docx -2. **Corto plazo**: Validar en 2-3 tipos de documentos adicionales para demostrar generalización -3. **Para la defensa**: Crear presentación con visualizaciones de resultados +### Dataset + +El dataset contiene **45 páginas** de 2 documentos UNIR: +- `src/dataset/0/`: Instrucciones TFE (24 páginas) +- `src/dataset/1/`: Plantilla TFE (21 páginas) + +#### Formato Hugging Face + +El dataset está disponible en formato Hugging Face en `src/dataset_hf/`: + +``` +src/dataset_hf/ +├── README.md # Dataset card +├── metadata.jsonl # Metadata (image_path, text, doc_id, page_num) +└── data/ # 45 imágenes PNG +``` + +#### Generar/Regenerar Dataset + +```bash +# Convertir de formato original a HF +source .venv/bin/activate +python src/dataset_formatting/convert_to_hf_dataset.py + +# Upload a Gitea packages (requiere GITEA_TOKEN) +./src/dataset_formatting/upload-dataset.sh $GITEA_TOKEN +``` + +#### Descargar Dataset + +```bash +# Desde Gitea packages +curl -O https://seryus.ddns.net/api/packages/unir/generic/ocr-dataset-spanish/1.0.0/dataset-1.0.0.tar.gz +tar -xzf dataset-1.0.0.tar.gz -C src/dataset_hf/ +``` --- diff --git a/src/dataset_formatting/convert_to_hf_dataset.py b/src/dataset_formatting/convert_to_hf_dataset.py new file mode 100755 index 0000000..019d384 --- /dev/null +++ b/src/dataset_formatting/convert_to_hf_dataset.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +"""Convert custom OCR dataset to Hugging Face format.""" + +import json +import shutil +from pathlib import Path + + +def convert_dataset(source_dir: str, output_dir: str): + """Convert folder-based dataset to HF ImageFolder format.""" + + source = Path(source_dir) + output = Path(output_dir) + data_dir = output / "data" + data_dir.mkdir(parents=True, exist_ok=True) + + metadata = [] + + for doc_folder in sorted(source.iterdir()): + if not doc_folder.is_dir(): + continue + + doc_id = doc_folder.name + img_dir = doc_folder / "img" + txt_dir = doc_folder / "txt" + + if not img_dir.exists() or not txt_dir.exists(): + continue + + for img_file in sorted(img_dir.glob("*.png")): + txt_file = txt_dir / f"{img_file.stem}.txt" + if not txt_file.exists(): + continue + + # Extract page number + page_num = int(img_file.stem.split("_")[-1]) + + # New filename: page_{doc_id}_{page_num:04d}.png + new_name = f"page_{doc_id}_{page_num:04d}.png" + + # Copy image + shutil.copy(img_file, data_dir / new_name) + + # Read text + text = txt_file.read_text(encoding="utf-8").strip() + + # Add metadata entry + metadata.append({ + "file_name": f"data/{new_name}", + "text": text, + "document_id": doc_id, + "page_number": page_num + }) + + # Write metadata.jsonl + with open(output / "metadata.jsonl", "w", encoding="utf-8") as f: + for entry in metadata: + f.write(json.dumps(entry, ensure_ascii=False) + "\n") + + # Write dataset card + write_dataset_card(output, len(metadata)) + + print(f"Converted {len(metadata)} samples to {output}") + + +def write_dataset_card(output_dir: Path, num_samples: int): + """Write HF dataset card.""" + card = f'''--- +dataset_info: + features: + - name: image + dtype: image + - name: text + dtype: string + - name: document_id + dtype: string + - name: page_number + dtype: int32 + splits: + - name: train + num_examples: {num_samples} +license: cc-by-4.0 +language: + - es +task_categories: + - image-to-text +tags: + - ocr + - spanish + - academic-documents + - unir +--- + +# UNIR OCR Dataset + +Dataset de documentos académicos en español para evaluación de sistemas OCR. + +## Descripción + +- **Idioma**: Español +- **Dominio**: Documentos académicos (instrucciones TFE de UNIR) +- **Formato**: Imágenes PNG (300 DPI) + texto ground truth +- **Total**: {num_samples} pares imagen-texto + +## Uso + +```python +from datasets import load_dataset + +dataset = load_dataset("path/to/dataset") + +for sample in dataset["train"]: + image = sample["image"] + text = sample["text"] +``` + +## Estructura + +Cada muestra contiene: +- `image`: Imagen de la página (PIL.Image) +- `text`: Texto ground truth extraído del PDF +- `document_id`: ID del documento fuente +- `page_number`: Número de página + +## Citación + +Parte del TFM "Optimización de Hiperparámetros OCR con Ray Tune" - UNIR 2025 +''' + (output_dir / "README.md").write_text(card, encoding="utf-8") + + +if __name__ == "__main__": + import sys + + source = sys.argv[1] if len(sys.argv) > 1 else "src/dataset" + output = sys.argv[2] if len(sys.argv) > 2 else "src/dataset_hf" + + convert_dataset(source, output) diff --git a/src/dataset_formatting/upload-dataset.sh b/src/dataset_formatting/upload-dataset.sh new file mode 100755 index 0000000..9522c0b --- /dev/null +++ b/src/dataset_formatting/upload-dataset.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Upload OCR dataset to Gitea generic packages +# +# Usage: +# ./src/dataset_formatting/upload-dataset.sh [token] +# +# Environment variables: +# GITEA_TOKEN - Gitea API token + +set -e + +GITEA_URL="https://seryus.ddns.net" +GITEA_ORG="unir" +PACKAGE_NAME="ocr-dataset-spanish" +VERSION="1.0.0" +DATASET_DIR="src/dataset_hf" +TARBALL="dataset-${VERSION}.tar.gz" + +# Get token +TOKEN="${1:-${GITEA_TOKEN}}" +if [ -z "$TOKEN" ]; then + echo "Error: No token provided" + echo "Usage: $0 [token]" + echo " or set GITEA_TOKEN environment variable" + exit 1 +fi + +# Check dataset exists +if [ ! -d "$DATASET_DIR" ]; then + echo "Error: Dataset not found at $DATASET_DIR" + echo "Run: python src/convert_to_hf_dataset.py first" + exit 1 +fi + +# Create tarball +echo "Creating tarball..." +tar -czvf "$TARBALL" -C "$DATASET_DIR" . +echo "Created: $TARBALL ($(du -h $TARBALL | cut -f1))" + +# Upload +echo "Uploading to Gitea packages..." +echo " URL: $GITEA_URL/api/packages/$GITEA_ORG/generic/$PACKAGE_NAME/$VERSION/$TARBALL" + +HTTP_CODE=$(curl -sS -w "%{http_code}" -o /tmp/upload_response.txt \ + -X PUT \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$TARBALL" \ + "$GITEA_URL/api/packages/$GITEA_ORG/generic/$PACKAGE_NAME/$VERSION/$TARBALL") + +if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then + echo "Success! Dataset uploaded." + echo "Download URL: $GITEA_URL/api/packages/$GITEA_ORG/generic/$PACKAGE_NAME/$VERSION/$TARBALL" + rm "$TARBALL" +elif [ "$HTTP_CODE" = "409" ]; then + echo "Package version already exists (HTTP 409)" + rm "$TARBALL" +else + echo "Error: Upload failed with HTTP $HTTP_CODE" + cat /tmp/upload_response.txt + rm "$TARBALL" + exit 1 +fi