本文旨在介绍本体的基本概念和通用构建方法。
构建本体的原因主要有以下几点:
在本文中,本体指对某个领域内的概念的正式且详细的描述,其包括:
一个本体及其 classes 的实例集构成一个知识库。实际应用中,构建一个本体包括:
下面介绍一种可行的构建本体的方法。首先,需要强调本体构建中的三条基础准则:
我们首先应该定义本体的领域和范围,即回答下列的基本问题:
在确定了本体的基本范围后,一种确定本体具体范围的方法是,列出一系列本体应该能够回答的问题,这些问题被称为 competency questions,其专注于本体所涉及的领域,但也不用过于具体,我们将用这些问题来对已完成的本体进行测试,观察其是否能提供足够的信息。
在从头开始构建本体之前,最好先调研是否有相关的本体已经被构建出来了。我们可以基于这些本体进行进一步的改进和扩展。当前大部分本体都以电子形式提供,能够直接导入,可以方便地进行扩展。
写下我们想要展示的所有术语的列表是很有用的。一开始并不需要考虑术语之间的关系或概念重叠等问题,先保证列表的全面性。
接下来的两步是开发类层次结构以及定义概念属性。这两步是本体设计中最重要的步骤,也是联系紧密的两步,我们通常先在层次结构中创建一些概念,然后描述这些概念的属性。
定义类及其层次结构通常有以下几种方法:
上述三种方法没有优劣之分,取决于开发者对于领域的视角。不论使用哪种方法,我们都需要先定义类,再定义层次结构。先从第三步中的列表中选取能描述对象独特性的术语作为类,然后将这些类按层次结构组织。
如果一个类 A 是类 B 的父类,则每一个 B 的实例都是 A 的实例。
仅仅靠类无法提供足够的信息,我们还需要定义类的属性来进一步描述类
我们已经从第三步的列表中选择了术语来构建类,大部分剩余的术语都将是类的属性。
一般来说,属性可以分为以下几种:
所有的子类都会继承其父类的属性,属性应该被放置到最宽泛的类中(即越靠近顶层越好)。
类的属性有着许多限制(facets),如值的类型、允许的值、值的数量等。下面将介绍一些常见的 facets:
定义一个属性可以有多少个值。有些本体只区分单数或复数的基数,有些本体则进一步定义基数最大和最小值;
描述一个属性的值的类型,常见的类型有:
需要注意的是,Instance 类型用于表示个体之间的关系,需要定义允许的类的列表:
对于 Instance 类型的属性,其允许的类的列表被称为属性的范围(range),而一个属性所属的类被称为该属性的领域(domain)。领域一般不需要单独指定,在设置属性时通常默认被设置的类为该属性的领域。
决定一个属性的领域和范围的法则是类似的:
尽量保持类的宽泛性,但不要过于宽泛。
最后一步是创造类的具体实例,步骤如下
本节介绍在定义类及其层次结构中可能会出现的错误。虽然类的层次结构取决于具体的应用场景,但是存在一些通用的规则。
类 A 是类 B 的子类表示 A 为 B 的一种,两者之间是 is-a 关系。一个常见错误是将单数的类作为其复数的子类,两者间并不满足"一种"关系,在命名时可以统一单复数来避免这一错误。
等级关系具有传递性:
如果 B 是 A 的子类,C 是 B 的子类,那么 C 是 A 的子类。
距离一个类最近的子类称为直接子类。类层次结构不是一成不变的,可能随着时间的推移需要重构结构。
此外,还要注意区分类及其名称:
类表示的是一类概念,而不是表示这些概念的词语。
相同概念的近义词不应该被表示成多个类。很多系统允许为类关联近义词,如果不能,应该在类的文档中说明。
在构建类的层次结构时,还应该避免类的循环,即 A 是 B 的子类,同时 B 又是 A 的子类,这意味着 A 与 B 等价。
Siblings 指同一类的不同直接子类,它们应该处于同一层级下。
关于 siblings 的数量:一般在 2-12 个之间:
有时候,如果没有自然的中间类,那么可以保持原样(不需要人造类)。
一个类可以同时是多个类的子类,它会继承所有父类的属性和限制。
一般来说,如果子类包含超类所不具有的特征时,可以考虑创建,包括:
在实际应用中,子类通常具有新属性,或新的属性值,抑或新的属性限制。但是,有时即便子类没有上述特征,也应该创建,例如:
最后,我们不应该为每种额外的限制都构建子类,需要在创建有用的新类和创建过多的类中间保持平衡。
有时候,我们需要考虑是创建新的类还是将其用不同的属性值区分。一般来说,应该遵循如下原则:
一般我们常将数字、颜色、地点作为属性值。当然也存在例外情况,比如不同颜色的酒适合当作不同的类。
有时候,我们需要决定一个具体的概念是一个类还是单个实例。一般来说,应该遵循如下原则:
只有类之间存在层级结构,知识表示系统中没有子实例的概念,因此我们需要将这些概念表示为类,即使其不再具有直接实例。
Protege 允许用户建立抽象类:
下面给出一些判断本体是否完整的规则:
本体不要过于具体,也不要过于宽泛,一般最多定义一层额外的等级。例外,本体应该只保留最关键的属性,包含一些额外的关系信息会影响本体的使用,如一个生物学试验本体,不能将试验者看做生物体的子类,应该在文档中进行注明。
许多系统要求在构建本体时明确哪些类是分离(disjoint)的,即这些类不含有共同的实例。明确分离的类有助于验证本体的合法性。
一个属性的值可能会影响另外一个属性的值。例如制造者与制造的东西,两者之间相互关联,已知 A 是 B 的制造者,则可以推断出 A 制造了 B,这种关系称为转置关系。
虽然这种关系看上去有些冗余,但从知识获取的角度保留两者更加方便。定义了转置关系后,知识系统会根据一个值自动填充另一个:
大部分系统允许为属性指定默认值。如果一个类的大部分实例都具有相同的某个属性值,则我们可以将其设置为默认值。默认值可以在该属性的限制内改为任意值。
注意:要区分默认属性值与属性值,属性值一旦确定是无法更改的。如所有甜酒的糖度属性都为 SWEET,这并不是默认属性,不可修改。
在本体中,为命名制定规范有助于本体更加容易被理解,也可以避免一些建模错误。
在制定命名规范时,我们需要明确系统的特征,例如:
对于一个本体中的命名,保持同样的大小写习惯可以提升其可读性。通常将类名首字母大写,属性名首字母小写(如果系统大小写敏感)。
当一个概念名称包含超过一个单词,我们需要进行分割,下面给出一些可能的选择:
一般如果系统允许,建议使用空格。如果要和其他系统交互,还要考虑那些系统是否支持空格。
在命名中使用单复数没有好坏之分,只要保持前后一致即可,通常用单数。有的系统可能会提前要求确定单复数并不允许更改。
有些系统会使用前缀或后缀来区分类和属性,如 has-
或 -of
。这种方法可以快速区分出类和属性,只是名称会稍长。
不要在名称后再添加 class、property、slot 这样的字符串,一般从上下文中已经可以区分类和属性,如类名首字母大写,属性名首字母小写。
尽量避免在名称中使用缩略词。对于一个类的所有直接子类,其名称中关于是否包括超类的名称应该统一。
本文简单介绍了如何构建一个本体,最重要的信息是:任何领域都没有单一的正确本体。构建本体是一个创造性的过程,本体的质量只能通过实际应用来评价。