2. 知识图谱基础:三元组、RDF、属性图、图数据库

知识图谱这东西,说到底就是把世界上的事物用“关系”串起来。你想想看,药物可以治疗疾病,药物有副作用,基因与疾病相关……这些关系放到一起,就是一个巨大的网络。我开始做药物重定位的时候,第一次接触知识图谱,当时就只有一个感受:这玩意儿太适合解决跨领域关联问题了。

但光有感受不行,得理解底层到底是怎么存的、怎么查的。这一节我就把四个核心概念串起来讲:三元组、RDF、属性图、图数据库。它们环环相扣,搞懂了,后面做特征分析才有底气。

2.1 三元组:知识图谱的最小单元

知识图谱里最基础的存储单元就是三元组。格式极其简单:

(主体, 关系, 客体)

说白了就是“主语-谓语-宾语”那一套。举个例子:

(二甲双胍, 治疗, 2型糖尿病)

这就代表“二甲双胍”这个药,有关系“治疗”,指向“2型糖尿病”。

我在项目里整理数据时,经常会碰到主体和客体都是药物的情况,比如:

(阿司匹林, 相互作用, 华法林)

这种二元关系用三元组存起来,机器就能直接理解。你想想看,如果我们把几万、几百万条这样的三元组拼到一起,是不是就是一个知识网络?

核心要点:三元组是图的边(关系),而主体和客体就是图的节点。每一个三元组就是一条有向边。

2.2 RDF:让三元组有了标准

有了三元组还不够,不同系统之间怎么交换数据?这时候RDF(Resource Description Framework)就站出来了。它是W3C定的一套标准,给每个实体一个全局唯一的URI,这样大家引用的资源就不会混淆。

举个例子,用Turtle格式写一个RDF三元组:

<http://example.org/drug/metformin>
    <http://example.org/predicate/treats>
    <http://example.org/disease/type2diabetes> .

看着挺啰嗦的,对吧?但好处是全局唯一,我当年对接外部数据源时,就靠URI避免了无数“同名不同义”的坑。

RDF还有几种常见的序列化格式:

格式 特点 常见场景
Turtle(.ttl) 简洁, 可读性好 手动编辑、小规模数据
RDF/XML 标准交换格式 企业系统、语义网工具
JSON-LD 与JSON兼容 Web API、前端集成
N-Triples 每行一个三元组,最朴素 大数据批量导入

我的经验:在药物重定位项目里,我优先用Turtle写原型,因为可以手工调。等数据量到百万级,改成N-Triples用RDF4J批量导入,性能差很多。

2.3 属性图:更贴近开发者的视角

RDF虽然标准,但有些场景用着别扭。比如要给一个药物节点加上“分子量”、“半衰期”这些属性,RDF里得拆成多个三元组,维护起来有点繁琐。这时候属性图模型就出现了。

属性图的核心思想很简单:节点和关系都可以带属性(键值对)。比如一个药物节点:

Node: Drug_Metformin
  Properties:
    name: "二甲双胍"
    molecular_weight: 129.16
    half_life: 6.2  // 单位小时

关系也可以带属性,比如“治疗”关系可以写上“证据等级:A级”。这一点我在做知识图谱特征工程时特别有用——可以直接把属性作为特征喂给模型。

比较一下RDF和属性图:

维度 RDF 属性图
节点标识 IRI(全局URI) 本地ID(可全局)
关系表达 三元组边 命名关系(可带属性)
属性存储 拆成多个三元组 键值对直接挂在节点/边上
查询语言 SPARQL Cypher、Gremlin
主要用途 语义网、数据交换 图数据库、知识图谱应用

避坑:我曾经在同一个项目里同时用RDF和属性图存储同一份数据,结果发现对齐实体成本极高。新项目我建议只选一种模型。如果数据需要频繁与外部交换,选RDF;如果主要是内部查询和推理,属性图更顺手。

2.4 图数据库:把图存下来、查出来

有了图模型,总得有个地方存吧?图数据库就是专门干这个的。它针对图的遍历(比如从某个药物出发,沿“治疗”关系找到所有疾病)做了深度优化,比你用关系数据库的JOIN快得多。

常见的图数据库:

  • Neo4j:属性图数据库的标杆,查询语言Cypher。社区活跃,文档齐全。我自己最开始就是从Neo4j入门的。
  • JanusGraph:支持大规模分布式图,底层用Cassandra或HBase。适合超大数据量。
  • Virtuoso / RDF4J:专为RDF设计,支持SPARQL。适合语义网场景。

举个例子,用Cypher查询“二甲双胍治疗的所有疾病”:

MATCH (drug:Drug {name: '二甲双胍'})-[r:TREATS]->(disease:Disease)
RETURN disease.name, r.evidence_level

用SPARQL查同样的东西:

PREFIX drug: <http://example.org/drug/>
SELECT ?disease ?level WHERE {
  drug:metformin drug:treats ?disease .
  OPTIONAL { ?disease drug:evidenceLevel ?level . }
}

个人建议:做药物重定位项目,前期数据量不超过千万级,Neo4j + Cypher是最快上手的选择。等需要跨机构数据交换时,再考虑RDF + SPARQL。

2.5 知识图谱基础框架图

下面这张SVG图把从三元组到图数据库的整体关系画出来了。你一看就明白它们之间怎么衔接的。

知识图谱基础要素关系图 三元组 (主体, 关系, 客体) RDF 标准 W3C,全局URI 属性图 节点/边带属性 RDF 序列化格式 Turtle, RDF/XML JSON-LD, N-Triples 属性图存储 Neo4j (Cypher) JanusGraph (Gremlin) 图数据库 Neo4j / JanusGraph / Virtuoso 说明:三元组是基础;RDF定义了全局标准,属性图更贴近应用;图数据库负责持久化与查询。

2.6 小结

这几个概念一开始可能觉得有些抽象,但实际用起来没想象中复杂。说白了,三元组就是积木块,RDF和属性图是两种搭建方式,图数据库就是搭好之后的乐高底板。我做药物重定位的第一步,就是把公开数据库(DrugBank、DisGeNET)转换成这些图结构,然后才能做特征分析。

记住一句话:选对模型,事半功倍。数据需要广泛交换?用RDF。需要快速查询和属性扩展?用属性图。

我的建议:刚开始学的时候,先动手建一个小型知识图谱(比如100个三元组),用Neo4j Desktop跑一遍Cypher。亲手操作比看十遍书都管用。