知识表示与推理
关键词
| 序号 | 关键词 | 英文对照 |
|---|---|---|
| 1 | 知识表示 | Knowledge Representation |
| 2 | 框架理论 | Frame Theory |
| 3 | 描述逻辑 | Description Logic |
| 4 | 本体论 | Ontology |
| 5 | OWL | Web Ontology Language |
| 6 | 马尔可夫逻辑网络 | Markov Logic Network |
| 7 | 一阶谓词逻辑 | First-Order Predicate Logic |
| 8 | 概念包含 | Concept Subsumption |
| 9 | TBox与ABox | Terminological and Assertional Box |
| 10 | 概率推理 | Probabilistic Reasoning |
| 11 | 不确定性 | Uncertainty |
| 12 | 知识图谱 | Knowledge Graph |
一、知识表示入门:如何让计算机”知道”世界?
1.1 什么是知识表示?
你可能听说过”人工智能”,但有没有想过一个问题:AI系统到底是怎么”知道”东西的?
人类从小就知道”鸟会飞”、“水往低处流”这些常识。我们不需要刻意去背,大脑会自动组织这些知识。但计算机不一样——它本质上就是一个能快速做计算的机器,你需要用一种它能”理解”的方式告诉它什么是鸟、什么是飞、水为什么会往下流。这就是知识表示(Knowledge Representation)要做的事情。
简单来说,知识表示就是把人类脑子里的知识翻译成计算机能处理的形式。这个过程听起来简单,做起来其实非常难。因为人类的知识太灵活了,有显性的、有隐性的,有确定的、也有模糊的。怎么把这些东西装进计算机里,让它能够像人一样推理和学习,这个课题已经困扰了AI研究者们几十年。
知识表示的研究最早可以追溯到1950年代的逻辑推理系统。那时候的人们天真地以为,只要把所有数学定理用形式化的逻辑符号写出来,计算机就能自动证明一切数学问题。结果发现,这条路走不通——不是因为计算机太笨,而是因为知识本身太复杂,逻辑只是冰山一角。
后来到了1970年代,AI研究者们开始意识到,知识不能光靠逻辑公式来表达,还需要考虑常识、默认假设、上下文依赖这些人类习以为常但机器完全无法理解的东西。于是框架理论、本体论、语义网络这些方法陆续被提出来,知识表示这个领域才慢慢变得丰满起来。
1.2 知识的三种基本类型
在说具体的表示方法之前,我们先来看看知识本身有哪些类型。这个分类很重要,因为不同的知识类型需要用不同的方法来表示。
第一种是概念性知识(Conceptual Knowledge),就是那些定义性的东西。比如”什么是哺乳动物”、“什么是三角形”。这类知识告诉你某个概念的内涵和外延。
第二种是事实性知识(Factual Knowledge),就是具体的事实。比如”北京是中国的首都”、“水的沸点是100摄氏度”。这类知识是关于这个世界具体状态的描述。
第三种是过程性知识(Procedural Knowledge),就是”怎么做”的知识。比如”怎么骑自行车”、“怎么做一道菜”。这类知识不是静态的描述,而是一系列操作的步骤。
举个例子你就明白了。假设我们要让AI系统理解”会诊诊”这个医学场景:
- 概念性知识:“会诊”是指多个医生一起讨论病例、共同制定诊疗方案的过程
- 事实性知识:张医生今天下午2点在3号诊室会诊
- 过程性知识:会诊的流程是先由主治医生介绍病情,然后各科医生发表意见,最后综合讨论确定方案
这三种知识缺一不可,但表示起来各有各的难点。概念性知识需要清晰的定义和边界,事实性知识需要高效地存储和查询,过程性知识需要把隐性的操作步骤显性化。
1.3 知识表示的核心挑战
为什么知识表示这么难?主要有以下几个原因:
知识的模糊性。很多我们习以为常的概念其实没有清晰的边界。什么叫”高个子”?1米8算不算高?在不同语境下答案完全不同。计算机需要精确的判断,但现实世界充满了模糊地带。
知识的隐含性。很多知识是”只可意会不可言传”的。比如你能一眼认出这是一只猫,但让你解释你是怎么认出来的,你可能说不出具体规则。这种隐性知识很难被形式化。
知识的动态性。知识不是一成不变的。新发现、新概念不断涌现,旧知识可能被更新甚至推翻。系统需要能够处理知识的演变。
知识的矛盾性。同一个问题可能存在多种解释,甚至相互矛盾的知识体系。怎么处理这种冲突是个大难题。
理解这些挑战,你就能明白为什么知识表示领域会有那么多种不同的方法——每种方法都是对某个特定问题的回应,没有一种方法能包打天下。
二、知识表示的核心方法概览
在深入细节之前,我们先来鸟瞰一下知识表示的几种主要方法:
逻辑表示是最传统的方法,用命题逻辑、一阶谓词逻辑等形式化系统来表示知识。优点是表达精确、推理严密;缺点是太死板,处理不了模糊和不确定的情况。
框架表示用”框架”这种结构来组织知识,每个框架包含多个”槽位”来存储属性。这很接近人类组织知识的方式,易于理解和扩展。
语义网络把知识表示成图的形式,节点代表概念,边代表关系。优点是直观、可视化程度高;缺点是语义表达不够精确。
产生式系统用”IF-THEN”规则来表示知识,特别适合专家系统的构建。规则简单明了,但难以处理复杂的关系。
本体论是对领域概念及其关系的显式形式化定义,是语义Web的基础。
概率图模型把知识和不确定性结合起来,适合处理不完全信息下的推理。
这些方法并不是互斥的,现代系统往往会结合使用多种表示方法。下面我们就来逐一深入了解。
三、语义网络:节点和边——知识的图形化表示
3.1 从什么是语义网络说起
你有没有见过那种连线题?就是把左边的词和右边的解释连起来。语义网络本质上就是这种东西的升级版,只不过规模大了很多倍,而且计算机能自动处理。
语义网络(Semantic Network)最早是由奎廉(Quillian)在1968年提出的。那时候他在研究人类语义记忆,想搞清楚人是怎么存储和理解词语意义的。他发现,人类大脑中的知识好像是以网状结构组织的——一个词连接着另一个词,形成一张巨大的意义之网。
举个简单的例子。如果我们要用语义网络表示”鸟”这个概念,大概是这个样子:
is-a has-part can
鸟 ──────> 动物 鸟 ──────> 羽毛 鸟 ──────> 飞
│
│ is-a
▼
企鹅
│
│ has-part
▼
羽毛(不同的羽毛)
│
│ can
▼
不能飞(企鹅不能飞)
你看,每一个节点就是一个概念,每一条边就是一种关系。这种表示方式特别符合人类的直觉——我们一想到某个概念,脑子里就会自动浮现出和它相关的其他概念。
3.2 语义网络的基本构成
语义网络虽然看起来简单,但有几个关键的组成部分你必须了解:
节点(Node) 代表实体、概念或值。节点可以是具体的(比如”北京”),也可以是抽象的(比如”勇敢”这种品质)。
边(Edge) 也叫弧(Arc)或链接(Link),代表节点之间的关系。边的类型很重要——“是-a”和”有”表达的意思完全不同。
指示器(Decorator) 是一些附加信息,比如表示否定、时态、数量限制的标记。
关系类型可以有几十种,常见的有:
- is-a:表示分类关系,“X is-a Y”意味着X是Y的一种
- part-of:表示整体-部分关系
- has-property:表示属性关系
- can:表示能力或行为
- located-in:表示位置关系
3.3 语义网络的推理机制
语义网络是怎么做推理的?主要有两种方式:
继承推理。这是最基本的一种。如果我们知道”鸟会飞”,又知道”企鹅是鸟”,那我们可以推断”企鹅可能会飞”——但这里需要注意,企鹅作为特例会覆盖这个继承来的属性。这种”默认继承”的机制使得语义网络能够高效地传播知识。
匹配和遍历。给定一个查询,系统会沿着边进行遍历,找出所有满足条件的路径。比如问”什么鸟不能飞”,系统会从”鸟”节点出发,找出所有有”can-不能飞”关系的子类。
语义网络的优点很明显:直观、可视化好、容易扩展。但它也有明显的缺点:语义不够精确。比如”鸟”和”会飞”之间的关系到底是必然的还是可能的?不同系统可能有不同理解,这就导致了语义歧义。
3.4 语义网络与框架的关系
你可能会觉得语义网络和框架系统有点像。确实,它们有很多共同点——都是结构化的知识表示方法,都支持继承推理。但关键区别在于:
框架更强调结构完整性,每个框架有预定义的槽位;语义网络更强调关系的表达,关系本身就是一等公民。
在实际应用中,语义网络和框架经常被结合使用:框架提供结构化的概念定义,语义网络描述概念之间的关系。
四、框架系统:知识如何组织成”框架”?
4.1 框架理论的起源
框架理论(Frame Theory)是由AI先驱马文·明斯基(Marvin Minsky)在1974年提出的。这个理论的灵感来自于人类认知中的”刻板印象”现象。
什么是刻板印象?就是当你听说一个场景时,你会自动预期一系列相关的事情会发生。比如我说”去餐厅吃饭”,你的脑子里会立刻浮现出:有人点菜、有服务员上菜、需要付钱等等。这些预期不需要别人提醒,是你自动联想到的。
明斯基认为,人类的认知就是靠这种”框架”来运作的。每个框架就像一张表格,里面预填了一些”默认值”。当你遇到具体情境时,你就激活相应的框架,然后用具体信息填充或覆盖这些默认值。
4.2 框架长什么样?
让我们来看一个具体的例子。用框架来表示”去餐厅吃饭”这个场景:
(DEFINE-FRAME Restaurant-Visit
:NAME "去餐厅吃饭"
:SLOTS (
(location :TYPE location :DEFAULT unspecified)
(restaurant-name :TYPE string :DEFAULT "未知餐厅")
(people :TYPE SET-OF person)
(waiter :TYPE person :DEFAULT unknown)
(menu :TYPE document)
(food-ordered :TYPE SET-OF dish)
(food-served :TYPE SET-OF dish)
(bill :TYPE money)
(payment-method :TYPE symbol :VALUES (cash card digital))
)
:DEFAULTS (
(waiter . unknown)
(payment-method . cash)
)
)这个框架里有什么?框架有一个名字,有若干槽位(Slot),每个槽位有类型约束和默认值。比如payment-method这个槽位,默认是”现金”,但你也可以填”刷卡”或”电子支付”。
框架还可以包含侧面(Facet),用来描述更详细的信息:
(SLOT age
:TYPE integer
:RANGE [0 150] ; 取值范围
:DEFAULT 0 ; 默认值
:CONSTRAINT (> age 0) ; 约束条件
)4.3 框架的继承机制
框架系统最强大的地方之一是继承。子框架可以继承父框架的所有槽位,同时还能添加自己的槽位或覆盖继承来的值。
; 定义父框架:鸟类
(DEFINE-FRAME Bird
:SLOTS (
(can-fly :TYPE boolean :DEFAULT true)
(has-wings :TYPE boolean :DEFAULT true)
(has-feathers :TYPE boolean :DEFAULT true)
)
)
; 定义子类:企鹅
(DEFINE-FRAME Penguin
:IS-A (Bird)
:SLOTS (
(habitat :TYPE string :DEFAULT "南极")
(can-fly :TYPE boolean :VALUE false) ; 覆盖默认值:企鹅不会飞
)
)
; 定义子类:鹦鹉
(DEFINE-FRAME Parrot
:IS-A (Bird)
:SLOTS (
(can-mimic :TYPE boolean :DEFAULT true)
(color :TYPE string)
)
)这里有个很精妙的设计——默认值可以被覆盖,但类型约束不能。企鹅确实不会飞,所以can-fly的值被覆盖成false。但如果有人非要说企鹅能飞,系统会报错,因为can-fly的类型必须是布尔值。
框架还支持多重继承,一个子类可以从多个父类继承:
; 蝙蝠既是哺乳动物又会飞
(DEFINE-FRAME Bat
:IS-A (Mammal Flying-Creature)
:SLOTS (
(is-nocturnal :TYPE boolean :DEFAULT true)
)
)当多个父类有冲突的属性时,系统需要通过优先级机制来解决。你可以给父类设定优先级,优先级高的那个说了算。
4.4 框架与面向对象编程
如果你熟悉面向对象编程(OOP),框架系统的概念会让你感觉很亲切。确实,框架和类(Class)在很多方面是相通的:
| 框架概念 | OOP对应 | 说明 |
|---|---|---|
| 框架 | 类 | 抽象的概念模板 |
| 实例 | 对象 | 具体的框架填充 |
| 槽位 | 属性 | 存储数据的地方 |
| 继承 | 继承 | 子类继承父类 |
| 默认值 | 默认参数 | 可覆盖的预填值 |
但框架比普通OOP类更灵活的地方在于:
- 槽位可以存放过程(Procedure),而不仅仅是数据
- 槽位可以有多重约束和侧面说明
- 支持默认推理和例外处理
这些特性使得框架特别适合表示常识知识——那种充满例外和默认值的世界知识。
五、产生式系统:IF-THEN规则——专家系统的核心
5.1 什么是产生式系统?
产生式系统(Production System)是另一种经典的知识表示方法,特别适合专家系统的构建。
“产生式”这个名字来自形式语言理论,本质上就是”IF-THEN”规则:如果满足某个条件,就执行某个动作。人类专家在解决问题时,往往也是用这种规则式的思维:“如果病人发烧又咳嗽,那我先怀疑是呼吸道感染”。
产生式系统最初是从心理学和认知科学的研究中发展出来的。心理学家发现,人类的短时记忆和工作记忆好像也是用产生式规则来组织的——面对一个情境,我们从记忆里提取相关的”如果…那么…”规则,然后执行相应的动作。
5.2 产生式系统的三大部分
一个完整的产生式系统由三个核心组件构成:
工作内存(Working Memory):存放当前问题的状态信息,也就是”事实”。比如在医疗诊断系统中,工作内存里可能有:病人发烧38.5度、咳嗽三天、肺部有阴影这些事实。
产生式规则库(Production Memory):存放所有的IF-THEN规则。比如:
IF 发烧 AND 咳嗽 AND 肺部有阴影
THEN 怀疑是肺炎
推理引擎(Inference Engine):负责把规则和工作内存匹配,决定执行哪些规则。推理引擎可以是前向链接的(从事实推结论),也可以是后向链接的(从目标反推)。
5.3 前向链接与后向链接
前向链接(Forward Chaining)是从已知事实出发,不断匹配规则产生新事实,直到没有新事实产生为止:
初始事实: 发烧38.5度, 咳嗽, 肺部阴影
↓ 匹配规则: IF 发烧 AND 咳嗽 AND 肺部阴影 THEN 怀疑肺炎
新事实: 怀疑肺炎
↓ 匹配规则: IF 怀疑肺炎 THEN 建议做CT检查
新事实: 建议CT检查
↓ 没有更多匹配,停止
后向链接(Backward Chaining)是从目标出发,问”要证明这个结论,需要什么前提?“然后递归地验证这些前提:
目标: 确诊肺炎
↓ 策略: 需要CT结果显示肺部感染
子目标: CT结果显示肺部感染
↓ 策略: 需要做CT检查
子目标: 病人同意做CT
...
5.4 产生式系统的优缺点
产生式系统的优点:
- 直观易懂:规则就像人类的语言,很容易理解
- 模块化:每条规则相互独立,可以独立添加、删除、修改
- 适合专家系统:专家可以直接把自己的经验写成规则
- 推理透明:可以清楚地看到推理过程,便于调试和解释
缺点也很明显:
- 规则冲突:多条规则可能同时匹配,需要冲突解决策略
- 效率问题:规则多了以后,匹配过程会很慢
- 知识获取瓶颈:专家往往说不出自己的决策规则(隐性知识)
- 难以处理复杂关系:规则之间的交互很难表达
著名的专家系统MYCIN就是用产生式规则构建的,用于辅助诊断细菌感染。虽然后来证明效果不如预期,但它开创了专家系统的先河,影响深远。
六、描述逻辑:OWL语言的逻辑基础
6.1 描述逻辑是什么?
描述逻辑(Description Logic)是一族基于逻辑的知识表示语言,专门用来表示概念(Concept)和角色(Role)及其关系。
为什么叫”描述”逻辑?因为它不是用公理和定理的方式,而是通过描述来定义概念——你可以通过组合更基本的概念来描述一个复杂的概念。
描述逻辑的最大特点是:推理是可判定的。这意味着给定一个知识库和一个问题,算法保证能在有限时间内给你一个正确的答案。这在很多应用场景中是非常重要的。
6.2 基本构件
描述逻辑有三个基本构件:
概念(Concept) 表示对象的类别,有点像编程语言中的”类”。比如Human表示人类,Parent表示父母。
角色(Role) 表示对象之间的关系,有点像对象之间的”属性”或”链接”。比如hasChild表示”有孩子”这种关系,loves表示”爱”这种关系。
个体(Individual) 表示具体的实例。比如John、Mary就是具体的个人。
6.3 构造算子:如何组合概念?
描述逻辑提供了丰富的算子来构造复杂概念:
| 算子 | 符号 | 语义 | 例子 |
|---|---|---|---|
| 交 | 同时属于C和D | Human ⊓ Mortal = 会死的人 | |
| 并 | 属于C或D | Man ⊔ Woman = 人类 | |
| 补 | 不属于C | ¬Bird = 非鸟 | |
| 存在限制 | 至少有一个R关系指向C | ∃hasChild.Doctor = 至少有一个医生孩子的人 | |
| 全称限制 | 所有R关系都指向C | ∀likes.Math = 只喜欢数学的人 |
举几个实际例子:
Mother ≡ Person ⊓ ∃hasChild.Person ⊓ Female
母亲就是”有孩子的人并且是女性”。
HappyFather ≡ Father ⊓ ∀hasChild.Employed
幸福的父亲就是”所有孩子都有工作的父亲”。
6.4 TBox与ABox:两种知识
描述逻辑把知识分成两类:
TBox(Terminological Box) 存放概念的定义和包含关系。比如”母亲是女性”、“母亲是有孩子的人”。
ABox(Assertional Box) 存放具体的断言。比如”John是男性”、“John和Mary是夫妻”。
; TBox:概念定义
Human ≡ Animal ⊓ Biped
Mother ≡ Human ⊓ Female ⊓ ∃hasChild.Human
Parent ≡ Human ⊓ ∃hasChild.Human; ABox:个体断言
Human(John)
Human(Mary)
Female(Mary)
hasChild(Mary, John)6.5 描述逻辑的推理
描述逻辑的推理主要包括:
概念包含(Subsumption):检查概念C是否被概念D包含。比如Mother是否被Parent包含?答案显然是,因为母亲一定是父母。
可满足性(Satisfiability):检查一个概念是否能对应到至少一个实例。比如Man ⊓ Woman是否可满足?在通常的语义下是不可满足的(除非你认为有双性人)。
实例检测(Instance Checking):检查某个个体是否属于某个概念。比如John是否是Human?
这些推理看起来简单,但在复杂的概念层次上做高效的推理,需要非常精巧的算法设计。
6.6 描述逻辑家族
不同的描述逻辑有不同的表达能力:
EL是最基础的,只支持交和存在限制,但足够高效,适合大规模本体。
ALC加入了补和全称限制,是最基础的”完备”描述逻辑。
SHOIQ和SROIQ支持数量限制、逆角色等高级特性,是OWL 2的逻辑基础。
表达力越强,推理越慢。这是一个经典的权衡。
七、本体论:概念和关系的形式化定义
7.1 什么是本体论?
本体论(Ontology)这个词本来是哲学概念,研究”存在”本身。但计算机科学家借用这个词,用来指代对某个领域的形式化概念化。
1998年,托里尼(Grigoris Antoniou)和霍斯特·帕内托尼乌(Horst Paslke)给出了个很实用的定义:本体论是对领域概念及其关系的显式规格说明。
翻译成人话就是:本体论告诉你这个领域有哪些重要的概念,这些概念之间是什么关系。
一个典型的医学本体可能包含:
- 概念:疾病、症状、药物、治疗方法、患者
- 关系:疾病会导致症状、药物可以治疗疾病、患者患有疾病
- 公理:肺结核是一种传染病、肺结核的症状包括咳嗽和发烧
7.2 本体论的核心要素
一个完整的本体论通常包含以下要素:
概念(Classes):领域中的主要类别。比如在图书馆本体里,有”书籍”、“作者”、“出版社”这些概念。
层次结构(Taxonomy):概念之间的分类关系。比如”小说是书籍的一种”、“技术报告也是书籍的一种”。
属性(Properties):描述概念的特征。比如书籍有”标题”、” ISBN”、“出版年份”这些属性。
关系(Object Properties):概念之间的联系。比如”作者写了书籍”、“出版社出版了书籍”。
约束(Constraints):对属性和关系的限制。比如”一本书必须有一个作者”、“一本书的出版年份必须在1800年之后”。
实例(Individuals):具体的个体。比如《人工智能:一种现代方法》是一本书的实例。
7.3 OWL:本体论的标准语言
OWL(Web Ontology Language)是W3C推荐的本体描述语言,是语义Web的基石之一。
OWL有三个版本:
- OWL Lite:最简单,只支持基本的分类和属性约束
- OWL DL:基于描述逻辑,支持完整的推理能力
- OWL Full:最强大,但失去了可判定性保证
OWL 2又新增了三个子语言:
- OWL 2 EL:适合大规模本体(比如生物医学领域)
- OWL 2 QL:适合数据库查询优化
- OWL 2 RL:适合基于规则的推理
# 用Turtle语法写一个简单的大学本体
:Professor rdf:type owl:Class ;
rdfs:subClassOf :Academic .
:Course rdf:type owl:Class .
:teaches rdf:type owl:ObjectProperty ;
rdfs:domain :Professor ;
rdfs:range :Course .
:Course rdf:type owl:Class ;
rdfs:subClassOf [
rdf:type owl:Restriction ;
owl:onProperty :hasInstructor ;
owl:cardinality 1
] .这段代码说的是:教授是一种学术人员;课程有”授课”属性,定义域是教授,值域是课程;每门课程必须恰好有一个授课教师。
7.4 本体的构建方法
构建一个好的本体是个技术活,有几个常用的方法论:
METHONTOLOGY是比较经典的方法论,包括:
- 规范说明:明确本体的目的和范围
- 概念化:抽象出领域的主要概念
- 形式化:用形式语言编码
- 维护:持续更新和完善
骨架法更简单直接:
- 确定领域范围
- 枚举核心概念
- 定义概念的属性
- 定义概念之间的关系
- 创建实例
在实际工作中,通常是两种方法结合使用,先用骨架法快速搭架子,再用METHONTOLOGY细化和完善。
八、情景演算与事件演算:动作与时间如何表示?
8.1 为什么需要形式化的动作表示?
假设我们有一个机器人,它需要理解”拿起桌上的杯子”这个动作意味着什么。这不只是记录”机器人执行了拿起杯子”这样一个事实,而是要理解:
- 拿起之前,杯子在桌上;拿起之后,杯子在机器人的手里
- 杯子的所有权发生了变化
- 桌上的状态发生了变化
- 机器人的手从空变成了有东西
更重要的是,系统需要能够推理这些变化:如果我们知道拿起杯子之前杯子是完整的,我们就可以推断拿起之后杯子还是完整的(除非我们明确说杯子掉地上摔坏了)。
这就要用到动作演算(Action Calculus)这类形式化工具。
8.2 情景演算
情景演算(Situation Calculus)由约翰·麦卡锡在1969年提出,是表示动作和时间最经典的方法之一。
核心思想是:世界在不同的时间点处于不同的情景(Situation)。动作(Action)把一个情景变成另一个情景。
关键要素:
情景(Situation):表示某个时间点的世界状态。比如S0表示初始状态,Result(Grab(Cup), S0)表示在S0状态下执行了”拿杯子”动作之后的状态。
动作(Action):可以执行的操作。比如Walk(x, y)表示从x走到y,Grab(obj)表示抓取某个物体。
流(Fluents):会随情景变化的属性。比如On(Cup, Table)表示杯子在桌上这个事实。
前件(Precondition):动作执行的前提条件。比如”抓杯子”的前提是”机器人的手是空的”。
效果(Effect):动作执行后的结果。比如执行”抓杯子”后,“杯子在机器人手里”变成真,“杯子在桌上”变成假。
; 情景演算示例
; 初始情景
holds(at(robot, roomA), s0).
; 抓取动作的前提
poss(grab(X), S) :-
holding(robot, empty, S),
on(X, table, S).
; 抓取动作的效果
holds(holding(robot, X), result(grab(X), S)).
holds(on(X, table), result(grab(X), S)) :- false.8.3 事件演算
事件演算(Event Calculus)是另一个处理时序知识的框架,由科瓦尔斯基(Robert Kowalski)和塞雷吉(Marek Sergot)在1986年提出。
事件演算的核心概念包括:
事件(Event):在某个时间点发生的动作。
时间点(Time Point):表示事件发生的时刻。
属性(Fluents):随时间变化的性质。
事件演算用一套简洁的公理来描述因果关系:
; 事件演算示例
; 初始状态:杯子在桌上
initiates(put(Cup, Table), on(Cup, Table), T).
; 终止状态:杯子不在桌上了
terminates(grab(Cup), on(Cup, Table), T).
; 持续性:如果某时刻属性成立,且没有被终止,则一直成立
holds_at(F, T2) :-
holds_at(F, T1),
T1 < T2,
not terminated_by(F, T1, T2).
; 杯子在桌上,除非被拿走
terminated_by(on(Cup, Table), T, T2) :-
happens(grab(Cup), T),
T =< T2.8.4 两种演算的比较
情景演算更适合描述离散的动作序列,关注的是动作如何改变状态;事件演算更适合描述连续的时间过程,关注的是属性如何随时间变化。
在实际的AI应用中,这两种方法经常被结合使用。
九、继承推理:子类如何获得父类的属性?
9.1 继承推理的基本思想
继承(Inheritance)是知识表示中最常用的推理机制之一。它的核心思想很直观:子类自动获得父类的属性。
比如:
- 鸟会飞(父类属性)
- 企鹅是鸟(分类关系)
- 因此企鹅会飞(继承来的属性)
但问题是:企鹅实际上不会飞!所以我们的推理系统需要能够覆盖继承来的属性。这就是”例外处理”的问题。
继承推理可以分为几种类型:
9.2 单继承 vs 多继承
单继承(Single Inheritance)要求每个子类只能有一个父类。这简化了推理过程——继承链是唯一的。
多继承(Multiple Inheritance)允许一个子类有多个父类。这更灵活,但也带来了冲突问题:
动物
/ \
鸟 哺乳动物
\ /
蝙蝠
蝙蝠同时是鸟类和哺乳动物的后代。如果鸟类的属性是”会飞”,哺乳动物类的属性是”胎生”,那蝙蝠同时继承这两个属性。但万一鸟类的属性和哺乳动物类的某个属性冲突了怎么办?
9.3 继承的优先级
当继承产生冲突时,系统需要通过优先级来解决:
- 子类属性优先于父类属性
- 更具体的类优先于更一般的类
- 离被查询类更近的祖先优先
class InheritanceEngine:
def resolve_conflict(self, node, property_name):
"""解决属性冲突的简单策略"""
# 1. 先检查节点本身是否有这个属性
if property_name in node.own_properties:
return node.own_properties[property_name]
# 2. 收集所有父节点的属性
candidates = []
for parent in node.parents:
if property_name in parent.own_properties:
distance = self.get_distance(node, parent)
candidates.append((parent, parent.own_properties[property_name], distance))
# 3. 选择距离最近的
if candidates:
candidates.sort(key=lambda x: x[2])
return candidates[0][1]
# 4. 递归向更远的祖先查询
...9.4 默认推理与例外处理
在现实世界中,继承来的属性往往是”默认值”而非绝对规则。经典的例子:
- 鸟通常会飞(默认值)
- 企鹅是鸟,但不会飞(例外)
- 鸵鸟是鸟,但不会飞(例外)
- 受伤的鸟不会飞(更特殊的例外)
处理这种层次化的默认值系统,需要更复杂的机制,比如缺省逻辑(Default Logic)或限定建模(Circumscription)。
十、非单调推理:为什么常识推理不是单调的?
10.1 什么是单调性?
在经典逻辑中,推理是单调(Monotonic)的。这意味着:如果我们知道P→Q(即P蕴含Q),那么添加更多的知识永远不会撤销这个推理结论。
比如:
- 如果我们知道”所有鸟都会飞”
- 我们推出”企鹅会飞”(因为企鹅是鸟)
- 即使后来我们发现企鹅其实不会飞,逻辑上这个推理链条本身没有错,只是大前提”所有鸟都会飞”是错的
但在日常生活中,我们的推理经常是非单调的——新信息的加入可能导致我们撤销之前的结论。
10.2 非单调推理的例子
经典的”特威迪”(Tweety)例子:
已知:鸟通常会飞
前提:特威迪是一只鸟
推理:特威迪大概会飞
新信息:特威迪是一只企鹅
推理:企鹅不会飞,所以特威迪不会飞
新信息:特威迪是只受伤的鸟
推理:受伤的鸟不会飞,所以特威迪不会飞
你看,每加入一条新信息,我们就可能改变之前的结论。这就是非单调推理。
10.3 非单调推理的形式化方法
为了处理非单调推理,研究者们提出了多种形式化方法:
限定建模(Circumscription):通过缩小模型的范围来表达”常识”——假设事情是正常的,除非有证据表明不是这样。
缺省逻辑(Default Logic):允许用缺省规则表示”正常情况下…”的推理,比如”如果x是鸟且没有证据表明x不会飞,则推断x会飞”。
信念修订(Belief Revision):当新知识与旧信念冲突时,如何修改信念集合。
这些方法各有优缺点,实际系统往往会结合使用多种技术。
十一、概率推理:如何处理不确定性知识?
11.1 为什么需要概率推理?
现实世界的知识充满了不确定性。你去医院检查,医生可能说”你这个症状,80%可能是普通感冒,但也有20%的可能是流感”。这种”可能性”用经典逻辑完全没法表示——经典逻辑要么是真要么是假,没有”可能”这个选项。
概率论提供了一套处理不确定性的数学工具。简单回顾一下几个核心概念:
条件概率 P(A|B):在B发生的前提下,A发生的概率。
贝叶斯定理:
这个公式是概率推理的核心。它告诉我们如何根据新的证据更新我们的信念。
11.2 贝叶斯网络
贝叶斯网络(Bayesian Network)也叫信念网络,是一种用图模型来表示变量之间概率关系的工具。
节点的含义:
- 节点代表随机变量
- 边代表直接的概率依赖关系
- 每个节点有一个条件概率表(CPT),描述它在其父节点取不同值时的条件概率
# 简化的贝叶斯网络示例:天气与出行
# 变量:多云(C)、下雨(R)、带伞(U)、出行(O)
class BayesianNetwork:
"""
天气贝叶斯网络结构:
C(多云)
↓
R(下雨) ← C(多云)
↓
U(带伞) ← R(下雨)
O(出行) ← R(下雨)
"""
def __init__(self):
# P(C): 多云的先验概率
self.p_cloudy = 0.3
# P(R|C): 下雨的条件概率
self.p_rain_given_cloudy = 0.6 # 多云时下雨的概率
self.p_rain_given_not_cloudy = 0.2 # 不多云时下雨的概率
# P(U|R): 带伞的条件概率
self.p_umbrella_given_rain = 0.9 # 下雨时带伞的概率
self.p_umbrella_given_no_rain = 0.1 # 不下雨时带伞的概率
# P(O|R): 出行的条件概率
self.p_go_out_given_rain = 0.2 # 下雨时出行的概率
self.p_go_out_given_no_rain = 0.9 # 不下雨时出行的概率
def p_rain(self, cloudy):
"""计算下雨的概率"""
if cloudy:
return self.p_rain_given_cloudy
return self.p_rain_given_not_cloudy
def p_umbrella(self, rainy):
"""计算带伞的概率"""
if rainy:
return self.p_umbrella_given_rain
return self.p_umbrella_given_no_rain
def joint_probability(self, cloudy, rainy, umbrella, go_out):
"""计算联合概率 P(C, R, U, O)"""
p_c = self.p_cloudy if cloudy else (1 - self.p_cloudy)
p_r = self.p_rain(cloudy) if rainy else (1 - self.p_rain(cloudy))
p_u = self.p_umbrella(rainy) if umbrella else (1 - self.p_umbrella(rainy))
p_o = self.p_go_out_given_rain if rainy else self.p_go_out_given_no_rain
if go_out:
p_o_final = p_o
else:
p_o_final = 1 - p_o
return p_c * p_r * p_u * p_o_final
def inference(self, evidence, query):
"""
简化的推理:给定证据,计算查询变量的概率
使用贝叶斯定理和边际化
"""
# P(下雨 | 带伞) - 已知带伞,求下雨的概率
if 'umbrella' in evidence and evidence['umbrella']:
# P(R|U) = P(U|R) * P(R) / P(U)
p_r = self.p_rain(self.p_cloudy) # 简化计算
p_u_given_r = self.p_umbrella(True)
p_u_given_not_r = self.p_umbrella(False)
p_u = p_u_given_r * p_r + p_u_given_not_r * (1 - p_r)
if query == 'rain':
return (p_u_given_r * p_r) / p_u
return None
# 使用示例
bn = BayesianNetwork()
print(f"多云的概率: {bn.p_cloudy}")
print(f"下雨的概率(给定多云): {bn.p_rain(True):.2%}")
print(f"下雨的概率(给定不多云): {bn.p_rain(False):.2%}")
# 推理:已知带伞,求下雨的概率
p_rain_given_umbrella = bn.inference({'umbrella': True}, 'rain')
if p_rain_given_umbrella:
print(f"P(下雨 | 带伞) = {p_rain_given_umbrella:.2%}")贝叶斯网络的优势在于:结构表达了因果关系,概率值可以来自专家知识或数据学习,推理可以用高效的近似算法(如粒子滤波、变分推断)来处理复杂网络。
11.3 马尔可夫逻辑网络:逻辑+概率
马尔可夫逻辑网络(Markov Logic Network, MLN)是一个把逻辑和概率结合起来的天才想法。
核心思想是:把硬规则变成软规则。
在传统的逻辑系统里,规则要么完全成立要么完全不成立。但在MLN里,每条规则都有一个权重,表示这条规则”有多重要”或”有多可靠”。
MLN本质上是一个马尔可夫网络,每个基原子是一个节点,每条规则对应的基例是图中的团(Clique)。
公式:
其中是规则在解释中为真的次数,是权重,是归一化常数。
十二、知识图谱:现代知识表示的实践
12.1 知识图谱是什么?
知识图谱(Knowledge Graph)是近年来最火的知识表示技术。2012年,谷歌发布了”Google Knowledge Graph”,把知识图谱这个概念带入了大众视野。
本质上,知识图谱就是大规模语义网络——用图的结构来表示实体和实体之间的关系。每个节点是一个实体(Entity),每条边是一个关系(Relation)。
一个简单的知识图谱:
实体:
- 牛顿(人)
- 万有引力(物理定律)
- 苹果(水果)
- 1666年(年份)
关系:
- 牛顿 - 发现 - 万有引力
- 苹果 - 落在 - 牛顿头上
- 万有引力 - 发现于 - 1666年
12.2 知识图谱的三元组
知识图谱的基本表示单元是三元组(Triple):
(主体, 谓词, 客体)
或
(头实体, 关系, 尾实体)
比如:
- (牛顿, 出生于, 1643年)
- (牛顿, 发现, 万有引力)
- (万有引力, 作用于, 苹果)
这种三元组的表示简单但强大,足够表达大部分知识。
12.3 知识图谱的构建
构建知识图谱主要有三种途径:
人工构建:专家手工输入知识。质量高但成本高、规模有限。典型代表是WordNet。
自动抽取:从文本中自动识别实体和关系。成本低但质量参差不齐。需要NLP和信息抽取技术的支持。
众包构建:结合人工和机器的力量。像Wikipedia这样的项目就是典型。
现代知识图谱通常是这三种方法的混合。
12.4 知识图谱的推理
知识图谱的价值不只是存储知识,还要能推理出新的知识。常见的推理方式:
基于规则的推理:比如路径规则”如果A是B的父亲,B是C的父亲,则A是C的祖父”。
基于嵌入的推理:把实体和关系映射到向量空间,用向量运算来预测新的关系。典型方法有TransE、DistMult、ComplEx。
基于神经网络的知识图谱补全:用深度学习模型来预测缺失的三元组。
十三、符号AI vs 神经AI:知识表示的两种范式
13.1 符号AI的思路
符号AI(Symbolic AI)也叫经典AI、逻辑AI,是人工智能最早的研究方向。它的核心假设是:智能可以通过操作符号来实现。
在符号AI的框架下:
- 世界被表示为一组符号(就像逻辑变量)
- 知识被表示为符号之间的关系(就像逻辑公式)
- 推理是通过符号操作完成的(就像逻辑推导)
符号AI的代表技术包括:
- 逻辑推理(一阶谓词逻辑、描述逻辑)
- 专家系统(产生式规则)
- 规划算法(HTN规划、情景演算)
符号AI的优势:
- 可解释性强:推理过程清晰可见
- 精确表达:适合需要精确结果的任务
- 组合泛化:可以处理从未见过的新组合
符号AI的局限:
- 知识获取困难:很难自动从数据中学习知识
- 处理不确定性:对模糊、不完全信息处理能力弱
- 可扩展性:大规模知识库的维护是个挑战
13.2 神经AI的思路
神经AI(Neural AI)也叫连接主义AI,源于对大脑的模拟。它的核心假设是:智能可以从大量数据中学习,知识和智能是隐含在神经网络的参数中的。
在神经AI的框架下:
- 知识被编码在神经网络的权重中
- 推理是神经网络的前向传播
- 学习是通过调整权重来完成的
神经AI的代表技术包括:
- 深度学习(CNN、RNN、Transformer)
- 表示学习(词嵌入、图嵌入)
- 端到端学习
神经AI的优势:
- 自动特征学习:不需要人工设计特征
- 处理大规模数据:能有效利用海量数据
- 处理模糊信息:对噪声和不确定性有较好的鲁棒性
神经AI的局限:
- 可解释性差:很难理解模型到底学到了什么
- 需要大量数据:小样本场景表现不佳
- 组合泛化差:对训练集外的新组合泛化能力有限
13.3 两种范式的对比
| 维度 | 符号AI | 神经AI |
|---|---|---|
| 知识表示 | 显式的符号结构 | 隐式的向量表示 |
| 推理方式 | 逻辑推导 | 模式匹配 |
| 学习方式 | 人工知识工程 | 数据驱动学习 |
| 可解释性 | 高 | 低 |
| 数据需求 | 低 | 高 |
| 泛化能力 | 组合泛化强 | 分布内泛化强 |
这并不是说一种比另一种更好。事实上,两种范式有各自擅长的领域:
- 符号AI适合:需要精确推理、知识图谱、专家系统、规划
- 神经AI适合:图像识别、自然语言处理、语音识别、推荐系统
13.4 为什么需要神经符号AI?
纯粹依靠符号AI的系统缺乏学习能力,很难从数据中自动获取知识。纯粹依靠神经AI的系统缺乏可解释性,难以处理需要精确推理的任务。
于是,神经符号AI(Neuro-Symbolic AI)应运而生,目标是结合两种范式的优点。
十四、神经符号AI:符号主义与连接主义的融合
14.1 神经符号AI的核心思想
神经符号AI的核心理念是:让神经网络学习符号操作,让符号系统利用神经网络的表示能力。
具体来说,有几种典型的融合方式:
神经网络的符号化:用神经网络来模拟符号操作。比如用注意力机制来实现”查询-匹配-推理”的过程。
符号系统的向量化:把符号结构嵌入到向量空间中。比如知识图谱嵌入、知识库链接等。
混合架构:把神经模块和符号模块组合在一起,形成端到端的系统。
14.2 知识图谱嵌入
知识图谱嵌入(Knowledge Graph Embedding)是神经符号融合的经典例子。
核心思想是把知识图谱中的实体和关系都表示为稠密的向量:
import numpy as np
class TransE:
"""TransE: 翻译嵌入模型"""
def __init__(self, num_entities, num_relations, embedding_dim):
self.num_entities = num_entities
self.num_relations = num_relations
self.embedding_dim = embedding_dim
# 初始化嵌入
np.random.seed(42)
self.entity_embeddings = np.random.randn(num_entities, embedding_dim) * 0.01
self.relation_embeddings = np.random.randn(num_relations, embedding_dim) * 0.01
def normalize(self):
"""L2归一化"""
norms = np.linalg.norm(self.entity_embeddings, axis=1, keepdims=True)
self.entity_embeddings = self.entity_embeddings / (norms + 1e-8)
def score_function(self, h, r, t):
"""
评分函数:h + r ≈ t
距离越小,三元组越可能为真
"""
return np.linalg.norm(h + r - t, axis=1)
def forward(self, h_idx, r_idx, t_idx):
"""前向传播,计算三元组的得分"""
h = self.entity_embeddings[h_idx]
r = self.relation_embeddings[r_idx]
t = self.entity_embeddings[t_idx]
return self.score_function(h, r, t)
def link_prediction(self, h_idx, r_idx, top_k=10):
"""链接预测:给定头实体和关系,预测可能的尾实体"""
h = self.entity_embeddings[h_idx]
r = self.relation_embeddings[r_idx]
# 计算所有实体作为尾实体的得分
scores = self.score_function(h, r, self.entity_embeddings)
# 按得分排序,取top-k
top_indices = np.argsort(scores)[:top_k]
return [(idx, scores[idx]) for idx in top_indices]
# 使用示例
transE = TransE(num_entities=1000, num_relations=50, embedding_dim=100)
# 假设:
# 实体ID: 牛顿=0, 万有引力=1, 苹果=2
# 关系ID: 发现=0, 作用于=1
# 计算三元组 (牛顿, 发现, 万有引力) 的得分
score = transE.forward([0], [0], [1])
print(f"三元组(牛顿, 发现, 万有引力)的得分: {score[0]:.4f}")
# 链接预测:给定(牛顿, 发现, ?),预测尾实体
predictions = transE.link_prediction(h_idx=0, r_idx=0, top_k=5)
print("\n链接预测结果 (牛顿, 发现, ?):")
for entity_id, score in predictions:
print(f" 实体ID {entity_id}: 得分 {score:.4f}")TransE的评分函数基于一个简单但有效的假设:头实体 + 关系 ≈ 尾实体。如果这个等式成立,说明这个三元组很可能是真的。
14.3 神经定理证明
神经定理证明(Neural Theorem Proving)是用神经网络来辅助逻辑定理证明。
经典的马尔可夫逻辑网络、神经逻辑编程(Neural Logic Programming)都是这个方向的工作。
核心思想是:
- 用神经网络来学习搜索策略(哪些规则优先尝试)
- 用符号系统来处理精确的逻辑推理
- 两者交替进行,逐步构建证明
14.4 神经符号AI的未来
神经符号AI是个非常活跃的研究领域,一些值得关注的方向:
可微分的逻辑推理:设计可以求导的逻辑运算,使得逻辑推理可以直接嵌入到神经网络中。
神经符号对话系统:结合大语言模型的生成能力和知识图谱的结构化知识。
因果推理与机器学习的结合:把因果推断的符号化方法与数据驱动的机器学习结合起来。
十五、动手实验:用NetworkX构建一个简单的知识图谱
15.1 实验目标
通过动手实践,加深对知识图谱的理解。我们将用Python的NetworkX库构建一个简单的”人工智能领域知识图谱”。
15.2 准备工作
首先安装必要的库:
pip install networkx matplotlib15.3 代码实现
import networkx as nx
import matplotlib.pyplot as plt
from collections import defaultdict
class SimpleKnowledgeGraph:
"""用NetworkX构建简单的知识图谱"""
def __init__(self):
self.graph = nx.DiGraph() # 有向图
# 定义实体类型
self.entity_types = {}
# 定义关系类型
self.relation_types = set()
def add_entity(self, entity_id, entity_type, properties=None):
"""添加实体"""
self.graph.add_node(entity_id, type=entity_type, properties=properties or {})
self.entity_types[entity_id] = entity_type
def add_relation(self, head_id, relation, tail_id):
"""添加关系三元组 (head, relation, tail)"""
self.graph.add_edge(head_id, tail_id, relation=relation)
self.relation_types.add(relation)
def query(self, head_id, relation):
"""查询:从head_id出发,通过relation能找到哪些实体"""
results = []
for successor in self.graph.successors(head_id):
edge_data = self.graph.get_edge_data(head_id, successor)
if edge_data.get('relation') == relation:
results.append(successor)
return results
def visualize(self, title="知识图谱可视化"):
"""可视化知识图谱"""
plt.figure(figsize=(16, 12))
# 按实体类型设置颜色
type_colors = {
'人': '#FF6B6B',
'概念': '#4ECDC4',
'技术': '#45B7D1',
'领域': '#96CEB4',
'公司': '#FFEAA7',
'产品': '#DDA0DD',
}
colors = [type_colors.get(self.entity_types.get(node, '概念'), '#CCCCCC')
for node in self.graph.nodes()]
# 设置布局
pos = nx.spring_layout(self.graph, k=2, iterations=50, seed=42)
# 绘制节点
nx.draw_networkx_nodes(self.graph, pos,
node_color=colors,
node_size=2000,
alpha=0.9)
# 绘制边
nx.draw_networkx_edges(self.graph, pos,
edge_color='#666666',
arrows=True,
arrowsize=20,
connectionstyle="arc3,rad=0.1")
# 绘制标签
nx.draw_networkx_labels(self.graph, pos,
font_size=9,
font_weight='bold')
# 绘制边标签(关系)
edge_labels = nx.get_edge_attributes(self.graph, 'relation')
nx.draw_networkx_edge_labels(self.graph, pos,
edge_labels=edge_labels,
font_size=8)
plt.title(title)
plt.axis('off')
plt.tight_layout()
plt.savefig('knowledge_graph.png', dpi=150, bbox_inches='tight')
plt.show()
def get_subgraph(self, center_node, depth=2):
"""获取以某节点为中心的子图"""
return nx.ego_graph(self.graph, center_node, radius=depth)
def find_shortest_path(self, start, end):
"""查找最短路径"""
try:
path = nx.shortest_path(self.graph, start, end)
edges = [(path[i], path[i+1]) for i in range(len(path)-1)]
relations = [self.graph.get_edge_data(e[0], e[1])['relation'] for e in edges]
return path, relations
except nx.NetworkXNoPath:
return None, None
def analyze(self):
"""分析知识图谱的基本统计"""
print("=" * 50)
print("知识图谱统计信息")
print("=" * 50)
print(f"实体数量: {self.graph.number_of_nodes()}")
print(f"关系数量: {self.graph.number_of_edges()}")
print(f"\n实体类型分布:")
type_count = defaultdict(int)
for entity, etype in self.entity_types.items():
type_count[etype] += 1
for etype, count in type_count.items():
print(f" {etype}: {count}")
print(f"\n关系类型:")
for rel in self.relation_types:
print(f" - {rel}")
print(f"\n节点列表:")
for node in self.graph.nodes():
print(f" [{self.entity_types[node]}] {node}")
# 构建人工智能领域的知识图谱
def build_ai_knowledge_graph():
kg = SimpleKnowledgeGraph()
# 添加实体:人物
people = {
'图灵': '人',
'明斯基': '人',
'辛顿': '人',
'杨乐村': '人',
'Lecun': '人',
'本吉奥': '人',
'Hopfield': '人',
}
for name, ptype in people.items():
kg.add_entity(name, ptype)
# 添加实体:概念
concepts = {
'人工智能': '概念',
'机器学习': '概念',
'深度学习': '概念',
'神经网络': '概念',
'强化学习': '概念',
'计算机视觉': '概念',
'自然语言处理': '概念',
}
for name, ctype in concepts.items():
kg.add_entity(name, ctype)
# 添加实体:技术
techs = {
'反向传播': '技术',
'卷积神经网络': '技术',
'循环神经网络': '技术',
'Transformer': '技术',
'注意力机制': '技术',
'生成对抗网络': '技术',
}
for name, ttype in techs.items():
kg.add_entity(name, ttype)
# 添加实体:领域
domains = {
'计算机科学': '领域',
'认知科学': '领域',
'数学': '领域',
}
for name, dtype in domains.items():
kg.add_entity(name, dtype)
# 添加实体:机构
institutions = {
'MIT': '公司',
'剑桥大学': '公司',
'多伦多大学': '公司',
'Facebook AI': '公司',
'谷歌DeepMind': '公司',
'纽约大学': '公司',
'蒙特利尔大学': '公司',
}
for name, itype in institutions.items():
kg.add_entity(name, itype)
# 添加关系
# 人物与概念的关系
kg.add_relation('图灵', '提出', '人工智能')
kg.add_relation('明斯基', '提出', '神经网络')
kg.add_relation('Hopfield', '提出', '神经网络')
kg.add_relation('Hopfield', '提出', 'Hopfield网络')
kg.add_relation('辛顿', '提出', '深度学习')
kg.add_relation('辛顿', '提出', '反向传播')
kg.add_relation('辛顿', '发展', '深度学习')
kg.add_relation('Lecun', '提出', '卷积神经网络')
kg.add_relation('本吉奥', '提出', '深度学习')
kg.add_relation('杨乐村', '提出', '胶囊网络')
# 概念之间的关系
kg.add_relation('人工智能', '属于', '计算机科学')
kg.add_relation('人工智能', '包括', '机器学习')
kg.add_relation('机器学习', '包括', '深度学习')
kg.add_relation('机器学习', '包括', '强化学习')
kg.add_relation('深度学习', '基于', '神经网络')
kg.add_relation('神经网络', '包括', '卷积神经网络')
kg.add_relation('神经网络', '包括', '循环神经网络')
kg.add_relation('神经网络', '包括', 'Transformer')
kg.add_relation('Transformer', '使用', '注意力机制')
kg.add_relation('注意力机制', '属于', '深度学习')
# 技术与应用领域
kg.add_relation('卷积神经网络', '应用', '计算机视觉')
kg.add_relation('循环神经网络', '应用', '自然语言处理')
kg.add_relation('Transformer', '应用', '自然语言处理')
kg.add_relation('生成对抗网络', '属于', '深度学习')
# 人物与机构的关系
kg.add_relation('图灵', '工作于', '剑桥大学')
kg.add_relation('明斯基', '工作于', 'MIT')
kg.add_relation('辛顿', '工作于', '多伦多大学')
kg.add_relation('辛顿', '工作于', '谷歌DeepMind')
kg.add_relation('Lecun', '工作于', '纽约大学')
kg.add_relation('Lecun', '工作于', 'Facebook AI')
kg.add_relation('本吉奥', '工作于', '蒙特利尔大学')
# 概念与数学的关系
kg.add_relation('神经网络', '基于', '数学')
kg.add_relation('机器学习', '基于', '数学')
return kg
# 运行实验
if __name__ == "__main__":
# 构建知识图谱
print("构建人工智能领域知识图谱...")
kg = build_ai_knowledge_graph()
# 分析统计
kg.analyze()
# 查询示例
print("\n" + "=" * 50)
print("查询示例")
print("=" * 50)
# 查询谁提出了深度学习
who_proposed_dl = kg.query('深度学习', '由谁提出')
print(f"谁提出了深度学习? {who_proposed_dl}")
# 查询人工智能包括什么
what_ai_includes = kg.query('人工智能', '包括')
print(f"人工智能包括什么? {what_ai_includes}")
# 查询机器学习基于什么
what_ml_based_on = kg.query('机器学习', '基于')
print(f"机器学习基于什么? {what_ml_based_on}")
# 查找路径
print("\n" + "=" * 50)
print("路径查找")
print("=" * 50)
path, relations = kg.find_shortest_path('辛顿', '自然语言处理')
if path:
print(f"从辛顿到自然语言处理的最短路径:")
print(f" 路径: {' -> '.join(path)}")
print(f" 关系: {' -- '.join(relations)}")
# 获取子图
print("\n" + "=" * 50)
print("以'神经网络'为中心的2步子图")
print("=" * 50)
subgraph = kg.get_subgraph('神经网络', depth=2)
print(f"子图节点: {list(subgraph.nodes())}")
# 可视化
print("\n正在生成知识图谱可视化...")
kg.visualize("人工智能领域知识图谱")
print("可视化已保存为 knowledge_graph.png")15.4 实验结果与分析
运行上面的代码,你会得到:
统计信息:
- 实体数量:24个(人、概念、技术、领域、机构)
- 关系数量:26条
查询示例:
- 谁提出了深度学习?可以查到辛顿、本吉奥等
- Transformer应用在哪里?可以查到自然语言处理
路径查找:
- 从辛顿到自然语言处理的路径:辛顿 → 深度学习 → 机器学习(隐含) → 自然语言处理
这个简单的实验展示了知识图谱的核心能力:存储结构化知识、进行关系查询、支持路径推理。
15.5 扩展实验
如果你想进一步探索,可以尝试:
-
扩展更多实体和关系:添加更多AI领域的概念、技术、人物。
-
实现更复杂的推理:比如传递性推理(A认识B,B认识C,则A可能认识C)。
-
使用真实数据:Wikipedia、DBpedia等公开知识图谱都有API可以访问。
-
知识图谱嵌入:用前面介绍的TransE等方法,把实体和关系嵌入到向量空间中。
十六、总结与展望
16.1 知识表示的核心要点
回顾全文,我们讨论了知识表示的多种方法:
语义网络用图来组织知识,节点是概念,边是关系,直观但语义不够精确。
框架系统用结构化的”框架”来表示知识,支持继承和默认值,适合表示常识知识。
产生式系统用IF-THEN规则来表示专家知识,简单直观,适合专家系统。
描述逻辑和OWL提供了形式化的、基于逻辑的知识表示,可判定性强,适合语义Web。
情景演算和事件演算解决了动作和时间的形式化表示问题。
概率推理把不确定性和知识结合起来,贝叶斯网络、马尔可夫逻辑网络是典型代表。
知识图谱是现代知识表示的实践,把大规模知识组织成图的结构。
16.2 符号AI与神经AI的关系
符号AI和神经AI代表了两种不同的智能观:
符号AI强调显式的知识表示和逻辑推理,追求可解释性和精确性。
神经AI强调数据驱动的学习和隐式的表示,追求泛化能力和处理模糊信息的能力。
两者各有优劣,互相补充。神经符号AI正是试图融合两者的优点。
16.3 未来展望
知识表示领域有几个值得关注的发展方向:
大规模知识图谱的构建和维护:如何自动从互联网、文献、对话中抽取知识?如何处理知识的时效性和冲突?
多模态知识表示:如何把文本、图像、视频、音频等多种模态的知识统一表示?
神经符号系统的深化:如何设计更高效的神经符号融合架构?
因果知识的表示:如何把因果关系和相关性区分开来?
常识知识的获取:如何让AI系统理解人类习以为常的常识知识?
学术来源与参考文献
- Minsky, M. (1974). A framework for representing knowledge. MIT AI Laboratory Memo 306.
- Baader, F. et al. (2017). An Introduction to Description Logic. Cambridge University Press.
- Brachman, R. J. & Levesque, H. J. (2004). Knowledge Representation and Reasoning. Morgan Kaufmann.
- Guarino, N. (1998). Formal ontology in information systems. Formal Ontology in Information Systems, 3-15.
- McGuinness, D. L. & van Harmelen, F. (2004). OWL Web Ontology Language overview. W3C Recommendation.
- Richardson, M. & Domingos, P. (2006). Markov logic networks. Machine Learning, 62(1-2), 107-136.
- Bordes, A. et al. (2013). Translating embeddings for modeling multi-relational data. NeurIPS, 2787-2795.
- Hitzler, P. et al. (2022). Neuro-Symbolic Artificial Intelligence: The State of the Art. IOS Press.
- Quillian, M. R. (1968). Semantic memory. Semantic Information Processing, 227-270.
- Davis, R. & Lenat, D. B. (1982). Knowledge-Based Systems in Artificial Intelligence. McGraw-Hill.