第3章 · 三元组、RDF、属性图模型
聊知识图谱,绕不开三个词:三元组、RDF、属性图。
很多人觉得它们是同一回事,或者认为RDF就是知识图谱的全部。其实不是。我一开始做药物靶点项目时也被绕晕过,用RDF搭了一个多月才发现有些场景根本不适合。嗯,先别急,我们一个一个拆开看。
3.1 三元组:知识图谱的“原子”
知识图谱最底层的单元就是三元组。说白了,就是三样东西拼在一起,表达一个事实。
- 主语(Subject) —— 你要描述的对象,比如“阿司匹林”
- 谓语(Predicate) —— 对象之间的关系或属性,比如“靶向”
- 宾语(Object) —— 关系的另一端,可以是实体或者值,比如“COX1”
举个例子:
<阿司匹林> <靶向> <COX1>
<COX1> <所属通路> <花生四烯酸代谢通路>
这样一条一条串起来,就构成了一张网。我在做药物重定位项目时,早期从公开数据库抽出来的三元组就超过2000万条——但你必须先保证每一条都正确,否则后面推理会崩。
3.2 RDF:标准化了三元组的写法
RDF全称Resource Description Framework,是W3C制定的标准。它没发明新东西,只是给三元组分了名词:用IRI(国际资源标识符)来来标识节点和关系,避免重名。
比如“COX1”可能出现在不同数据库里。RDF要求你写成完整IRI:
<http://dbpedia.org/resource/COX1> <http://example.org/targets> <http://dbpedia.org/resource/Aspirin>
看着挺啰嗦,但好处是全局唯一,不会搞混。RDF有多种序列化格式,我最常用Turtle,因为它可读性最好:
@prefix drug: <http://example.org/drug/> .
@prefix target: <http://example.org/target/> .
drug:Aspirin drug:targets target:COX1 .
target:COX1 rdf:type drug:Protein .
有个坑我踩过——RDF的rdf:type默认是rdfs:Class,但很多工具对owl:Class也支持,不统一的话推理会报错。所以你构建本体前缀时一定要检查OWL profile。
3.3 属性图模型:更懂“程序员”的表达
属性图模型(Property Graph Model)是另一个流派,Neo4j、JanusGraph、ArangoDB都用它。它跟RDF最大的区别是什么?
节点和关系都可以带键值对属性。
比如一个药物节点,我能在同一结构里直接写上它的分子量、CAS号、SMILES;一条靶向关系,我也可以带上结合亲和力IC50值。在RDF里你得为每个属性再写一个三元组,关联关系会变得很瘦长。
举个例子(JSON风格表示属性图):
节点: {id: "阿司匹林", label: "Drug", properties: {smiles: "CC(=O)OC1=CC=CC=C1C(=O)O", mw: 180.16}}
边: {from: "阿司匹林", to: "COX1", label: "targets", properties: {ic50: 0.5, assay: "in vitro"}}
看到没?所有信息集中在一条记录里,查询起来路径短。我个人在工程实践中更倾向属性图做OLTP系统,RDF做数据交换和推理。
3.4 RDF vs 属性图:一个表看清楚
| 维度 | RDF(三元组模型) | 属性图模型 |
|---|---|---|
| 基本单元 | 主体-谓词-客体(每行一个事实) | 节点 + 关系(可带属性) |
| 标识方式 | IRI(全局唯一) | 内部ID(通常自动生成) |
| 属性存储 | 需要额外三元组,产生大量中间节点 | 直接挂在节点或关系上 |
| 推理支持 | 强(RDFS/OWL规则引擎) | 弱(需要应用层实现) |
| 查询语言 | SPARQL | Cypher / Gremlin / GraphQL |
| 典型用途 | 知识图谱集成、开放数据、本体推理 | 实时图分析、社交网络、推荐系统 |
我曾经有一个项目,客户坚持用RDF存所有药物-靶点-通路数据,结果查询“找到靶向BRCA1且在乳腺癌中过表达的所有药物”需要十几跳,SPARQL写完人都傻了。后来切到属性图,同样的意图一条Cypher搞定。
3.5 一张图理解三者关系
下面的SVG把三元组、RDF、属性图的核心关系画出来了。你可以看到三元组是底层事实表达,RDF给三元组穿上标准化外衣,属性图则是另一种更“胖”但更灵活的结构。
3.6 到底怎么选?
如果你正在搭一个药物靶点知识图谱,我建议你按这个流程思考:
- 是否需要跨本体推理?(比如根据靶点家族预测新靶点)——选RDF。
- 你的数据源是不是各种异构格式?(CSV, XML, API, Excel)——RDF有标准映射工具。
- 用户是否主要做图遍历和属性过滤?(比如“找分子量<500且IC50<10nM的化合物”)——属性图更爽。
- 团队熟悉SQL还是SPARQL? 属性图的Cypher对SQL背景更友好。
讲到这儿,我想再提一个例子:我们在构建药物-副作用知识图谱时,原始数据来自SIDER数据库,每个副作用关联频率、占比、类型。如果用纯RDF,每个副作用-药物对要写5~6条三元组,数据量翻五倍。后来我把频率和占比作为属性塞到关系里,用属性图单条搞定,查询速度提升了20倍。当然,共享给外部合作方时,我们还是转成了RDF Turtle格式——因为对方只接受标准RDF。
所以,别把模型当信仰,它们是工具。选最合适的,存活的才久。