知识表示基础:RDF、RDFS、OWL、属性图模型与三元组

说到知识图谱,最绕不开的就是「怎么把知识装进去」。我刚开始接触这个领域时,也被一堆缩写搞得晕头转向——RDF、RDFS、OWL…… 后来花了很长时间才理清它们之间的关系。说白了,这些就是一套「给世界万物编字典」的规则。

实体 - 关系 - 属性三元组:最小知识单元

先看最基础的。知识图谱里,最小的知识单元就是一个三元组:

  • 实体(Subject)—— 你要描述的那个东西
  • 关系(Predicate)—— 连接两个实体的那条线
  • 实体/属性值(Object)—— 关系的另一端,可以是另一个实体,也可以是具体的值

举个我项目里的例子:描述“张三是某公司的员工”。三元组就是:

张三 -- 就职于 -- 某公司

这里“张三”和“某公司”是实体,“就职于”是关系。如果我想表达“张三的年龄是35岁”,三元组变成:

张三 -- 年龄 -- "35"

注意,这里的“35”是个字面量(属性值),不是实体。这就是实体 - 关系 - 属性三元组的基本套路。

避坑指南:我曾经在设计时把属性值也当作实体节点来处理,结果图变得无比臃肿。后来才发现,对于数值、日期这类标量属性,直接作为字面量挂在实体上就够了,别单独建节点。

RDF:资源描述框架

RDF(Resource Description Framework)是 W3C 搞出来的标准,用来表达三元组。它规定了三元组的序列化格式,比如 Turtle、XML、N-Triples 等。你看这个 Turtle 例子:

@prefix ex: <http://example.org/> .
ex:张三 ex:就职于 ex:某公司 .
ex:张三 ex:年龄 "35"^^xsd:integer .

每个三元组用句点结束,前缀用于缩短 URI。RDF 的核心思想是「万物皆资源,用 URI 命名」。我刚开始写 RDF 时老忘记加前缀,结果 URI 写满了整行,像个怪物。

但 RDF 有个局限——它不限制你用什么关系,也不定义实体类型。比如你可以写:

ex:张三 ex:是 ex:人类 .
ex:张三 ex:是 ex:超能力者 .

系统并不知道“人类”和“超能力者”是什么,也不会阻止你犯逻辑错误。这时候就需要 RDFS 或 OWL 来加约束了。

RDFS:加一层「类的谱系」

RDFS(RDF Schema)就像是给 RDF 加了一个「概念说明书」。它允许你定义类(Class)和属性(Property)的层级关系。比如:

ex:人类 rdf:type rdfs:Class .
ex:程序员 rdfs:subClassOf ex:人类 .
ex:年龄 rdf:type rdf:Property .
ex:年龄 rdfs:domain ex:人类 .
ex:年龄 rdfs:range xsd:integer .

这样系统就知道:程序员是人类的子类,年龄这个属性的定义域是人类,值域是整数。我遇到过一个坑:团队里有人把年龄的关系用在公司节点上,结果推理器报了错,就是因为没加 domain 约束。RDFS 能帮你做基础的推理,比如:如果“张三 is a 程序员”,而“程序员 is a 人类”,那么系统可以推断出“张三 is a 人类”。

一句话记住:RDF 只负责「写出来」,RDFS 负责「怎么组织这些概念」。

OWL:更强大的推理武器

OWL(Web Ontology Language)在 RDFS 基础上又升级了。它能表达更复杂的逻辑关系,比如:

  • 等价关系:ex:父亲 owl:equivalentClass ex:爸爸
  • 互斥关系:ex:男人 owl:disjointWith ex:女人
  • 属性特征:ex:配偶 rdf:type owl:TransitiveProperty(表示传递性)
  • 数量约束:ex:人类 owl:minCardinality "1"^^xsd:integer ; owl:onProperty ex:母亲

举个例子,你可以在 OWL 中定义:

ex:人类 owl:disjointWith ex:非生物 .
ex:人类 rdfs:subClassOf [
    rdf:type owl:Restriction ;
    owl:onProperty ex:母亲 ;
    owl:minCardinality 1
] .

这样推理器就能检查出:如果某个实体同时被标记为“人类”和“非生物”,那就出错了。我在做一个医疗知识图谱时,用 OWL 定义了药物的禁忌症互斥关系,确实省去了很多手工校验的工作。

但 OWL 也有代价——计算复杂度高,大规模数据里跑推理可能很慢。一般我会根据场景选 OWL 的子语言,比如 OWL 2 RL 或 EL,它们能在可接受的时间内完成推理。

属性图模型(Neo4j):更自由的图数据库

说完 RDF 家族,再来看另一种主流模型——属性图模型。Neo4j 就是典型代表。它不搞三元组那一套,而是用节点 + 关系 + 属性来建模:

  • 节点:可以带标签(Label),比如 Person、Company
  • 关系:有方向、有类型,比如 [就职于],还可以带属性
  • 属性:K-V 对,挂在节点或关系上

在 Neo4j 里,上面的例子用 Cypher 写就是:

CREATE (:Person {name: '张三', age: 35})
       -[:就职于 {入职年份: 2019}]->(:Company {name: '某公司'})

你会发现,属性图模型把属性直接内嵌到节点和关系里,不用再单独建立字面量节点。这在某些场景下查询更快。我做过一个实时推荐系统,用属性图模型比用纯 RDF 存储效率高很多,因为属性图可以快速沿着关系遍历。

但属性图模型也有弱点——它不支持 RDFS/OWL 级别的推理。如果你想自动推断出“张三 is 人类”,需要在应用里自己实现推理逻辑。所以我的经验是:

选型建议:如果你主要做推理、数据交换、开放知识图谱,选 RDF/OWL;如果你主要做图遍历、路径分析、实时查询,选属性图模型。

核心对比:一张表说清楚

为了方便对比,我把这几种表示方式整理成表格:

模型 核心单元 推理能力 典型工具 适合场景
三元组(基础) (实体, 关系, 实体/属性值) 无 任意 数据采集、初步存储
RDF 三元组 + URI 无 Jena, RDF4J 统一表示、数据交换
RDFS 类 + 属性层级 类层次推理 Jena, Protege 概念建模、简单约束
OWL 公理 + 约束 强推理 Pellet, HermiT 复杂领域、一致性校验
属性图模型 节点 + 关系 + 属性 无(需自定义) Neo4j, JanusGraph 图遍历、性能敏感场景

完整知识体系结构图

下面这张 SVG 图展示了本章的知识体系:从基础三元组出发,分别走向 RDF 体系(RDF→RDFS→OWL)和属性图体系,以及它们在关联校验中的角色。

知识表示基础体系结构 实体-关系-属性三元组 RDF(资源描述框架) RDFS(模式层) OWL(本体语言) 属性图模型 Neo4j 实现 图遍历+查询 知识表示是关联校验的基础,不同模型影响校验方法 左:语义推理型(RDF体系) vs 右:图遍历型(属性图体系)
重点:三元组是基础,RDF 是序列化标准,RDFS/OWL 是推理层,属性图是另一条路径。在关联校验课程中,我们主要用 RDF/OWL 做一致性检查,用属性图做结构探查。两者各有千秋,别混着用。

小结与实战准备

好了,这一章我把知识表示的核心概念过了一遍。你可能会问:这些跟我做关联校验有什么关系?嗯,关系很大。前面提到的 RDFS 和 OWL 推理能力,正是我们后面做规则校验、冲突检测时的底层引擎。而属性图模型则是我们做路径分析和模式匹配时的利剑。

警告:不要在一开始就把所有模型都套在一起。我见过一个项目,既用 RDF 存储又用 Neo4j 索引,还试图手动双向同步,最终数据不一致导致校验全废。选定一条主路,另一条做辅助查询就够了。