第4章 知识图谱生命周期:全流程拆解
药物知识图谱不是一次性建成的,它得走过六个关键阶段。我自己的团队在搭建药物靶点图谱时,这一步没走顺,后面全是坑。今天我把这六个阶段拆开讲,每个阶段有什么坑、有什么诀窍,都摊开来聊。
先看整体流程,我画了个图方便理解。
1. 知识获取——从源头捞数据
说白了,就是找到那些与药物相关的数据,把它们拿出来。数据源可杂了:论文、公开数据库(比如DrugBank、UniProt、CTD)、临床记录、专利、社交媒体……
我刚开始做的时候犯了错,以为爬下来就好。后来发现数据质量才是决定图谱上限的关键。举个例子,从PubMed摘出来的基因-疾病关系,很多是负样本(即某基因与疾病无关),如果不标记清楚,后面推理全乱套。
# 伪代码示意:从DrugBank提取药物-靶点关系
import requests
# 调用API获取XML数据,解析后存入中间表
# 注意过滤掉过期记录和撤回条目
2. 知识表示——给数据穿上衣服
你得到了原始数据,但机器看不懂。知识表示就是选一种形式让计算机理解。最主流的两种:RDF三元组和属性图。
我个人偏好属性图,因为药物数据经常需要附加很多属性(比如结合常数、副作用级别),用RDF的话声明会炸掉。不过也要看团队习惯。我有个朋友坚持RDF,后来他们用SPARQL确实在推理时很爽。
| 表示方式 | 典型技术 | 适合场景 |
|---|---|---|
| RDF三元组 | RDF/OWL, SPARQL | 开放互联、推理规则多 |
| 属性图 | Neo4j Cypher | 药物属性丰富、路径查询频繁 |
3. 知识融合——解决同名不同义
不同来源的数据,同一个实体可能叫法不一。比如“阿司匹林”在A库叫“Aspirin”,在B库叫“Acetylsalicylic acid”。实体对齐、实体消歧就是这阶段干的事。
我记得做药物重定位项目时,有两个数据库把“COX-2抑制剂”与“Celecoxib”的关系描述不同,一查才发现一个用的是药物机制分类,另一个用的是具体药物。不融合的话,图谱里会出现两个不同的Celecoxib。
常用方法:
- 基于字符串相似度(Levenshtein、Jaccard)
- 基于知识库的映射(利用外部标识符如ChEBI ID、PubChem CID)
- 基于嵌入的语义匹配
4. 知识存储——图谱住进仓库
图谱要持久化,不能每次都从CSV读吧。常用的存储引擎有RDF存储(比如Virtuoso、GraphDB)和图数据库(Neo4j、JanusGraph)。
我建议初创项目先用Neo4j,因为它可视化友好,调试方便。但注意,如果你的数据规模超过千万实体,索引和查询优化就得提前设计。我曾经因为忘了加索引,一个简单的邻居查询跑了30秒。
// Cypher示例:查询与“二甲双胍”有相互作用的药物
MATCH (d:Drug {name:'二甲双胍'})-[r:INTERACTS_WITH]->(d2:Drug)
RETURN d2.name, r.effect
5. 知识推理——让图谱自己长脑子
图谱里显式存储的是已知知识。推理就是利用规则、路径、嵌入等方法,推断出隐含的关系。比如“A药物抑制B靶点,B靶点激活C通路,那么A可能影响C通路”。
我在做药物副作用预测时,用了基于路径的推理:如果一个药物与一个蛋白有高亲和力,而该蛋白与某通路相关,那么该药的副作用可能波及该通路。结果发现不少FDA警告机制就是这么被发现的。
推理方法碎片:
- 基于规则(DL推理、SWRL)
- 基于图嵌入(TransE、RotatE)
- 基于图神经网络(R-GCN、CompGCN)
6. 知识应用——图谱真正产生价值
最后一步,把图谱集成到实际系统中:药物推荐、靶点发现、不良反应预警、智能问答等等。这一步往往最考验工程落地能力。
我参与过的一个智能决策系统,后端直接对接知识图谱API,前端医生输入药物名,系统通过推理返回禁忌症和替代方案。用户反馈查询速度是关键,所以我们专门做了缓存层预热热点。
典型应用形式:
- API/REST接口:后端接收查询,返回JSON结果
- 知识问答系统:自然语言转换为图查询
- 可视化仪表盘:用于药物研发分析师探索关系
# 简单的API查询示例(Flask)
@app.route('/drug_info')
def drug_info():
drug = request.args.get('name')
result = graph.run("MATCH (d:Drug {name: $name}) RETURN d", name=drug)
return jsonify(result.data())
整个流程走完一遍,你会发现它是个闭环。知识应用反馈的新需求会回到知识获取阶段。你想想看,没有一个项目是一次走完就永远不动的。这就是为什么我把生命周期画成一个循环而不是线性的原因。