初始化项目,由ModelHub XC社区提供模型
Model: lmolino/extractor_abreviaciones Source: Original Platform
This commit is contained in:
36
.gitattributes
vendored
Normal file
36
.gitattributes
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.model filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||||
|
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
||||||
193
README.md
Normal file
193
README.md
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
40
config.json
Normal file
40
config.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"_name_or_path": "/mnt/beegfs/sinai-data/meta-llama/Llama-3.2-1B-Instruct",
|
||||||
|
"architectures": [
|
||||||
|
"LlamaForCausalLM"
|
||||||
|
],
|
||||||
|
"attention_bias": false,
|
||||||
|
"attention_dropout": 0.0,
|
||||||
|
"bos_token_id": 128000,
|
||||||
|
"eos_token_id": [
|
||||||
|
128001,
|
||||||
|
128008,
|
||||||
|
128009
|
||||||
|
],
|
||||||
|
"head_dim": 64,
|
||||||
|
"hidden_act": "silu",
|
||||||
|
"hidden_size": 2048,
|
||||||
|
"initializer_range": 0.02,
|
||||||
|
"intermediate_size": 8192,
|
||||||
|
"max_position_embeddings": 131072,
|
||||||
|
"mlp_bias": false,
|
||||||
|
"model_type": "llama",
|
||||||
|
"num_attention_heads": 32,
|
||||||
|
"num_hidden_layers": 16,
|
||||||
|
"num_key_value_heads": 8,
|
||||||
|
"pretraining_tp": 1,
|
||||||
|
"rms_norm_eps": 1e-05,
|
||||||
|
"rope_scaling": {
|
||||||
|
"factor": 32.0,
|
||||||
|
"high_freq_factor": 4.0,
|
||||||
|
"low_freq_factor": 1.0,
|
||||||
|
"original_max_position_embeddings": 8192,
|
||||||
|
"rope_type": "llama3"
|
||||||
|
},
|
||||||
|
"rope_theta": 500000.0,
|
||||||
|
"tie_word_embeddings": true,
|
||||||
|
"torch_dtype": "bfloat16",
|
||||||
|
"transformers_version": "4.48.2",
|
||||||
|
"use_cache": true,
|
||||||
|
"vocab_size": 128256
|
||||||
|
}
|
||||||
12
generation_config.json
Normal file
12
generation_config.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"bos_token_id": 128000,
|
||||||
|
"do_sample": true,
|
||||||
|
"eos_token_id": [
|
||||||
|
128001,
|
||||||
|
128008,
|
||||||
|
128009
|
||||||
|
],
|
||||||
|
"temperature": 0.6,
|
||||||
|
"top_p": 0.9,
|
||||||
|
"transformers_version": "4.48.2"
|
||||||
|
}
|
||||||
3
model.safetensors
Normal file
3
model.safetensors
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:facb133f39098c03cab971fc8526c27bb3d91e81357b1c5f1c20ee6504a3fa95
|
||||||
|
size 2471645608
|
||||||
17
special_tokens_map.json
Normal file
17
special_tokens_map.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"bos_token": {
|
||||||
|
"content": "<|begin_of_text|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"eos_token": {
|
||||||
|
"content": "<|eot_id|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"pad_token": "<|eot_id|>"
|
||||||
|
}
|
||||||
3
tokenizer.json
Normal file
3
tokenizer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:6b9e4e7fb171f92fd137b777cc2714bf87d11576700a1dcd7a399e7bbe39537b
|
||||||
|
size 17209920
|
||||||
2064
tokenizer_config.json
Normal file
2064
tokenizer_config.json
Normal file
File diff suppressed because it is too large
Load Diff
3
training_args.bin
Normal file
3
training_args.bin
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0899a11c76db89c507ebff6a605a2245740a2b5fccf471fd4a078f7ca805c848
|
||||||
|
size 5496
|
||||||
Reference in New Issue
Block a user