Как мы сделали шаг в сторону автоматизации первичного приема и поможем вам сделать то же самое

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет! Меня зовут Егоров Мичил и я лидил команду по выполнению НИР (научно-исследовательская работа) для работы с заболевания на естественном языке. Сегодня мы расскажем вам как мы в составе пяти человек занимались разработкой модуля для предсказания предварительного диагноза с целью оптимизации потока пациентов в медицинских учреждениях. 

Мы верим, что использование современных алгоритмов и технологий в медицине способно сделать нашу жизнь лучше. Наш модуль предназначен для помощи врачам и медицинскому персоналу в принятии важных решений, оптимизации потока пациентов и обеспечения более эффективного и своевременного предоставления медицинской помощи.

Зачем мы это делаем?

Здоровье населения - важный фактор, который оказывает существенное влияние на общественное благосостояние. Это является результатов взаимодействия множества факторов, включающих социальные условия, психологические аспекты и экономические возможности. 

Важно разделять прием к специалисту на две части: первичная и вторичная. Первичный прием направлен на выявление примерного заболевания и направления на дальнейшие анализы и тесты. Дальше на вторичном приеме с нужными анализами и тестами разрабатывается методика лечения. А представьте, что если бы все пациенты приходили на первый прием с нужными тестами и анализами? Это бы сэкономило деньги и пациенту и позволило медицинскому персоналу сконцентрироваться на более неоднозначные кейсы пациентов!

К это большому челленджу уже было сделано несколько подходов, но унифицированного и готового решения нет. И тут в дело вступает использование чат-ботов и связанных технологий в медицинском общении - это удобное решение, которое делает первичное общение с врачами простым и автоматизированным, позволяя поддерживать непрерывное общение между службами здравоохранения и пациентами. 

Тут вы наверное подумаете "очередное решение основанное на чатгпт!", но вы правы только от части. Сфера здравоохранения требует интерпретируемых и воспроизводимых результатов. На данный момент чатГПТ удобный инструмент, но возложить на него судьбы пациентов не правильно и с точки зрения закона, так и этики. Поэтому хочется сделать интепретируемый, воспроизводимый и понятный всем инструмент для работы с пациентами.

Общий план и основная идея

Хочется в итоге для готового продукта видеть следующую модель взаимодействия:

  • Человек пишет что его беспокоит

  • Мы делаем предсказание заболевания и говорим что ему делать дальше

  • Пациент видит результат и может понять почему мы так решили

И тут возникает вопрос - а как определять болезнь по тому что пишет человек и как рекомендовать дальнейшие действия? Ответ банален - машинное обучение! Но в этой статье не будет много рассуждений про что это такое и как работает - мы расскажем максимально доступно и понятно. Так же приведем пример кода как все это может работать.

Идеальный сценарий использование модуля. Бот - https://t.me/distool_bot
Идеальный сценарий использование модуля. Бот - https://t.me/distool_bot

Поэтому у нас возникает следующий классический план для решений на основе машинного обучения:

  • Сбор данных

  • Обучение моделей

  • Валидация результатов

  • Если нас не устраивают результаты, возвращаемся на первый пункт

  • Если все хорошо - в прод!

Разработка

Хотелось разработать модульную систему, чтобы можно было комбинировать отдельный куски библиотеки и создавать любое решение. Поэтому мы выделили три главных модуля:

  • подмодуль поиска симптомов: модуль, построенный на основе SpaCy и Negex, который отвечает за распознавание симптомов и обработку отрицаний симптомов во входных текстовых данных;

  • подмодули классификации: были разработаны два разных модуля классификации, один основан на логистической регрессии, а другой на FEDOT AutoML framework, что обеспечивало гибкость и возможность выбора подходящего классификатора в зависимости от конкретной ситуации;

  • подмодуль интерпретации: этот модуль использовался для интерпретации решений, принятых модулями классификации, и предоставления понятных объяснений пользователям системы.

Тем самым можно использовать подмодули вместе или по отдельности, заменяя какой нибудь из них на собственное решение.

Сбор данных

Как оказалось, не так много структурированных данных, где пользователи деляться своими переживаниями и с диагназом от врача (очевидно), даже в специализированных формумах, можно достать скорее раздел болезни (https://meduniver.ru), чем конкретное заболевание. А без доступа к базам больниц, такие данные не достать. Как же мы выкрутиились из этой ситуации? ChatGPT.

Генерация анамнезов пациентов

Хотелось получать разнообразные анамнезы пациентов для заданной болезни. Тогда мы могли бы генерировать сколько угодно анамнезов пациентов для валидации и обучения моделей. Для этого мы придумали следующий промпт (запрос в gpt-3.5):

Ты пациент и пришел на первичный прием.
Ты не знаешь своего диагноза, поэтому не можешь о нем напрямую говорить.

Твой ответ обязательно следует следующим пунктам:

- ответ должен быть похож на естественную речь человека;

- напиши о том, как ты себя чувствуешь;

- напиши о том, какие симптомы проявлялись;

- сказать каких симптомов не было;

- в ответе не должен быть сам диагноз;

А так же в ответе должно быть выполнено хотя бы одно требование:

- когда начали проявляться первые симптомы;

- как прогрессировало ухудшение твоего состояния;

- хронические заболевания, если они могут связаны с твоей болезнью.

Основная идея в том, чтобы не давать ответы в тексте и генерировать максимально разнообразные анамнезы (мы еще подкрутили температуру до 2). И тем самым можно получать следующие ответы:

Здравствуйте, я не чувствую себя совсем хорошо. Я ощущаю сильный жжение и боль при мочеиспускании, а также часто хочу пойти в туалет. Эти симптомы появились несколько дней назад и не уменьшаются. Но у меня нет никакой температуры и болей в животе. Началось все после того, как я был на длинной поездке на автомобиле. У меня нет хронических заболеваний, которые могут быть связаны с этим.

Видим, что GPT-3.5 генерирует интересные кейсы пациентов, с проблемами на русском языке, но не суть.

Выделение симптомов для обучения моделей

Модели не достаточно знать про упоминания симптомов в анамнезе пациента. Очень важной информацией является отрицание симптома. Для валидации этого алгоритма тоже нужно собрать данные. Мы конечно можем вручную это разметить, мы это даже делали, но... опять же ChatGPT!

Изучай присылаемые тексты и выделяй из них симптомы в виде списка:

Требования к ответу:

- Разделяй сипмтомы на подтвержденные и отрицаемые;

- Не отвечай на приветствия в тексте;

- Не отвечай на вопросы в тексте;

- Не давай рекомендации и советы по поводу лечения;

Пример валидации промпта
Пример валидации промпта

Тем самым мы собрали с анамнезов еще и упоминаемые в них симптомы!

Модуль для извлечения симптомов

Общая идея выглядит так:

Пайплайн извлечения симптомов
Пайплайн извлечения симптомов

Подход основан на работу с предопределенным перечнем симптомов (сейчас 503 различных симптома). Это позволяет нашему модулю обнаруживать и отслеживать широкий спектр проявлений заболеваний.

В сердце этого процесса лежит фреймворк Scapy, который мы использовали для обработки неструктурированного текста, предоставленного пациентами. Однако мы столкнулись с проблемой: встроенная модель Scapy изначально не была нацелена на работу с медицинскими терминами и симптомами. Чтобы решить эту проблему, мы разработали уникальные шаблоны и подсказки, которые обучили модель определять нужные симптомы в тексте.

Как мы говорили до этого, мы должны проверять не только наличие, но и отрицание симптома. Иначе мы рискуем неправильно истолковать полученную информацию и, как следствие, ошибиться в диагнозе. Для этого мы использовали инструмент под названием negex, который анализирует контекст и определяет, есть ли в тексте отрицание относительно каждого симптома. Нам пришлось адаптировать его для работы с русским языком, и теперь он успешно справляется с задачей.

После обработки текста мы собираем все обнаруженные симптомы и составляем на их основе анамнез для каждого пациента. Так мы получаем векторное представление симптомов, которое в дальнейшем используется для обучения модели и предсказания болезни.

Валидация результатов

Нужно как то валидировать работу алгоритма - для этого мы и собрали данные по наличиям и отрицаниям симптомов. Но мы имеем дело не с обычной бинарной классификацией, поэтому стандартные способы подсчета метрик нам не помогут. Поэтому мы предлагаем собственный способ валидации алгоритма:

  1. VALID – разметчик указал отрицание или наличие симптома, и алгоритм правильно определил;

  2. INVALID – разметчик указал отрицание или наличие симптома, и алгоритм указал обратно;

  3. VALIDATE_MARKER –алгоритм нашел отсутствие или наличие определенного симптома, а разметчик его не нашел;

  4. VALIDATE_EXTRACTOR – разметчик нашел отрицание или наличие симптома, но модель его не нашла.

Таким образом была выделена метрика accuracy = (VALID + VALIDATE_MARKER * VALID / (VALID + INVALID)). Мы допускаем, что для симптомов из VALIDATE_MARKER, модель предсказывает с распределение ошибки как для INVALID и VALID.

Тем самым разработанная модель показала accuracy = 84%, чего как нам кажется, более чем достаточно, но всегда есть куда расти.

Модуль для предсказания болезни

Определение болезней - сердцевина нашей системы. Этот подмодуль берет на себя задачу анализа симптомов и их классификации для определения возможной болезни. Важно было не просто преобразовать векторы симптомов в диагнозы, но и сделать результаты легко интерпретируемыми для медицинских работников.

Мы приняли решение протестировать два подхода: классическую логистическую регрессию и AutoML коллег из ИТМО - FEDOT. FEDOT позволяет автоматически оптимизировать структуру и параметры модели, что подходит для наших целей. Однако, эта модель может быть сложной для интерпретации, что важно в медицинском контексте.

С другой стороны, логистическая регрессия, несмотря на свою простоту, обеспечивает прямые связи между коэффициентами модели и вероятностями болезней. Это делает её привлекательной для клинической практики, так как помогает не только определить состояние пациента, но и объяснить его.

В результате обучения модели мы получили следующие метрики:

Таблица сравнения различных моделей машинного обучения с заданным способом векторизации
Таблица сравнения различных моделей машинного обучения с заданным способом векторизации

Из таблицы видно, что все модели достаточно много ошибаются, однако если сравнить SymptomExtractor с базовым Tf-Idf, который переобучился на n-gram-ах, то становится очевидным, что подход с извлечением симптомов себя оправдывает и требует дальнейшей проработки со стороны обучающих данных. При малой уверенности модели в своем решении, предполагается уточнение у пациента дополнительной информации, и затем повторная классификация. При достаточно уверенных прогнозах (>0.6) модель показывает F1-меру = 0.89.

И самое интересное - вклад каждого сипмтома на определение болезни:

Вклад симптома на наличие или отрицание болезни
Вклад симптома на наличие или отрицание болезни

Из этой иллюстрации можно найти интересные выводы: Самым важным симптомом, указывающим на наличие ангины, с точки зрения статистической модели является анемия. Это может показаться нелогичным, так как анемия обычно не ассоциируется с ангиной. Однако этот результат может отражает то, что анемия может ухудшать симптомы ангины или увеличивать вероятность ее развития.

Заключение

Мы создали модули для извлечения и классификации симптомов пациентов из текстовых сообщений. Они успешно прошли тесты на большом наборе данных. Затем разработали модуль для определения болезней, используя два подхода: генетическое программирование и логистическую регрессию. Оба метода дали хорошие результаты.

Также создали модуль для определения срочности болезней, используя логистическую регрессию и нейронную сеть с механизмом самовнимания. 

Теперь система готова обрабатывать текстовые сообщения пациентов, выявлять симптомы и прогнозировать возможные заболевания, оценивая степень срочности медицинской помощи.

Но мы не останавливаемся на этом этапе и планируем использовать больше данных для обучения системы для прогнозирования заболеваний и расширять функционал. 

В этой статье мы не рассмотрели алгоритмы маркировки срочности приема и интерпертации результатов, так как он и так уже вышел довольно громоздкий и сложный для восприятия, но если вам будет интересно - мы выложим отдельный пост и расскажем в частности как нам помог Attention для определения срочности приема!

В течение проекта мы выложили несколько датасетов в публичный доступ: https://www.kaggle.com/datasets/egorovm/patient-disease, https://github.com/NIRMA-PATIENT-INTAKE/data, а так же open-source решение, который уже можно установить через PyPI и уже начать контрибьютить! https://github.com/niRMA-PATIENT-INTAKE/disease/. Пример использования модуля в виде телеграм бота (https://t.me/distool_bot) выше: https://github.com/NIRMA-PATIENT-INTAKE/telegram-interface.

Хочу сказать спасибо своей команде: Дмитрию Погребному, Маше Якубовой, Айталине Кривошапкиной и Анне Чижик за нашу плодотворную работу, и конечно же ИТМО, который позволил всем собраться и заниматься интересным нам всем проектом. Всем до новых встреч!

Источник: https://habr.com/ru/articles/752580/


Интересные статьи

Интересные статьи

История контроллеров Modicon и коммуникационного стандарта Modbus неразрывно связана с развитием «автоматизации» технологических процессов в промышленности и внедрением цифровых технологий. С чего все...
В этой статье я дам рекомендации по созданию платёжных форм, которые будут выгодно отличаться от форм ваших конкурентов. Каждый пункт рекомендаций будет сопровождаться примером кода. По...
Привет, меня зовут Алексей Кафтанов, я — руководитель компании FullStack (входит в ГК «Автомакон»). Мы занимаемся разработкой мобильных и web-приложений. В начале года у нас появился инт...
В статье перечислены особенности двух популярных форматов сериализации, которые следует учитывать архитектору, выбирая один из них. Читать далее
Привет, Хабр! представляю вашему вниманию перевод статьи «How to make your HTML responsive by adding a single line of CSS» автора Per Harald Borgen. В этой статье я научу вас, как использо...