Files
extractor_abreviaciones/README.md

193 lines
6.6 KiB
Markdown
Raw Permalink Normal View History

---
language: es
license: apache-2.0
tags:
- medical
- clinical-nlp
- abbreviation-detection
- spanish
- cardiology
- llama
metrics:
- precision
- recall
- f1
---
# LLaMA 3.2-1B Medical Abbreviation Detector (Spanish)
## Descripción del Modelo
Este modelo es una versión especializada de **LLaMA 3.2-1B Instruct** ajustada mediante fine-tuning para la **detección automática de abreviaciones médicas en textos clínicos en español**. Forma parte del sistema SimpliMed desarrollado para la simplificación de informes de alta hospitalaria en el ámbito de la cardiología.
El modelo ha sido entrenado específicamente para identificar:
- **Abreviaturas**: formas truncadas (ej: "a.c." = antes de comida)
- **Siglas**: iniciales de palabras (ej: "EPOC" = enfermedad pulmonar obstructiva crónica)
- **Acrnimos**: siglas lexicalizadas (ej: "DIU" = dispositivo intrauterino)
- **Símbolos médicos**: notación clínica (ej: "mmHg", "mg", "cm")
### Formato de Salida
```json
{
"formas_abreviadas": ["HTA", "IAM", "FEVI", "EPOC"],
"simbolos_medicos": ["mmHg", "mg/dl", "cm", "ml"]
}
```
## Rendimiento
El modelo supera significativamente a los métodos basados en expresiones regulares:
| Sistema | Precisión | Recall | F1 Score |
|---------|-----------|--------|----------|
| **SLM (este modelo)** | **0.8902** | **0.9283** | **0.9024** |
| Expresiones regulares | 0.6271 | 0.7675 | 0.6704 |
## Entrenamiento
### Corpus de Entrenamiento
- **Fuente**: Informes de alta hospitalaria del Hospital Universitario de Jaén (especialidad de cardiología)
- **Anotación**: Automática con GPT-4o
- **Diccionario de referencia**: 7,054 abreviaciones médicas del diccionario SEDOM (Sociedad Española de Documentación Médica)
- **Tamaño del corpus**: 70% del total de informes disponibles
### Hiperparámetros
```python
{
"per_device_train_batch_size": 2,
"per_device_eval_batch_size": 1,
"num_train_epochs": 3,
"eval_steps": 10,
"save_steps": 500,
"gradient_accumulation_steps": 4,
"learning_rate": 1e-4,
"seed": 42,
"max_seq_length": 2048
}
```
### Frameworks
- PyTorch
- Hugging Face Transformers
- vLLM (para inferencia eficiente)
## Uso
```python
import json
import re
from openai import OpenAI
class ExtractorAbreviaciones:
def __init__(self, ruta_modelo, ruta_prompt, base_url="http://localhost:8000/v1"):
self.model_path = ruta_modelo
self.prompt = self._cargar_prompt(ruta_prompt)
self.client = OpenAI(base_url=base_url, api_key="token-abc123")
def _cargar_prompt(self, ruta_prompt):
with open(ruta_prompt, "r", encoding="utf-8") as file:
return file.read()
def _extraer_listas(self, texto):
"""Fallback para extraer listas si el JSON no parsea correctamente"""
patrones = {
"formas_abreviadas": re.compile(r'"formas_abreviadas": \[([^\]]+)\]'),
"simbolos_medicos": re.compile(r'"simbolos_medicos": \[([^\]]+)\]')
}
datos = {"formas_abreviadas": [], "simbolos_medicos": []}
for clave, patron in patrones.items():
coincidencia = patron.search(texto)
if coincidencia:
elementos = [x.strip().strip('"') for x in coincidencia.group(1).split(',')]
datos[clave] = elementos
return datos
def extraer_abreviaciones(self, texto):
"""Extrae todas las abreviaciones (combinando ambas categorías)"""
datos = self.extraer_abreviaciones_simbolos(texto)
return list(set(datos["formas_abreviadas"]) | set(datos["simbolos_medicos"]))
def extraer_abreviaciones_simbolos(self, text, temperature=0.0, max_new_tokens=128):
"""
Extrae abreviaciones y símbolos médicos de un texto.
Args:
text (str): El texto clínico a analizar
temperature (float): Temperatura para la generación (0.0 = determinista)
max_new_tokens (int): Número máximo de tokens a generar
Returns:
dict: {"formas_abreviadas": [...], "simbolos_medicos": [...]}
"""
try:
messages = [
{"role": "system", "content": self.prompt},
{"role": "user", "content": text}
]
response = self.client.chat.completions.create(
model=self.model_path,
messages=messages,
max_tokens=max_new_tokens,
temperature=temperature
)
resp = response.choices.message.content
# Intentar parsear como JSON
try:
return json.loads(resp)
except json.JSONDecodeError:
# Buscar inicio del JSON
inicio_json = resp.find("{")
if inicio_json != -1:
json_str = resp[inicio_json:]
try:
return json.loads(json_str)
except json.JSONDecodeError:
return self._extraer_listas(resp)
else:
return self._extraer_listas(resp)
except Exception as e:
print(f"Error en la solicitud: {str(e)}")
return {"formas_abreviadas": [], "simbolos_medicos": []}
# Ejemplo de uso
extractor = ExtractorAbreviaciones(
ruta_modelo="lmolino/extractor_abreviaciones",
ruta_prompt="prompt_abreviaciones.txt"
)
texto = "Paciente con HTA e IAM previo. TA: 140/90 mmHg."
resultado = extractor.extraer_abreviaciones_simbolos(texto)
print(resultado)
# {"formas_abreviadas": ["HTA", "IAM", "TA"], "simbolos_medicos": ["mmHg"]}
```
## Limitaciones y Consideraciones
1. **Dominio específico**: El modelo ha sido entrenado principalmente con informes de cardiología, por lo que su rendimiento puede variar en otras especialidades médicas, aunque su diseño es generalista.
2. **Sensibilidad al formato**: El modelo puede tener dificultades con textos completamente en mayúsculas, donde pierde pistas tipográficas distintivas.
3. **Desambiguación contextual**: Para abreviaciones con múltiples significados (ej: "HTP" = hipertensin portal vs. hipertensión pulmonar), se requiere un módulo adicional de desambiguación basado en contexto clínico.
4. **Dependencia del diccionario SEDOM**: Las abreviaciones detectadas se validan contra el diccionario de 7,054 entradas del SEDOM.
## Casos de Uso
- Preprocesamiento de informes médicos
- Sistemas de simplificación de textos clínicos
- Normalización de terminología médica
- Asistencia en la comunicación médico-paciente
- Análisis de calidad de documentación clínica
## Licencia
Apache 2.0