VladimirRH/ruRoberta-large-medical-router
ruRoberta-large-medical-router
LoRA-дообученная ai-forever/ruRoberta-large для классификации медицинских жалоб на русском языке по 12 врачебным специальностям. Модель предсказывает, к какому специалисту стоит обратиться на основе текстового описания симптомов.
⚠️ Это учебный/pet-проект, а не медицинское изделие. Модель не проходила клинической валидации и не предназначена для использования в реальной клинической практике — ни как единственный источник для маршрутизации пациентов, ни как основание для медицинских решений. Используйте только в исследовательских/образовательных целях, на свой риск, без каких-либо гарантий точности.
Классы
Гинеколог, Терапевт, Невролог, Гастроэнтеролог, Дерматолог, Отоларинголог, Уролог, Травматолог, Стоматолог, Хирург, Проктолог, Офтальмолог
Как использовать
from transformers import pipeline
clf = pipeline("text-classification", model="VladimirRH/medical-triage-clf")
clf("тянущая боль внизу живота, задержка цикла")
# [{'label': 'Гинеколог', 'score': 0.91}]Модель обучена через peft/LoRA и опубликована в смёрженном виде (merge_and_unload), поэтому для инференса peft не требуется — работает как обычная модель AutoModelForSequenceClassification.
Пороговая фильтрация низкоуверенных предсказаний (опционально)
Softmax-score не откалиброван идеально, но если нужно отсекать неуверенные предсказания:
def classify_with_abstention(text, threshold=0.7):
result = clf(text)[0]
if result["score"] < threshold:
return {"label": "нет уверенности в ответе", "score": result["score"]}
return resultПорог 0.7 — отправная точка, а не откалиброванное значение; перед использованием в своих целях желательно подобрать его на собственной валидационной выборке через анализ compromise между coverage и accuracy-at-threshold.
Данные
- Обучающий датасет: `VladimirRH/medical-routing-dataset`, ~1200 размеченных жалоб пациентов на русском языке.
- Базовые ~1000 строк дополнены ~200 синтетически сгенерированными примерами для четырёх наименее представленных классов (Хирург, Проктолог, Стоматолог, Офтальмолог), чтобы частично сгладить дисбаланс классов (изначальный разброс — от 39 до 230 примеров на класс).
- Синтетические данные сгенерированы с помощью LLM, не являются реальными жалобами пациентов.
- Train/val/test разбиение — стратифицированное, 80/10/10.
Обучение
- Базовая модель:
ai-forever/ruRoberta-large - Метод: LoRA (
peft),r=8,lora_alpha=16,lora_dropout=0.1,target_modules=["query", "value"],bias="none" - 5 эпох,
learning_rate=2e-4,batch_size=16 - Балансировка классов при обучении —
WeightedRandomSampler(обратные частоты класса) - Отбор лучшего чекпоинта — по
macro F1на валидации
Результаты на тестовой выборке
Accuracy: 0.721, Macro F1: 0.690 (support = 122)
Известные ограничения
- Датасет небольшой (~1200 строк), тест — всего 122 строки. У нескольких классов (Отоларинголог, Травматолог, Уролог) support в тесте 5-6 примеров — метрики по ним статистически шумные, одна-две ошибки существенно меняют F1. Stratified k-fold CV не проводился, поэтому устойчивость приведённых цифр к выбору сплита не проверялась.
- Терапевт — стабильно самый слабый класс (F1 0.48, recall 0.40). Это, вероятно, не недостаток данных, а природа самой категории: жалобы с неспецифическими или пересекающимися симптомами объективно можно отнести и к Терапевту, и к профильному специалисту.
- Уролог — заметно просел после добавления синтетических данных по другим классам (0.769 → 0.444 F1 между итерациями); при крошечном support (6) не ясно, реальная это деградация или шум одного сплита.
- Модель не видела реальных клинических данных, синтетическая часть датасета может иметь стилистические артефакты LLM-генерации.
Автор
Учебный проект. Hugging Face: VladimirRH
