Постройте сеть биомедицинских знаний с помощью НЛП

Исходный узел: 1401511

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

Пример подграфа, показывающий взаимосвязь аскорбиновой кислоты с другими биомедицинскими концепциями. Изображение автора.

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

Теперь у вас может быть команда экспертов в предметной области, которая наметит для вас все эти связи между лекарствами, болезнями и другими биомедицинскими концепциями. Но, к сожалению, не многие из нас могут позволить себе нанять команду врачей, которые сделают за нас всю работу. В этом случае мы можем прибегнуть к методам НЛП для автоматического извлечения этих отношений. Хорошая часть заключается в том, что мы можем использовать конвейер НЛП для чтения всех исследовательских работ, а плохая часть в том, что не все полученные результаты будут идеальными. Однако, учитывая, что у меня нет группы ученых, готовых вручную извлечь отношения, я прибегну к использованию методов НЛП, чтобы построить собственный граф биомедицинских знаний.

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

Бумага была написана Мохаммадреза Ахмади. PDF-версия статьи доступна по лицензии CC0 1.0. Мы пройдем следующие шаги, чтобы построить граф знаний:

  • Чтение документа PDF с помощью OCR
  • Предварительная обработка текста
  • Распознавание и связывание биомедицинских концепций
  • Извлечение отношения
  • Пополнение внешней базы данных

К концу этого поста вы построите график со следующей схемой.

Схема биомедицинского графа. Изображение автора.

Мы будем использовать Neo4j, базу данных графов, в которой представлена ​​модель графа помеченных свойств, для хранения нашего графа. У каждой статьи может быть один или несколько авторов. Мы разделим содержание статьи на предложения и воспользуемся НЛП для извлечения как медицинских сущностей, так и их взаимосвязей. Может показаться нелогичным, что мы будем хранить отношения между сущностями как промежуточные узлы, а не отношения. Критическим фактором, стоящим за этим решением, является то, что мы хотим иметь контрольный след исходного текста, из которого было извлечено отношение. В модели графа свойств с метками у вас не может быть отношения, указывающего на другое отношение. По этой причине мы реорганизуем связь между медицинскими понятиями в промежуточный узел. Это также позволит эксперту в предметной области оценить, правильно ли было извлечено отношение или нет.

Попутно я также продемонстрирую приложения использования построенного графа для поиска и анализа хранимой информации.

Давайте прямо в это погрузимся!

Если этот подробный образовательный контент вам полезен, подпишитесь на нашу рассылку исследований ИИ быть предупрежденным, когда мы выпустим новый материал.

Чтение документа PDF с помощью OCR

Как уже упоминалось, версия исследовательской статьи в формате PDF доступна для общественности по лицензии CC0 1.0, что означает, что мы можем легко загрузить ее с помощью Python. Мы будем использовать питессеракт библиотека для извлечения текста из PDF. Насколько я знаю, библиотека pytesseract — одна из самых популярных библиотек для OCR. Если вы хотите следовать примерам кода, я подготовил Блокнот Google Colab, поэтому вам не нужно копировать и вставлять код самостоятельно.

import requests
import pdf2image
import pytesseract pdf = requests.get('https://arxiv.org/pdf/2110.03526.pdf')
doc = pdf2image.convert_from_bytes(pdf.content) # Get the article text
article = []
for page_number, page_data in enumerate(doc): txt = pytesseract.image_to_string(page_data).encode("utf-8") # Sixth page are only references if page_number < 6: article.append(txt.decode("utf-8"))
article_txt = " ".join(article)

Предварительная обработка текста

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

import nltk
nltk.download('punkt') def clean_text(text): """Remove section titles and figure descriptions from text""" clean = "n".join([row for row in text.split("n") if (len(row.split(" "))) > 3 and not (row.startswith("(a)")) and not row.startswith("Figure")]) return clean text = article_txt.split("INTRODUCTION")[1]
ctext = clean_text(text)
sentences = nltk.tokenize.sent_tokenize(ctext)

Связывание биомедицинских именованных объектов

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

Извлечение биомедицинских понятий. Изображение автора.

В этом примере модель НЛП идентифицировала в тексте гены, болезни, лекарства, виды, мутации и пути. Как уже упоминалось, этот процесс называется распознаванием именованных объектов. Обновлением распознавания именованных объектов является так называемое связывание именованных объектов. Метод связывания именованных сущностей обнаруживает релевантные понятия в тексте и пытается сопоставить их с целевой базой знаний. В биомедицинской области некоторые из целевых баз знаний:

Зачем нам связывать медицинские учреждения с целевой базой знаний? Основная причина в том, что это помогает нам справиться с неоднозначностью сущностей. Например, нам не нужны отдельные объекты на графике, представляющие аскорбиновую кислоту и витамин С, поскольку эксперты в предметной области могут сказать вам, что это одно и то же. Вторая причина заключается в том, что, сопоставляя понятия с целевой базой знаний, мы можем обогатить нашу графовую модель, извлекая информацию о сопоставленных понятиях из целевой базы знаний. Если мы снова воспользуемся примером с аскорбиновой кислотой, мы можем легко получить дополнительную информацию из базы данных CHEBI, если мы уже знаем ее значение. ЧЕБИ ID.

Данные по обогащению аскорбиновой кислоты доступны на веб-сайте CHEBI. Весь контент на сайте доступен в разделе Лицензия CCBY 4.0. Изображение автора.

Я искал приличную предварительно обученную биомедицинскую именованную сущность с открытым исходным кодом в течение некоторого времени. Многие модели НЛП сосредоточены на извлечении только определенного подмножества медицинских понятий, таких как гены или болезни. Еще реже можно найти модель, которая обнаруживает большинство медицинских концепций и связывает их с целевой базой знаний. К счастью, я наткнулся на БЕРНЕ[1], инструмент распознавания нейронных биомедицинских объектов и многотипной нормализации. Если я правильно понимаю, это точно настроенная модель BioBert с различными именованными моделями связывания сущностей, интегрированными для сопоставления концепций с биомедицинскими целевыми базами знаний. Мало того, они также предоставляют бесплатную конечную точку REST, поэтому нам не нужно сталкиваться с головной болью, связанной с получением зависимостей и модели для работы. Биомедицинская визуализация распознавания именованных объектов, которую я использовал выше, была создана с использованием модели BERN, поэтому мы знаем, что она обнаруживает гены, болезни, лекарства, виды, мутации и пути в тексте.

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

import hashlib def query_raw(text, url="https://bern.korea.ac.kr/plain"): """Biomedical entity linking API""" return requests.post(url, data={'sample_text': text}).json() entity_list = []
# The last sentence is invalid
for s in sentences[:-1]: entity_list.append(query_raw(s)) parsed_entities = []
for entities in entity_list: e = [] # If there are not entities in the text if not entities.get('denotations'): parsed_entities.append({'text':entities['text'], 'text_sha256': hashlib.sha256(entities['text'].encode('utf-8')).hexdigest()}) continue for entity in entities['denotations']: other_ids = [id for id in entity['id'] if not id.startswith("BERN")] entity_type = entity['obj'] entity_name = entities['text'][entity['span']['begin']:entity['span']['end']] try: entity_id = [id for id in entity['id'] if id.startswith("BERN")][0] except IndexError: entity_id = entity_name e.append({'entity_id': entity_id, 'other_ids': other_ids, 'entity_type': entity_type, 'entity': entity_name}) parsed_entities.append({'entities':e, 'text':entities['text'], 'text_sha256': hashlib.sha256(entities['text'].encode('utf-8')).hexdigest()})

Я проверил результаты связывания именованных объектов, и, как и ожидалось, они не идеальны. Например, он не определяет стволовые клетки как медицинское понятие. С другой стороны, он обнаружил единую сущность под названием «сердце, мозг, нервы и почки». Тем не менее, BERN по-прежнему остается лучшей биомедицинской моделью с открытым исходным кодом, которую мне удалось найти во время моего расследования.

Построить граф знаний

Прежде чем рассматривать методы извлечения отношений, мы построим граф биомедицинских знаний, используя только сущности, и рассмотрим возможные приложения. Как уже упоминалось, я подготовил Блокнот Google Colab которые вы можете использовать, чтобы следовать примерам кода в этом посте. Для хранения нашего графика мы будем использовать Neo4j. Вам не нужно заниматься подготовкой локальной среды Neo4j. Вместо этого вы можете использовать бесплатный экземпляр Neo4j Sandbox.

Neo4j Песочница

Запустите Пустой проект в песочнице и скопируйте данные подключения в блокнот Colab.

Детали подключения Neo4j Sandbox. Изображение автора.

Теперь вы можете продолжить и подготовить соединение Neo4j в ноутбуке.

from neo4j import GraphDatabase
import pandas as pd host = 'bolt://3.236.182.55:7687'
user = 'neo4j'
password = 'hydrometer-ditches-windings'
driver = GraphDatabase.driver(host,auth=(user, password)) def neo4j_query(query, params=None): with driver.session() as session: result = session.run(query, params) return pd.DataFrame([r.values() for r in result], columns=result.keys())

Мы начнем с импорта автора и статьи в график. Узел статьи будет содержать только заголовок.

author = article_txt.split("n")[0]
title = " ".join(article_txt.split("n")[2:4]) neo4j_query("""
MERGE (a:Author{name:$author})
MERGE (b:Article{title:$title})
MERGE (a)-[:WROTE]->(b)
""", {'title':title, 'author':author})

Если вы откроете браузер Neo4j, вы должны увидеть следующий график.

Изображение автора.

Вы можете импортировать предложения и упомянутые объекты, выполнив следующий запрос Cypher:

neo4j_query("""
MATCH (a:Article)
UNWIND $data as row
MERGE (s:Sentence{id:row.text_sha256})
SET s.text = row.text
MERGE (a)-[:HAS_SENTENCE]->(s)
WITH s, row.entities as entities
UNWIND entities as entity
MERGE (e:Entity{id:entity.entity_id})
ON CREATE SET e.other_ids = entity.other_ids, e.name = entity.entity, e.type = entity.entity_type
MERGE (s)-[m:MENTIONS]->(e)
ON CREATE SET m.count = 1
ON MATCH SET m.count = m.count + 1
""", {'data': parsed_entities})

Вы можете выполнить следующий запрос Cypher для проверки построенного графа:

MATCH p=(a:Article)-[:HAS_SENTENCE]->()-[:MENTIONS]->(e:Entity)
RETURN p LIMIT 25

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

Извлечение объекта сохраняется в виде графика. Изображение автора.

Приложения графа знаний

Даже без потока извлечения отношений у нашего графа уже есть пара вариантов использования.

Поисковая

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

MATCH (e:Entity)<-[:MENTIONS]-(s:Sentence)
WHERE e.name = "autoimmune diseases"
RETURN s.text as result

Итоги

Изображение автора.

Анализ совпадений

Второй вариант — анализ совпадений. Вы можете определить совпадение между медицинскими сущностями, если они появляются в одном и том же предложении или статье. Я нашел статью [2], в которой используется сеть медицинских совпадений для прогнозирования новых возможных связей между медицинскими объектами.

Предсказание ссылок в сети совместного появления MeSH: предварительные результаты – PubMed

Вы можете использовать следующий запрос Cypher, чтобы найти сущности, которые часто встречаются в одном и том же предложении.

MATCH (e1:Entity)<-[:MENTIONS]-()-[:MENTIONS]->(e2:Entity)
MATCH (e1:Entity)<-[:MENTIONS]-()-[:MENTIONS]->(e2:Entity)
WHERE id(e1) < id(e2)
RETURN e1.name as entity1, e2.name as entity2, count(*) as cooccurrence
ORDER BY cooccurrence
DESC LIMIT 3

Итоги

сущность1 сущность2 совпадение
кожные заболевания диабетические язвы 2
хронические раны диабетические язвы 2
кожные заболевания хронические раны 2

Очевидно, что результаты были бы лучше, если бы мы анализировали тысячи и более статей.

Проверьте опыт автора

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

Выполните следующий запрос Cypher, чтобы проверить, какие медицинские учреждения наш единственный автор упомянул в исследовательской статье.

MATCH (a:Author)-[:WROTE]->()-[:HAS_SENTENCE]->()-[:MENTIONS]->(e:Entity)
RETURN a.name as author, e.name as entity,
MATCH (a:Author)-[:WROTE]->()-[:HAS_SENTENCE]->()-[:MENTIONS]->(e:Entity)
RETURN a.name as author, e.name as entity, count(*) as count
ORDER BY count DESC
LIMIT 5

Итоги

автор организация считать
Мохаммадреза Ахмади коллаген 9
Мохаммадреза Ахмади ожоги 4
Мохаммадреза Ахмади кожные заболевания 4
Мохаммадреза Ахмади ферменты коллагеназы 2
Мохаммадреза Ахмади Буллезный эпидермолиз 2

Извлечение отношения

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

Я искал доступные модели извлечения биомедицинских отношений, но не нашел ничего, что работало бы «из коробки» или не требовало тонкой настройки. Кажется, что область извлечения отношений находится на переднем крае, и, надеюсь, мы увидим больше внимания к ней в будущем. К сожалению, я не эксперт НЛП, поэтому я избегал тонкой настройки собственной модели. Вместо этого мы будем использовать экстрактор нулевых отношений, основанный на статье Изучение предела нулевого выстрела FewRel[3]. Хотя я бы не рекомендовал запускать эту модель в производство, она достаточно хороша для простой демонстрации. Модель доступна на ОбниматьЛицо, поэтому нам не нужно заниматься обучением или настройкой модели.

from transformers import AutoTokenizer
from zero_shot_re import RelTaggerModel, RelationExtractor model = RelTaggerModel.from_pretrained("fractalego/fewrel-zero-shot")
tokenizer = AutoTokenizer.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
relations = ['associated', 'interacts']
extractor = RelationExtractor(model, tokenizer, relations)

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

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

import itertools
# Candidate sentence where there is more than a single entity present
candidates = [s for s in parsed_entities if (s.get('entities')) and (len(s['entities']) &gt; 1)]
predicted_rels = []
for c in candidates: combinations = itertools.combinations([{'name':x['entity'], 'id':x['entity_id']} for x in c['entities']], 2) for combination in list(combinations): try: ranked_rels = extractor.rank(text=c['text'].replace(",", " "), head=combination[0]['name'], tail=combination[1]['name']) # Define threshold for the most probable relation if ranked_rels[0][1] &gt; 0.85: predicted_rels.append({'head': combination[0]['id'], 'tail': combination[1]['id'], 'type':ranked_rels[0][0], 'source': c['text_sha256']}) except: pass # Store relations to Neo4j
neo4j_query("""
UNWIND $data as row
MATCH (source:Entity {id: row.head})
MATCH (target:Entity {id: row.tail})
MATCH (text:Sentence {id: row.source})
MERGE (source)-[:REL]-&gt;(r:Relation {type: row.type})-[:REL]-&gt;(target)
MERGE (text)-[:MENTIONS]-&gt;(r)
""", {'data': predicted_rels})

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

Извлеченные отношения, хранящиеся в графе. Изображение автора.

Вы можете проверить извлеченные отношения между сущностями и исходным текстом с помощью следующего запроса Cypher:

MATCH (s:Entity)-[:REL]->(r:Relation)-[:REL]->(t:Entity), (r)<-[:MENTIONS]-(st:Sentence)
RETURN s.name as source_entity, t.name as target_entity, r.type as type, st.text as source_text

Итоги

Изображение автора.

Как уже упоминалось, модель НЛП, которую я использовал для извлечения отношений, не идеальна, и, поскольку я не врач, я не знаю, сколько связей она упустила. Однако те, которые он обнаружил, кажутся разумными.

Пополнение внешней базы данных

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

Вы можете получить идентификатор MeSH буллезного эпидермолиза с помощью следующего запроса:

MATCH (e:Entity)
WHERE e.name = "Epidermolysis bullosa"
RETURN e.name as entity, e.other_ids as other_ids

Вы можете пойти дальше и проверить MeSH, чтобы найти доступную информацию:

Данные, связанные с MeSH

Скриншот автора. Данные предоставлены Национальной медицинской библиотекой США.

Вот скриншот доступной информации о буллезном эпидермолизе на веб-сайте MeSH. Как уже упоминалось, я не врач, поэтому я точно не знаю, как лучше всего смоделировать эту информацию на графике. Однако я покажу вам, как получить эту информацию в Neo4j, используя процедуру apoc.load.json для получения информации из конечной точки MeSH REST. Затем вы можете попросить эксперта в предметной области помочь вам смоделировать эту информацию.

Запрос Cypher для получения информации из конечной точки MeSH REST:

MATCH (e:Entity)
WHERE e.name = "Epidermolysis bullosa"
WITH e, [id in e.other_ids WHERE id contains "MESH" | split(id,":")[1]][0] as meshId
CALL apoc.load.json("https://id.nlm.nih.gov/mesh/lookup/details?descriptor=" + meshId) YIELD value
RETURN value

Граф знаний как ввод данных для машинного обучения

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

Авторские права © 2017 Манан Шах, SNAP Group. Изображение доступно по лицензии MIT в https://github.com/snap-stanford/cs224w-notes.

Предположим, вы построили граф биомедицинских знаний, содержащий медицинские объекты и понятия, их отношения и обогащение из различных медицинских баз данных. Вы можете использовать методы внедрения узлов, чтобы изучить представления узлов, которые представляют собой векторы фиксированной длины, и ввести их в свой рабочий процесс машинного обучения. Этот подход используется в различных приложениях, начиная от перепрофилирования лекарств и заканчивая прогнозированием побочных эффектов или побочных эффектов. Я нашел исследовательскую работу, в которой используется связать прогноз потенциальных методов лечения новых заболеваний[4].

Заключение

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

Как всегда, код доступен на GitHub.

Рекомендации

[1] Д. Ким и др.., «Инструмент распознавания нейронных именованных объектов и нормализации нескольких типов для биомедицинского анализа текста», в Доступ IEEE, том. 7, стр. 73729–73740, 2019, doi: 10.1109/ACCESS.2019.2920708.

[2] Кастрин А., Риндфлеш Т.С., Христовски Д. Предсказание ссылок в сети совместного возникновения MeSH: предварительные результаты. Stud Health Technol Inform. 2014;205:579–83. PMID: 25160252.

[3] Четоли, А. (2020). Изучение предела нулевого выстрела FewRel. В Материалы 28-й Международной конференции по компьютерной лингвистике (стр. 1447–1451). Международный комитет по компьютерной лингвистике.

[4] Чжан Р., Христовски Д., Шутте Д., Кастрин А., Фишман М. и Киликоглу Х. (2021). Перепрофилирование лекарств для COVID-19 через завершение графа знаний. Журнал биомедицинской информатики, 115, 103696.

Эта статья изначально была опубликована в На пути к науке о данных и повторно опубликовано в TOPBOTS с разрешения автора.

Понравилась эта статья? Подпишитесь на новые обновления AI.

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

сообщение Постройте сеть биомедицинских знаний с помощью НЛП Появившийся сначала на ТОП-БОТЫ.

Отметка времени:

Больше от ТОП-БОТЫ