约翰·麦卡锡与逻辑AI:常识形式化如何影响现代人工智能
2026/8/30 11:41:23 网站建设 项目流程

提到人工智能,很多读者第一反应是神经网络、大模型、深度学习。但在这些技术成为主流之前,人工智能还有一条同样重要、甚至更“硬核”的技术脉络:用逻辑来刻画智能。这条脉络的代表人物,就是约翰·麦卡锡(John McCarthy)。这篇文章不打算讲神经网络反向传播,而是想带你回到逻辑 AI 的出发点,看看麦卡锡当年提出的核心问题——如何把常识形式化——为什么到今天依然是值得研究的课题。

文章会从麦卡锡的学术背景讲起,梳理“人工智能”这个概念的由来,解释一阶逻辑、情境演算、非单调逻辑这些听起来抽象、但在实际系统中仍然发挥作用的工具。中间会给出三个可以直接运行的 Python 示例,帮助你理解逻辑推理、行动规划和常识推理的实现思路。最后还会讨论逻辑方法在现代 AI 工程中的位置,以及几个容易踩坑的认知误区。

1. 背景与核心概念:麦卡锡与逻辑主义 AI

1.1 约翰·麦卡锡是谁

约翰·麦卡锡(1927—2011)是美国计算机科学家,1971 年图灵奖获得者,LISP 语言的发明者。他在 1955 年与马文·明斯基、克劳德·香农等人共同发起达特茅斯会议,正式提出了“Artificial Intelligence”这一术语。达特茅斯会议后来被普遍视为人工智能作为独立学科的起点。

麦卡锡的研究风格非常鲜明:他认为智能行为可以而且应该用形式逻辑来表达。程序员把世界知识写成逻辑公式,机器通过推导得出结论。这个思路后来被称为“逻辑主义 AI”或“符号主义 AI”,与基于神经元连接的连接主义路线形成了长期并行的两股力量。

值得注意的是,麦卡锡不仅是一位理论家,他也非常重视工程实现。LISP 就是他在 1958 年左右为 AI 研究设计的编程语言,至今仍在某些符号计算领域使用。他写过程序验证数学定理,也设计过接收邮件、规划行动的早期智能系统,这些工作都贯穿了同一个信念:逻辑是描述知识的最佳语言。

1.2 “人工智能”这个词从哪里来

1955 年,麦卡锡等人提交了一份名为《A Proposal for the Dartmouth Summer Research Project on Artificial Intelligence》的提案。提案中明确写道:人工智能研究的目标是“让机器使用语言、形成抽象和概念、解决目前只有人类才能解决的问题,并改进自身”。

这份提案后来在 1956 年夏天转化为达特茅斯研讨会。虽然会议规模不大,但参与者几乎都是后来 AI 领域的奠基人物。正是在这段时期,“人工智能”作为一个学术方向被确定下来。麦卡锡本人倾向于用一种谨慎而精确的方式来定义 AI:不是模拟人的大脑神经元,而是描述智能行为背后的逻辑结构。

这个定义影响了之后几十年的研究走向。许多早期 AI 系统,比如专家系统、定理证明器、规划系统,走的都是“知识 + 推理”的路线。它们不依赖海量数据,而是依赖精心编写的规则和知识库。

1.3 什么是逻辑主义 AI

逻辑主义 AI 的核心可以概括为一句话:知识用逻辑公式表示,推理用逻辑规则完成。

举个例子。如果知识库里有两条公式:

  • 所有人都终有一死。
  • 苏格拉底是人。

那么逻辑推理系统可以自动推导出:苏格拉底终有一死。

这个模式看起来简单,却包含了一个非常强的假设:世界上的知识可以被编码为形式化语言。麦卡锡并不认为所有知识都能轻松变成公式,但他相信这是一个值得追求的目标。他在多篇论文中反复强调,常识推理是 AI 最困难也最核心的问题,而逻辑是研究这个问题的合适框架。

逻辑主义 AI 在 20 世纪 60 到 80 年代非常兴盛,后来因为知识获取困难、推理效率低、难以处理不确定性等缺点而受到批评。但它的思想遗产一直延续着,今天的知识图谱、语义网、规则引擎、规划算法,本质上都带有逻辑主义 AI 的基因。

1.4 为什么现在还要回头看麦卡锡

当前深度学习的成功让很多人产生了“AI 就是统计学习”的错觉。但仔细看工业界,逻辑方法依然活跃:银行的规则引擎、电商的促销策略配置、医疗知识库的推理校验、自动驾驶的行为决策……这些场景都需要显式的规则和可控的推理,不能完全交给黑盒模型。

麦卡锡当年问的问题——“如何让机器理解并运用常识”——至今没有完全解决。大语言模型在自然语言任务上表现惊人,但它对物理世界常识的理解是否可靠,仍然存在争议。回头看麦卡锡的工作,并不是要否定深度学习,而是帮我们理解 AI 的另一个维度:如何把知识表示得让机器能推理、能解释、能验证。

2. 为什么 AI 需要形式化常识

2.1 常识推理和普通推理的区别

普通推理指的是从明确的前提出发,推导出必然结论。比如:

  • 前提 1:今天下雨。
  • 前提 2:如果下雨,地面会湿。
  • 结论:地面湿了。

这种推理是确定性的,逻辑教科书上讲的大部分内容都属于这一类。但人类的大量日常推理并不是这样的。我们经常使用一些“默认成立但允许例外”的规则,比如说:

  • 鸟会飞。

这句话在绝大多数情况下成立,但当我们知道某只鸟是企鹅时,就会自动推翻这个结论。这种“默认成立、例外推翻”的推理,就是麦卡锡所说的常识推理。

常识推理看起来简单,却非常难形式化。问题在于:一个知识系统如何知道“企鹅是鸟”,却又不至于错误地推出“企鹅会飞”?如何让机器知道“人一般有两只手”,但遇到特殊情况时又能接受例外?这些在人类看来自然的判断,机器处理起来并不容易。

2.2 形式化的价值

可能有人会问:既然常识这么难形式化,为什么还要坚持做?直接用统计模型不是更省事吗?

形式化的价值在于它带来了精确性和可验证性。一条逻辑规则写清楚后,机器可以严格证明结论是否正确;知识库出现矛盾时,逻辑系统可以定位到哪些公式互相冲突;系统做出决策时,推理链可以完整回放,让人知道“为什么这样决定”。

这在涉及安全、合规、审计的场景中特别重要。比如银行审批贷款,如果系统拒绝了一位客户,金融监管机构可能要求解释原因。规则引擎可以给出完整的推理路径:收入不达标、征信记录不良、负债率过高等。而一个纯神经网络模型很难提供同样透明的解释。

麦卡锡坚持形式化常识,本质上是在追求一种“可解释、可验证的智能”。这个追求并没有因为深度学习的兴起而过时。

2.3 经典难题:Tweety 问题

“Tweety 问题”是 AI 常识推理中最著名的例子之一。Tweety 是一只鸟,根据默认规则“鸟会飞”,我们倾向于推断 Tweety 会飞。但如果后来知道 Tweety 是一只企鹅,结论就变成了 Tweety 不会飞。

问题在于:经典一阶逻辑是单调的。单调的意思是,如果一条结论已经从前提前提推导出来,那么增加更多前提不会推翻它。也就是说,一旦系统从“鸟会飞”推出“Tweety 会飞”,之后再加入“Tweety 是企鹅”这条信息,就与已有结论产生了矛盾。

人类显然不是这样推理的。我们会根据新证据不断修正旧结论。为了在逻辑系统中容纳这种常识推理,麦卡锡在 20 世纪 70 年代末提出了“限界理论”(Circumscription),专门处理例外的默认规则。这个话题我们会在第 5 节详细展开。

2.4 常识知识库为什么难建

常识知识库的难点不仅是规则怎么写,还在于知识的体量极其庞大。麦卡锡本人曾参与过 Cyc 项目的早期讨论——Cyc 是道格拉斯·莱纳特发起的项目,目标就是把人类常识编码成机器可读的知识库。Cyc 花了数十年、积累了数百万条常识公式,但距离覆盖完整的“人类常识”依然遥远。

除了数量大,常识还具有上下文敏感性。“椅子”在客厅里是坐具,在拍卖会上是标的物,在仓库里是库存。一个概念在不同的上下文中含义不同,这在逻辑系统中很难建模。麦卡锡后来提出了“上下文逻辑”(Context Logic)来应对这个问题,但至今没有形成一套普遍接受的解决方案。

3. 一阶逻辑在 AI 中的基础用法

3.1 谓词、常量和量词

要理解逻辑 AI,首先要掌握一阶逻辑的基本元素。一阶逻辑包含:

  • 常量(Constant):表示具体的个体,比如socratestweety
  • 变量(Variable):表示未确定的个体,常用XY表示。
  • 谓词(Predicate):表示个体之间的关系或属性,比如human(socrates)表示“苏格拉底是人”。
  • 量词(Quantifier):forall表示“对所有”,exists表示“存在”。
  • 逻辑连接词:andornotimplies

一条典型的规则是:

forall X: human(X) -> mortal(X)

读作“对于所有 X,如果 X 是人,那么 X 终有一死”。

知识库就是一组由谓词公式构成的事实和规则。推理器的工作,就是把规则与事实匹配起来,生成新事实。

3.2 用 Python 实现一个极简前向链推理器

前向链(Forward Chaining)是一种常见的推理策略:从已知事实出发,反复应用规则,推导出新的结论。下面用一个极简代码演示这个过程。

# -*- coding: utf-8 -*- """ 极简前向链推理器 规则:人都是会死的 事实:苏格拉底是人 目标:证明苏格拉底会死 """ knowledge_base = [ { "description": "人都是会死的", "antecedents": [("human", "X")], "consequent": ("mortal", "X") } ] facts = {("human", "socrates")} def substitute(atom, mapping): """将规则中的变量替换为具体个体""" pred, var = atom if var in mapping: return (pred, mapping[var]) return atom def forward_chaining(kb, facts, target): """前向链推理主流程""" max_steps = 10 for step in range(max_steps): derived = set() for rule in kb: for fact in facts: pred, arg = rule["antecedents"][0] fact_pred, fact_obj = fact if pred == fact_pred: mapping = {arg: fact_obj} consequent = substitute(rule["consequent"], mapping) if consequent not in facts: derived.add(consequent) print(f"第 {step + 1} 轮:由 {fact} " f"通过规则“{rule['description']}”得到 {consequent}") if not derived: print("没有新的结论可以推导。") break facts |= derived if target in facts: print(f"目标 {target} 成立。") return True return False if __name__ == "__main__": print("初始事实:", facts) forward_chaining(knowledge_base, facts, ("mortal", "socrates"))

这段代码虽然简单,但包含了一个推理系统的基本结构:知识库、事实集合、规则匹配、变量替换、循环推导。真实系统中的规则引擎,比如 Drools 的 Rete 算法,本质上是把同样的思路做了工程级优化,可以应对数十万条规则。

3.3 运行结果与解读

直接运行上面的代码,输出如下:

初始事实: {('human', 'socrates')} 第 1 轮:由 ('human', 'socrates') 通过规则“人都是会死的”得到 ('mortal', 'socrates') 目标 ('mortal', 'socrates') 成立。

这个例子说明了逻辑 AI 最核心的机制:规则加事实,通过推理产生新知识。现代知识图谱中的推理也采用类似模式。例如,当图谱中有“马云是阿里巴巴创始人”和“阿里巴巴是一家中国公司”时,通过规则可以推出“马云与中国的公司有关联”。

3.4 一阶逻辑的边界

一阶逻辑表达力很强,但不是万能的。它有两个明显的限制:一是表达不确定性和概率比较困难;二是规则一旦写入,就要求严格一致,真实世界中常见的不一致信息会让经典逻辑系统崩溃。

麦卡锡很清楚这些限制。他提出常识形式化问题时,并没有要求用标准的一阶逻辑解决所有问题,而是不断扩展逻辑框架,比如增加时间维度、行动维度、默认规则等。这些扩展构成了 20 世纪 70 到 80 年代逻辑 AI 研究的主要线索。

4. 情境演算:形式化行动与变化

4.1 为什么需要行动逻辑

世界上有很多知识是关于“动作”和“变化”的。机器人把一个箱子从 A 点推到 B 点,路径规划系统决定车辆从当前位置行驶到目的地,智能助理安排会议并发送邀请……这些都需要描述“执行某个动作之后,世界变成什么样子”。

麦卡锡在 1963 年研究“猴子与香蕉问题”时,最早尝试用逻辑描述行动。1969 年,他与帕特·海耶斯发表了著名论文《Some Philosophical Problems from the Standpoint of Artificial Intelligence》,正式提出了情境演算(Situation Calculus)这个框架。

情境演算的核心思想是:把世界的历史看成一系列“情境”(Situation),每个情境对应一个世界状态;动作(Action)将一个情境转换为另一个情境;世界的动态属性用“流”(Fluent)表示,比如“箱子在位置 B”。

4.2 基本概念:Situation、Action、Fluent

  • 情境(Situation):世界的一个快照,用符号表示,如s0表示初始情境。
  • 动作(Action):改变世界状态的操作,如go(monkey, window)表示猴子走到窗户旁。
  • 流(Fluent):随情境变化的谓词,如box_at(window, s0)表示在情境 s0 中箱子在窗户旁。

在情境演算中,一条推理链就对应一个动作序列。比如:

s0 -> go(monkey, window) -> s1 s1 -> push(monkey, box, banana) -> s2 s2 -> climb(monkey) -> s3 s3 -> grasp(monkey) -> s4

其中 s3 的情境满足“猴子在箱子上”,s4 的情境满足“猴子拿到香蕉”。

4.3 猴子与香蕉问题的 Python 模拟

为了便于理解,我用 Python 把猴子与香蕉问题简化成一个状态转移系统。每个情境用一个对象表示,动作对应一个函数,函数接收情境并返回新情境。

# -*- coding: utf-8 -*- """ 猴子与香蕉问题的情境演算模拟 场景:猴子在门口,箱子在窗户下,香蕉挂在房间中央上方 目标:猴子拿到香蕉 行动条件: 1. 猴子必须走到箱子旁 2. 猴子必须把箱子推到香蕉正下方 3. 猴子必须爬上箱子 4. 猴子必须伸手抓香蕉 """ class Situation: def __init__(self, monkey_at="door", box_at="window", on_box=False, has_banana=False): self.monkey_at = monkey_at self.box_at = box_at self.on_box = on_box self.has_banana = has_banana def __repr__(self): return (f"Situation(monkey_at={self.monkey_at}, " f"box_at={self.box_at}, on_box={self.on_box}, " f"has_banana={self.has_banana})") def go(s, target): """行动:猴子走到 target 位置 前提:猴子没有在箱子上,否则无法移动 """ if not s.on_box: return Situation(monkey_at=target, box_at=s.box_at, on_box=s.on_box, has_banana=s.has_banana) return s def push(s, target): """行动:猴子把箱子推到 target 位置 前提:猴子与箱子在同一位置 """ if s.monkey_at == s.box_at: return Situation(monkey_at=target, box_at=target, on_box=s.on_box, has_banana=s.has_banana) return s def climb(s): """行动:猴子爬上箱子 前提:猴子与箱子在同一位置 """ if s.monkey_at == s.box_at: return Situation(monkey_at=s.monkey_at, box_at=s.box_at, on_box=True, has_banana=s.has_banana) return s def grasp(s): """行动:猴子拿香蕉 前提:猴子在箱子上,且箱子在香蕉正下方 """ if s.on_box and s.box_at == "banana_pos": return Situation(monkey_at=s.monkey_at, box_at=s.box_at, on_box=s.on_box, has_banana=True) return s if __name__ == "__main__": s0 = Situation() print("初始状态:", s0) s1 = go(s0, "window") print("走到箱子旁:", s1) s2 = push(s1, "banana_pos") print("推箱子到香蕉下:", s2) s3 = climb(s2) print("爬上箱子:", s3) s4 = grasp(s3) print("拿到香蕉:", s4)

这里每个函数都检查了前提条件。背景是麦卡锡研究中的“动作前提”概念:不是所有动作在所有情境下都合法。比如猴子不在箱子旁时,climb动作不能执行。这个设计在后来演变成了机器人规划中的“前提-效果”表示法。

4.4 框架问题:比表面看起来更麻烦

当你用逻辑描述一个动作时,会立刻遇到一个棘手的问题:执行动作后,哪些事实保持不变?

还是用猴子问题的例子。猴子从门口走到窗户旁,这个动作改变了monkey_at的值,但箱子的位置没有变,天花板的高度没有变,墙壁的颜色没有变。如果逻辑系统要为每个动作显式写出所有“不受影响”的属性,知识库会变得极其庞大。这就是 AI 中的“框架问题”(Frame Problem)。

麦卡锡和海耶斯在 1969 年的论文中明确指出了框架问题。这个问题看起来像是技术细节,实际上触及了知识表示的核心:我们如何在继承“大多数属性不因动作改变”的默认判断,同时又不漏掉那些真正会发生变化的属性?这个问题催生了很多后续工作,包括非单调逻辑、动作语言、计划规划算法等。

5. 非单调逻辑与中间结论

5.1 单调性的局限

经典逻辑有一个重要性质:单调性(Monotonicity)。用大白话说就是:已经推出的结论,不会因为加入新前提而被撤回。

单调性对数学推理是正确的。但在常识推理里,这个性质反而成了障碍。我们前面提到的 Tweety 例子是典型的反例:系统一开始会合理推出“Tweety 会飞”,加入“Tweety 是企鹅”后,这个结论应该被撤回。

麦卡锡敏锐地意识到:要让逻辑系统支持常识推理,必须放弃严格的单调性。他提出了一套名为“限界理论”(Circumscription)的方法,后来通常译作“中间结论”或“最小模型推理”。

5.2 Circumscription 的核心思想

限界理论的基本想法是:当系统默认一个命题为真时,只把满足该命题的对象限制为“目前已知的、能推导出的那些”,不默认存在未知的反例。

具体到“鸟会飞”的例子:

  • 系统知道 Tweety 是一只鸟。
  • 系统默认“鸟会飞”。
  • 系统不知道 Tweety 是否是企鹅。
  • 于是推导出 Tweety 会飞。
  • 如果之后加入“Tweety 是企鹅”,这条新信息推翻默认结论,系统不再认为 Tweety 会飞。

限界理论的关键在于“默认”机制。它允许系统在缺少反例信息时做出假设,并在反例出现后收回假设。这种推理方式被称为“非单调推理”(Non-monotonic Reasoning)。

5.3 用默认规则模拟常识推理

下面这段代码模拟了“默认规则 + 例外处理”的常识推理过程。它不涉及完整的限界理论,但呈现出同样的问题结构和处理方式。

# -*- coding: utf-8 -*- """ 常识推理模拟:鸟会飞,但企鹅例外 规则:鸟( X ) 且 X 不是企鹅 -> 会飞( X ) """ birds = {"tweety", "polly", "pengy"} penguins = {"pengy"} can_fly = set() for bird in birds: if bird not in penguins: can_fly.add(bird) print(f"{bird} 是鸟,且没有证据表明它是企鹅 → 默认它会飞") else: print(f"{bird} 是企鹅 → 默认规则被推翻,它不会飞") print("会飞的鸟:", can_fly)

运行结果:

tweety 是鸟,且没有证据表明它是企鹅 → 默认它会飞 polly 是鸟,且没有证据表明它是企鹅 → 默认它会飞 pengy 是企鹅 → 默认规则被推翻,它不会飞 会飞的鸟: {'tweety', 'polly'}

这个例子会带给你一个核心感受:常识推理的真实形态不是“永远正确”,而是“在相对充足证据下尽量合理”。麦卡锡追求的并不是让机器变成百科全书,而是让机器具备根据不完整信息做合理假设的能力。

5.4 对后续逻辑学的影响

限界理论不是唯一处理默认推理的方案。同时期还有赖特的“默认逻辑”(Default Logic)和麦卡锡的“限界逻辑”相互竞争又互相启发。这些研究共同奠定了非单调逻辑这一分支,深刻影响了人工智能中的知识表示、信念修正、数据库视图更新等方向。

今天你在规则引擎里看到的salience(规则优先级)、activation group(激活组)等机制,本质上就是在工程层面处理“默认规则何时生效、何时失效”的问题。理解非单调逻辑,会让你设计规则系统时看得更深一层。

6. 麦卡锡遗产在现代 AI 中的体现

6.1 Prolog 与规则引擎

要感受逻辑 AI 的现代生命力,最直接的方式是接触 Prolog。20 世纪 70 年代初诞生的 Prolog 把逻辑程序设计变成现实:程序员声明事实和规则,运行时系统自动完成推理和回溯。很多早期专家系统就是用 Prolog 写的。

在工程领域,规则引擎比 Prolog 更为常见。比如 Java 生态中的 Drools,允许业务人员用类似“When 条件 Then 动作”的语法配置规则,系统运行时根据事实匹配规则并触发动作。这种设计在风控、定价、审批等业务中大量存在。本质上,它们仍然延续了麦卡锡的工作:用逻辑表达式描述业务知识,用推理机制自动执行决策。

6.2 描述逻辑与知识图谱

知识图谱是当前工业界应用最广的知识表示技术之一。它的数学基础是描述逻辑(Description Logic),一种比一阶逻辑表达力更弱、但推理复杂度更可控的逻辑系统。Google 的知识图谱、电商的商品关系网络、金融领域的实体关系分析,都大量使用这一套思想。

描述逻辑与一阶逻辑的关系可以理解为:牺牲一部分表达力,换取更高效、可判定的推理。这正是麦卡锡“知识表示要同时考虑表达力和计算效率”这一思路的延续。你如果接触过 OWL、SPARQL、RDFS,其实就是在使用逻辑主义 AI 的现代版本。

6.3 逻辑与大语言模型的互补

虽然大语言模型在很多任务上表现出色,但它本质上是基于概率的文本生成系统,不是严格逻辑推理器。它可能知道“苏格拉底是人”和“人都会死”,却不保证能稳定推出“苏格拉底会死”。特别是涉及长链推理、多步条件判断时,模型的输出可能不一致。

所以现在很多研究开始做“符号逻辑 + 大模型”的融合:用大模型完成自然语言理解和知识抽取,再用逻辑推理器完成严格的推导和验证。Google 的 GraphCast、各类知识图谱问答系统、微软的 Logic Integrator 等方向,都是这个思路的代表。麦卡锡如果看到今天,或许会欣慰:他坚持的逻辑方法并没有消失,只是换了一种方式与统计学习共存。

6.4 学习顺序建议

如果你对逻辑 AI 产生兴趣,可以从这样一条路径入手:

  • 先掌握一阶逻辑的基本语法和语义,能够手写逻辑公式。
  • 用一个简单的推理器(比如本文的 Python 示例)理解前向链和反向链。
  • 学习 Prolog,至少完成几个经典排序、家族关系、路径搜索题目。
  • 了解法律、金融等领域用的规则引擎,读 Drools 官方文档。
  • 再进入描述逻辑和知识图谱,理解 OWL 的建模思路。
  • 最后回到常识推理,读麦卡锡的经典论文,比如《Some Philosophical Problems from the Standpoint of Artificial Intelligence》。

这条路线从形式逻辑出发,经过工程化实现,最后回到理论问题,对理解 AI 的全貌很有帮助。

7. 常见问题与误区

7.1 常见问题速查

下表总结了逻辑 AI 学习中最常见的问题、可能原因和实践建议。

问题现象常见原因解决思路
觉得逻辑 AI 过时了被深度学习热点影响,忽视了知识图谱和规则引擎的工业应用调研 Drools、知识图谱、专家系统的实际部署案例
一阶逻辑表达不了复杂知识对逻辑表达能力边界理解不足学习高阶逻辑、模态逻辑、描述逻辑的区别
推理系统运行很慢知识库过大或推理策略不当换用高效模式匹配算法,或降低逻辑表达力
规则总出现矛盾默认规则与例外规则没有合理分层引入优先级、非单调逻辑思想
分不清“逻辑”在 AI 和硬件中的区别术语多义性明确语境:AI 逻辑是符号推理,硬件逻辑是电路状态
不理解为什么要学 McCarthy 的思想将 AI 等同于神经网络了解 AI 历史与知识表示在企业系统中的作用

7.2 重点误区澄清

第一个误区是“逻辑 AI 就是专家系统,早就过时了”。实际上专家系统只是逻辑 AI 的一种应用形态。知识图谱、语义网、规则引擎、规划系统都还在广泛使用逻辑方法。说它过时,就像说“深度学习的卷积网络过时了”一样不准确。

第二个误区是把“AI 里的逻辑”与硬件中的“逻辑分析仪”混为一谈。在数字电路领域,logic analyzer是一种硬件调试工具,用来采集数字信号时序;在 AI 领域,logic指符号推理系统。两者只是同一个英文单词,技术栈完全不同。看到“逻辑”这个词,先分清上下文,再讨论技术方案。

第三个误区是认为一阶逻辑可以表达所有知识。一阶逻辑无法表达“大多数”“通常”“大约”这类带程度和统计性质的知识。麦卡锡提出非单调逻辑和上下文逻辑,正是为了弥补这些缺口。理解一个形式系统的边界,往往比理解它的能力更重要。

7.3 如何排查推理结果不符合预期

如果你在实际项目中写了一个规则系统,但推理结果与预期不符,可按下面的顺序排查:

  1. 检查事实是否完整。很多问题是因为遗漏了关键事实。
  2. 检查规则前件是否写错。特别是变量名是否统一,比如一个规则里用了大写 X,另一个规则里用了小写 x。
  3. 检查是否有默认规则与例外规则冲突。确认异常分支优先级是否更高。
  4. 检查规则是否出现无限循环。观察推理轮数是否超过预期。
  5. 用最小知识库手工模拟推理,比较手工结果和系统输出。

这个排查顺序在规则系统开发中非常实用,可以节省大量调试时间。

8. 最佳实践与工程建议

8.1 选型:什么场景适合逻辑方案

并不是所有 AI 问题都适合用逻辑方法。我建议用下面几个标准判断:

  • 需要可解释性:比如金融风控、医疗诊断、法律合规,推理过程需要能审计。
  • 知识结构清晰:领域规则明确、关系稳定,适合写成公式或规则。
  • 数据量有限:不想依赖大量标注数据,希望通过人工知识构建系统。
  • 需要精确约束:比如工业控制系统中的安全限制,必须保证某些边界条件百分之百成立。

如果需求是图像识别、自然语言生成、语义匹配等感知类任务,那么神经网络仍然是更可靠的选择。逻辑方法与深度学习的核心差异在于:前者擅长处理“规则明确、需要解释”的决策,后者擅长处理“特征复杂、模式模糊”的感知。

8.2 知识库设计原则

设计知识库时,优先考虑下面几条原则:

  • 原子化规则:一条规则只表达一个结论,避免大而全的规则。
  • 变量命名统一:全局约定变量名的范围和命名规范,防止连错变量。
  • 分层组织:将通用规则、领域规则、用户特殊规则分层存放,便于维护和权限控制。
  • 版本管理:规则变更影响面大,知识库本身也应该纳入版本控制系统。
  • 冲突检测:在发布规则前运行冲突检测工具,比较不同规则之间的前置条件和结论。

在麦卡锡的框架里,知识库不仅是数据,更是一种“理论”。理论会演进,会出错,需要被不断修正。把知识库当软件工程对待,能减少很多上线后的意外。

8.3 推理性能优化

逻辑推理的性能瓶颈通常出现在规则匹配阶段。最简单的情形是:每条规则都要扫描全部事实,时间复杂度是 O(规则数 × 事实数)。随着规模增长,这种暴力匹配会变得不可接受。

实用的优化方向包括:

  • 使用索引:按谓词名建立事实索引,减少无效匹配。
  • 使用 Rete 算法:Drools、Jess 等现代规则引擎采用的就是这种高效模式匹配算法。
  • 限制知识库范围:按业务域切分知识库,避免跨域规则全局运行。
  • 使用前向链与反向链的混合策略:根据查询目标选择起点,减少无效推导。

8.4 开放世界假设与封闭世界假设

知识表示领域有两个基础设定,初学者很容易混淆:

  • 封闭世界假设(Closed World Assumption,CWA):知识库里没有的事实就是假。数据库系统遵循这个假设。
  • 开放世界假设(Open World Assumption,OWA):知识库里没有的事实是未知,不是假。语义网遵循这个假设。

举个例子:知识库中没有“小明有驾照”,在数据库里就可以推“小明没有驾照”,在语义网里只能推“小明是否有驾照未知”。

麦卡锡的常识推理在很多时候更接近开放世界假设,因为常识知识天然不完整。设计系统时,如果业务要求“未记录即拒绝”,就选择封闭世界;如果业务需要允许未来补充信息,就选择开放世界。两者混用会导致规则语义模糊,结果出现偏差。

8.5 逻辑 + 统计的混合路线

现代 AI 系统极少只用纯逻辑。更常见的模式是:

  • 用深度学习做实体识别和关系抽取,从非结构化文本中获得知识。
  • 将抽取结果转换成逻辑三元组,存入知识图谱。
  • 用规则引擎或描述逻辑推理器保证知识一致性和决策可解释。
  • 再用机器学习为规则添加权重或概率,处理不确定情况。

这种混合架构既保留了逻辑方法可解释、可验证的优点,又能利用深度学习的感知和泛化能力。你可以把麦卡锡的遗产理解成决策层的那部分骨架,深度学习负责输入层的理解,两者互补而不是互斥。

9. 总结

这篇长文围绕约翰·麦卡锡的“人工智能、逻辑与常识形式化”这一主题,梳理了逻辑 AI 的核心脉络。我们从麦卡锡和达特茅斯会议出发,理解“人工智能”这一术语的由来;讨论了一阶逻辑在知识表示中的基础作用,并用 Python 演示了前向链推理;随后介绍了情境演算和经典框架问题,理解了机器描述行动变化的主要方式;再通过 Tweety 问题引入非单调逻辑和限界理论,明白了常识推理为什么无法用经典逻辑直接表达。

三个可运行的 Python 示例分别对应了知识推理、行动规划和常识默认规则,你可以直接复制到本地运行、修改、观察结果。如果你在学习过程中遇到与预期不符的输出,参考第 7 节的排查思路,往往能快速定位问题。

对于想深入学习的读者,建议按下面的顺序继续:先熟练一阶逻辑,再学 Prolog,然后阅读麦卡锡关于情境演算和限界理论的原始论文,最后结合 Drools 或知识图谱工程实践,把这些理论落到真实代码里。理解麦卡锡的意义,不在于记住一个历史人物,而在于真正理解“知识表示 + 推理”在人工智能中的基石地位。当你面对一个新问题时,先问一句:这适合用逻辑来描述吗?如果适合,就试着把知识写下来,让机器推一推。你会发现,这套诞生于几十年前的方法,在今天依然充满生命力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询