元数据卡
- 前置知识:ch01 搜索算法、Vol 10 概率论
- 预计时间:45 分钟
- 核心难度:进阶
- 阅读模式:高度专注
- 完成标志:能构建逻辑推理系统、表示约束满足问题、理解贝叶斯网络的推理机制
你的进度
模型工坊的第一张工作台上,你学会了搜索——在已知空间中找路。
但阿花下封信里问:“如果知识本身就不完整呢?”你放下信纸,看向第二张工作台。这里有另一套工具:逻辑推理、概率网络——不是找路,而是在不确定性中做判断。
你的任务
搜索假设你能枚举所有状态。但现实中,知识往往是碎片化的、有噪声的。你需要一种"表示"来封装知识,再配一套"推理"机制来得出新结论。本章走三条路:逻辑(确定性)、CSP(约束驱动)和贝叶斯网络(概率驱动)。
本章分层
- 必读:命题逻辑推理、约束满足问题、贝叶斯网络表示
- 选读:贝叶斯网络精确推理与近似推理
- 进阶:将知识表示视为搜索空间的设计问题
破局 · 溯源
你看到一个规则:"如果下雨,地上会湿。"现在地上是湿的——你得出结论:下过雨。这个推理对吗?它依赖一个隐含假设:没有其他原因能让地变湿。你做了"假言推理"(Modus Ponens)的反向——但在现实逻辑中,这属于"肯定后件"谬误。
真正可靠的知识系统,不仅要能推理,还要能评估推理的可靠性。这就是本章的出发点。
命题逻辑与推理
命题逻辑是最朴素的知识表示语言。每个命题取真或假,用逻辑连接词(→, ∧, ∨, ¬)组合。
# 简单的基于规则的推理引擎
rules = [
("下雨", "地湿"), # 下雨 → 地湿
("地湿", "地面打滑"), # 地湿 → 地面打滑
]
def forward_chain(facts, rules):
"""前向链推理:从已知事实推导新事实"""
known = set(facts)
changed = True
while changed:
changed = False
for premise, conclusion in rules:
if premise in known and conclusion not in known:
known.add(conclusion)
changed = True
return known
facts = forward_chain(["下雨"], rules)
print(facts) # {'下雨', '地湿', '地面打滑'}前向链从已知事实出发,反复应用规则直到饱和。后向链则从目标出发,逆向搜索:要证明"地面打滑",需要证明"地湿",需要证明"下雨"。
约束满足问题
现实推理中很多是约束驱动的。比如排课:每个老师不能在同一时间上两门课,每门课有固定教室容量——你是在满足所有约束的前提下,找到一个赋值。
CSP 用变量、值域、约束三元组建模:
from itertools import product
def backtrack_search(variables, domains, constraints):
"""回溯搜索解决 CSP"""
assignment = {}
def consistent(var, value, assignment):
return all(
constraint(var, value, v, assignment[v])
for v in assignment
for constraint in constraints.get((var, v), [])
)
def search(assignment):
if len(assignment) == len(variables):
return assignment
var = next(v for v in variables if v not in assignment)
for value in domains[var]:
if consistent(var, value, assignment):
assignment[var] = value
result = search(assignment)
if result:
return result
del assignment[var]
return None
return search({})示例:地图着色——相邻区域不能用同色。
variables = ['WA', 'NT', 'SA', 'Q', 'NSW', 'V', 'T']
domains = {v: ['R', 'G', 'B'] for v in variables}
constraints = {}
pairs = [('WA','NT'),('WA','SA'),('NT','SA'),('NT','Q'),
('SA','Q'),('SA','NSW'),('SA','V'),('Q','NSW'),
('NSW','V')]
for a, b in pairs:
constraints[(a,b)] = [lambda x, xv, y, yv: xv != yv]
print(backtrack_search(variables, domains, constraints))
# {'WA': 'R', 'NT': 'G', 'SA': 'B', 'Q': 'R', 'NSW': 'G', 'V': 'R', 'T': 'R'}CSP 的难点不在表达力,在搜索效率。变量顺序和值序的启发式(MRV、度启发式、最小约束值)能极大影响回溯次数。
贝叶斯网络
逻辑系统不能处理不确定性。贝叶斯网络用图结构表示变量间的概率依赖关系:节点是随机变量,有向边表示"直接影响",每个节点有一个条件概率表。
# 一个简单的贝叶斯网络推理
# 事件:下雨 → 地湿
# 洒水器 → 地湿
# 下雨 和 洒水器 独立
import numpy as np
class BayesNet:
def __init__(self):
self.nodes = {}
self.cpts = {}
def add_node(self, name, parents, prob_table):
self.nodes[name] = parents
self.cpts[name] = prob_table
# 给定证据,用枚举法计算边际概率
def enumeration_ask(query, evidence, net):
"""枚举所有隐变量来计算 P(query | evidence)"""
hidden = [v for v in net.nodes if v not in evidence and v != query]
return _enumerate_all(net.variables(), evidence, hidden, net)
# 实际推理用变量消除法更高效
def variable_elimination(net, query, evidence, ordering):
"""变量消除法"""
factors = []
for var in net.variables():
factor = net.make_factor(var, evidence)
factors.append(factor)
for var in ordering:
if var not in query and var not in evidence:
factors = _sum_out(var, factors)
result = _normalize(_pointwise_product(factors))
return result贝叶斯网络的精确推理是 NP-hard(变量消除在最坏情况下指数级复杂度),因此大网络通常用近似推理如吉布斯采样、似然加权。
常见陷阱
- 逻辑系统中的"封闭世界假设":没被证明真就视为真?还是没被证明真就视为假?换在 AI 语境下就是默认否定还是默认肯定。
- CSP 中约束的一致性与可满足性不同——保证节点一致、弧一致不一定保证解存在。
- 贝叶斯网络的条件独立假设是关键——如果你加入的条件概率表不满足图结构,推理会出错。
- 贝叶斯网络的方向性决定了因果关系,但相关不等于因果——两个观测变量相关可能来自第三个未观测的共因。
通关挑战
- 热身(15 分钟):实现一个后向链推理引擎,输入目标"地面打滑",输出需要哪些初始事实。
- 挑战(30 分钟):用 CSP 实现一个简单的数独求解器(9x9,回溯 + MRV 启发式)。
- 观察:构建一个 3 节点的贝叶斯网络(A→B→C),给定 P(A)、P(B|A)、P(C|B),计算 P(B|C=1)。对比枚举法和变量消除法的步骤数。
旅人笔记
知识表示决定了 AI 系统能"想"什么,推理机制决定了它"怎么想"。逻辑给出保证,概率给出灵活性,两者的结合是通向真正智能推理的基础。
-> 下一站预告
光会搜索和推理还不够——智能体需要在没有完整知识的情况下,通过与环境交互来学习。这就是强化学习要做的事。