用 NLP 构建生物医学知识图谱

源节点: 1401511

我已经演示了如何 从维基百科页面创建知识图. 然而,由于这篇文章引起了很多关注,我决定探索使用 NLP 技术构建知识图谱的其他领域。 在我看来,生物医学领域是一个典型的例子,将数据表示为图表是有意义的,因为您经常分析基因、疾病、药物、蛋白质等之间的相互作用和关系。

显示抗坏血酸与其他生物医学概念的关系的示例子图。 图片由作者提供。

在上面的可视化中,我们有抗坏血酸,也称为维生素 C,以及它与其他概念的一些关系。 例如,它表明维生素 C 可用于治疗慢性胃炎。

现在,您可以让一个领域专家团队为您绘制药物、疾病和其他生物医学概念之间的所有这些联系。 但是,不幸的是,我们中没有多少人能负担得起聘请一支医生团队为我们做这项工作。 在这种情况下,我们可以求助于使用 NLP 技术来自动提取这些关系。 好的部分是我们可以使用 NLP 管道来阅读所有的研究论文,坏的部分是并非所有获得的结果都是完美的。 然而,鉴于我身边没有准备好手动提取关系的科学家团队,我将求助于使用 NLP 技术来构建我自己的生物医学知识图谱。

我将在这篇博文中使用一篇研究论文来引导您完成构建生物医学知识图谱所需的所有步骤—— 皮肤再生和毛发生长的组织工程.

这篇论文是由 穆罕默德礼萨·艾哈迈迪. 本文的 PDF 版本在 CC0 1.0 许可下可用。 我们将通过以下步骤来构建知识图谱:

  • 使用 OCR 读取 PDF 文档
  • 文字预处理
  • 生物医学概念识别与链接
  • 关系抽取
  • 外部数据库扩充

在本文结束时,您将使用以下模式构建一个图。

生物医学图表模式。 图片由作者提供。

我们将使用 Neo4j(一个具有标记属性图模型的图数据库)来存储我们的图。 每篇文章可以有一个或多个作者。 我们将文章内容拆分成句子,并使用 NLP 来提取医学实体及其关系。 我们将实体之间的关系存储为中间节点而不是关系可能有点违反直觉。 这个决定背后的关键因素是我们想要对从中提取关系的源文本进行审计跟踪。 使用带标签的属性图模型,您不能有一个关系指向另一个关系。 为此,我们将医学概念之间的联系重构为一个中间节点。 这也将允许领域专家评估关系是否被正确提取。

在此过程中,我还将演示使用构造图搜索和分析存储信息的应用程序。

让我们开始吧!

如果这些深入的教育内容对您有用, 订阅我们的AI研究邮件列表 当我们发布新材料时被提醒。

使用 OCR 读取 PDF 文档

如前所述,该研究论文的 PDF 版本在 CC0 1.0 许可下可供公众访问,这意味着我们可以使用 Python 轻松下载它。 我们将使用 pytesseract 库以从 PDF 中提取文本。 据我所知,pytesseract 库是 OCR 比较流行的库之一。 如果您想跟随代码示例,我准备了一个 谷歌 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)

生物医学命名实体链接

现在是激动人心的部分。 对于那些不熟悉 NLP 和命名实体识别和链接的人,让我们从一些基础知识开始。 命名实体识别技术用于检测文本中的相关实体或概念。 例如,在生物医学领域,我们要识别文本中的各种基因、药物、疾病和其他概念。

生物医学概念提取。 图片由作者提供。

在这个例子中,NLP 模型识别了文本中的基因、疾病、药物、物种、突变和通路。 如前所述,此过程称为命名实体识别。 命名实体识别的升级是所谓的命名实体链接。 命名实体链接技术检测文本中的相关概念并尝试将它们映射到目标知识库。 在生物医学领域,一些目标知识库是:

为什么我们要将医疗实体链接到目标知识库? 主要原因是它帮助我们处理实体消歧。 例如,我们不希望图中表示抗坏血酸和维生素 C 的单独实体,因为领域专家可以告诉您它们是同一件事。 第二个原因是,通过将概念映射到目标知识库,我们可以通过从目标知识库中获取有关映射概念的信息来丰富我们的图模型。 如果我们再次使用抗坏血酸的例子,如果我们已经知道它,我们可以很容易地从 CHEBI 数据库中获取其他信息 车比ID.

CHEBI 网站上提供了有关抗坏血酸的丰富数据。 网站上的所有内容都可以在 CC BY 4.0 许可证。 图片由作者提供。

一段时间以来,我一直在寻找一个体面的开源预训练生物医学命名实体链接。 许多 NLP 模型专注于仅提取特定的医学概念子集,例如基因或疾病。 更难找到能够检测大多数医学概念并将其链接到目标知识库的模型。 幸运的是我偶然发现 伯尔尼[1],一种神经生物医学实体识别和多类型归一化工具。 如果我理解正确的话,它是一个微调的 BioBert 模型,其中集成了各种命名实体链接模型,用于将概念映射到生物医学目标知识库。 不仅如此,它们还提供免费的 REST 端点,因此我们不必处理让依赖项和模型正常工作的头痛。 我上面使用的生物医学命名实体识别可视化是使用 BERN 模型创建的,因此我们知道它可以检测文本中的基因、疾病、药物、物种、突变和通路。

不幸的是,BERN 模型并没有为所有概念分配目标知识库 ID。 所以我准备了一个脚本,首先查看是否为概念提供了不同的 id,如果没有,它将使用实体名称作为 id。 我们还将计算句子文本的 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 仍然是我在调查期间能找到的最好的开源生物医学模型。

构建知识图谱

在研究关系提取技术之前,我们将仅使用实体构建生物医学知识图并检查可能的应用。 如前所述,我准备了一个 谷歌 Colab 笔记本 您可以使用它来遵循本文中的代码示例。 为了存储我们的图表,我们将使用 Neo4j。 您不必准备本地 Neo4j 环境。 相反,您可以使用免费的 Neo4j Sandbox 实例。

Neo4j 沙盒

开始 沙盒中的空白项目 并将连接详细信息复制到 Colab 笔记本。

Neo4j 沙盒连接详细信息。 图片由作者提供。

现在您可以继续在笔记本中准备 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

关系抽取

现在我们将尝试提取医学概念之间的关系。 根据我的经验,关系提取至少比命名实体提取难一个数量级。 如果您不应该期望命名实体链接的完美结果,那么您肯定可以预料到关系提取技术会出现一些错误。

我一直在寻找可用的生物医学关系提取模型,但没有发现任何开箱即用或不需要微调的模型。 关系提取领域似乎处于最前沿,希望我们将来会看到更多的关注。 不幸的是,我不是 NLP 专家,所以我避免微调我自己的模型。 相反,我们将使用基于论文的零样本关系提取器 探索 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

成果

图片由作者提供。

如前所述,我用来提取关系的 NLP 模型并不完美,而且由于我不是医生,我不知道它漏掉了多少连接。 但是,它检测到的那些似乎是合理的。

外部数据库扩充

正如我之前提到的,我们仍然可以使用 CHEBI 或 MESH 等外部数据库来丰富我们的图。 例如,我们的图表包含一个医学实体 大疱性表皮松解症 我们也知道它的 MeSH id。

您可以使用以下查询检索大疱性表皮松解症的 MeSH id:

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 端点获取信息来检索此信息。 然后,您可以请领域专家帮助您对这些信息进行建模。

从 MeSH REST 端点获取信息的 Cypher 查询是:

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 Manan Shah,SNAP 集团。图像可在 MIT 许可下使用 https://github.com/snap-stanford/cs224w-notes.

假设您构建了一个生物医学知识图谱,其中包含医学实体和概念、它们的关系以及来自各种医学数据库的丰富内容。 您可以使用节点嵌入技术来学习节点表示,它们是固定长度的向量,并将它们输入到您的机器学习工作流程中。 各种应用都在使用这种方法,从药物再利用到药物副作用或副作用预测。 我发现一篇研究论文使用 链接预测新疾病的潜在治疗方法[4]。

结论

生物医学领域是知识图谱适用的主要例子。 有许多应用程序,从简单的搜索引擎到更复杂的机器学习工作流程。 希望通过阅读这篇博文,您对如何使用生物医学知识图来支持您的应用程序提出了一些想法。 你可以开始一个 免费的 Neo4j 沙盒 并从今天开始探索。

与往常一样,代码可在 GitHub上.

参考资料

[1] D.金 .,“用于生物医学文本挖掘的神经命名实体识别和多类型规范化工具”,在 IEEE访问, 卷。 7, pp. 73729–73740, 2019, doi: 10.1109/ACCESS.2019.2920708。

[2] Kastrin A, Rindflesch TC, Hristovski D. MeSH 共现网络中的链接预测:初步结果。 螺柱健康技术通知。 2014;205:579–83。 PMID:25160252。

[3] Cetoli, A. (2020)。 探索 FewRel 的零射击极限。 在 第28届计算语言学国际会议论文集 (第 1447-1451 页)。 国际计算语言学委员会。

[4] Zhang, R.、Hristovski, D.、Schutte, D.、Kastrin, A.、Fiszman, M. 和 Kilicoglu, H. (2021)。 通过知识图完成对 COVID-19 的药物再利用. 生物医学信息学杂志,115,103696。

这篇文章最初发表于 走向数据科学 并在获得作者许可的情况下重新发布到TOPBOTS。

喜欢这篇文章吗? 注册以获取更多AI更新。

我们会在发布更多技术教育时通知您。

该职位 用 NLP 构建生物医学知识图谱 最早出现 热门.

时间戳记:

更多来自 热门