3. 知识图谱构建流程:数据抽取、实体识别、关系抽取、知识融合
做靶点知识图谱,最核心的就是怎么把散落在论文、数据库、临床报告里的信息抓出来,再变成结构化的三元组。你可能会想,这事听起来不就是“爬虫+规则”嘛?其实远没那么简单。我做过几个靶点项目,踩过不少坑,今天就把这四步拆开讲透。
先说整体流程。说白了就是四步接力:数据抽取 → 实体识别 → 关系抽取 → 知识融合。每一步都会影响后面的质量,哪个环节偷懒,图就长歪了。
3.1 数据抽取 —— 从哪来,怎么取
数据抽取是地基。我的习惯是先列数据源清单,按结构化程度分三类:
| 数据源类型 | 示例 | 抽取方式 | 注意点 |
|---|---|---|---|
| 结构化数据库 | DrugBank、UniProt | SQL/API直接导出 | 权限与版本管理 |
| 半结构化文档 | PubMed XML、JSON-LD | XPath/JSON解析 | 字段嵌套复杂 |
| 非结构化文本 | 论文全文、专利 | NLP管道(PDF解析+文本清洗) | PDF表格提取是老大难 |
我曾在项目里遇到一个坑:从PubMed Central下载的全文XML,有的段落里嵌着<table-wrap>标签,里面的药物-靶点关系直接丢在表格里。如果你只用常规文本抽取,这些信息就漏了。所以我后来加了一个专门的表格提取模块,用pdfplumber+正则把行数据还原。
3.2 实体识别 —— 把名字捡出来
实体识别是NER(Named Entity Recognition)的任务。对靶点领域来说,实体类型主要是:基因、蛋白质、疾病、药物、通路、表型。我推荐先用BioBERT等预训练模型微调,再配合词典回退。
下面是我常用的一个NER推理代码示例(基于HuggingFace):
from transformers import pipeline
ner_pipeline = pipeline(
"token-classification",
model="dmis-lab/biobert-base-cased-v1.1",
aggregation_strategy="simple"
)
text = "BRAF V600E mutation activates MAPK signaling in melanoma."
result = ner_pipeline(text)
for ent in result:
print(f"{ent['word']} -> {ent['entity_group']} (score={ent['score']:.3f})")
# 输出类似:
# BRAF -> Gene (score=0.997)
# MAPK -> Pathway (score=0.982)
# melanoma -> Disease (score=0.991
实体识别的输出格式一般做成JSON Lines,每一行一个文档,包含实体列表和位置。
3.3 关系抽取 —— 谁和谁有什么关系
有了实体,接下来要连接它们。关系抽取分两种路子:
- 基于规则+模板:写正则或依存句法模式。比如“XXX inhibits YYY” -> 关系=抑制。优点是可控、可解释;缺点是泛化差,每加一个关系就要写一套模板。
- 基于深度学习:用BERT-based关系分类模型,把实体对+上下文输入,输出关系类型。我用的是
BioBERT-large在BioRel数据集上调优。
我个人经验是:先做规则打底,再用模型召回。原因很简单——靶点关系数量有限(抑制、激活、结合、磷酸化等),规则能覆盖80%的显式关系,模型用来补全那些绕弯子的表达。比如“通过激活PI3K/AKT通路,促进了肿瘤细胞增殖”——这里面“促进了”是个因果关系的表达,规则很难抓,但模型能学。
实际项目中的选择建议:
- 对于固定短语(“binds to”、“interacts with”):用正则足够
- 对于复杂长句:用BioBERT关系分类模型(注意:此处无链接,仅为示例)
- 做好冲突处理:同一对实体在不同句子中关系冲突时,记录置信度,让融合阶段裁决
3.4 知识融合 —— 把碎片拼成一张图
这一步是知识图谱的“合并同类项”。从多个数据源来的实体,可能指代同一个真实世界对象。比如“p53”、“TP53”、“肿瘤蛋白53”都是同一个基因。不做融合,图谱里就会有一堆孤立节点。
融合核心操作:
- 实体对齐:使用字符串相似度(编辑距离、Jaro-Winkler) + 外部词典(UniProt ID→HGNC symbol)
- 指代消解:处理“it”、“该蛋白”等代词,需要在关系抽取时保留上下文
- 冲突消解:同一个关系在不同来源中给出矛盾信息(例如文献A说“抑制”,文献B说“激活”),我们通常保留高频或高权威源,并附加证据链接
我负责过的一个靶点图谱项目,从DrugBank、DisGeNET、STRING三个源整合,最初实体数量超过300万,经过融合后压缩到97万,减少了三分之二冗余。这里最关键的一步是标准化ID映射。下面是一个简单的ID映射表结构设计:
-- 示例:映射表 schema (SQLite)
CREATE TABLE entity_mapping (
local_id TEXT PRIMARY KEY,
source_db TEXT,
source_id TEXT,
unified_id TEXT,
entity_type TEXT,
synonym_list TEXT
);
-- 统一ID生成规则:entityType:source:sourceId
-- 例如 "Gene:UniProt:P04637" -> 统一ID "Gene:TP53"
有了映射表,后面的图谱构建就好做了——直接通过unified_id关联三元组。
我常用的融合验证方法:随机抽取100条对齐候选,人工检查。如果准确率低于95%,就退回调整阈值或补充词典。别信模型输出的概率,尤其当两个实体名称差异很小时。
3.5 回看整个流程:迭代大于一次成型
你可能会问,这四步做完一次就完了?我负责任地告诉你:不可能。知识图谱构建是一个迭代循环。我在第一个靶点图谱项目里,第一版做完实体识别,发现大量“基因-药物”关系没抽出来,原因是关系抽取模型在训练时缺少“regulation”这类宽泛关系的样本。后来我回去补充了1000条标注数据,重新训练,覆盖率才上来。
所以我的建议是:先做最小可用版本,跑通四步流程,再针对痛点局部优化。没必要一开始就追求95%以上的准确率,60%能用,就能帮你发现很多上游问题。