2. 知识图谱基础:三元组、实体、关系与语义网络

说起知识图谱,很多人第一反应是Google那个搜索框下面的知识卡片。其实说白了,知识图谱就是一种用图结构来组织知识的技术。它的核心,就是三元组。

我刚开始接触这个领域的时候,总觉得"三元组"这名字挺唬人。后来才发现,它就是我们日常说话里最自然的单位——谁,干了什么,对谁。比如"阿司匹林抑制COX-2酶",去掉那些修饰,留下来的骨架就是阿司匹林、抑制、COX-2酶。就这么简单。

2.1 实体与关系:图的节点和边

先说说实体。实体就是知识图谱里的"节点",可以是一个具体的药物、一个蛋白质、一个疾病,甚至一个抽象的术语。在药物靶点发现里,我常用的实体类型包括:

  • 药物 (Drug) — 比如伊马替尼、阿司匹林
  • 靶点 (Target) — 比如EGFR、COX-2
  • 疾病 (Disease) — 比如肺癌、类风湿关节炎
  • 基因 (Gene) — 比如ABL1、PTGS2
  • 通路 (Pathway) — 比如JAK-STAT信号通路

关系就是连接这些实体的"边"。关系的类型决定了知识图谱能表达什么。给你看一个简单的对比:

关系类型例子说明
抑制伊马替尼 抑制 ABL1药物对靶点的抑制作用
激活EGF 激活 EGFR配体-受体激活
治疗伊马替尼 治疗 CML药物对症的疾病
相互作用EGFR 相互作用 STAT3蛋白-蛋白相互作用

看到没?就是这三元组模板。我以前做过一个项目,要把PubMed里20万篇文献的关系抽出来,结果发现最头疼的不是抽关系本身,而是怎么统一关系类型。比如"抑制"和"下调",很多文献混着用,你不规范化,后面推理全是错的。嗯,这里要注意——关系类型一定要提前定义好一个可控的词汇表。我当时就是吃了这个亏,后来重写了整个映射逻辑。

2.2 三元组:知识的原子单位

三元组的通用形式是 (主语, 谓语, 宾语),在RDF标准里叫 (主体, 属性, 客体)。在知识图谱里,主语和宾语都是实体,谓语就是关系。

举个例子:

(阿司匹林, 抑制, PTGS2)
(PTGS2, 参与, 前列腺素合成通路)
(前列腺素合成通路, 关联疾病, 疼痛)

这三条三元组连起来,就能回答"阿司匹林为什么能镇痛"这种问题。说白了,知识图谱就是靠这种链式推理来发现新知识的。

你可能会问:那一个三元组能表示复杂关系吗?比如"伊马替尼治疗慢性粒细胞白血病",其中"慢性粒细胞白血病"是一个疾病,但可能还有更细的亚型。这时候我们可以引入URI来唯一标识每个实体,避免歧义。RDF标准里每个实体都用IRI来表示:

<http://example.org/drug/imatinib> 
  <http://example.org/relation/treats> 
  <http://example.org/disease/cml> .

我不建议你在项目早期就把IRI设计得太复杂。先拿短名字跑起来,等数据量上去了再标准化。我吃过那种"一上来就搞本体设计"的亏——纠结了一个月的IRI层级,最后业务需求一变,全废了。

2.3 语义网络:从三元组到图

三元组本身是离散的,但把它们放在一起,就形成了一张语义网络。网络中的每个实体连出来的边,构成了它的语义上下文。

想象一下,我们有三个实体:阿司匹林、布洛芬、COX-2。如果三元组是:

(阿司匹林, 抑制, COX-2)
(布洛芬, 抑制, COX-2)
(COX-2, 参与, 炎症反应)

那么这张小图里,阿司匹林和布洛芬就通过COX-2建立了间接联系。在做药物重定位时,我们经常利用这种模式——如果药物A和药物B共享了同一个靶点或通路,它们可能具有相似的适应症。我做过一个案例:用这个逻辑从已经上市的药里找到了几个老药的新用途,其中一个后来还进了临床前验证。

绘制整个知识图谱的结构,可以帮我们直观理解实体之间的连通性。下面这张图展示了药物-靶点-通路-疾病的核心连接模式:

知识图谱核心结构:三元组构成的语义网络 药物(Drug) 靶点(Target) 通路(Pathway) 疾病(Disease) 抑制 参与 关联 调节 💡 每个三元组都是一条有向边,组合起来就能查询和推理。 例如: 药物抑制靶点 → 靶点参与通路 → 通路关联疾病 → 发现新药适应症

在构建语义网络时,有几个基本原则我建议你记住:

  • 一致的关系方向 — 比如"抑制"和"被抑制"不要混用,统一从主体指向客体。
  • 实体去重 — 同一个药物可能在不同数据库里叫不同的名字,要用唯一ID对齐。我当时用的UniProt ID和DrugBank ID做锚点。
  • 稀疏性处理 — 真实知识图谱里很多实体只有一两条边,推理时需要借助路径传播信号。图神经网络就是干这事的。

2.4 三元组存储与查询

手工写三元组文本还行,数据量一大就必须上专业的图数据库。常见的存储方案有:

  • RDF三元组库 — 如Apache Jena、Virtuoso,支持SPARQL查询。
  • 属性图 — 如Neo4j,用Cypher查询,节点和边都可以带属性。
  • 关系型数据库 — 最简单的就是用一张三列的表来存,但查询性能差。

我个人习惯在项目早期用CSV或者JSON存三元组,方便迭代。等确定了Schema再迁移到图数据库。下面是一个简单的JSON格式示例:

[
  {"subject": "imatinib", "predicate": "inhibits", "object": "ABL1"},
  {"subject": "ABL1",      "predicate": "involved_in", "object": "cell_proliferation"},
  {"subject": "imatinib", "predicate": "treats", "object": "CML"}
]

这种格式的好处是容易解析,也容易用Python转成各种图结构的输入。我写过一个脚本,直接从PubMed挖掘出来的三元组转成这个JSON,然后再喂给图神经网络训练。

⚠️ 避坑提醒: 我曾在构建三元组时踩过一个坑——关系类型命名不规范。比如"inhibits"和"negative_regulation"其实是同一个意思,但两个不同的数据源用了不同的标签。最后联合查询时,明明有路径却查不出来。建议一开始就定好关系词汇表,并记录映射关系。
💡 实用技巧: 如果你在三元组里需要表达权重或置信度,可以考虑给关系加上属性。比如“抑制”关系可以带一个confidence: 0.95的字段,这样在后续特征学习时可以过滤低质量的边。

2.5 小结:从三元组到知识图谱特征学习

总结一下,知识图谱的基础就是三元组。实体是节点,关系是边,整个图就是一个语义网络。在这个网络上,我们可以做路径分析、子图匹配,甚至用图神经网络(GNN)学出每个节点的向量表示,用于药物靶点预测。