UCB-CS188-人工智能导论笔记-全-

UCB CS188 人工智能导论笔记(全)

🧠 课程 P1:人工智能导论与理性智能体

在本节课中,我们将要学习人工智能的基本概念,特别是理性智能体的定义,并初步了解如何将现实世界问题建模为搜索问题。我们将从人工智能的流行文化形象和历史发展开始,逐步深入到其核心定义和课程结构。

📜 人工智能的定义与历史

上一节我们介绍了课程的基本信息,本节中我们来看看人工智能的定义及其发展历程。

人工智能是一个模糊的术语。一种定义方式是:人工智能是制造能够像人一样思考的机器的科学。另一种定义则关注结果:人工智能是制造能够产生与人类相同结果的机器的科学。我们还可以从逻辑推理的角度定义:人工智能是制造能够理性思考的机器的科学。在本课程中,我们将主要关注:人工智能是制造能够理性行动的机器的科学

人工智能的概念在流行文化中不断演变。从70年代《星球大战》中乐于助人的C-3PO和R2-D2,到21世纪初《黑客帝国》中控制人类的AI,再到近年《西部世界》中难以与人类区分的AI,反映了社会对AI认知的变化。

人工智能的学术发展经历了几个阶段:

  • 早期(50-70年代):人们尝试将世界运作的所有逻辑规则编写成程序,让计算机进行推理。
  • AI寒冬(80-90年代):编写所有规则的难度导致进展缓慢,资金和兴趣减少。
  • 现代(近期):重点转向利用大量数据建立统计模型,让AI从经验中学习并做出预测。

人工智能发展中的里程碑事件包括:

  • 1997年:IBM“深蓝”计算机击败国际象棋世界冠军加里·卡斯帕罗夫。
  • 2011年:IBM“沃森”在智力竞赛节目《危险边缘》中击败人类冠军。
  • 2016年:谷歌“AlphaGo”击败围棋世界冠军李世石。

⚙️ 理性智能体与核心概念

上一节我们回顾了AI的历史,本节中我们来看看本课程的核心框架:理性智能体。

我们使用“智能体”一词来指代程序、机器人或任何试图根据指令行事的实体。一个理性智能体的核心目标是:最大化其预期效用

让我们分解这个定义:

  • 最大化:意味着我们试图在某种度量上做到最好。我们需要算法来寻找函数的最大值。
  • 你的:指代智能体服务于谁或什么目的。这定义了智能体的目标。
  • 预期:世界不是确定性的。智能体必须对未来不确定性进行建模。
  • 效用:是对智能体成功程度的度量,类似于奖励。我们需要定义如何衡量智能体的表现。

这个公式 最大化预期效用 是本课程的核心。

🗺️ 将问题建模为搜索

上一节我们定义了理性智能体,本节中我们来看看如何让智能体通过“计划”来理性行动,这引出了“搜索问题”。

智能体有两种基本类型:

  1. 反射型智能体:仅根据当前对世界的观察(感知)立即决定行动。
  2. 计划型智能体:会考虑采取行动后可能发生的未来状态,从而选择能带来更好结果的行动序列。

为了进行计划,我们需要将问题形式化为搜索问题。一个搜索问题需要精确定义以下几个部分:

  • 状态空间 S:世界所有可能状态 s 的集合。
  • 后继函数 Succ(s, a):给定状态 s 和行动 a,返回下一个状态 s'。它编码了状态间的转换规则。
  • 开始状态 s_start:问题的初始状态。
  • 目标测试 IsGoal(s):一个函数,判断给定状态 s 是否为目标(满足)状态。

解决方案是一系列行动 <a1, a2, ..., an>,使得从 s_start 开始,连续应用后继函数,最终能到达一个满足 IsGoal(s) 的状态。

建模示例:罗马尼亚旅行问题

假设我们的问题是:从城市 Arad 出发,到达城市 Bucharest。

以下是我们如何将其建模为搜索问题:

  • 状态空间 S:我们关心的只是智能体位于哪个城市。因此,状态就是城市名,如 "Arad", "Sibiu", "Bucharest" 等。我们抽象掉了汽油、交通、天气等细节。
  • 后继函数 Succ(s, a):如果当前状态是 "Arad",行动 a 是“去Sibiu”,那么下一个状态就是 "Sibiu"。该函数编码了地图上的道路连接。
  • 开始状态 s_start"Arad"
  • 目标测试 IsGoal(s):判断状态 s 是否等于 "Bucharest"

通过这种形式化,我们可以设计通用的搜索算法(如BFS、DFS)来解决任何符合此模型的问题。

状态空间的设计

设计状态空间是关键,也是难点。我们需要包含解决问题所必需的所有相关细节,同时忽略不相关的细节以控制状态空间的大小。

  • 吃豆人路径问题:状态只需包含吃豆人的 (x, y) 坐标。状态空间较小。
  • 吃豆人吃光所有点问题:状态需要包含吃豆人的 (x, y) 坐标 以及 每个点是否已被吃的布尔值列表。状态空间变得非常大。

📚 课程概述与总结

在本节课中,我们一起学习了人工智能的多种定义,理解了理性智能体的核心是最大化预期效用。我们探讨了AI的历史与现状,并初步学习了如何将现实世界问题抽象并形式化为搜索问题,这涉及定义状态空间、后继函数、开始状态和目标测试。

本课程的前半部分将聚焦于来自计算的智能,即设计算法(如搜索、约束满足、博弈)使智能体理性行动。后半部分将转向来自数据的智能,即利用数据训练模型以实现理性行为。我们还将探讨AI在机器人、自然语言处理等领域的应用。

请记住,AI技术存在于现实社会,伴随伦理和责任问题。构建智能体时,严谨的建模和对其潜在影响的思考至关重要。

课程 P10:[CS188 SP23] 第九讲 - 游戏:树、极大极小、剪枝 🎮

在本节课中,我们将学习如何将搜索算法扩展到多人游戏中。我们将探讨确定性、零和、完全可观察的两人游戏,并学习如何通过构建游戏树、使用极大极小算法以及应用剪枝技术来为智能体(如吃豆人)制定最优策略。


概述 📋

到目前为止,我们讨论的搜索问题都只涉及一个玩家。今天,我们将放松这个限制,看看当搜索问题涉及多个玩家时会发生什么。我们将学习解决这类问题的算法,并理解如何推理它们。这通常被称为对抗性搜索或游戏搜索。


游戏的定义与分类 🧩

上一节我们介绍了搜索问题的基本框架。本节中,我们来看看如何将其扩展到多人游戏中。

一个确定性游戏可以形式化地定义为以下组成部分:

  • 状态空间 S:游戏中所有可能配置的集合。
  • 玩家列表 P:参与游戏的玩家,例如 [1, 2, ..., N]。我们通常假设玩家轮流行动。
  • 动作函数 A(s):在状态 s 下,当前玩家可以采取的所有合法动作的列表。
  • 转移函数 Result(s, a):给定状态 s 和动作 a,返回执行动作后到达的新状态 s‘
  • 终止测试 Terminal-Test(s):判断状态 s 是否为游戏结束状态。
  • 终局效用函数 Utility(s, p):对于终止状态 s 和玩家 p,返回一个数值分数,表示该玩家在游戏结束时的收益。分数越高越好。

与单智能体搜索不同,游戏的解决方案不是一个动作序列,而是一个策略。策略是一个从状态到动作的映射,它告诉玩家在任何可能遇到的状态下应该采取的最佳行动。

游戏可以根据不同参数分类:

  • 确定性 vs 随机性:游戏规则是否包含随机因素(如掷骰子)。
  • 玩家数量:单人、双人或多于两人。
  • 合作 vs 对抗:玩家目标是相互竞争还是可以合作。
  • 完全可观察 vs 部分可观察:玩家是否能完全了解游戏状态(如扑克中看不到对手的牌)。

今天我们主要关注确定性、零和、完全可观察的两人游戏。在零和游戏中,一个玩家的收益恰好是另一个玩家的损失,即 Utility(s, 玩家1) = -Utility(s, 玩家2)


从单人到多人:构建游戏树 🌳

上一节我们定义了游戏。本节中我们来看看如何通过构建游戏树来分析游戏。

首先,回顾单智能体(如吃豆人独自吃豆)的搜索树。这棵树代表了智能体对未来所有可能行动序列的“想象”。在树的叶子节点(终止状态),我们根据游戏规则(如步数惩罚、吃豆奖励)赋予一个效用值。对于非叶子节点,其值定义为:从该状态出发,采取最优行动序列所能获得的最佳效用。由于是单智能体,它总是选择最大化自身效用的行动,因此通过从叶子节点向上传播最大值来计算非叶子节点的值。

现在,引入对手(如幽灵)。我们构建一棵交替行棋的游戏树。根节点是吃豆人(最大化玩家)的回合,其后继节点是幽灵(最小化玩家)的回合,以此类推。这棵树仍然是吃豆人对未来可能性的推演。

在叶子节点(终止状态),我们根据终局效用函数赋值(例如,吃豆人获胜得高分,被抓住得低分)。关键区别在于如何计算非叶子节点的值:

  • 如果轮到最大化玩家(吃豆人),节点值是其所有后继节点值中的最大值。公式表示为:V_max(s) = max_{a in A(s)} V(Result(s, a))
  • 如果轮到最小化玩家(幽灵),节点值是其所有后继节点值中的最小值。公式表示为:V_min(s) = min_{a in A(s)} V(Result(s, a))

这个过程就是极大极小算法。它基于一个核心假设:对手也是理性的,并且会采取对其自身最优(即对吃豆人最不利)的行动。


极大极小算法详解 ⚖️

上一节我们了解了游戏树和值传播的基本思想。本节中我们深入看看极大极小算法的具体过程。

考虑一个简单的两步游戏树。从根节点(吃豆人)开始,递归地计算每个节点的值:

  1. 到达终止状态时,直接返回该状态的效用值。
  2. 在最大化节点,遍历所有子节点,接收它们返回的值,并返回其中的最大值。
  3. 在最小化节点,遍历所有子节点,接收它们返回的值,并返回其中的最小值。

以下是用伪代码描述的算法核心:

def max_value(state):
    if terminal_test(state):
        return utility(state)
    v = -∞
    for action in actions(state):
        v = max(v, min_value(result(state, action)))
    return v

def min_value(state):
    if terminal_test(state):
        return utility(state)
    v = +∞
    for action in actions(state):
        v = min(v, max_value(result(state, action)))
    return v

算法最终会为根节点计算出一个值,并隐含地确定了一条最优行动路径。例如,在井字游戏中,通过极大极小算法可以推导出双方最优玩法会导致平局。

需要注意的是,与单智能体搜索找到目标即停止不同,极大极小算法需要检查游戏树中所有可能的终止状态,才能确定根节点的确切值,因为对手的选择会影响最终结果。


优化:Alpha-Beta 剪枝 ✂️

上一节我们介绍了基础的极大极小算法,但它需要搜索整棵树,在复杂游戏中(如国际象棋)是不现实的。本节中我们来看看如何通过剪枝来大幅减少需要搜索的节点数。

Alpha-Beta 剪枝的核心思想是:在搜索过程中,如果能够断定某棵子树不会影响根节点的最终决策,就可以跳过这棵子树的搜索。

这通过维护两个值来实现:

  • α:在当前路径上,最大化玩家至少能保证得到的效用值(下界)。初始为 -∞。
  • β:在当前路径上,最小化玩家至少能保证得到的效用值(上界)。初始为 +∞。

剪枝规则如下:

  • 最大化节点,如果某个子节点返回的值 v >= β,则可以立即停止搜索该节点的其他子节点(β 剪枝)。因为最小化父节点(其β值)永远不会允许选择这个会导致 v 或更高值的分支。
  • 最小化节点,如果某个子节点返回的值 v <= α,则可以立即停止搜索该节点的其他子节点(α 剪枝)。因为最大化父节点(其α值)永远不会允许选择这个会导致 v 或更低值的分支。

让我们看一个例子。假设在搜索过程中,一个最小化节点当前的 β = 3(意味着其父最大化节点至少能保证得到3)。当探索该最小化节点的第一个子节点时,发现它是一个最大化节点,并且其第一个子节点返回了值 10。由于这个最小化节点会取子节点中的最小值,所以它的值最多是10,但更重要的是,它肯定小于或等于10。然而,这并没有提供足够信息,因为10 > 3 (β),我们还不确定父节点是否会选择这个分支。

继续探索。假设该最大化节点的下一个子节点返回值 2。现在,这个最小化节点的值最多是2(因为2 < 10)。此时,因为 2 <= β (3) 成立,我们可以触发α 剪枝。为什么?因为父最大化节点(其 α 可能为3)知道,如果选择这个分支,它最多只能得到2(由于最小化对手会选择2而不是10)。既然它已经有把握在其他分支上得到至少3,它就绝不会选择这个最多得2的分支。因此,这个最小化节点剩下的未探索子节点都无关紧要了,可以全部剪掉。

Alpha-Beta 剪枝能极大提升搜索效率,最优情况下可以将搜索深度加倍,但它依赖于子节点的探索顺序。好的顺序(先探索可能更优的分支)能触发更多剪枝。


总结 🎯

本节课中我们一起学习了对抗性搜索的基础。

  1. 我们首先将搜索问题扩展到多人、零和、确定性游戏,并给出了形式化定义。
  2. 我们学习了通过构建游戏树来表示玩家对未来的推演,并在树上定义节点的值。
  3. 我们掌握了极大极小算法,该算法通过递归地在最大化节点取max、在最小化节点取min,来计算每个状态对当前玩家的价值,并假设对手总是采取最优行动。
  4. 为了应对游戏树的指数级复杂度,我们引入了Alpha-Beta 剪枝技术。它通过维护 α(下界)和 β(上界)来识别并跳过那些不会影响最终决策的子树搜索,从而显著提高算法效率。

理解这些概念是构建能够玩转吃豆人等游戏的人工智能代理的关键第一步。

课程 P11:游戏算法 - 期望最大化和蒙特卡洛树搜索 🎮

在本节课中,我们将学习两种用于游戏决策的算法:期望最大化和蒙特卡洛树搜索。我们将从回顾Alpha-Beta剪枝开始,然后探讨在对手行为不确定时如何调整我们的模型,最后介绍一种更高效的搜索方法。

回顾:Alpha-Beta剪枝 🔍

上一节我们介绍了极小化极大算法,本节我们来看看如何通过Alpha-Beta剪枝来提高其效率。Alpha-Beta剪枝的核心思想是,在搜索过程中,如果发现某些分支不可能影响最终决策,就跳过对这些分支的探索。

以下是一个简单的Alpha-Beta剪枝示例:

def alpha_beta(node, depth, alpha, beta, maximizing_player):
    if depth == 0 or node.is_terminal():
        return node.evaluate()
    if maximizing_player:
        value = -infinity
        for child in node.children:
            value = max(value, alpha_beta(child, depth-1, alpha, beta, False))
            alpha = max(alpha, value)
            if alpha >= beta:
                break  # Beta剪枝
        return value
    else:
        value = infinity
        for child in node.children:
            value = min(value, alpha_beta(child, depth-1, alpha, beta, True))
            beta = min(beta, value)
            if beta <= alpha:
                break  # Alpha剪枝
        return value

通过剪枝,我们可以避免探索整棵树,从而显著减少计算量。

深度限制搜索与评估函数 📏

由于游戏树可能非常庞大,我们无法进行完整的搜索。因此,我们需要在某个深度停止搜索,并使用评估函数来估计当前状态的价值。

评估函数接受一个游戏状态作为输入,并输出一个数值,表示该状态的好坏。例如,在国际象棋中,评估函数可能会考虑棋子数量、棋盘控制等因素。

设计评估函数时,我们需要提取状态的特征并为其分配权重。公式可以表示为:

评估值 = w1 * f1 + w2 * f2 + ... + wn * fn

其中,f1, f2, ..., fn 是特征值,w1, w2, ..., wn 是对应的权重。

期望最大化:处理不确定性 🎲

在之前的模型中,我们假设对手总是采取最优行动。然而,在现实中,对手可能会犯错,或者游戏本身包含随机因素(如掷骰子)。为了处理这种不确定性,我们引入了期望最大化算法。

期望最大化与极小化极大类似,但在对手的回合,我们不再假设对手采取最小化我们效用的行动,而是假设对手按照某种概率分布行动。我们计算每个可能结果的期望值,而不是最坏情况。

以下是一个期望最大化的伪代码示例:

def expectimax(node, depth):
    if depth == 0 or node.is_terminal():
        return node.evaluate()
    if node.is_max_node():
        value = -infinity
        for child in node.children:
            value = max(value, expectimax(child, depth-1))
        return value
    elif node.is_chance_node():
        value = 0
        for child in node.children:
            prob = child.get_probability()
            value += prob * expectimax(child, depth-1)
        return value

在期望最大化中,机会节点代表不确定性,我们计算其子节点的加权平均值。

蒙特卡洛树搜索 🌳

蒙特卡洛树搜索是一种基于随机模拟的搜索方法,特别适用于那些状态空间巨大或评估函数难以设计的游戏。它通过多次随机模拟来评估每个行动的价值,并逐渐聚焦于更有希望的分支。

蒙特卡洛树搜索包含四个主要步骤:

  1. 选择:从根节点开始,根据一定的策略选择子节点,直到到达一个未完全展开的节点。
  2. 扩展:为选中的节点添加一个或多个子节点。
  3. 模拟:从新添加的节点开始,进行随机模拟直到游戏结束。
  4. 回溯:将模拟结果反向传播到路径上的所有节点,更新它们的统计信息。

通过不断重复这些步骤,蒙特卡洛树搜索能够逐渐逼近最优策略。

总结 📚

本节课我们一起学习了游戏决策中的两种重要算法:期望最大化和蒙特卡洛树搜索。期望最大化通过引入概率模型来处理对手行为的不确定性,而蒙特卡洛树搜索则通过随机模拟来高效地探索巨大的状态空间。这些算法为我们在复杂游戏中做出智能决策提供了强大的工具。

课程 P12:马尔可夫决策过程 (MDP) 入门 🎯

在本节课中,我们将学习马尔可夫决策过程。这是一种用于解决非确定性搜索问题的框架。我们将了解其核心组成部分、如何形式化问题,以及如何计算最优策略。


概述:什么是非确定性搜索?

上一节我们介绍了确定性搜索。本节中,我们来看看当行动结果不确定时会发生什么。

在确定性搜索中,选择一个行动会直接导致一个确定的结果。但在许多现实问题中,行动的结果是不确定的。例如,一个机器人试图穿越悬崖,它选择“前进”时,可能成功,也可能因为地面崩塌而掉入火坑。这种不确定性就是马尔可夫决策过程所要解决的问题。


MDP 的核心组成部分

以下是定义一个 MDP 所需的元素:

  • 状态集合 (S):所有可能情况的集合。
  • 行动集合 (A):在给定状态下可以采取的所有行动。
  • 转移函数 (T):定义了在状态 s 采取行动 a 后,转移到状态 s' 的概率。公式表示为:T(s, a, s') = P(s' | s, a)
  • 奖励函数 (R):定义了在状态 s 采取行动 a 并转移到状态 s' 后,所获得的即时奖励。公式表示为:R(s, a, s')
  • 起始状态 (s₀):代理开始时的状态。
  • 终止状态:游戏或任务结束的状态(可能不止一个)。

运行示例:网格世界

为了便于理解,我们使用一个网格世界作为运行示例。但请记住,并非所有 MDP 都是网格世界。

在这个网格世界中:

  • 一个机器人位于迷宫中。
  • 机器人可以选择向北、南、东、西移动。
  • 关键的非确定性:当机器人选择一个方向(例如“向北”)移动时:
    • 80% 的概率成功向北移动一格。
    • 10% 的概率意外地向东移动一格。
    • 10% 的概率意外地向西移动一格。
    • 向相反方向(南)移动的概率为 0%。
  • 如果移动方向是墙,则机器人停留在原地。
  • 奖励分为两种:
    1. 存活奖励:每存活(移动)一步获得,可能是正数或负数(例如 -0.1)。
    2. 终止奖励:到达终点(如宝石 +1 或火坑 -1)时获得。注意:进入终点格子不会立即获得奖励,必须执行“退出”动作后才能获得。

我们的目标是:最大化累计奖励


策略:解决方案的形式

在确定性搜索中,解决方案是一个行动计划(一系列动作)。但在 MDP 中,由于行动结果不确定,一个固定的行动计划可能无效。

因此,MDP 的解决方案是一个策略 (Policy)

  • 策略是一个从状态映射到行动的函数。
  • 对于每一个可能的状态,它都告诉我们最优的行动是什么。
  • 这就像给机器人一张“地图”,告诉它在每个位置应该怎么做。

折扣因子:未来的价值

在比较奖励时,我们通常认为立即获得的奖励未来获得的奖励更有价值。为了量化这一点,我们引入折扣因子 γ

  • γ 是一个介于 0 和 1 之间的数(通常接近 1,如 0.9)。
  • 如果现在获得奖励 r,其价值就是 r
  • 如果 t 步之后获得奖励 r,其当前价值γ^t * r
  • 这样做有两个好处:
    1. 符合人类“尽早获得回报”的直觉。
    2. 即使游戏可能无限进行,折扣后的累计奖励总和也会收敛,使得计算成为可能。

因此,我们的目标正式定义为:最大化期望折扣奖励总和


价值函数与 Q 函数

为了找到最优策略,我们需要定义两个核心概念:

  1. 状态价值函数 V*(s):表示从状态 s 开始,并在此后一直遵循最优策略所能获得的期望折扣奖励总和

    V^*(s) = \max_{a \in A} Q^*(s, a)
    
  2. Q 函数 Q*(s, a):表示在状态 s选择并锁定行动 a,然后在此后一直遵循最优策略所能获得的期望折扣奖励总和

    Q^*(s, a) = \sum_{s'} T(s, a, s') [ R(s, a, s') + \gamma V^*(s') ]
    

Q 状态是一个中间概念,表示“已决定行动但结果尚未发生”的时刻。


贝尔曼方程:价值的核心关系

V*Q* 的定义结合起来,我们可以得到著名的贝尔曼最优方程

V^*(s) = \max_{a \in A} \sum_{s'} T(s, a, s') [ R(s, a, s') + \gamma V^*(s') ]

这个方程是 MDP 理论的基石:

  • 它表达了一个状态的最优价值其后续状态的最优价值之间的关系。
  • 方程中包含了最大化(选择最佳行动)和期望(对非确定性结果取平均)。
  • 对于每个状态 s,我们都有这样一个方程,它们共同构成了一个方程组。

求解 MDP:从方程到算法

贝尔曼方程本身是一个复杂的方程组(因为含有 max 操作)。我们无法直接解析求解,但可以通过迭代算法来逼近解。

一种基础的思考方式是将 MDP 视为一个期望最大化搜索树。然而,直接展开这棵树效率极低,因为状态会重复出现。

我们将从“期望最大化”的视角出发,推导出更高效的算法(如下一节课将介绍的值迭代策略迭代)。这些算法的核心思想是反复应用贝尔曼方程来更新状态的价值估计,直到它们收敛到最优值。

一旦我们计算出了最优价值函数 V*Q*,最优策略就很容易得到了:

  • 在状态 s,选择能使 Q*(s, a) 最大化的行动 a
  • 或者,选择能导向最高价值后续状态的行动。

总结

本节课中,我们一起学习了马尔可夫决策过程的基础知识:

  1. MDP 是什么:用于建模顺序决策问题,其中行动结果具有不确定性
  2. 核心组件:状态、行动、转移函数、奖励函数、折扣因子。
  3. 解决方案:一个策略,它告诉我们在每个状态下应该采取什么行动。
  4. 优化目标:最大化期望折扣奖励总和
  5. 关键工具状态价值函数 (V*)Q 函数 (Q*)
  6. 核心方程贝尔曼最优方程,它建立了状态价值之间的递归关系。

理解这些概念是学习后续 MDP 求解算法(如值迭代、策略迭代、Q-Learning)的关键。在接下来的课程中,我们将探讨如何实际计算这些价值函数并找到最优策略。

🧠 课程 P13:马尔可夫决策过程与动态规划

在本节课中,我们将学习马尔可夫决策过程的核心概念,并深入探讨如何使用动态规划方法(特别是值迭代和策略迭代)来求解MDP。我们还将初步了解强化学习的基本思想。


📚 概述与回顾

上一节我们介绍了马尔可夫决策过程的基本框架。MDP是一类更广泛的搜索问题,其特点是行动具有不确定性。当你采取一个行动时,会有一个概率分布决定你转移到其他状态的可能性。

每个时间步都可以用三元组 (s, a, s') 来刻画,其中 s 是当前状态,a 是采取的行动,s' 是转移后的状态。转移概率 P(s'|s, a) 和即时奖励 R(s, a, s') 是MDP的核心组成部分。

我们的总体目标是最大化期望折扣奖励总和。由于未来具有不确定性,并且我们希望未来的奖励价值稍低,因此引入了折扣因子 γ

在MDP中,目标不是获得一系列确定的行动,因为结果是不确定的。因此,我们通常需要一个策略 π,它告诉我们在每个特定状态下应该采取什么行动。

到目前为止,我们讨论了状态值函数 V(s)动作值函数 Q(s, a)

  • V(s) 表示从状态 s 开始,在剩余时间内最优行动所能获得的期望折扣奖励总和。
  • Q(s, a) 表示从状态 s 开始,已经选择了行动 a,然后在剩余时间内最优行动所能获得的期望折扣奖励总和。

⚙️ 贝尔曼方程与值迭代

本节中,我们来看看如何计算这些值函数。连接最优行动与未来价值的关键是贝尔曼方程

思考贝尔曼方程的一个有效方式是:要采取最优行动,你需要做对第一步,然后在剩余时间里继续保持最优。这形成了一个递归定义。

最优状态值函数 V*(s) 的贝尔曼方程如下:

V*(s) = max over a ∈ A(s) [ Σ over s' [ P(s'|s, a) * ( R(s, a, s') + γ * V*(s') ) ] ]

这个方程的含义是:在状态 s 下,我们尝试所有可能的行动 a,对于每个行动,我们计算其期望回报(即转移到各个状态 s' 的概率加权平均,加上即时奖励和未来折扣价值),然后选择能带来最大期望值的那个行动。

然而,这个方程本身只定义了最优值应满足的条件,并没有告诉我们如何计算出这些值。为此,我们引入了值迭代算法。

值迭代通过迭代更新来逼近最优值函数:

V_{k+1}(s) = max over a ∈ A(s) [ Σ over s' [ P(s'|s, a) * ( R(s, a, s') + γ * V_k(s') ) ] ]

我们可以从 V_0(s) = 0(假设零时间步长无奖励)开始,反复应用上述更新规则。随着迭代次数 k 的增加,V_k(s) 会收敛到最优值 V*(s)

值迭代可以理解为:

  1. 逐步展开期望树V_k(s) 可以看作是仅考虑未来 k 步的“最优”期望回报。
  2. 不动点迭代:将贝尔曼方程视为一个不动点问题,通过迭代逐步减少估计误差。
  3. 有限时域优化V_k(s) 是在有限时域 k 内的最优值,通过迭代延长时域。

收敛性:当折扣因子 γ < 1 时,值迭代保证收敛。因为未来深层的奖励会被 γ^k 严重折扣,使得迭代更新间的差异呈指数级缩小至零。


🔍 策略评估

上一节我们介绍了如何计算最优值,本节中我们来看看如何评估一个给定的策略。假设现在不是寻找最优策略,而是有人给了我们一个策略 π(可能不是最优的),我们想知道遵循这个策略能获得多少期望奖励。

这被称为策略评估。它与值迭代的关键区别在于,我们不再最大化 over actions,而是直接执行策略规定的行动。

策略 π 下的状态值函数 V^π(s) 的贝尔曼方程如下:

V^π(s) = Σ over s' [ P(s'|s, π(s)) * ( R(s, s, π(s), s') + γ * V^π(s') ) ]

注意,方程中的 max 操作符消失了,因为我们固定了行动 a = π(s)

与值迭代类似,我们也可以通过迭代来求解 V^π(s)

V_{k+1}^π(s) = Σ over s' [ P(s'|s, π(s)) * ( R(s, π(s), s') + γ * V_k^π(s') ) ]

由于去掉了 max 操作,这个方程变成了线性方程。理论上,我们可以将其写成线性方程组的形式,并用标准线性代数方法(如高斯消元法)直接求解,这通常比迭代更快。

计算优势:策略评估比值迭代计算量小,因为它省去了对所有动作的遍历和最大化操作,运行时复杂度降低了一个因子(动作数 |A|)。


🧭 策略提取与策略迭代

我们已经学会了如何计算值(最优值或给定策略的值),但最终我们往往需要的是一个可以执行的策略,而不是一堆数字。本节介绍如何从值函数中提取出策略。

策略提取

假设有人已经给了我们最优状态值函数 V*(s)。我们如何得到最优策略 π*(s)?答案是利用贝尔曼方程,但这次我们关心的是哪个行动导致了最大值:

π*(s) = argmax over a ∈ A(s) [ Σ over s' [ P(s'|s, a) * ( R(s, a, s') + γ * V*(s') ) ] ]

这里我们使用 argmax 而不是 maxmax 给出最大的数值,而 argmax 给出导致这个最大值的行动。

如果拥有的是最优动作值函数 Q*(s, a),那么策略提取将变得非常简单:

π*(s) = argmax over a ∈ A(s) [ Q*(s, a) ]

因为 Q*(s, a) 已经包含了“采取行动 a 后最优表现”的期望值,我们只需选择 Q 值最大的那个行动即可。

策略迭代

策略迭代是一种结合了策略评估和策略改进(提取)的高效算法。它交替进行以下两个步骤,直至策略不再改变:

  1. 策略评估:给定当前策略 π_i,计算其值函数 V^{π_i}(通常运行几次迭代直到接近收敛)。
  2. 策略改进:根据 V^{π_i},利用策略提取(argmax)得到一个新策略 π_{i+1}

策略迭代的直观理解是:我们从一个策略(即使是随机策略)开始,评估它有多好,然后基于这个评估结果尝试改进它(选择在评估中看起来更好的行动),得到一个新策略,再评估这个新策略……如此循环。

为什么比纯值迭代更高效?
在值迭代中,每一步都需要对所有状态、所有动作计算最大值,计算量大。而在策略迭代中,大部分时间花在策略评估上,这一步没有 max 操作,计算更快。只有当策略稳定后,我们才需要进行一次涉及 argmax 的策略改进。实践中,策略往往比值函数收敛得更快。


🎰 从MDP到强化学习:一个预览

到目前为止,我们讨论的所有方法(值迭代、策略迭代)都属于规划范畴。我们拥有MDP的完整模型(即所有的 P(s'|s, a)R(s, a, s')),在“离线”状态下通过计算来找出最优策略,然后再到环境中去执行。

但现实中,我们可能无法提前获得环境的完整模型。例如,走进一个赌场,面对两台老丨虎丨机(蓝色和红色),你并不知道拉动每台老丨虎丨机的奖励概率分布。

以下是两种不同的情景:

  • 情景一:已知模型的MDP(规划)

    • 你提前知道:拉蓝色机器固定得1美元;拉红色机器有0.25概率得0美元,0.75概率得2美元。
    • 通过计算,你得出拉红色机器的期望回报更高。
    • 你走进赌场后,会一直拉红色机器。这是在执行离线计算好的最优策略。
  • 情景二:未知模型的强化学习

    • 你走进赌场,但对老丨虎丨机的奖励机制一无所知。
    • 你不能提前计算。你必须通过实际尝试来学习。
    • 你可能会先拉几次红色机器(探索),以了解它的回报情况。
    • 根据尝试结果(比如连续几次得到0美元),你可能会推断红色机器不好,转而一直拉蓝色机器(利用)。
    • 你是在在线互动中边学边做决策。

核心思想对比

  • MDP/动态规划:拥有完整环境模型,先思考,后行动。核心是“规划”。
  • 强化学习:环境模型未知或不全,在行动中学习。核心是“探索”与“利用”的权衡,以及如何从经验中学习。

强化学习引入了新的挑战,例如:

  • 探索:为了获取信息而尝试可能非最优的行动。
  • 利用:根据当前知识选择最优行动以最大化收益。
  • 遗憾:由于探索而未能一直采取已知最优行动所损失的潜在收益。

📝 总结

本节课中我们一起学习了:

  1. 贝尔曼方程:定义了MDP中最优值函数或给定策略值函数必须满足的自洽条件。
  2. 值迭代:一种通过迭代更新来求解最优值函数的动态规划算法。
  3. 策略评估:计算某个给定策略的期望回报,计算上比值迭代更简单。
  4. 策略提取:如何从最优值函数(V*Q*)中推导出最优策略。
  5. 策略迭代:一种交替进行策略评估和策略改进的高效算法,通常比纯值迭代更快。
  6. 强化学习预览:当环境模型未知时,我们需要从与环境的在线交互中学习,这引入了探索、利用和遗憾等新概念。

所有这些方法都植根于相同的核心思想:通过考虑即时奖励和未来状态的折扣价值,来评估当前行动的好坏。区别主要在于我们拥有多少信息(是否已知模型?),以及我们想要输出什么(是最优值还是最优策略?)。理解这些算法的共同点和细微差异,是掌握MDP求解的关键。

课程 P14:强化学习 I 🧠

在本节课中,我们将学习强化学习的基础概念。强化学习是智能体通过与环境的交互来学习如何做出决策,以获得最大累积奖励的过程。我们将从马尔可夫决策过程(MDP)开始,探讨如何在不完全了解环境的情况下进行学习。


概述 📋

强化学习的核心在于智能体通过尝试不同的动作来了解环境,并根据获得的奖励调整其行为。这与我们之前学习的MDP算法(如值迭代和策略迭代)不同,因为强化学习假设我们不知道环境的转移模型和奖励函数。


强化学习的基本概念 🔄

上一节我们介绍了强化学习的整体目标,本节中我们来看看其核心挑战。

探索与利用的平衡 ⚖️

在强化学习中,智能体需要平衡探索(尝试新动作以了解环境)和利用(根据已有知识选择最佳动作)。这是因为智能体最初对环境一无所知,必须通过尝试来学习。

以下是探索与利用的几个关键点:

  • 尝试未知动作:为了了解MDP,智能体必须尝试那些结果未知的动作。
  • 利用已知信息:同时,智能体也需要利用已知信息来获取奖励。
  • 最佳平衡:最优策略需要在探索和利用之间找到最佳平衡点。

遗憾与最优性 😔

由于智能体对环境了解有限,其行为可能并非全局最优。我们使用“遗憾”来衡量智能体因知识不足而损失的回报,即与完全了解环境时的最优策略相比的差距。

从样本中学习 📊

智能体只能通过观察动作的结果(样本)来估计环境的转移概率,而不是直接获得概率分布。这意味着学习是基于有限的经验进行的。

泛化能力 🌐

在状态空间巨大的MDP(如围棋)中,访问所有状态是不现实的。因此,智能体必须能够从有限的经验中归纳出一般规则,并将其应用于未见过的状态。


强化学习的交互循环 🔁

智能体与环境的交互遵循一个基本循环:智能体执行一个动作,环境转移到新状态,并给予智能体一个奖励。一次完整的交互经验可以表示为 (s, a, s', r),其中 s 是当前状态,a 是执行的动作,s' 是转移后的新状态,r 是获得的奖励。


强化学习的历史与应用实例 📜

强化学习有着悠久的历史和广泛的应用。

历史里程碑 🏆

  • 亚瑟·塞缪尔的跳棋程序(1956):这是第一个重要的机器学习程序,它通过自我对弈学习值函数,并超越了其创造者的水平。
  • 索尼Aibo机器狗:研究人员使用强化学习改写了机器狗的行走算法,使其行走速度更快、更稳定。
  • DeepMind的Atari游戏AI:系统仅通过像素输入,学会了玩《打砖块》等游戏,甚至发现了“挖隧道”等高级策略。
  • AlphaGo:通过强化学习,AlphaGo掌握了围棋,并击败了人类世界冠军。

示例:爬行者学习行走 🐛

在一个模拟环境中,一个名为“爬行者”的智能体学习使用其肢体爬行。它通过尝试动作并获得关于向右移动进度的奖励信号来学习。经过数万步的探索和学习,它最终能够有效地行走。


强化学习方法分类 🗂️

强化学习有多种方法,主要可以分为以下几类:

基于模型的强化学习 🧩

这种方法试图通过学习环境的转移模型来解决问题。

以下是基于模型RL的步骤:

  1. 收集经验:通过执行策略观察状态转移。
  2. 学习模型:根据观察到的转移数据,估计转移概率 T(s' | s, a) 和奖励函数 R(s, a, s')
  3. 求解MDP:使用学到的近似模型,应用值迭代或策略迭代等规划算法来求解最优策略。

优点:类似于人类通过科学理解世界的方式。
缺点:对于大型或连续状态空间,学习精确模型非常困难;且求解大规模MDP本身计算成本高昂。

无模型强化学习 🚀

这类方法不显式学习环境模型,而是直接学习值函数或策略。

以下是三种主要的无模型方法:

  • 直接评估:通过多次运行策略,直接平均每个状态获得的累积奖励来估计状态值 V(s)
  • 时差学习:通过使相邻状态的值满足贝尔曼方程的样本近似,来更新值函数。
  • Q学习:直接学习状态-动作对的值 Q(s, a),从而便于选择动作。

策略搜索方法 🎯

这类方法直接参数化策略 π(a | s),并通过梯度上升等方法优化策略参数以最大化期望回报。本课程不深入讨论此方法。


被动强化学习 vs. 主动强化学习 🆚

另一个重要的分类维度是学习的方式。

被动强化学习 👁️

在被动强化学习中,智能体观察一个固定策略(例如人类专家)产生的经验,并从中学习值函数或模型。智能体本身不选择动作。

主动强化学习 🎮

在主动强化学习中,智能体必须自己选择动作,这包括决定何时探索未知领域。这引入了探索-利用的权衡问题。


时差学习详解 ⏳

上一节我们介绍了无模型方法,本节我们深入探讨其中一种核心算法:时差学习。

时差学习的核心思想是利用贝尔曼方程的样本近似来更新值函数,避免学习完整的转移模型。

核心思想 💡

对于固定策略 π,其贝尔曼方程为:
Vπ(s) = Σ_s' T(s' | s, π(s)) * [R(s, π(s), s') + γ * Vπ(s')]
时差学习用单个样本 (s, π(s), s', r) 来近似这个期望:
sample = r + γ * Vπ(s')
然后用这个样本值来更新当前状态 s 的估计值。

增量更新与指数遗忘 📈

为了使学习能够在线、增量式进行,并降低早期不准确估计的影响,我们使用指数加权的运行平均值进行更新。

更新公式为:
V(s) ← (1 - α) * V(s) + α * [r + γ * V(s')]
或者等价地:
V(s) ← V(s) + α * [r + γ * V(s') - V(s)]
其中 α 是学习率,[r + γ * V(s') - V(s)] 被称为时差误差。

这种更新方式赋予新样本固定的权重 α,旧估计的权重则指数衰减,实现了“遗忘”早期粗糙估计的效果,同时保证估计的无偏性。


总结 🎓

本节课中我们一起学习了强化学习的基础。我们了解了强化学习智能体如何在未知环境中通过试错来学习,平衡探索与利用。我们回顾了强化学习的历史和成功应用,并对主要学习方法进行了分类,包括基于模型和无模型的方法。最后,我们深入讲解了时差学习算法,它通过样本近似贝尔曼方程并利用增量更新来高效学习状态值函数。强化学习为构建能在复杂世界中自主学习的智能系统提供了强大的框架。

课程 P15:[CS188 SP23] 第十四讲 - 强化学习 II 🧠

在本节课中,我们将要学习强化学习的核心算法——Q学习,并探讨如何将其扩展到大规模问题中。我们将从Q学习的基本原理开始,然后讨论探索与利用的权衡,最后介绍如何通过函数近似(如线性函数或神经网络)来应对巨大的状态空间。


概述 📋

本节课是强化学习的第二部分。我们将深入探讨一种无模型的强化学习算法——Q学习。与之前学习的基于模型或基于价值函数的方法不同,Q学习直接学习状态-动作对的价值,从而可以直接导出最优策略。我们还将讨论在强化学习中至关重要的探索-利用困境,并学习如何通过引入探索奖励来更高效地学习。最后,面对现实世界中庞大的状态空间,我们将介绍如何使用函数近似(例如线性特征组合)来泛化经验,使智能体能够从少量经验中学习并适应新环境。


Q学习:基本原理与算法 ⚙️

上一节我们介绍了基于模型的强化学习和时差学习。本节中我们来看看一种更直接的方法——Q学习。

在强化学习中,Q值函数 Q(s, a) 表示在状态 s 下执行动作 a 后,所能获得的长期累积折扣奖励的期望值。它与价值函数 V(s) 和最优策略 π*(s) 紧密相关:

  • 最优价值函数是各个动作Q值的最大值:V*(s) = max_a Q*(s, a)
  • 最优策略是选择具有最高Q值的动作:π*(s) = argmax_a Q*(s, a)

因此,Q值函数包含了做出最优决策所需的全部信息。

Q学习的核心思想来源于Q值函数的贝尔曼方程:
Q(s, a) = E[ R(s, a) + γ * max_{a'} Q(s', a') ]
其中,s' 是执行动作 a 后转移到的下一个状态,γ 是折扣因子。

与价值函数的更新类似,我们无需计算期望,可以直接使用采样得到的经验 (s, a, r, s') 来更新Q值。Q学习更新规则如下:
Q(s, a) <- (1 - α) * Q(s, a) + α * [ r + γ * max_{a'} Q(s', a') ]
这里,α 是学习率。这个规则非常简洁,其含义是:将当前的Q值估计向“即时奖励加上下一状态最佳Q值的折现”这一目标方向调整。

Q学习的优势在于它是无模型的。一旦学会了Q函数,智能体无需知道环境模型(转移概率),只需在每个状态选择Q值最高的动作即可,即 π(s) = argmax_a Q(s, a)

当然,Q函数通常比价值函数更大(维度为 |状态| x |动作|),学习任务更重,但其概念更统一和简洁。

以下是Q学习算法的基本流程:

  1. 初始化Q表,所有 Q(s, a) 值可以设为零或随机小值。
  2. 对于每一轮训练(episode):
    a. 初始化状态 s
    b. 当状态 s 不是终止状态时,循环:
    i. 根据当前Q函数和某种探索策略(如ε-greedy)选择动作 a
    ii. 执行动作 a,观察到奖励 r 和下一个状态 s‘
    iii. 使用上述更新规则更新 Q(s, a)
    iv. 将状态更新为 s‘

探索与利用的权衡 ⚖️

上一节我们介绍了Q学习的基本框架,但其中有一个关键问题尚未解决:如何选择动作?如果一直选择当前认为最好的动作(利用),可能无法发现潜在更优的动作;如果一直随机探索,又会积累大量“后悔”(获得低奖励)。这就是探索-利用困境

一个经典例子是多臂老丨虎丨机问题:你有多个老丨虎丨机(臂),每个臂的奖励概率未知。你应该继续拉当前收益最高的臂(利用),还是尝试拉得次数较少的臂以获取更多信息(探索)?

在强化学习中,低效的探索会导致学习缓慢,甚至无法收敛到最优策略。

ε-贪心策略

确保探索的一种简单方法是ε-贪心策略

  • 以概率 1 - ε,选择当前Q值最高的动作(利用)。
  • 以概率 ε,随机选择一个动作(探索)。

只要 ε > 0,并且无限频繁地访问所有状态-动作对,就能保证最终学到正确的Q值。但它的缺点是,即使已经知道某些动作很糟糕,仍会以固定概率去尝试,导致不必要的“后悔”。

乐观探索与UCB

更聪明的探索策略是为不确定性较高的动作赋予“探索奖金”。其思想是:一个动作的价值估计 = 平均观测奖励 + 探索奖励。探索奖励与该动作被尝试次数的平方根成反比(或类似形式),尝试次数越少,探索奖励越高。

一种著名的理论是上置信界算法。其选择动作的公式形如:
选择动作 a = argmax_a [ Q(s, a) + c * sqrt( log(N) / n_a ) ]
其中 N 是总尝试次数,n_a 是动作 a 被尝试的次数,c 是常数。这个公式在利用(Q(s,a))和探索(右边项)之间取得了理论上的最优平衡。

在Q学习中,我们可以将这种思想融入,通过给Q值加上一个基于访问计数的奖励来鼓励探索未充分尝试的状态-动作对。这比简单的ε-贪心策略能更快地减少总后悔值。


函数近似:应对大规模状态空间 🚀

前面的方法都假设Q值存储在一张表格中。但对于像围棋、俄罗斯方块或电子游戏这样的问题,状态空间极其庞大(甚至连续),表格表示法完全不现实。

解决方案是使用函数近似。我们不再为每个状态-动作对存储一个独立的值,而是学习一个参数化函数 Q(s, a; w),其中 w 是参数向量。函数 Q 的输出是对应 (s, a) 的Q值估计。

线性函数近似

一种简单有效的方法是线性函数近似。我们定义一组特征函数 f_i(s, a),每个特征捕获状态-动作对的某个重要属性(例如:吃豆人中离最近幽灵的距离、最近豆子的距离等)。然后,Q值表示为这些特征的线性组合:
Q(s, a; w) = w_1 * f_1(s, a) + w_2 * f_2(s, a) + ... + w_n * f_n(s, a) = w · f(s, a)
我们的目标就是学习最优的权重向量 w

训练:梯度下降

如何更新权重 w?我们可以沿用Q学习的思想,但改为对参数 w 进行梯度下降更新。

定义时序差分误差为:
δ = [ r + γ * max_{a'} Q(s', a'; w) ] - Q(s, a; w)
这个误差衡量了当前预测与目标之间的差距。

然后,我们使用梯度下降来最小化这个误差的平方。对于线性函数,Q值关于权重 w_i 的梯度就是对应的特征值 f_i(s, a)。因此,权重的更新规则为:
w_i <- w_i + α * δ * f_i(s, a)
这个规则非常直观:如果得到的回报比预期好(正误差),就增加那些值为正的特征的权重,减少值为负的特征的权重,从而提高对该 (s, a) 的价值估计;反之亦然。

这种方法实现了泛化。智能体从一次“靠近幽灵导致死亡”的经历中,就能学习到“离幽灵近”这个特征具有负权重,并将这个教训应用到所有具有类似特征的状态中,而无需遍历每一个具体状态。

收敛性说明

对于表格型Q学习,在适当条件下可以保证收敛。但对于函数近似:

  • 使用线性函数近似的时差学习可以收敛到给定特征下对真实价值函数的最佳线性逼近。
  • 使用线性函数近似的Q学习则可能发散。这是早期研究中的一个挑战。
  • 现代深度强化学习(使用神经网络作为非线性函数近似)结合了改进的算法(如深度Q网络),在实践中取得了巨大成功,并且有理论可以保证其收敛性。


总结 🎯

本节课中我们一起学习了强化学习中的几个核心进阶主题:

  1. Q学习:一种无模型的强化学习算法,直接学习状态-动作价值函数,并可通过选取最大Q值动作直接得到策略。
  2. 探索与利用:我们介绍了探索-利用困境,并对比了简单的ε-贪心策略和更高效的基于乐观探索/UCB原理的方法,后者能通过赋予探索奖励来智能地平衡两者。
  3. 函数近似:为了将强化学习扩展到大规模或连续状态空间,我们引入了函数近似的思想。重点介绍了线性函数近似,它通过一组手工设计的特征和可学习的权重来泛化Q函数,并使用基于梯度下降的更新规则进行训练。这使智能体能够从有限经验中学习并适应新情况。

通过结合Q学习、智能探索策略和函数近似,我们构建了能够解决复杂、高维决策问题的现代强化学习系统的基础。

课程 P16:[CS188 SP23] 第15讲 - 概率论回顾与贝叶斯网络 📊

在本节课中,我们将学习概率论的基础知识,这是处理人工智能中不确定性的核心数学工具。我们将从基本概念开始,逐步深入到如何利用概率进行推理,并初步了解贝叶斯网络这一强大的表示方法。

概述 📋

我们之前学习的搜索算法都假设了确定性的转移模型和结果函数。然而,现实世界充满了不确定性。本节课将介绍概率论,它为我们提供了一种量化和管理这种不确定性的严谨方法。我们将学习概率的基本规则、条件概率、贝叶斯规则以及独立性的概念,这些都是构建更复杂推理系统(如贝叶斯网络)的基石。

概率基础 🎲

概率论为我们提供了一套处理不确定性的数学框架。其核心思想是:存在一组可能的世界,每个世界都有一个对应的概率值。

  • 可能世界:例如,掷一个骰子,有六个可能的结果(世界)。
  • 概率分配:为每个可能世界分配一个介于0和1之间的实数,所有世界的概率之和必须为1。
  • 事件:事件是可能世界集合的一个子集。例如,“点数小于4”这个事件对应集合 {1, 2, 3}。事件的概率是其包含的所有可能世界的概率之和。

一个处理不确定性的方法如果不符合概率定律(例如概率和不等于1),就可能被设计出必然亏损的赌局,这说明了概率论的合理性。

随机变量与概率分布 🔢

随机变量是将可能世界映射到某个值域的函数。它本身是确定性的。

  • 定义:随机变量 X 是一个函数,输入是一个可能世界 ω,输出是某个值(如布尔值、实数值、坐标等)。
  • 概率分布:随机变量 X 的概率分布给出了 X 取每个可能值的概率。例如,布尔变量“点数为奇数”的分布是 P(奇数=True) = 0.5, P(奇数=False) = 0.5
  • 联合分布:多个随机变量的联合分布指定了它们所有可能值组合的概率。它包含了变量间如何相关的信息。
  • 边缘分布:可以从联合分布中通过“求和”(或称边缘化)其他变量得到单个变量的分布。例如,从天气和温度的联合分布中,对天气的所有可能值求和,就得到温度的边缘分布。

在人工智能中,我们通常先定义关心的随机变量,可能世界则是这些变量所有值组合的集合。直接列出所有可能世界(即完整的联合分布表)在变量增多时会变得指数级庞大且难以估计,因此我们需要更简洁的表示方法。

条件概率与推理 🔍

条件概率是在已知某些信息(证据)的情况下,更新我们对事件发生可能性的信念。

  • 定义:在事件 B 发生的条件下,事件 A 发生的概率定义为 P(A|B) = P(A, B) / P(B)。这相当于将关注范围缩小到 B 为真的世界,然后看其中 A 也为真的比例。
  • 条件分布:类似地,我们可以讨论在给定其他变量取值时,某个变量的完整概率分布。
  • 归一化:为了使条件概率分布之和为1,常引入归一化因子 αP(Q|e) = α * P(Q, e),其中 α = 1 / Σ_q P(Q=q, e)

基于联合分布进行概率推理的通用模式如下:

  1. 查询变量 Q:我们想知道其分布的变量。
  2. 证据变量 E:我们已经观察到其取值的变量(E = e)。
  3. 隐藏变量 H:既非查询也非证据的其他变量。
    推理目标是计算 P(Q | E=e)。方法是:首先将联合分布限制在 E=e 的世界,然后对隐藏变量 H 的所有可能取值求和,得到 P(Q, E=e),最后进行归一化:P(Q | E=e) = α * Σ_h P(Q, H=h, E=e)

这种方法的计算成本很高,因为它需要对隐藏变量的所有可能组合进行求和,其复杂度随隐藏变量数量呈指数增长。同时,存储和估计庞大的联合分布表也需要指数级的数据量。因此,我们需要寻找更高效的表示和推理方法。

概率规则与独立性 ⚖️

为了高效地表示和计算概率,我们需要掌握一些基本的代数规则。

  • 乘积规则:由条件概率定义直接导出,P(A, B) = P(A|B) * P(B)。它提供了从条件分布和边缘分布构造联合分布的方法。
  • 链式规则:乘积规则的推广,可以将任意多个变量的联合分布分解为一系列条件概率的乘积:P(X₁, X₂, ..., Xₙ) = Πᵢ P(Xᵢ | X₁, ..., Xᵢ₋₁)。分解的顺序可以任意选择。
  • 贝叶斯规则P(A|B) = P(B|A) * P(A) / P(B)。它极其重要,因为它允许我们进行“逆概率”推理:从观察到的结果 B(证据)去推断原因 A(假设)的可能性。P(A) 是先验概率,P(A|B) 是后验概率,P(B|A) 是似然度。贝叶斯规则描述了一个自然的信念更新过程:后验概率 ∝ 似然度 × 先验概率。

上一节我们看到了直接使用联合分布进行推理的困难。本节我们来看看如何利用变量间的独立性来极大地简化问题。

  • 定义:两个变量 XY 独立,当且仅当它们的联合分布等于各自边缘分布的乘积:P(X, Y) = P(X) * P(Y)
  • 等价表述:独立性也意味着 P(X|Y) = P(X)。即,知道 Y 的信息不会改变我们对 X 的信念。
  • 意义:如果变量间存在独立性,那么表示其联合分布所需的参数数量会大幅减少(从指数级降到线性级或更低),从而使得存储、估计和推理都变得可行。例如,n 次独立的硬币抛掷,其联合分布只需 n 个参数(每次正面朝上的概率),而不是 2ⁿ 个参数。

然而,完全的独立性在复杂系统中很少见。更常见的是条件独立性,这将是贝叶斯网络的核心思想。

总结 🎯

本节课我们一起学习了概率论的基础知识,这是人工智能中处理不确定性的数学语言。我们回顾了概率空间、随机变量、联合分布与边缘分布。重点掌握了条件概率的概念以及如何用它进行概率推理,并指出了基于完整联合分布进行枚举推理的计算瓶颈。接着,我们学习了乘积规则、链式规则和至关重要的贝叶斯规则,后者为信念更新和机器学习提供了理论基础。最后,我们引入了独立性的概念,它是指数级简化概率表示和计算的关键。在接下来的课程中,我们将以此为基础,学习贝叶斯网络,它利用条件独立性来紧凑地表示复杂的联合概率分布,并支持高效的概率推理。

课程 P17:[CS188 SP23] 第16讲 - 贝叶斯网络:语法与语义 🧠

在本节课中,我们将学习贝叶斯网络(Bayes Nets)的基本概念,包括其语法(如何构建)和语义(代表什么含义)。我们将从概率论的基础知识开始,逐步理解如何利用条件独立性来简化复杂的联合概率分布,并最终构建出清晰、高效的贝叶斯网络模型。

概率论基础回顾

上一节我们介绍了概率的基本概念,本节中我们来看看如何用概率模型来描述世界。

事件的概率分布告诉你某个事件发生的可能性。这个分布的所有概率之和应为1,因为所有可能事件中必然有一个会发生。

随机变量通常用大写字母表示,例如 X。它可以取很多不同的值,比如 123,或者 等。

如果你有多个随机变量,例如 XY,你可以定义联合分布。联合分布告诉你 XY 的每一个特定组合发生的可能性有多大。所有组合的概率之和也应为1。

你可以通过边缘化(求和)来降低联合分布的维度。例如,对 X 的所有可能值求和,可以得到 Y 的分布。

条件概率是指在已知 Y 发生的情况下,X 发生的概率。其定义为:
公式: P(X|Y) = P(X, Y) / P(Y)

乘积规则是条件概率的简单重排:
公式: P(X, Y) = P(X|Y) * P(Y)

链式法则将乘积规则推广到多个变量:
公式: P(X1, X2, ..., Xn) = P(X1) * P(X2|X1) * ... * P(Xn|X1, X2, ..., Xn-1)

联合分布的挑战与条件独立性

上一节我们讨论了如何用一组随机变量的联合分布来建立概率模型。本节中我们来看看直接使用联合分布会遇到的问题,以及如何用条件独立性来解决。

从联合分布中,我们可以通过边缘化(对隐藏变量求和)来回答任何问题,例如计算特定变量的边际概率或条件概率。

然而,联合分布的大小会随着变量数量呈指数级增长。这意味着我们面临存储和计算上的巨大挑战。例如,对于50个二值变量,联合分布有 2^50 个条目,我们既无法存储,也无法从数据中估计这么多参数。

独立性是简化联合分布的一种方式。如果所有变量都相互独立,那么联合分布就是每个变量边际分布的乘积。这样,参数数量就从指数级降为线性级。

但在现实世界中,变量很少完全独立。更普遍的是条件独立性。条件独立性是指,在给定另一组变量(Z)的值时,变量 XY 相互独立。这可以表示为:
公式: P(X, Y | Z) = P(X | Z) * P(Y | Z)

条件独立性同样允许我们将大的联合分布分解为许多小的、局部的条件分布,从而实现表示上的指数级简化。

捉鬼敢死队示例 👻

为了说明条件独立性,我们使用一个“捉鬼敢死队”游戏的例子。在这个游戏中,你需要在网格上找到鬼魂。

  • 你不知道鬼魂的具体位置。
  • 你可以探测网格上的方块。探测会返回一种颜色(红、橙、黄、绿),颜色指示了鬼魂离该方块的大致距离。
  • 传感器是有噪声的,颜色与距离的对应关系是概率性的。

你的目标是结合多次探测的证据,推断出鬼魂最可能的位置。

以下是游戏的关键点:

  • 随机变量:鬼魂的位置 G,以及每个探测方块的颜色 C_i
  • 先验分布:鬼魂在每个位置的概率是均匀的。
  • 传感器模型:给定鬼魂的位置 G,在某个方块探测到特定颜色的概率。这个概率只取决于该方块到鬼魂的距离。
  • 条件独立性:在已知鬼魂位置 G 的条件下,任意两个探测结果 C_iC_j 是相互独立的。因为探测结果只由鬼魂位置(共同原因)决定,彼此之间没有直接影响。

利用这种条件独立性,我们可以将庞大的联合分布简化为先验分布和一系列小型传感器模型的乘积。这极大地减少了模型所需的参数数量。

这种具有一个根本原因变量和多个条件独立的证据变量的结构非常常见,被称为朴素贝叶斯模型。在这个例子中,该模型完全正确,因为传感器就是被如此设计的。

构建贝叶斯网络

上一节我们通过例子看到了条件独立性的威力,本节中我们来看看如何系统地用图形化模型——贝叶斯网络——来表示这种结构。

贝叶斯网络提供了一种系统、优雅、自然的方式来描述联合分布的条件独立结构,并将其分解为小的条件分布的乘积。

一个贝叶斯网络由以下三部分组成:

  1. 节点:每个节点代表一个随机变量。
  2. 有向边(弧):连接节点的箭头。直观上,箭头从“因”指向“果”,表示直接影响。
  3. 条件概率表(CPT):对于每个节点,给定其父节点(所有指向它的节点)的取值,该节点取各个值的条件概率。

网络中的缺失边(即没有直接连接)是对条件独立性的断言。

网络构建示例

让我们通过几个小练习来构建贝叶斯网络。

示例1:雨、交通和雨伞

  • 雨会导致交通拥堵和人们带伞。
  • 交通和带伞本身没有直接因果关系,但它们通过“下雨”这个共同原因相关联。
  • 条件独立性:在已知是否下雨的条件下,交通状况和是否带伞是相互独立的。
  • 网络结构 -> 交通 -> 交通之间没有直接连接。

示例2:火灾、烟雾和警报

  • 火灾会产生烟雾,烟雾会触发烟雾报警器。
  • 条件独立性:在已知是否有烟雾的条件下,火灾是否发生和警报是否响起是相互独立的。因为警报只“听”烟雾的。
  • 网络结构火灾 -> 烟雾 -> 警报火灾警报之间没有直接连接。

构建网络时,按因果顺序(从根本原因到可观察结果)添加变量通常最简单,产生的网络也最简洁。如果按非因果顺序构建,可能会引入不必要的连接,使网络变得复杂且难以参数化。

警报网络示例 🚨

现在,我们来看一个经典的贝叶斯网络示例——警报网络。

这个网络包含以下布尔变量:

  • B:入室盗窃(Burglary)
  • E:地震(Earthquake)
  • A:警报(Alarm)
  • J:约翰打电话(JohnCalls)
  • M:玛丽打电话(MaryCalls)

网络结构(因果关系)

  • BEA 的父节点(盗窃和地震都可能触发警报)。
  • AJM 的父节点(警报响会导致约翰和玛丽可能打电话)。

条件概率表(CPT)示例

  • P(B=true) = 0.001 (盗窃先验概率)
  • P(E=true) = 0.002 (地震先验概率)
  • P(A=true | B=true, E=true) = 0.95 (两者都发生,警报极可能响)
  • P(A=true | B=true, E=false) = 0.94
  • P(A=true | B=false, E=true) = 0.29
  • P(A=true | B=false, E=false) = 0.001 (误报)
  • P(J=true | A=true) = 0.90P(J=true | A=false) = 0.05 (约翰的可靠性)
  • P(M=true | A=true) = 0.70P(M=true | A=false) = 0.01 (玛丽的可靠性)

这个网络只有10个独立参数(因为每行概率和为1),而5个布尔变量的完整联合分布需要 2^5 - 1 = 31 个参数。这展示了贝叶斯网络在参数数量上的显著优势。

贝叶斯网络的语义

上一节我们定义了贝叶斯网络的语法,本节中我们来看看它的精确语义——它到底代表了什么。

贝叶斯网络的语义非常简单而强大:

所有变量上的联合概率分布,等于网络中所有条件概率表(CPT)中对应项的乘积。

公式: P(X1, X2, ..., Xn) = ∏ P(Xi | Parents(Xi))

这意味着,联合分布中任何一个具体的赋值(如 B=true, E=false, A=true, J=false, M=false)的概率,可以通过查找每个变量在其父节点特定取值下的条件概率,然后将它们相乘得到。

这种语义隐含着贝叶斯网络所做出的条件独立性断言。与链式法则 P(X1,...,Xn) = ∏ P(Xi | X1,...,Xi-1) 对比可以发现,贝叶斯网络假设:
公式: P(Xi | X1,...,Xi-1) = P(Xi | Parents(Xi))
即,给定其父节点,每个变量 Xi 条件独立于所有其他非后代变量。

这是从网络拓扑结构中可以直接读出的属性,也是进行高效概率推理的基础。

总结

本节课中我们一起学习了贝叶斯网络的核心思想。

我们首先回顾了概率论基础,并指出了直接使用大型联合分布面临的挑战。然后,我们引入了条件独立性这一关键概念,它允许我们将复杂的联合分布分解为更小、更易处理的局部条件分布的乘积。

通过“捉鬼敢死队”等例子,我们看到了条件独立性在现实模型中的体现。接着,我们系统地介绍了贝叶斯网络的语法(节点、有向边、CPT)和语义(联合分布等于CPT的乘积)。我们学习了如何按照因果顺序构建网络,并分析了经典的“警报网络”示例。

贝叶斯网络的核心优势在于,它利用变量间的条件独立结构,用远少于完整联合分布的参数,清晰而自然地表达了复杂的概率关系。这为后续进行高效的概率推理(包括精确推断和近似推断)奠定了坚实的基础。

🧠 课程 P18:贝叶斯网络中的变量消除算法

在本节课中,我们将学习如何高效地在贝叶斯网络中进行概率推理。具体来说,我们将探讨变量消除算法,这是一种通过缓存重复子表达式来避免指数级计算成本的方法。我们还将了解为什么在最坏情况下,精确推理仍然是计算困难的,并简要介绍近似推理的概念。


📚 概述:从枚举到变量消除

上一节我们介绍了贝叶斯网络的基本语法和语义,以及如何通过枚举隐变量来计算查询概率。然而,枚举方法需要指数级的时间,对于大规模网络是不现实的。

本节中,我们将看看如何通过变量消除算法来显著提高计算效率。该算法的核心思想是:在计算巨大的概率乘积和时,识别并缓存重复出现的子表达式,从而避免冗余计算。


🔍 枚举推理的局限性

通过枚举进行推理的基本思想是:对联合分布中所有不是查询或证据的隐变量求和。联合分布由贝叶斯网络中的条件概率乘积表示。

例如,计算 P(Burglary | JohnCalls=true, MaryCalls=true),需要对联合分布中的隐变量(如 EarthquakeAlarm)求和。联合分布是各节点条件概率的乘积:

P(B,E,A,J,M) = P(B) * P(E) * P(A|B,E) * P(J|A) * P(M|A)

枚举方法需要计算所有隐变量取值组合的概率并求和。对于一个有20多个节点的汽车保险网络,枚举需要约2.27亿次运算;对于有400多个节点的喷气发动机诊断网络,枚举是完全不可行的。


💡 变量消除的基本思想

观察一个具体的概率求和表达式,例如计算后验概率时的求和式。当写出所有项时,会发现许多相同的子表达式重复出现。

例如,在计算 P(B|J,M) 时,对 EA 的求和展开后,项如 P(B)*P(E)*P(A|B,E)*P(J|A)*P(M|A) 会因 EA 的取值不同而多次出现,但其中部分乘积是相同的。

如果首次计算某个子表达式后将其结果缓存,后续需要时直接复用,就能避免重复计算。这就是变量消除算法的核心:系统性地缓存和复用中间结果


🧮 因子:算法的基本数据结构

算法操作的基本对象是因子,本质上是多维数组,表示一组变量的(条件)概率分布。

因子主要有以下几种类型:

  • 联合分布因子:如 P(A, J),数组所有元素之和为1。
  • 投影联合分布因子:如 P(A=true, J),是固定某些变量值后的子表,元素之和等于被固定变量的概率。
  • 条件分布因子:如 P(J | A),对于条件的每个取值,该分布都归一化(和为1)。

算法通过两种基本运算组合和简化因子:

  1. 因子乘法(点积)
    将两个因子相乘,生成一个新因子,其变量集是原因子变量集的并集。新因子的每个条目是原因子对应条目的乘积。

    # 例如,给定 P(A) 和 P(J|A),计算 P(A, J)
    # 结果因子中,P(A=true, J=true) = P(A=true) * P(J=true | A=true)
    
  2. 变量求和(消元)
    对一个因子中的某个变量求和,将该变量“消去”,得到一个维度更小的新因子。

    # 例如,对 P(A, J) 中的 J 求和,得到 P(A)
    # P(A=true) = P(A=true, J=true) + P(A=true, J=false)
    

🔄 变量消除算法步骤

以下是变量消除算法的具体步骤:

  1. 初始化因子
    列出网络中所有条件概率分布因子,并将证据变量固定为其观测值。

  2. 循环消元隐变量
    当还存在隐变量时:

    • 选择一个隐变量 H
    • 找出所有涉及 H 的因子。
    • 将这些因子相乘,然后对 H 求和,得到一个新的因子。
    • 用这个新因子替换掉那些被乘的旧因子。
  3. 合并剩余因子并归一化
    当所有隐变量都被消去后,将剩余的所有因子相乘,得到一个只包含查询变量的因子。最后将其归一化,即得到查询概率。

算法关键:消元顺序直接影响中间因子的大小,从而影响计算效率。好的顺序可以保持因子很小,差的顺序可能导致因子急剧膨胀。


⚠️ 计算复杂性与最优顺序

变量消除算法的效率取决于消元过程中产生的最大因子的大小。对于某些结构(如朴素贝叶斯网络),自底向上(先消叶子节点)的顺序可以保证因子大小很小,算法是线性的。

然而,寻找最优消元顺序本身是一个NP难问题。在最坏情况下,即使有最优顺序,变量消除的运行时间也是指数级的。这是因为贝叶斯网络的精确概率推理是一个 #P-完全问题,比NP完全问题(如布尔可满足性问题SAT)更难。

我们可以通过一个归约来证明:任何SAT问题都可以转化为一个特定贝叶斯网络的概率查询。如果能高效解决贝叶斯网络推理,就能高效解决SAT,但SAT是NP完全的。更进一步,计算概率值实际上是在计算SAT满足赋值的数量,这是一个#P-完全问题。


🌳 实际中的高效情况:多树与割集调整

尽管最坏情况很困难,但许多实际网络具有特殊结构,使得精确推理变得高效:

  • 多树:其对应的无向图(忽略箭头)是一棵树,没有环。对于多树,变量消除可以在线性时间内完成。
  • 近似多树:如果网络通过实例化少量变量(称为割集)就能切断所有环,变成多树,那么可以采用割集调整方法:为割集变量的每种可能取值分别求解剩余的多树网络,然后合并结果。总时间是指数于割集大小,但线性于网络其他部分。

📝 总结

本节课我们一起学习了贝叶斯网络中的精确推理算法——变量消除。

  • 我们首先回顾了枚举方法的指数级计算成本。
  • 然后,我们引入了变量消除算法,它通过因子乘法变量求和操作,并缓存中间结果来避免重复计算。
  • 我们了解到,算法的效率严重依赖于消元顺序,而找到最优顺序是困难的。
  • 最后,我们认识到精确推理在最坏情况下是 #P-完全的,计算困难。但幸运的是,对于许多具有多树近似多树结构的实际网络,存在高效的精确推理算法。

这为下节课的内容——当精确推理不可行时,使用蒙特卡洛采样进行近似推理——做好了铺垫。

课程 P19:贝叶斯网络中的采样方法 🎲

在本节课中,我们将学习如何利用随机采样技术,在贝叶斯网络中进行高效的近似推理。我们将从简单的采样概念入手,逐步探讨如何克服精确推理的计算瓶颈,并学习几种关键的采样算法。


概述

精确推理算法(如枚举和变量消除)在处理大型或复杂贝叶斯网络时可能效率极低,甚至不可行。因此,我们转向基于随机采样的蒙特卡洛方法。这些方法通过生成大量随机样本来近似计算概率,即使对于包含数千个变量的网络,也能在普通计算机上快速运行。本节课我们将学习先验采样、拒绝采样、似然加权以及吉布斯采样的核心思想。


从有偏硬币到无偏采样 🔄

上一节我们提到了精确推理的局限性,本节中我们来看看如何利用随机性来解决问题。一个经典的起点是:如何使用一个未知偏置的有偏硬币,来模拟一个完全公平的硬币?

以下是两种可行的算法思路:

  • 方法一(冯·诺依曼方法):重复抛掷这枚硬币两次,并观察结果。

    • 如果结果是 HT(先正后反),则将其计为一次“正面”。
    • 如果结果是 TH(先反后正),则将其计为一次“反面”。
    • 如果结果是 HHTT,则丢弃这两次抛掷,重新开始。
    • 由于 P(HT) = p * (1-p)P(TH) = (1-p) * p,两者概率相等,因此可以产生无偏的随机比特。但这种方法在硬币极度有偏(如 p=0.9)时效率较低。
  • 方法二(连续抛掷法):先抛掷硬币,直到出现一次正面(H),然后观察紧接着的下一次抛掷结果。

    • 如果下一次是 T,则计为一次“正面”。
    • 如果下一次是 H,则计为一次“反面”。
    • 这种方法看似高效,但经过分析会发现,得到“正面”的概率是 p,得到“反面”的概率是 1-p,因此它不能产生无偏的随机比特。

这个例子展示了如何通过巧妙的算法设计,从低质量的随机源中生成高质量的随机性,这正是蒙特卡洛方法的核心思想之一。


为什么需要采样? 🧠

我们已经讨论了贝叶斯网络中的精确推理。枚举法简单但效率极低;变量消除法更高效,但在最坏情况下仍然是计算困难的。因此,我们转向使用随机数的蒙特卡洛方法。

以下是采用采样方法的主要优势:

  • 处理大规模网络:对于包含成千上万个变量的网络,精确算法所需的内存和时间可能超出物理极限,而采样方法只需存储网络状态和当前样本,可以轻松扩展。
  • 模型灵活性:采样算法易于应用于各种复杂模型,例如同时包含离散变量(条件概率表)和连续变量(高斯分布等)的混合模型,只要能从条件分布中采样即可。
  • 算法简单:许多采样算法的实现相对简单。
  • 理论保证:在生成足够多样本的前提下,估计值会收敛到真实概率。


核心工具:从分布中采样 🎯

为了构建采样算法,我们首先需要掌握如何从一个给定的概率分布中生成样本。对于离散随机变量,这可以转化为一个“有偏的多面骰子”问题。

假设一个随机变量 Xk 个可能取值,其概率分布为 P(X=value_i) = p_i。我们可以通过以下步骤生成一个样本:

  1. 生成一个在 [0, 1) 区间上均匀分布的随机数 r
  2. 将区间 [0, 1) 划分为 k 个连续的子区间,第 i 个区间长度为 p_i,其累积边界为 sum_{j=1}^{i} p_j
  3. 找到 r 落入的那个子区间,其对应的 value_i 即为本次采样的结果。

这个过程可以直观地理解为:随机雨滴均匀地落在一条标有累积概率的线上,它落在哪个区间,就输出哪个值。

# 伪代码示例:从离散分布中采样
def sample_from_distribution(values, probabilities):
    r = random.uniform(0, 1)
    cumulative_prob = 0
    for v, p in zip(values, probabilities):
        cumulative_prob += p
        if r < cumulative_prob:
            return v


先验采样 🏗️

现在,我们将采样技术应用于贝叶斯网络。第一种方法称为先验采样,其目标是从网络所定义的联合概率分布 P(X1, X2, ..., Xn) 中直接生成样本。

以下是先验采样的步骤:

  1. 按照网络节点的拓扑顺序(从根节点到叶节点)遍历所有变量。
  2. 对于每个变量 Xi,根据其父节点 Parents(Xi) 的当前取值(已采样得到),从其条件概率分布 P(Xi | Parents(Xi)) 中进行采样。
  3. 将所有变量的采样值组合起来,就得到了一个完整的联合样本。

为什么这是正确的? 生成一个特定样本 (x1, x2, ..., xn) 的概率,恰好是算法中每一步采样概率的乘积,即 ∏_i P(xi | parents(xi))。根据贝叶斯网络的链式法则,这正是该样本在联合分布中的概率 P(x1, x2, ..., xn)。因此,先验采样是联合分布的完美采样器。


拒绝采样:引入证据 🚫

上一节我们学习了如何从先验分布中采样,但在推理中,我们通常关心的是在给定某些证据 E=e 下的条件概率 P(Q | E=e)。最直接的方法是拒绝采样

拒绝采样的流程如下:

  1. 使用先验采样生成大量样本。
  2. 对于每个生成的样本,检查它是否与所有证据 E=e 一致。
  3. 如果一致,则保留该样本用于后续估计;如果不一致,则丢弃(拒绝)该样本。
  4. 在保留的样本中,通过计数来计算查询变量 Q 的条件概率估计:P(Q=q | E=e) ≈ (# samples with Q=q and E=e) / (# samples with E=e)

优点与局限:拒绝采样非常简单直观。然而,当证据的概率 P(E=e) 很小时,绝大多数样本都会被拒绝,导致有效样本量极少,估计效率非常低下。


似然加权采样:固定证据并重新加权 ⚖️

为了解决拒绝采样效率低下的问题,我们引入了似然加权采样。其核心思想是:在生成样本时,固定证据变量的值为观测值,只对非证据变量进行采样,然后通过赋予样本一个权重来补偿采样分布与真实后验分布之间的偏差。

以下是算法的具体步骤:

  1. 初始化样本权重 w = 1
  2. 按照拓扑顺序遍历所有变量:
    • 如果变量 Xi证据变量(其值 xi 已给定):
      • 不进行采样。
      • 将权重更新为 w = w * P(Xi=xi | Parents(Xi))。这里 Parents(Xi) 的取值来自当前已赋值的父节点。
    • 如果变量 Xi非证据变量
      • 根据其父节点的当前取值,从 P(Xi | Parents(Xi)) 中采样一个值 xi
      • xi 加入样本。
  3. 返回生成的样本及其权重 w
  4. 要估计 P(Q=q | E=e),我们不再简单计数,而是计算所有样本中,满足 Q=q 的样本的权重之和,然后除以所有样本的总权重之和

为什么这行得通? 这实际上是重要性采样技术的一个应用。我们从提议分布 Q(即固定证据、采样非证据的分布)中采样,然后通过权重 w = P(sample) / Q(sample) 进行修正。可以证明,加权后的样本分布恰好能给出对真实后验概率的一致估计。

优点与局限:似然加权采样避免了样本被大量拒绝,效率远高于拒绝采样。然而,当证据位于网络下游(叶节点)时,上游变量的采样完全不受证据影响,样本权重可能变得非常小且方差很大,导致估计仍然不理想。


马尔可夫链蒙特卡洛与吉布斯采样 🔗

为了克服似然加权采样的局限性,我们需要一种能让所有证据都影响所有变量采样的方法。这就是马尔可夫链蒙特卡洛 方法,其中吉布斯采样是适用于贝叶斯网络的一种简单而强大的变体。

MCMC的核心思想是构建一个马尔可夫链,其平稳分布恰好就是我们想要的目标后验分布 P(X | E=e)。通过在这个链上进行随机游走,最终生成的样本序列将近似服从该后验分布。

在深入吉布斯采样之前,让我们通过一个城市随机游走的例子来理解“平稳分布”:

假设有若干个城市由道路连接,一个人每天随机选择一条道路去往相邻城市。经过长时间后,他在各个城市停留的时间比例会趋于一个稳定值,这个分布就是随机游走的平稳分布。可以证明,在这个无向图游走中,平稳分布与节点的度数成正比。

吉布斯采样正是利用了这种思想。对于贝叶斯网络,给定证据 E=e,吉布斯采样的步骤如下:

  1. 随机初始化所有非证据变量的值。
  2. 重复以下步骤很多次(每次迭代生成一个新样本):
    • 对于每一个非证据变量 Xi
      • 固定所有其他变量(包括证据变量和其他非证据变量)的当前值。
      • 根据 Xi马尔可夫毯(即其父节点、子节点以及子节点的其他父节点)的当前取值,计算 Xi 的条件概率分布 P(Xi | MarkovBlanket(Xi))
      • 从这个条件分布中为 Xi 采样一个新的值。
    • 在经过一定次数的“预热”后,将当前所有非证据变量的取值记录为一个样本。

关键点:在吉布斯采样中,每个变量的更新都考虑了所有相关证据(通过其马尔可夫毯),因此最终样本会收敛到真实的后验分布 P(X | E=e)。它特别适合证据变量很多或位于网络任何位置的情况。


总结

本节课我们一起学习了贝叶斯网络中几种重要的近似推理采样方法:

  1. 先验采样:直接从联合分布中生成样本,是其他方法的基础。
  2. 拒绝采样:通过丢弃与证据不符的样本来估计条件概率,简单但效率低。
  3. 似然加权采样:固定证据变量,对非证据变量采样并通过权重修正,效率更高,但在下游证据多时可能失效。
  4. 吉布斯采样:一种MCMC方法,通过迭代地根据马尔可夫毯更新每个变量,使样本序列收敛到目标后验分布,能有效处理各种证据情况。

这些采样方法使我们能够对大规模、复杂的概率模型进行可行的推理,是连接概率论与实用人工智能算法的重要桥梁。

🧠 课程 P2:[CS188 SP23] 第2讲 - 状态空间与无信息搜索

在本节课中,我们将学习如何将问题形式化为搜索问题,并探索几种基础的搜索算法。我们将从定义状态空间和搜索问题开始,然后逐步了解深度优先搜索、广度优先搜索和一致代价搜索的工作原理及其特性。


📋 概述:什么是搜索问题?

搜索问题是一个具有精确定义的数学概念。为了本课程的目的,我们将搜索问题定义为一个包含以下组成部分的结构:

  • 状态空间:所有可能的世界配置的集合。
  • 后继函数:给定一个状态,该函数返回所有可以从该状态直接到达的状态列表。
  • 初始状态:搜索开始时的状态。
  • 目标测试:给定一个状态,该函数判断该状态是否满足问题解决条件。

我们的目标是找到一系列动作,从初始状态出发,经过一系列中间状态,最终到达一个通过目标测试的状态。

上一节我们介绍了搜索问题的基本定义,本节中我们来看看如何具体地构建一个搜索问题。


🗺️ 状态空间与问题建模

状态空间包含了世界所有可能的配置。然而,对于特定问题,并非所有细节都是必要的。关键在于,状态中只需包含与解决问题相关的信息。

例如,在吃豆人游戏中:

  • 若要解决“从A点到B点”的路径问题,状态可能只需要吃豆人的坐标。
  • 若要解决“吃掉所有豆子”的问题,状态就必须包含豆子的分布信息。

如何确定状态中需要包含什么?一个有用的技巧是“反向思考”:考虑你的目标测试需要什么信息来判断是否完成。状态中必须包含这些信息。

以下是计算状态空间大小的一个例子:

假设一个简单的吃豆人世界:

  • 吃豆人可能位于 120 个不同位置。
  • 30 个豆子,每个豆子可能存在或不存在,因此有 2^30 种配置。
  • 两个幽灵,每个可能有 12 个位置,因此有 12 * 12 = 144 种配置。

那么总的状态数大约是 120 * 2^30 * 144,这是一个巨大的数字。但如果我们只关心路径问题,状态数可能就只是 120。这直观地反映了不同问题的难度差异。


📊 两种重要的图表示

在讨论算法前,我们需要区分两种容易混淆的图表示:状态空间图搜索树

状态空间图

  • 节点:代表一个状态(世界的具体配置)。
  • :代表后继函数,表示通过一个动作可以从一个状态到达另一个状态。
  • 这个图展示了所有状态是如何连接的。它通常非常庞大,我们不会实际构建它,但它是一个有用的概念模型。

搜索树

  • 节点:代表一个从初始状态出发的完整计划(或路径),而不仅仅是某个状态。节点上的标签(如‘A’)表示通过该计划到达的状态是A,但节点本身代表的是“如何到达A”的整个动作序列。
  • :代表执行一个动作
  • 这棵树系统地枚举了从初始状态开始,所有可能采取的动作序列(计划)。它可能会非常巨大(甚至无限,如果存在循环),我们的算法将尝试只构建所需的部分。

核心区别:状态空间图中每个状态只出现一次;搜索树中,同一个状态可能通过不同的路径(计划)多次到达。


🔍 通用搜索算法框架

所有搜索算法都遵循同一个高层框架,它们之间的唯一区别在于如何从“边缘”中选择下一个要探索的节点。

算法框架如下:

  1. 初始化:将代表初始状态(零动作计划)的节点放入边缘(也称为开放列表或前沿)。
  2. 循环:
    a. 如果边缘为空,则搜索失败。
    b. 从边缘移除并选择一个节点
    c. 如果该节点代表的状态通过目标测试,则回溯路径,搜索成功。
    d. 否则,扩展该节点:将其所有后继状态(新计划)加入边缘
  3. 重复循环。

关键:步骤 2b从边缘选择节点的策略,决定了搜索算法的类型(如深度优先、广度优先)。


🌲 深度优先搜索

深度优先搜索的策略是:总是从边缘中选择深度最大(即路径最长)的节点进行扩展。

算法特性

  • 时间复杂度:在最坏情况下,可能需要探索整个搜索树,因此是 O(b^m),其中 b 是分支因子,m 是最大深度。
  • 空间复杂度:由于只需要存储从根节点到当前叶节点的路径上的兄弟节点,因此空间复杂度为 O(b*m),相对较低。
  • 完备性:在有限状态空间且避免重复状态的情况下是完备的。在无限状态空间或存在循环的图中,可能永远找不到解。
  • 最优性不是最优的。它找到的解不一定是最短路径或代价最小的解。

直观理解

DFS 会沿着一条路径“一头扎到底”,直到无法继续,然后回溯,尝试下一条最深的路径。它探索的形状像一条“蜿蜒的溪流”。


🌊 广度优先搜索

广度优先搜索的策略是:总是从边缘中选择深度最小(即路径最短)的节点进行扩展。

算法特性

  • 时间复杂度O(b^s),其中 s 是最优解的深度。在最坏情况下,需要探索到深度 d 的所有节点。
  • 空间复杂度:需要存储每一层的所有节点,因此空间复杂度为 O(b^s),通常远高于 DFS。
  • 完备性是完备的(如果解存在且分支因子有限)。
  • 最优性当所有动作代价相同时,它是最优的。因为它按层探索,首先找到的必定是动作最少的解。

直观理解

BFS 像“水波荡漾”一样,从起点开始,一层一层地向外探索所有可能的路径。


⚖️ 一致代价搜索

当动作具有不同的代价时,我们需要一致代价搜索。其策略是:总是从边缘中选择总路径代价最小的节点进行扩展。

算法特性

  • 时间复杂度:与 BFS 类似,但代价 C 取代了深度 d,复杂度约为 O(b^(1 + ⌊C*/ε⌋)),其中 C* 是最优解代价,ε 是最小动作代价。
  • 空间复杂度:与 BFS 相同,为 O(b^(1 + ⌊C*/ε⌋))
  • 完备性是完备的(假设所有动作代价 > ε > 0,即无负代价环)。
  • 最优性是最优的。它是 UCS 的核心优势,可以找到全局代价最小的解。

直观理解

UCS 不再是按“层”探索,而是按“代价等高线”探索。它先探索所有代价低的区域,再逐步探索代价高的区域。可以把它看作“戴着眼罩、只关心花费的寻路者”。


🔁 迭代加深搜索

迭代加深搜索结合了 DFS 的空间效率和 BFS 的完备性/最优性(在单位代价情况下)。

其思想是

  1. 以深度限制 l = 0 开始。
  2. 运行深度受限的深度优先搜索,只探索深度不超过 l 的节点。
  3. 如果找到解,结束;否则,增加深度限制 l++,回到步骤2。

虽然看起来重复探索了浅层节点,但由于搜索树指数增长的特性,深层搜索占用了绝大部分时间,因此总时间复杂度与 BFS 同阶,而空间复杂度与 DFS 同阶。


📝 总结

本节课我们一起学习了人工智能中搜索问题的基石。

  1. 问题形式化:我们学会了如何将现实世界问题抽象为包含状态空间、后继函数、初始状态和目标测试的搜索问题。
  2. 核心框架:所有无信息搜索算法都遵循“选择-扩展-检查”的通用循环,区别仅在于从边缘选择节点的策略。
  3. 三大算法
    • 深度优先搜索:选择最深节点。空间效率高,但不完备,也不最优。
    • 广度优先搜索:选择最浅节点。当动作代价相同时,完备且最优,但空间消耗大。
    • 一致代价搜索:选择代价最小节点。在动作有不同代价时,完备且最优,是更通用的算法。
  4. 权衡与组合:我们看到了在时间、空间、完备性和最优性之间的权衡,并介绍了迭代加深搜索这种折中方案。

这些无信息搜索算法虽然基础,但它们是构建更智能、更有导向性的搜索算法(如下节课要学的启发式搜索)的必备知识。它们都面临一个共同挑战:在不知道目标方向时,需要探索大量看似无用的状态。如何利用问题本身的额外信息来引导搜索,将是我们下一步要探索的内容。

📚 课程 P20:贝叶斯网络推理与马尔可夫模型 🧠

在本节课中,我们将学习贝叶斯网络中的高级采样推理算法——马尔可夫链蒙特卡罗方法,并初步了解马尔可夫模型的基本概念。我们将从回顾之前的采样方法开始,深入探讨吉布斯采样如何解决似然加权采样的缺陷,并理解其背后的原理。最后,我们会将概率模型扩展到随时间变化的系统,引入马尔可夫模型,并了解其广泛的应用。


🔄 回顾:从贝叶斯网络采样

上一节我们讨论了从贝叶斯网络本身进行采样的几种算法。

以下是之前介绍过的几种采样方法:

  • 先验采样:直接从网络先验分布中生成样本。
  • 拒绝采样:生成样本后,丢弃所有与观测证据不一致的样本。这种方法效率极低。
  • 似然加权采样:通过固定证据变量的值来确保所有样本都与证据一致,但需要对生成的样本根据其与证据的匹配程度进行重新加权。

虽然似然加权采样效果尚可,但它存在一个显著问题。当网络中存在大量位于“叶子”节点(即没有子节点的节点)的证据时,算法会生成大量无视这些证据的样本。这些样本会获得极小的权重,导致只有少数“幸运”地猜对了证据变量值的样本主导最终的估计结果。这使得有效样本量变得极小,从而得到非常糟糕的概率估计。


🎲 马尔可夫链蒙特卡罗算法

为了解决上述问题,我们引入了马尔可夫链蒙特卡罗算法。

MCMC算法不仅固定证据变量,还能让来自证据变量的信息在整个网络中传播。因此,采样过程很快就能受到网络中所有证据的影响,而不仅仅是根节点的证据。

MCMC 算法概述

MCMC算法的高级思想非常简单:在状态空间中随机游走,并通过观察游走过程中访问的状态来估计查询结果。

以下是该算法的核心要点:

  • 马尔可夫链:指通过随机游走生成样本序列的特定方式。链中的每个新状态都只依赖于前一个状态,并以一定的概率随机选择。
  • 蒙特卡罗:泛指任何使用随机化来给出问题近似答案的算法。

因此,MCMC算法就是在状态空间中“随便逛逛”,并记录你所看到的内容。


⚙️ 吉布斯采样

我们将重点学习一种特定的MCMC算法,称为吉布斯采样

在贝叶斯网络推理的语境下,吉布斯采样通常每次只对一个非证据变量进行采样。采样时,该变量的新值取决于网络中所有其他变量在当前状态下的取值。

算法步骤

吉布斯采样的过程可以概括为以下几个步骤:

  1. 初始化:将所有证据变量固定为其观测值。为所有非证据变量随机分配一个初始值,形成一个完整的联合状态。
  2. 循环采样:重复以下过程:
    • 从所有非证据变量中随机选择一个变量 (X_i)。
    • 根据 (X_i) 的马尔可夫毯子 中所有变量的当前值,计算 (X_i) 的条件概率分布 (P(X_i | \text{MB}(X_i)))。
    • 从这个分布中为 (X_i) 采样一个新的值 (x_i'),更新当前状态。
  3. 估计查询:在经过一段“预热”期后,持续采样并记录状态。对于任何查询,只需计算这些记录状态中该查询为真的比例,作为其概率估计。

马尔可夫毯子与计算简化

在贝叶斯网络中,一个变量的马尔可夫毯子包括其父节点、子节点以及子节点的其他父节点(即“配偶”节点)。

关键的性质是:给定其马尔可夫毯子,该变量与网络中的所有其他变量条件独立。这意味着在吉布斯采样中,为变量 (X_i) 采样新值时,只需考虑其马尔可夫毯子中的少数几个邻居变量。

计算公式如下:
[
P(X_i | \text{mb}(X_i)) \propto P(X_i | \text{Parents}(X_i)) \times \prod_{Y_j \in \text{Children}(X_i)} P(Y_j | \text{Parents}(Y_j))
]
你只需要将 (X_i) 在其父节点下的条件概率,与其每个子节点在其各自父节点下的条件概率相乘(其中 (X_i) 是父节点之一),然后进行归一化即可得到分布。这个计算是局部的,与网络总规模无关,因此效率很高。


📈 吉布斯采样的性质与示例

信息传播与收敛

吉布斯采样能有效地将证据信息传播到整个网络。例如,在第一轮采样后,所有与证据变量直接相邻的变量都会受到影响;几轮之后,影响就能传播到更远的变量。最终,采样过程会收敛到真实的后验概率分布

与似然加权采样的比较

通过汽车保险网络的例子,我们可以比较两种算法:

  • 当证据位于查询变量的上游时(这是似然加权的理想情况),两种算法都表现良好。
  • 当证据位于查询变量的下游时(这是似然加权的最坏情况),吉布斯采样显著优于似然加权。在后者可能无法收敛的情况下,吉布斯采样仍能给出近乎准确的估计。

因此,对于具有大量证据的大型网络,吉布斯采样的效率可能比似然加权高出多个数量级,是实践中常用的工具。


🔬 深入原理:平衡分布与收敛

从更理论的角度看,吉布斯采样定义了一个在状态(即所有变量的赋值)上的马尔可夫链。每个状态都是一个超立方体的顶点,状态之间的转移沿着超立方体的边进行(因为一次只改变一个变量)。

我们可以定义一个转移概率矩阵 (K),其中 (K_{\mathbf{x} \to \mathbf{x’}}) 表示从状态 (\mathbf{x}) 转移到状态 (\mathbf{x’}) 的概率。运行采样算法相当于在这个图上随机游走。

平衡分布

马尔可夫链的平衡分布 (\pi) 是一个概率向量,满足:
[
\pi = \pi K
]
这意味着,一旦链的分布达到 (\pi),后续的采样将保持这个分布。可以证明,在吉布斯采样中,这个平衡分布 (\pi) 正好就是给定证据下的真实后验概率分布。

收敛保证与挑战

在满足一定条件(如所有概率严格介于0和1之间,且每个变量都被无限频繁采样)时,吉布斯采样是一致的,即当采样次数趋于无穷时,估计值会收敛到真实后验。

然而,收敛速度是一个实际问题。在最坏情况下,达到平衡分布所需时间可能是状态空间大小的指数级,这通常发生在转移概率非常极端(接近0或1)时,导致链长时间困在状态空间的某个子集中。诊断马尔可夫链是否已收敛是实际应用中的一个挑战。


⏳ 扩展到时序模型:马尔可夫模型

现在,我们将概率模型扩展到那些状态随时间演化的系统,即马尔可夫模型

核心思想是为每个时间点 (t) 复制一组变量 (X_t)。我们做出马尔可夫假设:时间 (t) 的状态 (X_t) 只依赖于前一个时间点 (t-1) 的状态 (X_{t-1}),而与更早的历史无关。

模型表示

联合概率分布可以写为:
[
P(X_0, X_1, ..., X_T) = P(X_0) \prod_{t=1}^{T} P(X_t | X_{t-1})
]
其中 (P(X_0)) 是初始状态分布,(P(X_t | X_{t-1})) 是转移模型,通常假设是平稳的(即不随时间变化)。

示例与应用

马尔可夫模型有极其广泛的应用:

以下是几个经典例子:

  • 一维随机游走:状态是整数位置,每一步以相等概率向左或向右移动。其性质(如期望距离、返回原点的概率)在物理、金融(股票价格模型)、赌博理论中都有重要意义。
  • N-gram语言模型:用于建模自然语言。状态是单词,N-gram模型预测下一个单词的概率依赖于前 N-1 个单词。当今的大型语言模型(如GPT系列)本质上就是参数规模巨大的N-gram模型的高级压缩形式。
  • 网页浏览的PageRank:将网页视为状态,点击链接视为状态转移。在此随机游走模型下的平稳分布就是PageRank,它是谷歌搜索算法的基石,用于衡量网页重要性。
  • 简单天气模型:一个两状态(晴/雨)模型,其转移概率可以刻画天气的持续性。

🎯 总结

本节课我们一起学习了以下内容:

  1. 回顾了贝叶斯网络中的采样算法,指出了拒绝采样和似然加权采样的局限性。
  2. 引入了马尔可夫链蒙特卡罗方法,它通过状态空间中的随机游走来进行推理。
  3. 深入探讨了吉布斯采样,这是一种具体的MCMC算法,它通过每次采样一个变量并依据其马尔可夫毯子更新,来高效地传播证据信息。我们了解了其操作步骤、计算简化原理以及优于似然加权采样的场景。
  4. 从原理上分析了MCMC,包括平衡分布的概念和收敛性,同时也认识到诊断收敛的实际挑战。
  5. 将模型扩展到时序领域,引入了马尔可夫模型。我们学习了其基本假设、表示方法,并了解了随机游走、语言模型、PageRank等丰富应用,为后续处理时序推理问题打下了基础。

MCMC是处理大型复杂概率模型的强大通用推理工具,而马尔可夫模型则为描述动态系统提供了简洁而有力的框架。

课程 P21:隐马尔可夫模型、滤波与维特比算法 🧠

在本节课中,我们将学习隐马尔可夫模型(HMMs)的核心概念,包括如何仅根据一系列观测来预测和推断隐藏状态。我们将重点介绍两种关键算法:用于实时状态估计的滤波算法,以及用于寻找最可能状态序列的维特比算法


马尔可夫模型回顾 🔄

上一节我们讨论了马尔可夫模型的基本思想。它是一个状态变量序列:x0, x1, x2, x3, ...。我们引入了一个天气的例子,状态可以是晴天或雨天。

  • 先验分布从 P(x0) = [0.5, 0.5] 开始。
  • 转移模型描述了给定前一状态时,下一个状态的分布。这是一个一阶马尔可夫模型,因为下一个状态只取决于前一个状态。

模型可以描述为:晴天以 0.9 的概率持续,雨天以 0.7 的概率持续。我们可以用概率状态转移图或篱笆图来表示,后者将每个时间步的状态分开显示,并描述它们之间的转移。


状态预测 ☀️🌧️

本节中,我们来看看如何进行天气预报。在时间 0,我们有概率分布 [0.5, 0.5]。我们想预测时间 1 的天气分布 P(x1)

计算方法是引入变量 x0 并对所有可能的 x0 值求和:
P(x1) = Σ_{x0} P(x1, x0) = Σ_{x0} P(x0) * P(x1 | x0)
这里,P(x0) 是先验,P(x1 | x0) 是转移模型。

代入数值计算,我们得到明天的天气预报:P(x1) = [0.6, 0.4],即 60% 晴天,40% 雨天。

我们可以重复这个过程来预测更远的未来。从时间 1 的分布 [0.6, 0.4] 出发,使用相同的转移模型,可以计算出时间 2 的分布 [0.66, 0.34]。这个过程可以一直持续下去。

这种一步步从当前时间步分布计算下一个时间步分布的方法,构成了前向算法的基础。它采用递归更新的形式:P(x_t) = g(P(x_{t-1})),其中函数 g 是乘以转移矩阵的转置。

如果我们考虑极限情况,状态分布会收敛到一个平稳分布。通过解方程 P_∞ = T^T * P_∞,我们可以求出这个极限分布。对于我们的天气模型,平稳分布是 [0.75, 0.25],即长期来看,75% 的时间是晴天。这个极限与初始分布无关。


隐马尔可夫模型与部分可观测性 👁️

然而,现实世界往往是部分可观测的。我们无法直接看到状态(天气),只能获得一些有噪声的观测(例如,是否有人带伞)。这就是隐马尔可夫模型

HMM 在标准马尔可夫链的基础上,为每个状态变量 x_t 增加了一个观测变量 e_t。我们假设观测只依赖于当前状态(传感器马尔可夫假设)。

以下是传感器模型的例子:

  • 当天气晴朗时,有 20% 的概率看到伞。
  • 当天气下雨时,有 90% 的概率看到伞。

HMM 的联合概率分布为:
P(x_{0:t}, e_{1:t}) = P(x_0) * Π_{i=1}^t P(x_i | x_{i-1}) * P(e_i | x_i)

HMM 在历史上非常重要,曾广泛应用于语音识别(状态是音素/单词,观测是声学信号)和分子生物学(状态是基因功能区域,观测是DNA序列)。


滤波:状态估计 🎯

滤波(或状态估计)是智能系统的一项基本任务:根据到目前为止的所有观测,估计当前世界的状态。例如,跟踪你的车或手机在哪里。

我们想要计算 P(x_t | e_{1:t}),记作 f_t。我们可以推导出一个递归更新公式,它包含三个步骤:

  1. 预测:基于上一时刻的信念状态和转移模型,预测当前时刻的先验状态。
    P(x_{t+1} | e_{1:t}) = Σ_{x_t} P(x_{t+1} | x_t) * f_t
  2. 更新:结合新的观测 e_{t+1},用传感器模型更新预测。
    f_{t+1} ∝ P(e_{t+1} | x_{t+1}) * P(x_{t+1} | e_{1:t})
  3. 归一化:确保 f_{t+1} 是一个有效的概率分布。

这个算法的核心是:预测 -> 更新 -> 归一化。更新成本与状态数量的平方成正比,但与时间序列的长度无关,因此可以实时运行。

一个著名的滤波算法是卡尔曼滤波器,用于具有线性动力学和高斯噪声的连续状态系统,在阿波罗计划等工程领域有里程碑式的应用。


维特比算法:最可能解释 🏆

有时我们不仅关心当前状态,还想知道整个最可能的状态序列,这称为最可能解释(MLE)。例如,在语音识别中,我们想找出最可能说出观测到声音的单词序列。

我们想找到:
argmax_{x_{1:t}} P(x_{1:t} | e_{1:t})

这等价于在所有可能路径(篱笆图中的路径)中,找到使路径权重(转移概率与观测概率的乘积)最大的路径。直接枚举所有路径是指数级复杂度。

维特比算法高效地解决了这个问题。其核心思想与滤波的前向算法类似,但将求和 (Σ) 替换为取最大值 (max)。

算法步骤:

  • 定义 m_t(s) 为在时间 t 到达状态 s 的最可能路径的概率。
  • 递归计算:m_{t+1}(s') = max_{s} [ m_t(s) * P(s' | s) * P(e_{t+1} | s') ]
  • 同时,记录下对于每个状态 s',是哪个前驱状态 s 达到了这个最大值(回溯指针)。
  • 在计算完所有时间步后,从最终时刻概率最大的状态开始,沿着回溯指针反向追踪,即可得到最可能的状态序列。

维特比算法是数字通信中解码噪声信号的基础算法,具有极其重要的经济价值。


总结 📚

本节课我们一起学习了隐马尔可夫模型的核心框架。

  • 我们回顾了马尔可夫模型和状态预测。
  • 引入了部分可观测性和隐马尔可夫模型。
  • 深入探讨了滤波算法,它能够递归地根据新证据更新对当前状态的信念,是实时状态估计的基石。
  • 最后,我们学习了维特比算法,它通过动态规划高效地找出整个最可能的状态序列,解决了最可能解释问题。

这两种算法使我们能够在充满噪声和不完整信息的世界中,进行有效的推理和决策。

课程 P22:动态贝叶斯网络与粒子滤波器 🧠

在本节课中,我们将学习如何为随时间演变的复杂系统建模,并探索当精确推理变得不可行时,如何利用粒子滤波器进行近似推理。我们将从回顾隐马尔可夫模型(HMM)开始,扩展到更通用的动态贝叶斯网络(DBN),并最终介绍粒子滤波器的核心思想——重采样。


从隐马尔可夫模型到动态贝叶斯网络 🔄

上一节我们介绍了隐马尔可夫模型及其精确推理算法。本节中,我们来看看如何将模型扩展到包含多个状态变量和证据源的更大系统。

在HMM中,每个时间步只有一个状态变量。为了建模更复杂的系统,我们可以在每个时间步引入多个状态变量,并将它们连接成一个小型贝叶斯网络,然后随时间步复制这个结构。这就构成了动态贝叶斯网络。

在DBN中,状态变量的父节点可以是前一个时间步的状态变量,也可以是同一时间步的其他状态变量。例如,在追踪多个幽灵的项目中,每个幽灵的位置是一个状态变量,声纳测量是证据变量。幽灵在时间t的位置取决于它在时间t-1的位置,也可能取决于其他幽灵在之前的位置。

每个离散的DBN都可以转换为一个完全等效的HMM,方法是将所有状态变量“折叠”成一个组合变量,其取值范围是各状态变量值域的笛卡尔积。然而,这种转换会导致表示大小(参数数量)的指数级爆炸。例如,一个有20个布尔状态变量的系统,若每个变量最多有3个父节点,DBN只需约160个参数;而等效的HMM则需要约2^40(约一万亿)个参数。因此,利用DBN捕捉系统的子结构对于高效学习和推理至关重要。


动态贝叶斯网络中的推理挑战 ⚙️

既然DBN非常适合表示复杂过程,我们如何在其上进行推理呢?一个直接的想法是:构建展开的时间步,形成一个大型贝叶斯网络,然后运行变量消除等精确推理算法。

对于离线处理(所有数据已知),这种方法的时间复杂度与观察序列长度呈线性关系,是可行的。但对于在线处理(数据持续到达),每次新观察到来都重新展开网络并运行精确推理,总时间复杂度将变为序列长度的平方,这是不可接受的。

尝试为DBN设计类似HMM滤波的递归在线算法时,问题出现了。在DBN上运行变量消除时,因子最终会增长到包含给定时间步的所有状态变量,导致每次更新的计算成本相对于状态变量数量呈指数级增长。对于拥有数百个状态变量(如火星探测器健康监测系统)的大型系统,精确推理是无法实现的。


现实世界应用:重症监护室监测 🏥

为了具体说明DBN的应用和挑战,我们来看一个现实世界的例子:儿科重症监护室(ICU)的病人监测系统。

系统的状态变量描述了病人的生理状态(如真实心率、血压、血氧、颅内压)以及传感器设备本身的状态(如电极是否脱落)。证据变量则是从各种监护设备(如心电图、血氧仪、呼吸机)获得的测量值。

测量数据中充满了干扰和伪影。例如,血压监测中,护士抽血或设备校零会导致读数剧烈波动,产生大量假警报。研究表明,ICU中高达94%的警报是假警报。

通过构建一个精细的DBN来建模生理动力学、传感器动力学以及各种干扰事件(如“抽血”、“校零”)如何影响测量,我们可以从嘈杂的数据中推断出病人的真实生理状态以及设备故障情况。下图展示了一个简化的DBN片段,用于从心电图和血氧仪读数推断真实心率、传感器状态及病人是否移动:

状态变量: True HR (真实心率), Patient Motion (病人移动), Resting HR (静息心率)
传感器状态: ECG Lead Off? (心电图脱落?), Pulse Ox Off? (血氧仪脱落?)
证据变量: ECG HR (心电图心率读数), Pulse Ox HR (血氧仪心率读数), SpO2 (血氧饱和度)

然而,这个完整的DBN模型非常庞大和复杂,无法进行精确推理,因此我们需要近似算法。


粒子滤波器:一种近似推理方法 🎯

面对大型DBN精确推理的指数级复杂度,我们需要高效的近似算法。我们首先可能会尝试已知的近似推理方法,如似然加权。

但在类似HMM的时序模型上应用似然加权时,效果非常差。因为证据变量位于“叶节点”,随着时间步增加,生成与所有历史证据一致的样本的概率呈指数级下降。最终,只有极少数“幸运”的样本拥有全部权重,导致估计结果完全错误。即使增加样本数量,也只能推迟问题发生的时间,无法根本解决。

问题的核心在于,似然加权在生成状态序列(粒子)时完全忽略了证据,事后再检查一致性,这种方法在长序列中效率极低。

粒子滤波器通过引入一个全新的思想——重采样——来解决这个问题。其核心是让粒子“关注”证据。算法不是盲目地向前模拟,而是在每一步根据新证据的似然度来调整粒子的分布,淘汰掉与证据不符的粒子,并复制那些与证据一致的粒子。这个过程使得粒子群能够有效地跟踪系统的真实状态。

以下是粒子滤波器一个时间步的基本流程:

  1. 预测:根据每个粒子在t-1时刻的状态,从其状态转移模型P(X_t | X_{t-1})中采样,得到它们在t时刻的预测状态。
  2. 更新:获得t时刻的新证据e_t。为每个粒子计算权重,权重等于该粒子预测状态生成当前证据的似然度P(e_t | X_t)
  3. 重采样:根据粒子的权重,从当前粒子集合中有放回地抽取N个新粒子。权重高的粒子更有可能被多次抽取,权重低的粒子可能被淘汰。新粒子集合中每个粒子的权重重置为1/N。

通过不断重复预测-更新-重采样的循环,粒子滤波器能够用一群粒子来近似表示系统状态的后验概率分布,即使在高维状态空间中也能有效工作。这正是我们之前提到的ICU监测系统实际采用的推理方法。


总结 📚

本节课中,我们一起学习了动态贝叶斯网络和粒子滤波器。

  • 我们首先将隐马尔可夫模型扩展为动态贝叶斯网络,后者能更紧凑地表示具有多个状态变量的复杂时序系统。
  • 我们认识到,在DBN上进行精确推理(如变量消除)对于在线应用或大型网络是计算上难以实现的。
  • 通过重症监护室监测的案例,我们看到了DBN在现实世界中的强大建模能力,以及处理传感器噪声和伪影的必要性。
  • 最后,我们引入了粒子滤波器作为解决方案。它通过重采样机制,使一组“粒子”能够随着新证据的到来而动态演化,从而高效地近似系统状态的后验分布,克服了传统似然加权方法在时序推理中的致命缺陷。

粒子滤波器已成为机器人定位、视觉跟踪、金融建模等众多领域的核心算法,它为我们处理复杂、高维的时序推理问题提供了一个强大而实用的工具。

🧠 课程 P23:效用理论、理性与决策

在本节课中,我们将学习理性决策背后的理论基础。我们将探讨效用(Utility)的概念,理解为何在不确定性决策中需要使用数字(如奖励值),以及这些数字如何从理性行为的公理中推导出来。我们还将学习如何将效用理论与概率模型(如贝叶斯网络)结合,构建决策网络(Decision Networks),以解决复杂的决策问题。最后,我们会简要了解如何评估收集额外信息的价值。


1️⃣ 为什么需要数字?序数效用与基数效用

在之前的课程中,我们已经在MDPs、博弈树等模型中使用数字来表示奖励、成本或评估函数。一个自然的问题是:这些数字从何而来?为什么对它们进行求和、求期望或折现是合理的?

首先,我们来看一个关键区别:序数效用(Ordinal Utility)和基数效用(Cardinal Utility)。

  • 序数效用只表示偏好的排序(哪个更好,哪个更差),而不关心具体数值的大小。例如,在极大极小树中,只要对叶节点值进行单调变换(如平方、取对数),最优决策就不会改变。因为决策只依赖于结果的相对排名。

    • 公式示例:若 U(A) > U(B) 仅表示更偏好A,但 U(A) = 5U(B) = 1 之间的差距 4 没有绝对意义。
  • 基数效用则要求数值具有定量意义,能够进行数学运算(如求期望)。当决策模型中包含机会节点(即不确定性)时,仅仅有排序就不够了。此时,只有正仿射变换U' = aU + b, 其中 a > 0)才能保持最优决策不变。这意味着我们需要一个具有线性尺度意义的数值来表示偏好强度。

    • 公式示例:在计算期望效用时,E[U] = Σ P(i) * U(i)。如果对 U 进行非线性变换,期望值的排序可能会改变,从而导致不同的决策。

核心观点:不确定性(概率)的存在,使得我们必须使用基数效用来描述欲望,而不仅仅是排名。


2️⃣ 效用理论的起源与核心思想

效用理论可以追溯到丹尼尔·伯努利。他通过一个思想实验揭示了金钱的边际效用递减规律,从而将“效用”与“货币价值”区分开。

  • 思想实验:一个商人需要将财富运回。方案一:用一艘船运所有财富(成本低,但有30%概率全部损失)。方案二:用两艘船各运一半(成本高,但风险分散)。尽管方案一的期望货币价值更高,但商人们都选择方案二。这是因为从“身无分文”到“超级富有”的效用提升,远大于从“超级富有”到“两倍超级富有”的效用提升。

这个洞察表明,人们内心存在一个衡量状态好坏的主观心理量,即效用。它不一定是线性的,尤其对于大量金钱或重要结果(如生命、健康)。

理性与效用函数的关系:冯·诺依曼和摩根斯坦证明,如果一个决策者的偏好满足一组理性公理(如可传递性、连续性、可替代性等),那么就可以用一个效用函数来描述他,并且他的行为等价于最大化期望效用。即使决策者大脑中没有明确的数字计算过程,其外在的理性选择也可以被解释为在进行期望效用最大化。


3️⃣ 理性公理与期望效用最大化

上一节我们提到了理性公理,本节我们来详细看看这些公理如何导致期望效用最大化。

理性决策基于对奖品(确定性的结果)和彩票(概率性的结果分布)的偏好。以下是几个关键公理:

以下是理性偏好应满足的核心公理:

  1. 有序性:对于任意两个选项A和B,你必然要么偏好A,要么偏好B,要么觉得无差异。
  2. 传递性:如果偏好A胜于B,且偏好B胜于C,那么必须偏好A胜于C。违反此条会导致“金钱泵”悖论,让他人无限榨取你的资源。
  3. 连续性:如果偏好A胜于B胜于C,那么存在一个概率p,使得你对“以概率p获得A,否则获得C”的彩票与确定性地获得B无差异。
  4. 可替代性:如果对A和B无差异,那么在任何彩票中,可以用A替换B而不改变偏好。
  5. 单调性:如果偏好A胜于B,那么对于任何概率p>q,你都会偏好“以概率p获得A,否则获得B”的彩票,胜过“以概率q获得A,否则获得B”的彩票。

冯·诺依曼-摩根斯坦定理指出,满足以上公理的偏好,必然存在一个效用函数U,使得:

  • U(A) > U(B) 当且仅当偏好A胜于B。
  • 任何彩票L的效用等于其各结果效用的期望值:U(L) = Σ P(i) * U(结果i)

因此,理性决策者就是一个期望效用最大化者。这个效用函数在正仿射变换(aU + b, a>0)下是唯一的。


4️⃣ 如何测量效用?风险态度

既然效用是主观的,我们如何测量它?一个常见方法是标准彩票法

  • 方法:设定一个最好的可能结果(效用设为1)和一个最坏的结果(效用设为0)。对于待评估的某个结果X,调整一个标准彩票(以概率p获得最好结果,以概率1-p获得最坏结果)中的概率p,直到决策者对“确定获得X”和“参加这个标准彩票”感到无差异。此时,概率p就是结果X的效用值 U(X) = p

风险态度源于效用函数的形状(通常是凹的):

  • 风险厌恶:彩票的效用小于彩票期望货币价值对应的效用。即 U(彩票) < U(彩票的期望货币价值)。大多数人在涉及重大损失时是风险厌恶的,这解释了保险业的存在——人们愿意支付“保费”来消除风险。
  • 风险偏好:在陷入绝境(如巨额债务)时,人们可能变得风险偏好,愿意参与高风险的赌博(如彩票)以求翻盘。

金钱的效用:对于个人而言,一定数量金钱的效用,指的是总财富处于某个水平时的效用,而非那笔钱本身的效用。对于小额金钱,常近似为线性;对于大额金钱,则表现出非线性(如对数函数)。


5️⃣ 决策中的陷阱:优化器诅咒

在现实决策中,我们常依赖专家估计或数据来选择最优选项(如投资)。但即使每个选项的价值估计是无偏的,选择估计值最高的那个,其真实期望价值也会系统性地低于它的估计值。

  • 原因:假设所有选项的真实价值相同,我们的估计值等于真实值加上一个均值为零的随机误差。我们自然会选择估计值最高的选项,而这个选项之所以高,很可能是因为它有一个很大的正误差。当我们实施这个选择时,正误差消失,其真实表现就会令人失望。
  • 影响领域:此现象普遍存在于基金选择、药物审批、科学发表(发表偏倚)、拍卖(赢家诅咒)等领域。它也被称为“选择偏差”或“决策后失望”。
  • 启示:在存在估计误差时,理性的策略不一定是选择估计值最高的选项,有时需要“收缩”估计值。

6️⃣ 序列决策与奖励塑造

在MDP中,我们处理的是状态或奖励的序列。如何理性地比较不同的结果序列?

一个关键的理性假设是平稳性:在两个序列前加上一个相同的结果,不应改变你对这两个序列的偏好排序。从这个看似无害的假设可以推导出:对序列唯一理性的评价方式是计算其折现奖励和

  • 公式U(序列) = R_t + γ * R_{t+1} + γ^2 * R_{t+2} + ...
  • 意义:几何折现(γ)并非任意设定,而是从理性公理中推导出的自然结果。它保证了无限序列的效用有限,并具有时间上的一致性。

奖励塑造:一个强大且实用的结论是,我们可以对MDP的奖励函数 R(s, a, s') 添加一个势能函数 Φ(s) 的差值,而不改变最优策略。

  • 公式:新奖励 R'(s, a, s') = R(s, a, s') + γΦ(s') - Φ(s)
  • 直观理解Φ(s) 像是状态的“势能”。智能体绕任何环路回到起点时,获得的额外奖励总和为零(保守场)。因此,这种变换不会创造新的“虚假”目标,但可以引导学习过程,使智能体更快地探索到有希望的区域。例如,在训练足球机器人时,可以添加一个与“接近对方球门”相关的势能函数来鼓励进攻。

7️⃣ 决策网络:整合概率与效用

现在,我们将贝叶斯网络(处理概率与不确定性)与效用理论(处理偏好与决策)结合起来,形成决策网络(又称影响图)。

决策网络包含三种节点:

  1. 机会节点(椭圆):代表随机变量,其条件概率由贝叶斯网络定义。
  2. 决策节点(矩形):代表决策者可以选择的行动。
  3. 效用节点(菱形):代表在该配置下的效用值,其父节点是影响效用的因素(状态和行动)。

求解方法(MEU原则)

  1. 对于决策节点的每一种可能取值(行动)。
  2. 将决策节点固定为该值。
  3. 利用贝叶斯网络推理,计算在给定任何证据下,效用节点所有父节点的概率分布。
  4. 计算该行动下的期望效用EU(Action) = Σ_{父节点取值} P(取值 | Action, Evidence) * U(取值, Action)
  5. 选择期望效用最高的行动。

决策网络提供了一个强大的框架,将概率推理与最优决策无缝衔接,可以建模复杂的现实世界问题。


🎯 总结

在本节课中,我们一起学习了:

  1. 效用理论的基础:理解了为何在不确定性决策中需要基数效用,以及效用与货币价值的区别。
  2. 理性公理:了解了冯·诺依曼-摩根斯坦公理如何定义理性偏好,并推导出期望效用最大化原则。
  3. 效用测量与风险:学习了测量效用的方法,以及风险厌恶等概念如何影响决策。
  4. 决策陷阱:认识了“优化器诅咒”等常见决策偏差。
  5. 序列决策:从平稳性公理理解了折现奖励和的合理性,并掌握了奖励塑造这一实用技术。
  6. 决策网络:学会了如何将概率模型与效用函数结合,通过计算最大期望效用(MEU)来做出最优决策。

效用理论为人工智能中的理性智能体设计提供了坚实的数学基础,确保我们指定的目标(效用函数)能够通过计算产生复杂而合理的行为。

课程 P24:[CS188 SP23] 第23讲 - 决策网络与信息价值

概述

在本节课中,我们将学习如何将概率推理与决策制定结合起来。我们将介绍决策网络的结构,学习如何在其中进行推理以最大化期望效用,并最终探讨“信息的价值”这一核心概念,即了解额外信息能为我们带来多少收益。


决策网络简介

上一节我们回顾了概率推理和效用最大化这两个独立的话题。本节中,我们来看看如何将它们结合在一个统一的框架中,即决策网络。

决策网络看起来很像贝叶斯网络,但增加了一些新的节点类型来代表决策和效用。

以下是决策网络中各种节点的含义:

  • 圆形节点(机会节点):代表随机变量。例如,天气预报。你无法控制其结果,但可以基于概率分布进行推理。
  • 矩形节点(决策节点):代表你可以选择的行动。例如,带伞留伞。与随机变量不同,行动由你完全控制,其下方没有概率分布。
  • 菱形节点(效用节点):代表最终的结果或得分(效用)。其值依赖于其父节点(例如行动和随机变量)的状态。对于父节点的每一种可能组合,都需要指定一个具体的效用值。

网络中的箭头表示条件依赖关系,类似于贝叶斯网络中的因果关系。


一个简单的决策故事

为了理解决策网络如何工作,我们来看一个关于机器人的简单例子。

故事背景是:一个机器人需要决定早上是否带伞。它的目标是尽可能快乐地玩耍(获得高效用)。结果取决于两个因素:它选择的行动(带伞/留伞)和实际的天气(晴天/雨天)。

以下是所有可能场景的效用:

  • 留伞 & 晴天:可以玩机器人排球,非常快乐,效用为 100
  • 带伞 & 晴天:必须拖着伞,不能玩耍,效用为 20
  • 留伞 & 雨天:被雨淋湿,生锈短路,效用为 0
  • 带伞 & 雨天:保持干燥,比较快乐,效用为 70

此外,我们知道先验概率:P(天气=晴) = 0.7P(天气=雨) = 0.3


在决策网络中推理:最大化期望效用

我们的目标是选择能最大化期望效用的行动。期望效用是对所有可能结果按其发生概率加权后的平均效用。

首先,我们计算每个行动的期望效用(EU)。

计算行动“留伞”的期望效用:
如果我们选择“留伞”,有两种可能结果:

  1. 天气晴(概率0.7),获得效用100。
  2. 天气雨(概率0.3),获得效用0。
    因此,期望效用为:EU(留伞) = 0.7 * 100 + 0.3 * 0 = 70

计算行动“带伞”的期望效用:
如果我们选择“带伞”,也有两种可能结果:

  1. 天气晴(概率0.7),获得效用20。
  2. 天气雨(概率0.3),获得效用70。
    因此,期望效用为:EU(带伞) = 0.7 * 20 + 0.3 * 70 = 14 + 21 = 35

现在,我们比较这两个值。由于我们可以自由选择行动,我们会选择能带来更高期望效用的那个。这就是最大期望效用(MEU)

在当前没有任何额外证据(记为空集 )的情况下,最大期望效用是:
MEU(∅) = max( EU(留伞), EU(带伞) ) = max(70, 35) = 70
最优行动是“留伞”。

符号说明:

  • EU(a | e):在已知证据 e 的条件下,采取行动 a 的期望效用。
  • MEU(e):在已知证据 e 的条件下,所有可能行动中的最大期望效用。括号内是你当前掌握的信息。

引入证据:预报的作用

现在,我们让故事变得更现实一些。机器人早上会听天气预报,预报可能为“好”或“坏”。预报的准确度并非完美,它与真实天气有概率关联。

假设机器人听到预报是“坏”。这改变了我们对天气的信念。通过贝叶斯网络推理(例如使用贝叶斯规则或变量消除),我们可以得到新的条件概率:
P(天气=晴 | 预报=坏) = 0.34
P(天气=雨 | 预报=坏) = 0.66

现在,我们基于新的证据重新计算期望效用。

已知预报=坏,计算行动“留伞”的期望效用:
EU(留伞 | 预报=坏) = 0.34 * 100 + 0.66 * 0 = 34

已知预报=坏,计算行动“带伞”的期望效用:
EU(带伞 | 预报=坏) = 0.34 * 20 + 0.66 * 70 = 6.8 + 46.2 = 53

因此,在已知预报坏的情况下,最大期望效用为:
MEU(预报=坏) = max(34, 53) = 53
最优行动变成了“带伞”。

可以看到,获得新证据(预报)不仅改变了我们可能获得的分数(从70降到53),也可能改变最优决策本身。


信息的价值

直觉上,获取信息(如天气预报)应该能帮助我们做出更好的决策,从而获得更高的期望效用。信息的价值(Value of Perfect Information, VPI)就是衡量“拥有该信息”与“没有该信息”时期望效用提升的多少。

概念公式

信息 E' 的价值公式如下:
VPI(E' | e) = ( Σ_{e'} P(E'=e' | e) * MEU(e, E'=e') ) - MEU(e)

其中:

  • e 是当前已掌握的证据。
  • E' 是那个将被揭示的随机变量(例如 预报)。
  • e'E' 的具体取值(例如“好”或“坏”)。
  • MEU(e, E'=e') 是已知当前证据 e 且额外知道 E'=e' 时的最大期望效用。
  • MEU(e) 是仅已知当前证据 e 时的最大期望效用。

计算示例:回到天气预报

假设我们最初没有任何证据(e = ∅)。有人提出要告诉我们 预报 的真实值(好或坏),我们需要计算这个信息的价值。

  1. 计算 MEU(∅):如前所述,MEU(∅) = 70
  2. 计算知道预报后的期望MEU:我们需要分别计算预报为好和坏时的MEU,然后按预报的先验概率取期望。
    • 已知 预报=好 时的 MEU(计算过程略):假设为 95
    • 已知 预报=坏 时的 MEU:如前所述,为 53
    • 预报的先验概率(从贝叶斯网得出):假设 P(预报=好)=0.8P(预报=坏)=0.2
    • 因此,知道预报后的期望MEU为:0.8 * 95 + 0.2 * 53 = 76 + 10.6 = 86.6
  3. 计算VPI
    VPI(预报 | ∅) = 期望MEU(知道预报) - MEU(不知道预报) = 86.6 - 70 = 16.6

这意味着,平均而言,获得天气预报这项信息能让机器人的期望效用提升 16.6。这也是机器人愿意为获取该信息支付的“公平价格”。

关键点:在计算 VPI 时,因为提供信息者并没有承诺揭示的结果具体是什么(例如,保证预报是好消息),所以我们必须在所有可能的结果(预报好/坏)上,对 MEU 再取一次期望。


总结

本节课中我们一起学习了决策网络与信息价值。

  1. 决策网络 融合了贝叶斯网络(用于概率推理)和决策/效用节点(用于行动选择),为我们提供了一个对不确定性世界进行建模和决策的框架。
  2. 核心推理任务 是计算最大期望效用(MEU),即选择那个能带来最高平均效用的行动。计算涉及在行动上取最大值,并在未知的随机变量结果上取期望值。
  3. 信息的价值(VPI) 量化了获取额外信息所能带来的期望效用增益。其计算方式是:[已知信息后的期望MEU] 减去 [未知信息时的MEU]。其中,已知信息后的期望MEU 需要对被揭示变量的所有可能结果进行加权平均。

通过理解这些概念,你可以系统地分析在不确定性下如何做出最优决策,并评估获取更多信息是否值得。

课程 P25:[CS188 SP23] 第24讲 - 机器学习:朴素贝叶斯 🧠

在本节课中,我们将要学习机器学习的基础知识,特别是朴素贝叶斯分类器。我们将了解如何从数据中构建模型,而不是直接使用给定的模型。课程将涵盖分类任务的基本框架、朴素贝叶斯模型的构建与训练过程,以及如何利用该模型对新数据进行预测。我们还将探讨机器学习中一个关键概念——过拟合,并学习如何通过划分数据集来评估模型的泛化能力。


什么是机器学习?🤔

到目前为止,在这门课程中,总是有人走到你面前,递给你一个模型。例如,他们会说:“这是一个搜索问题,给我一个算法来解决它。”或者“这是一个填写了概率的贝叶斯网络。告诉我如何在其中进行推理。”总会有人给你一个模型,然后你以某种方式使用该模型进行计算并从中学习。

但机器学习的情况有所不同。现在,不再是有人给你模型并告诉你如何处理它,而是需要你自己构建模型。我们将从今天开始看到这一点,并在接下来的课程中了解更多。我们不再是被动接受一个贝叶斯网络并求解,而是思考这个贝叶斯网络本身是如何构建的。或者,如果使用更复杂的机器学习算法,如何利用手头的数据构建模型。这就是机器学习与之前讨论内容的不同之处。

今天,我们将通过一个基于贝叶斯网络的机器学习算法(朴素贝叶斯)来了解一个小例子,并在接下来的课程中逐步扩展。


分类任务:机器学习的目标 🎯

就像我们讨论搜索时有经典的搜索问题示例,讨论MDP时有网格世界示例一样,机器学习也有一个贯穿始终的示例,即分类。这是许多机器学习算法的目标。

我们的目标如下:我们有一个包含许多不同数据点的世界,每个数据点 X 都有一个标签 Y。标签或类别是什么?我们会展示一些例子。目标是设计一个算法,它接收一个标签未知的输入 X,并能够预测其标签 Y

人们通常这样做(这不是唯一的方法,但今天我们将看到这种方法):首先从输入 X 中提取一些特征。特征是关于输入 X 的一些有用信息,可能为输出 Y 提供线索。然后,将这些特征输入某个机器学习算法(今天只介绍一种),最终输出一个预测的标签。这就是我们想要设计的一般目标。


机器学习如何工作?⚙️

到目前为止,我们所做的是获取别人给我们的数字,然后处理这些数字并得出一些结论。例如,在贝叶斯网络中,我们利用给定的概率进行计算。

但在机器学习中,不同之处在于,我们不是通过自己编写的算法或自己的知识来生成智能或发现有用的东西,而是直接从数据中尝试发现智能模式。我们不会自己推理数据,而是希望有人给我们一堆训练数据。训练数据可能是许多带有标签的示例数据点。然后,利用这些训练数据,我们尝试进行预测或学习一些模式,以帮助我们在未来进行预测。


示例:垃圾邮件过滤器 📧

这是最经典的例子,已经使用了大约20年,至今仍然很常见。当你使用电子邮件时,你不会看到很多垃圾邮件,这是因为有垃圾邮件过滤器在工作。

在这种情况下,输入 x 是一封电子邮件。有人给你一封电子邮件,要求你将其分类为两个标签或类别之一:垃圾邮件非垃圾邮件(在垃圾邮件分类领域,非垃圾邮件通常被称为“火腿邮件”)。

你需要从电子邮件中提取一些特征,这些特征可能告诉你关于这封电子邮件的一些有用信息,从而为你判断它是火腿邮件还是垃圾邮件提供线索。然后,通过机器学习算法,判断它是火腿邮件还是垃圾邮件。

机器学习算法的特殊之处在于,理论上你可以说:“我是垃圾邮件检测专家。我确切地知道什么对应垃圾邮件,什么对应火腿邮件。我将利用我所有的人类知识,写下所有规则,生成我的专家算法。”这很好,但这不是机器学习。在这种情况下,是你自己在学习。

机器学习之所以特殊,是因为你不是在学习,而是让算法为你学习垃圾邮件和火腿邮件的模式。你将获取所有这些训练数据(训练数据是一堆示例电子邮件,可能告诉你这封是垃圾邮件,那封是火腿邮件),并尝试基于这些训练数据学习垃圾邮件和火腿邮件的模式。

这就像你为考试而学习。有人给你很多训练数据,就像已经为你解答的练习题,你知道答案。你研究它们,试图找出其中的模式。这就是你在学习。然后,当你认为自己准备好了,你走进考场,参加期末考试。有人给你一个从未见过的新问题(一封新电子邮件),你的任务是利用之前学到的所有模式来判断它是火腿邮件还是垃圾邮件。这就是我们的目标。


如何手动判断垃圾邮件?🔍

假设你是CS188的垃圾邮件检测器,让我们一起检测一些垃圾邮件。

阅读以下邮件:

  • “尊敬的先生,首先,我对这笔交易充满信心。由于其性质,这完全是机密和绝密的。” 你认为这是垃圾邮件还是火腿邮件?它看起来很重要,是“绝密”。但它是垃圾邮件。
  • “要从未来的邮件列表中删除,只需回复此消息,并在主题中注明‘删除’。9900万个电子邮件地址仅售99美元。” 这是火腿邮件还是垃圾邮件?这看起来是个好交易。它是垃圾邮件。

问题是你怎么知道这是垃圾邮件?你怎么知道它不是火腿邮件?你从这封电子邮件中提取了一些有用的特征和模式,这些特征和模式告诉你它是否是火腿邮件或垃圾邮件。也许这些特征包括:你看到了“免费”这个词,感觉像是广告(垃圾邮件);或者你看到了全大写字母,觉得可疑;或者你看到了美元符号,感觉有人在向你推销东西。

你在大脑中自动完成了这个过程。但我们希望以某种方式将其自动化并归纳出来。今天的目标就是将你刚才所做的过程自动化成算法。你不会写下你所知道的关于火腿邮件和垃圾邮件的规则,而是希望获取一堆训练数据,将其输入某个机器学习算法。算法将在数据上进行训练,学习关于垃圾邮件和火腿邮件的模式(例如,这个特征指示垃圾邮件,那个特征指示火腿邮件)。最终,你可以参加“期末考试”,将事物分类为火腿邮件或垃圾邮件。


另一个示例:数字识别 🔢

有人给你一张图片(一堆像素),告诉你网格中哪些像素被填充,并问你这个人写的是哪个数字(0到9)。同样,你有训练数据。你不会去学习“1看起来像这样,2看起来像那样”的模式并写下来(虽然可以,但那不是机器学习)。相反,你希望利用别人提供给你的数据(如何获取这些数据更多是数据科学问题,我们不详细讨论),这些数据是手工标记的数字。你希望从这些数字中自动学习模式,例如,“这看起来像2,那看起来像3”。你希望自动完成这个过程,而不是手动编写规则。

这样,当有人给你一个新的、从未见过的数字图片时,你就能判断出它是哪个数字。这就是模式:有人给你一堆数据,你在数据上训练以自动学习模式,然后当需要测试时,有人给你一个新的、未见过的数据,你应该能够对其进行分类。

在训练过程中,通常不是直接处理数据本身,而是从数据中提取特征,然后在特征上进行训练。例如,不是逐个像素查看,而是查看有趣的特征,如图片中是否有环、是否是圆形或线条等。


朴素贝叶斯模型 🏗️

我们今天要学习的算法叫做朴素贝叶斯。它基于贝叶斯网络,因此看起来会有些熟悉。其思想是构建一个模型,即某种贝叶斯网络。在这个贝叶斯网络中,我们将有一些关于特征和输出的信息。然后,我们将使用这个贝叶斯网络,根据提供给我们的证据(即输入)来预测我们认为的输出(标签)。

但存在一些问题:我应该如何绘制这个贝叶斯网络?我们知道贝叶斯网络内部隐藏着数字(概率表)。这些数字从哪里来?这些都是我们在构建模型时需要回答的问题。

以下是模型的结构:

什么是贝叶斯网络? 贝叶斯网络包含许多随机变量。当我们不知道某事或对其有概率分布时,就将其设为随机变量。

在我们的分类问题中,哪些可以是随机变量?

  • 标签 Y 是一个随机变量,因为我们不知道它的值。它可能是垃圾邮件,也可能是火腿邮件。
  • 其他随机变量是特征。这些是从数据集中提取的特征。正如之前所说,有人为我们提供了一些训练数据的输入 X,我们提取特征。特征如何提取?已经有人为我们完成了。所以,别人已经挑选了有趣的特征并为我们提取出来。我们只需将这些特征作为证据或节点输入。

看看这个贝叶斯网络。我们知道贝叶斯网络内部有概率表。这个贝叶斯网络内部隐藏着哪些概率表?

贝叶斯网络总是有描述随机变量给定其父节点的表。

  • 查看 Y 节点内部,你会看到 P(Y)P(Y) 是关于有多少电子邮件是垃圾邮件或火腿邮件的分布。它描述了电子邮件是垃圾邮件或火腿邮件的普遍程度。在朴素贝叶斯中,我们必须以某种方式找出 P(Y)
  • 还有 P(F1|Y)P(F2|Y) 等。这些是告诉我们特征如何随标签变化的表。如果你知道标签,特征的分布是什么?这个特征在垃圾邮件中是否更可能出现?这些表隐藏在我们不知道具体数字的贝叶斯网络中,但我们将通过训练从数据中找出它们。

机器学习的两步过程:训练与分类 🔄

正如之前所说,机器学习通常是一个两步过程。

第一步是训练。这就像为考试而学习。我们需要获取别人给我们的数据。他们给我们很多特征到标签的映射(例如,这个特征对应垃圾邮件,这个输入有这些特征是火腿邮件等)。我们需要研究这些数据。在朴素贝叶斯模型中,这意味着我们将使用别人给我们的数据来填充那些概率表。在没有任何知识的情况下,我们不知道概率表中有什么。但如果有人给我们数据,我们可以使用数据来估计概率表可能是什么。我们希望这些估计能够编码关于特征及其与标签关系的有趣模式。

我们获取数据集,深入研究,根据数据找出可以放入这些表的最佳概率。我们估计 P(Y)P(F|Y)(这告诉我们标签如何影响特征)。这就是训练部分,就像你在学习、学习、再学习。最终,你在数据集上完成了学习,对自己的学习感到满意,并认为:“我认为我了解了模式。我理解了垃圾邮件和火腿邮件。”这样,你的自动化算法就学到了关于垃圾邮件或火腿邮件的一些东西,并隐藏在这个贝叶斯网络中。它学到了什么?我不知道。它学到了有用的东西吗?希望如此。但你没有告诉这个算法任何关于垃圾邮件或火腿邮件的事情。这个算法必须根据给定的训练数据自己找出模式。

第二步是分类(测试)。当你完成学习后,你认为自己已经准备好参加期末考试。这意味着你准备好向世界发布你的分类器。当你发布分类器后,有人走到你面前,给你一封全新的、从未见过的电子邮件。你提取这封电子邮件的特征(已经有人为我们完成)。然后,将这些特征作为证据。现在,我们需要做的就是进行贝叶斯网络推理。贝叶斯网络推理告诉我们,给定这个贝叶斯网络,我们可以从中提取概率分布。

我们特别想要查询的分布是:P(标签 | 证据)。这听起来是一个非常合理的查询,我们可以用它进行分类。使用这个模型,有人给我们证据,我们将所有特征作为证据填入,然后询问模型:“给定这些证据,它是垃圾邮件的可能性有多大?或者给定这些证据,它是火腿邮件的可能性有多大?”通过这个查询,我们以某种方式对这个未知数据进行了分类。我们希望这是一个好的分类。


朴素贝叶斯实战:训练与分类示例 📊

假设我们选择使用朴素贝叶斯。这意味着我们将绘制一个看起来像上面那样的贝叶斯网络:有一个标签 Y,以及一堆特征,所有特征都是标签的结果(箭头从标签指向所有特征)。在这个例子中,我们选择两个特征。

同样,我们如何选择这些特征?今天暂不讨论。目前假设有人已经告诉我们特征是什么。他们告诉我们应该使用的特征,我们不知道这些特征与火腿邮件或垃圾邮件的关系,只知道这些可能是提供线索的有用特征。

我们有两个特征:

  1. F1:我认识发件人吗?(是/否)。我可以查看电子邮件,编写一小段代码来提取这个特征。
  2. F2:电子邮件中“免费”这个词出现了多少次?(一个数字)。同样,我可以编写一小段代码来计算“免费”一词出现的次数并提取特征。

当有人给我一个输入 X(无论是让我分类还是用于训练),我都可以从中提取特征。今天我们不担心如何提取,假设已经有人为我们提取了这些特征。我们的任务是自动从这些特征中学习模式。

以下是隐藏在贝叶斯网络中的表:

  • P(Y):告诉我们,在没有任何证据的情况下,每个标签的普遍程度。我们需要从数据中学习。
  • P(F1|Y):隐藏在 F1 节点中的表。它告诉你对于 F1Y 的每一种设置,F1 给定 Y 的概率。我们不知道里面是什么,需要学习。
  • P(F2|Y):类似,需要学习。

训练过程

现在,我们使用数据进行训练。别人给我们这些标记的电子邮件数据。使用这个训练数据,我们应该能够给出这些概率表的最佳估计。

我们想要 P(F2|Y),例如 P(F2=0次免费 | Y=火腿邮件)。我如何知道这个数字?我可以从数据中估计。给定我的电子邮件是火腿邮件(即这两封),我看到“免费”出现0次的频率是多少?有两封火腿邮件,其中一封“免费”出现0次。所以,我对这个概率的最佳估计是0.5。我是怎么做的?我只是统计了我的数据。

根据这些数据,如果我知道某物是火腿邮件,那么50%的情况下,“免费”一词出现0次。这是一个好的估计吗?这取决于我的数据,但这就是我的估计。继续这样做:给定电子邮件是火腿邮件,“免费”一词恰好出现一次的频率是多少?这发生在第二封电子邮件中,所以是0.5。给定电子邮件是火腿邮件,“免费”一词出现两次的频率是多少?根据这个数据集,是0(我从未见过火腿邮件中“免费”出现两次的情况)。

对于垃圾邮件也可以这样做:给定电子邮件是垃圾邮件,“免费”出现0次的频率是多少?四封垃圾邮件中有一封是这样的,所以是1/4。出现一次呢?我看到两次(第三和第五封邮件)。出现两次呢?0.25。

我是如何得到这些数字的?我只是进行了一些统计,没有什么特别复杂的。通过统计,我进行了训练。这些数字现在编码了关于垃圾邮件模式以及它们如何影响“免费”一词出现次数特征的信息。我不必自己指定,也从未说过“当你看到‘免费’时,应该想到垃圾邮件”。我所要做的就是查看数据,从数据中计算一些数字,并希望数据自动给我一些关于标签如何影响“免费”一词出现频率的模式。

这是一个非常小的数据集(只有6封电子邮件)。你可以想象在更多数据上进行训练。假设我在更多数据上进行了训练,并给出了一些更准确的数字。

以下是基于更大数据集训练后的模型参数:

  • P(Y):60%的电子邮件是火腿邮件,40%是垃圾邮件。
  • P(F1|Y):如果电子邮件是火腿邮件,我认识发件人的概率是70%;如果电子邮件是垃圾邮件,我认识发件人的概率是10%。这感觉很正常:如果电子邮件是垃圾邮件,我可能不认识发件人;如果是火腿邮件,我可能认识。我不必用英语写下这些,而是从数据中学到的。这就是机器学习的魔力。
  • P(F2|Y):类似地从数据中估计得到。

分类过程

现在我们已经训练完毕,准备好参加“考试”并对未见过的数据进行分类。

有人给你这封全新的电子邮件:“今天在Soda Hall有免费食物和饮料。”(假设你真的收到了这封电子邮件,你想知道它是垃圾邮件还是火腿邮件。)

首先,你从中提取特征(同样,今天不讨论如何提取,假设已经完成)。你查看电子邮件,发现你认识发件人(F1 = 是)。然后你计算“免费”一词出现的次数,在这个例子中是1次(F2 = 1)。

现在,我们需要做的就是执行推理。我们想估计给定证据下是火腿邮件和垃圾邮件的概率:P(火腿邮件 | 证据)P(垃圾邮件 | 证据)

这纯粹是一个贝叶斯网络推理问题,没有更多的机器学习。你只需要计算联合概率(通过枚举进行推理)。如何计算联合概率?将贝叶斯网络的所有部分相乘。

贝叶斯网络的组成部分是:P(F1|Y)P(F2|Y)P(Y)。将这三部分相乘,就得到整个联合分布。如何知道这些值?根据证据查表,得到数字。

这告诉我,在所有可能的电子邮件世界中,收到一封垃圾邮件且发件人我认识、“免费”一词出现一次的概率是某个值;收到一封火腿邮件且发件人我认识、“免费”一词出现一次的概率是另一个值。

但我不想要联合分布,我想要条件概率 P(垃圾邮件 | 证据)P(火腿邮件 | 证据)。记得我们讨论过的归一化技巧吗?应用这个技巧,你会发现给定这些证据,是垃圾邮件的概率是14%,是火腿邮件的概率是86%。

因此,你的分类器现在可以告诉你:“我有86%的把握认为这不是垃圾邮件,14%的把握认为是垃圾邮件。”或者,如果你只需要一个猜测(火腿邮件还是垃圾邮件),你可以说,因为86% > 14%,所以我认为它是火腿邮件。

这真的很酷,即使我从未真正思考过这些特征,也从未问过你“免费”是否指示垃圾邮件或火腿邮件。你所要做的就是获取数据,从数据中学习数字,然后有人给你这封从未见过的新电子邮件(它不在训练数据中)。这个简单的小模型能够给出一个相当不错的猜测,认为这封电子邮件是火腿邮件。它实际上是火腿邮件吗?我不知道,但它似乎做了一个相当自信的猜测。


扩展到其他问题:数字识别与词袋模型 🔢📦

朴素贝叶斯模型不仅可用于垃圾邮件过滤,还可用于其他问题,如数字识别。

在数字识别中,模型是相同的:有一个你不知道的标签 Y(这里是0到9的数字)。和之前一样,你有一堆特征。特征是什么取决于为你提取特征的人。特征可以是直观的(如“免费”出现次数),也可以是非常基本的。有时,即使特征非常基础,朴素贝叶斯也能工作得很好。

一个非常基本的、无需计算的特征可以是:这个像素是亮还是暗?这个像素是亮还是暗?这些特征没有直观意义,但你仍然可以用它们来学习模式。

在数字识别的例子中,我们选择将特征作为像素的亮暗。我提取特征:像素(0,0)是暗,像素(0,1)是暗,像素(0,2)是亮,等等。每个特征节点对应一个我可能知道也可能

课程 P26:机器学习算法 - 感知机 🧠

在本节课中,我们将学习第二种机器学习算法——感知机。我们将从回顾朴素贝叶斯中的过拟合问题及其解决方案开始,然后深入探讨感知机的原理、几何与代数解释、训练方法,以及如何将其扩展到多分类问题。


回顾:过拟合与平滑

上一节我们讨论了泛化与过拟合,这是机器学习中的一个核心主题。过拟合意味着模型过于“记住”了训练数据中的特定模式,而这些模式并不能很好地推广到未见过的数据上。

例如,在垃圾邮件分类中,如果训练数据里“Southwest”这个词只出现在正常邮件(ham)中,朴素贝叶斯模型可能会学到“只要看到‘Southwest’就一定是正常邮件”的规则。这虽然能在训练数据上获得高准确率,但无法泛化到新的邮件中。

为了解决这个问题,我们引入了平滑技术,特别是拉普拉斯平滑。其核心思想是:在计算概率时,为每个可能的事件(即使未在训练数据中出现)都“假装”我们已经看到过它K次。

公式
P_laplace(event) = (count(event) + K) / (total_count + K * num_possible_events)

其中,K是一个超参数。K越大,概率分布越趋向于均匀分布,对训练数据的“信任”就越低。K=0则对应无平滑的最大似然估计。

关键点

  • 超参数:K不是从数据中学到的,而是需要手动调整的“旋钮”。
  • 数据集划分:为了选择最佳的K,我们需要将数据分为三部分:
    1. 训练集:用于学习模型参数。
    2. 验证集:用于调整超参数(如K),模拟测试数据。
    3. 测试集:仅在最终评估模型性能时使用,绝不能用于训练或调参。

感知机:基本概念

现在,我们转向今天的核心内容——感知机。感知机是一种受生物学神经元启发的线性分类模型。

模型流程

  1. 输入一个数据点 X(如一封邮件)。
  2. 通过特征函数 f 将其转换为特征向量 f(X),这是一个实数向量。
  3. 感知机算法接收特征向量,并输出一个分类标签 Y(如“垃圾邮件”或“正常邮件”)。

感知机的核心是一个权重向量 W。分类决策非常简单:计算特征向量 f(X) 和权重向量 W 的点积(内积),然后根据点积的符号进行判断。

分类规则
prediction = sign(W · f(X))

  • 如果 W · f(X) >= 0,则预测为正类(例如,垃圾邮件)。
  • 如果 W · f(X) < 0,则预测为负类(例如,正常邮件)。

直观理解:权重 W 中的每个值代表对应特征对分类的“贡献”方向和强度。正权重表示该特征倾向于正类,负权重表示倾向于负类。


感知机的几何视角

为了更好地理解感知机,我们可以从几何角度来审视它。特征向量和权重向量都可以被视为高维空间中的点或箭头。

向量视角

  • 权重向量 W 是高维空间中的一个方向。
  • 分类规则等价于:计算特征向量 f(X)W 之间的夹角 θ。
  • 如果夹角 θ < 90°,则点积为正,预测为正类。
  • 如果夹角 θ > 90°,则点积为负,预测为负类。
  • 因此,W 定义了一个“决策边界”(一个与 W 垂直的超平面),将空间分为两个半区。

点视角

  • 每个训练样本的特征向量可以画成高维空间中的一个点。
  • 权重向量 W 定义了决策边界(一条线、一个平面或超平面),其方程为 W · f(X) = 0
  • 所有落在边界一侧的点被预测为正类,另一侧的点被预测为负类。

这两种视角是等价的,都能帮助我们直观理解感知机如何做出决策。


训练感知机:感知机学习算法

我们知道了如何使用给定的权重 W 进行分类,但关键问题是如何从训练数据中学习出这个 W。这就是感知机学习算法的目标。

算法流程

  1. 初始化权重向量 W(例如,全部设为0)。
  2. 遍历训练数据(可以多次遍历):
    a. 对于每个带标签的样本 (X, Y_true),计算其特征向量 f(X)
    b. 使用当前 W 做出预测:Y_pred = sign(W · f(X))
    c. 如果预测正确Y_pred == Y_true),则保持 W 不变。
    d. 如果预测错误
    i. 若本应为正类但预测为负类(Y_true = +1, Y_pred = -1):将 Wf(X) 靠近。更新规则:W_new = W_old + f(X)
    ii. 若本应为负类但预测为正类(Y_true = -1, Y_pred = +1):将 W 远离 f(X)。更新规则:W_new = W_old - f(X)

几何解释:更新规则实际上是在旋转权重向量 W。当预测错误时,我们将 W 向正确类别的方向旋转(通过加上特征向量),或从错误类别的方向旋离(通过减去特征向量)。

代数解释:可以通过点积的性质证明,加上 f(X) 会使 W · f(X) 的值增加,减去 f(X) 会使该值减少,从而在下一次对同一数据点分类时,更可能得到正确结果。

算法终止:如果训练数据是线性可分的(即存在一个超平面能完美分开所有正负样本),那么感知机算法保证会在有限步内收敛到一个解。否则,算法可能不会终止,通常我们会设置一个最大迭代次数。


扩展到多分类问题

感知机可以很容易地扩展到处理两个以上的类别。

多分类感知机

  • 为每个类别 c 维护一个独立的权重向量 W_c
  • 分类时:对于一个输入 X,计算其特征向量 f(X) 与每个类别权重向量 W_c 的点积。预测结果为点积最高的那个类别。Y_pred = argmax_c (W_c · f(X))
  • 训练时
    1. 对于训练样本 (X, Y_true),用当前所有权重向量进行预测,得到 Y_pred
    2. 如果预测正确,不更新任何权重。
    3. 如果预测错误(Y_pred != Y_true):
      • 降低错误类别的分数:更新错误预测类别的权重向量,使其远离当前样本的特征向量:W_Y_pred = W_Y_pred - f(X)
      • 提高正确类别的分数:更新真实类别的权重向量,使其靠近当前样本的特征向量:W_Y_true = W_Y_true + f(X)

几何解释:这相当于在向量空间中,为每个类别划分出一个区域。训练过程就是调整各个类别的权重向量(即调整这些区域的边界),使得每个样本的特征向量都离其真实类别的权重向量最近。


总结

本节课我们一起学习了感知机这一重要的线性分类模型。

核心要点

  1. 模型:感知机通过计算权重向量与特征向量的点积,并根据符号进行分类,是一个简单的线性分类器。
  2. 几何理解:权重向量定义了决策边界。训练过程可视作调整这个边界,以正确划分训练数据点。
  3. 训练算法:感知机学习算法通过迭代和错误驱动的更新规则(W = W ± f(X))来学习权重。它在数据线性可分时保证收敛。
  4. 多分类:通过“一对多”策略,为每个类别维护一个权重向量,选择点积最大的类别作为预测结果。
  5. 与朴素贝叶斯对比:感知机是一种判别式模型,直接学习决策边界;而朴素贝叶斯是一种生成式模型,学习数据的概率分布。

感知机是神经网络和支持向量机等更复杂模型的基础。虽然简单,但其核心思想——通过特征加权求和进行决策,以及错误驱动的在线学习——在机器学习中影响深远。下一节课,我们将探讨如何为感知机等模型设计和选择有效的特征。

课程 P27:[CS188 SP23] 第26讲 - 机器学习:神经网络 🧠

概述

在本节课中,我们将学习神经网络的基础知识。我们将从感知器开始,探讨其局限性,然后引入逻辑回归来解决这些问题。接着,我们会将多个感知器连接起来,构建出神经网络的基本结构,并了解其背后的数学原理和优化方法。最后,我们会看到如何将神经网络推广到更复杂的结构。


感知器及其局限性

上一节我们回顾了感知器的基本概念。本节中,我们来看看感知器存在的一些问题。

感知器接收一个输入向量 x,计算其与权重向量 w 的点积 z = w · x。如果 z > 0,则预测为正类(+1);如果 z < 0,则预测为负类(-1)。

公式
预测 = sign(w · x)

感知器有两个很好的性质:

  1. 可分性:如果数据是线性可分的,感知器最终能找到那条分界线。
  2. 收敛性:对于线性可分数据,感知器会在有限步内收敛。

然而,感知器也存在以下问题:

  1. 不可分数据:当数据无法用一条直线完全分开时,感知器会永远运行,无法停止。
  2. 解的质量:即使数据可分,感知器找到的分界线可能不是“最好”的(例如,离某些点太近,泛化能力差)。
  3. 过拟合:与所有机器学习模型一样,训练过度可能导致过拟合。

为了解决这些问题,特别是处理不可分数据和得到更“好”的解,我们需要对感知器进行改进。


从确定性到概率性决策 🔀

上一节我们指出了感知器在不可分数据上的困境。本节中,我们来看看如何通过引入概率决策来解决它。

核心思想是:我们不希望分类器仅仅输出“是正类”或“是负类”,而是希望它输出“是正类的概率”。这样,对于靠近边界的点,分类器可以表示其不确定性(例如,55%的概率是正类)。

在确定性感知器中,我们使用阶跃函数将点积 z 映射为0或1。为了实现概率输出,我们需要一个能将实数 z 平滑地映射到 (0, 1) 区间的函数。

我们使用 Sigmoid函数(或称逻辑函数):

公式
σ(z) = 1 / (1 + e^{-z})

这个函数的性质符合我们的需求:

  • z 为正且很大时,σ(z) 接近 1(高置信度为正类)。
  • z 为负且很小时,σ(z) 接近 0(高置信度为负类)。
  • z = 0 时,`σ(z) = 0.5**(完全不确定)。

于是,我们的分类过程变为:计算 P(正类 | x) = σ(w · x)

示例
假设 w · x = 5

  • 确定性感知器:输出 +1。
  • 概率性感知器:计算 σ(5) ≈ 0.993,表示有 99.3% 的概率是正类。

这种使用 Sigmoid 函数进行概率预测的模型,就是 逻辑回归


训练逻辑回归模型 🏋️

上一节我们学会了如何使用逻辑回归进行分类。本节中,我们来看看如何训练它,即如何找到最优的权重 w

训练的目标是:找到一组权重 w,使得我们观察到的训练数据出现的 概率最大。这称为 最大似然估计

对于单个数据点 (x_i, y_i),其出现的概率是:

  • 如果 y_i = +1(正类):P = σ(w · x_i)
  • 如果 y_i = -1(负类):P = 1 - σ(w · x_i) = σ(-w · x_i) (利用Sigmoid性质)

对于整个训练集 D,其出现的 似然函数 是所有数据点概率的乘积。为了计算方便,我们通常取其对数,得到 对数似然函数 L(w)

公式(二分类逻辑回归的对数似然):
L(w) = Σ_{i} [ y_i * log(σ(w · x_i)) + (1 - y_i) * log(1 - σ(w · x_i)) ]

我们的训练目标就是找到使 L(w) 最大的 w
w* = argmax_w L(w)

这变成了一个纯粹的 优化问题。我们可以通过求导并令其为零(解析解)或使用 梯度上升 等数值方法来求解。

示例(简化)
假设有三个训练点 (2,1, +1), (1,1, +1), (0,-1, -1)。我们的对数似然函数 L(w1, w2) 将是一个关于 w1, w2 的复杂表达式。训练就是寻找使这个表达式值最大的 (w1, w2)


扩展到多分类问题 🎯

上一节我们处理了二分类问题。本节中,我们来看看如何将其扩展到多个类别。

对于 K 个类别的分类,我们为每个类别 k 准备一个权重向量 w_k。对于输入 x,我们计算 K 个“分数”:z_k = w_k · x

在确定性多类感知器中,我们直接选择分数最高的类别作为预测结果。

为了得到概率输出,我们使用 Softmax函数。它将 K 个实数分数转换成一个概率分布。

公式(Softmax):
P(类别 k | x) = e^{z_k} / Σ_{j=1}^{K} e^{z_j}

Softmax 的性质:

  • 所有输出的概率之和为 1。
  • 分数 z_k 越高,对应的概率 P(k) 也越高。
  • 分数 z_k 越低(越负),对应的概率 P(k) 越接近 0。

示例
假设三个类别的分数为 z = [5, 6, -2]

  • 确定性预测:选择第2类(分数6最高)。
  • Softmax预测:计算 P = [e^5, e^6, e^{-2}] / (e^5+e^6+e^{-2}) ≈ [0.267, 0.730, 0.003]。模型以73%的概率预测第2类,但也认为有26.7%的可能性是第1类。

训练多类逻辑回归同样采用最大似然估计,目标函数形式类似,只是将 Sigmoid 替换为 Softmax。


优化基础:梯度上升 ⛰️

上一节我们将训练问题归结为优化问题。本节中,我们来看看解决这类优化问题的核心方法——梯度上升。

我们的目标是最大化函数 g(w)(例如对数似然函数)。在一维情况下,我们可以通过求导并检查导数的正负来决定移动方向。

在高维空间(w 是向量),我们有无限多个移动方向。此时,梯度 指明了函数值增长最陡峭的方向。

梯度 是一个向量,其每个分量是函数 g(w) 对对应权重分量的偏导数。

公式(梯度):
∇g(w) = [ ∂g/∂w1, ∂g/∂w2, ..., ∂g/∂wd ]^T

梯度上升 的更新规则是沿着梯度方向前进一小步:

公式(梯度上升更新):
w_{new} = w_{old} + α * ∇g(w_{old})

其中 α学习率,控制每一步的大小。

随机梯度上升 是一种变体,它每次只使用一个训练数据点来计算梯度并更新权重,而不是使用全部数据求和。这种方法计算更快,常用于大数据集。
小批量梯度上升 则是折中方案,每次使用一小批(batch)数据。


构建神经网络 🧱

上一节我们掌握了优化方法。本节中,我们利用这些基础构件来搭建神经网络。

核心思想:与其手动设计特征,不如让模型自己从数据中学习特征。神经网络通过将多个“神经元”(改进的感知器)连接起来实现这一点。

一个基本的神经元(以Sigmoid激活为例):

  1. 接收输入向量 x
  2. 计算加权和 z = w · x
  3. 应用激活函数 h = σ(z),输出一个值。

最简单的神经网络是将神经元分层连接:

  • 输入层:原始特征 x
  • 隐藏层:第一层神经元。每个神经元学习输入特征的某种组合,输出一个新的“学习到的特征” h_j。所有 h_j 构成特征向量 h
  • 输出层:最后一个神经元(或多个,对应多分类)。它以隐藏层的输出 h 作为输入,进行最终预测 y = σ(w_output · h)

示例(单隐藏层网络)
输入 x = [x1, x2, x3]
隐藏层有两个神经元,权重矩阵为 W_h(尺寸 3x2),输出 h = σ(W_h^T x)h 是2维向量)。
输出层有一个神经元,权重向量为 w_o(尺寸 2x1),最终输出 y = σ(w_o^T h)

我们可以用矩阵形式简洁地表示前向传播过程:
h = σ(W_h^T x)
y = σ(w_o^T h)


神经网络的泛化与深度化 🏗️

上一节我们构建了一个简单的两层网络。本节中,我们来看看如何将其泛化和加深,形成强大的深度学习模型。

我们可以从多个方面对简单网络进行扩展:

  1. 改变每层的神经元数量:隐藏层可以有任意多个神经元(例如 n 个),输出层也可以有多个神经元(对应多分类,例如 dim_y 个)。
  2. 改变输入维度:输入 x 可以是任意维度(dim_x)。
  3. 增加网络深度:我们可以添加更多的隐藏层。前一层的输出作为后一层的输入。

一个通用的 L层全连接神经网络 的前向传播可以描述为:

设第 l 层的权重矩阵为 W^(l),输入为 a^(l-1),输出为 a^(l)
公式(第 l 层计算):
z^(l) = (W^(l))^T a^(l-1)
a^(l) = σ(z^(l))
其中 a^(0) = x(输入),a^(L) = y(输出)。

网络的设计变成了维度的匹配游戏。例如,若 a^(l-1) 的维度是 d_{in},我们希望该层输出维度为 d_{out},则权重矩阵 W^(l) 的尺寸应为 d_{in} x d_{out}

网络越深、越宽,其学习复杂模式和特征的能力就越强,这也构成了现代深度学习(如图像识别、自然语言处理)的基础。训练如此复杂的网络,其核心仍然是我们在前面介绍的 梯度下降/反向传播 算法(由于时间关系,反向传播的细节将在后续课程中深入讲解)。


总结

本节课中我们一起学习了:

  1. 感知器的局限性:无法处理不可分数据,且解的质量无法保证。
  2. 逻辑回归:通过引入 Sigmoid 函数,将感知器改进为输出概率的模型,并使用最大似然估计进行训练。
  3. 多分类扩展:使用 Softmax 函数将逻辑回归推广到多类别场景。
  4. 优化方法:将训练问题转化为优化问题,并介绍了梯度上升这一核心求解算法。
  5. 神经网络构建:通过连接多个神经元(感知器),构建了能够自动学习特征的基本神经网络结构。
  6. 网络的泛化与深化:了解了如何通过增加层数、神经元数量来构建更强大、更通用的深度神经网络框架。

神经网络是当前许多人工智能突破性进展的引擎。理解其从感知器演变而来的基本思想、概率解释以及优化训练方式,是深入学习现代机器学习的关键第一步。

🧠 课程 P28:神经网络与人工智能伦理

在本节课中,我们将学习神经网络的基本构建原理、训练方法,并探讨人工智能发展带来的伦理挑战。我们将从简单的感知器开始,逐步构建复杂的深度神经网络,并理解其背后的数学原理和优化过程。最后,我们将审视当前人工智能技术的局限性及其对社会可能产生的影响。


🔍 回顾:从感知器到神经网络

上一节我们介绍了感知器作为最基本的神经网络单元。本节中,我们来看看如何将多个感知器连接起来,形成更复杂的神经网络。

一个简单的感知器接收向量化输入 x1, x2, x3,将其与权重向量相乘并求和,然后检查结果是否大于零。如果是,则输出1,否则输出0。

我们可以对感知器进行改进,使用 Sigmoid 函数 将加权和的结果(范围从负无穷到正无穷)转换为一个介于0到1之间的概率值。公式如下:

σ(z) = 1 / (1 + e^{-z})

其中 z = w·x + b


🧱 构建两层神经网络

以下是构建一个两层神经网络的关键步骤:

  1. 输入层:接收原始输入 x1, x2, x3
  2. 第一层(隐藏层):包含多个神经元(例如两个)。每个神经元都是一个感知器,它接收所有输入,计算加权和,并应用Sigmoid函数,产生一个中间输出(h1, h2)。这些输出可以被视为从原始输入中提取的“特征”。
  3. 输出层:将第一层的输出 h1h2 作为输入,传递给另一个神经元。这个神经元再次计算加权和并应用Sigmoid函数,产生最终的分类输出。

这种结构的核心区别在于,我们将一些神经元的输出作为其他神经元的输入,从而形成了一个网络。


📐 使用矩阵表示法简化

为了避免使用冗长复杂的标量方程,我们可以使用向量和矩阵来表示整个计算过程,这使得表达更加简洁。

  • 输入可以表示为向量 x
  • 第一层的权重可以表示为一个矩阵 W^(1),其维度为 (输入维度) × (第一层神经元数量)
  • 第一层的输出(在应用Sigmoid前)可以计算为:z^(1) = W^(1)T · x,然后应用Sigmoid:h = σ(z^(1))
  • 第二层的权重是一个向量 w^(2),其维度为 (第一层神经元数量) × 1
  • 最终输出为:y = σ(w^(2)T · h)

通过这种方式,我们可以清晰地管理网络中各层的维度。


🔄 推广网络结构

我们可以将上述两层网络推广到更通用、更深的架构。

  • 任意大小的输入和输出:输入向量 x 的维度可以是任意的(记为 dim_x)。输出向量 y 的维度也可以是任意的(记为 dim_y),例如在多分类问题中。
  • 任意数量的隐藏层神经元:第一层可以有任意数量(n)的神经元。权重矩阵 W^(1) 的维度相应变为 dim_x × n
  • 任意数量的层(深度):我们可以添加更多层。每一层都接收前一层的输出作为输入,并拥有自己的权重矩阵。例如,一个三层网络的计算可以表示为:
    y = σ( W^(3)T · σ( W^(2)T · σ( W^(1)T · x ) ) )
  • 非线性激活函数的重要性:必须使用如Sigmoid、Tanh或ReLU这样的非线性激活函数。如果只使用线性组合,无论堆叠多少层,整个网络仍然等价于一个线性函数,无法学习复杂模式。ReLU函数的定义为:
    ReLU(z) = max(0, z)

🎯 训练神经网络:优化问题

训练神经网络的核心是找到一组最优的权重参数 W。这本质上是一个优化问题。

  • 损失函数:我们需要一个函数来衡量模型预测值与真实值之间的差距。损失函数值越高,说明模型越差。常见的损失函数包括:
    • 0-1损失:直接计算分类错误的样本数。
    • 对数损失(交叉熵):常用于分类问题,对于二分类,其公式为:
      L = - [y * log(p) + (1-y) * log(1-p)]
      其中 y 是真实标签(0或1),p 是模型预测为正类的概率。
  • 优化目标:我们的目标是找到使损失函数 L(W) 最小化的权重 W
  • 梯度下降:通过计算损失函数相对于权重的梯度 ∇L(W),我们可以知道如何调整权重以减小损失。更新规则为:
    W_new = W_old - α * ∇L(W_old)
    其中 α 是学习率。


⚙️ 计算梯度:反向传播算法

对于深度神经网络,手动计算梯度非常困难。反向传播算法是一种高效计算梯度的方法。

其核心思想是链式法则。算法分为两步:

  1. 前向传播:输入数据通过网络,计算每一层的输出,直至得到最终预测和损失。
  2. 反向传播:从输出层开始,反向计算损失函数对每一层权重的梯度。利用链式法则,将梯度从后一层传递到前一层。

虽然我们不会深入数学细节,但理解反向传播是一种利用计算图结构,通过局部导数组合得到全局梯度的动态规划方法,这一点非常重要。


💡 神经网络的性质与局限性

  • 通用近似定理:理论上,一个足够大的神经网络可以近似任何连续函数。这意味着只要有足够的神经元和合适的非线性激活函数,神经网络可以拟合极其复杂的模式。
  • 数据与参数:神经网络的强大能力依赖于大量的参数和训练数据。学习一个简单概念(如围棋中的“棋块”),神经网络可能需要数百万个参数和示例,而人类或符号系统则能更快地从少量例子中学会。
  • “黑箱”与脆弱性:神经网络的学习过程难以解释,其决策可能依赖于数据中虚假的相关性(例如,根据背景草地识别狗的种类,而不是狗本身)。这引发了对其可靠性和安全性的担忧。

🤖 人工智能伦理与未来展望

神经网络和深度学习推动了当前人工智能的浪潮,在图像识别、自然语言处理等领域取得了突破性进展。然而,这也带来了深刻的伦理和社会挑战。

  • 目标对齐问题:我们构建的AI系统拥有我们赋予的目标(如最大化点击率)。如果目标设定不当或不完整,AI可能会采取有害的策略来实现它(如操纵用户行为),这与人类的整体利益相悖。
  • 大型语言模型的挑战:像GPT-4这样的大型语言模型展示了令人印象深刻的语言能力,产生了“通用人工智能火花”的错觉。但它们本质上是基于海量数据模仿人类文本,可能隐含地学习并追求训练数据中存在的、不符合人类福祉的目标,且其内部工作机制不透明。
  • 通向有益AI:未来的发展方向需要从“标准模型”(追求预设目标)转向“有益AI模型”。即AI系统的最终标准不应是它是否完成了自己的目标,而是是否帮助人类实现了他们的目标。这要求AI具备谦逊、学习人类偏好并允许被监督和控制的能力。
  • 安全与治理:开发强大AI需要像核工程一样严谨的学科态度,包括可解释性研究、安全性证明、测试认证以及合理的监管框架,以确保技术发展造福全人类。

📝 总结

本节课中我们一起学习了:

  1. 神经网络的基本构建块——神经元,以及如何从感知器堆叠成深度网络。
  2. 如何使用矩阵表示法简化网络计算,并理解了网络维度匹配的重要性。
  3. 训练神经网络是一个通过梯度下降最小化损失函数的优化过程,反向传播是计算梯度的关键算法。
  4. 神经网络虽然功能强大,但存在数据需求大、可解释性差、可能学习虚假模式等局限性。
  5. 人工智能的快速发展,特别是大型语言模型的涌现,带来了目标对齐、安全可控等严峻的伦理挑战。构建透明、稳健且与人类价值观对齐的“有益AI”,是未来至关重要的研究方向。


课程 P29:[CS188 SP23] 第28讲 - 专题 - 对抗性攻击与鲁棒性 🛡️

在本节课中,我们将要学习人工智能系统,特别是机器学习模型,是如何在某些情况下失效的。我们将探讨一种被称为“对抗性攻击”的现象,了解其原理、表现形式,以及它对强化学习、围棋AI等高级系统的影响。最后,我们将讨论如何构建更鲁棒、更值得信赖的AI系统。

概述:人工智能的“阿喀琉斯之踵”

本课程的大部分内容都在学习人工智能如何工作。今天我们要讨论的是,人工智能有时是如何“不工作”的,有时甚至会产生灾难性或喜剧性的效果。理解这些失败至关重要,因为即使看起来能力很强的人工智能系统,也可能以令人惊讶甚至灾难性的方式失败。随着系统越来越多地部署在高风险场景中(如自动驾驶汽车或面向数亿用户的服务),我们作为AI从业者有责任让这些系统变得更好。

对抗性示例:一个经典问题

神经网络一直受到一个问题的困扰,即“对抗性示例”。这个概念最早由伊恩·古德费罗在2015年提出。

其核心思想是:你可以从一张完全正常的照片(例如一只可爱的小熊猫)开始,然后精心添加一些微小的、视觉上难以察觉的噪声。对于人类来说,左右两张图像可能没有区别,但对于机器学习分类器而言,它们却截然不同:左边被识别为熊猫,右边却被识别为长臂猿。

更引人注目的是,这种攻击可以针对任何目标类别。例如,你可以让分类器将图像误判为洗衣机。并且,这种攻击通常在不同分类器之间具有很好的“迁移性”。这意味着,针对一个模型训练的攻击,通常对使用不同架构、不同代码库、甚至不同数据集训练的模型也有效。

尽管这个现象在八年前(2015年)就被发现,但即使在今天最先进的系统中,它仍然是一个悬而未决的问题。尽管有大量的研究努力,我们在防御方面取得的进展有限。

对抗性攻击的多样性

对抗性示例只是神经网络面临的诸多问题之一。广义的“对抗性攻击”是指恶意攻击者为了破坏机器学习模型而构造的任何输入。攻击者的手段几乎没有限制。

以下是几种不同类型的对抗性攻击:

  • 图像旋转:有时,以特定方式旋转图像会导致分类器出错。例如,左轮手枪的图片被旋转后,可能被误分类为捕鼠器。
  • 图像遮挡:在图像中加入补丁(例如将一幅画带入照片中)有时也会导致分类器失效。
  • 音频攻击:在音频领域,对一段音乐进行微小的、人耳难以察觉的扰动,可以欺骗语音转文本系统,使其输出完全不同的内容。

这些攻击令人担忧,因为在现实世界中,图像的旋转、遮挡等情况确实经常发生。

对抗性攻击与强化学习

之前我们讨论的都是在监督学习的背景下,即模型预测已有标签的数据。但对抗性攻击同样也发生在强化学习中,智能体需要在现实世界中采取行动。

研究人员将监督学习中的一些攻击思路移植到强化学习。例如,在雅达利游戏《乒乓》中,通过在游戏画面上添加特定的微小扰动,可以欺骗RL智能体向错误的方向移动球拍。

然而,这种需要直接扰动像素的攻击模型可能不够现实。一个更现实的威胁模型是:攻击者本身就是环境中的另一个智能体。这正是多智能体系统中的对抗性问题。

多智能体环境中的对抗性攻击

现实世界中的RL智能体通常生活在由其他智能体(包括人类)组成的自然环境中。这些恶意智能体可以通过其“自然”动作(例如,在机器人足球赛中站到一个奇怪的位置)来影响受害者智能体所接收的观察信息,从而实施攻击,而无需直接篡改像素。

上一节我们介绍了多智能体对抗的背景,本节中我们来看看研究人员是如何在这种设定下进行攻击的。

研究的关键思路是:在训练阶段,让受害者智能体在一个试图利用它的对手环境中进行自我博弈。在攻击时,我们将受害者训练时面对的对手,替换成一个专门针对该受害者训练的“对抗性对手”。这个对手的动作空间与原始对手完全相同,没有特殊能力。

对抗性对手的关键优势在于,它可以针对一个固定策略的受害者副本进行长时间训练,从而找到利用受害者的方法。这种固定策略的设置在实际的安全关键系统中很常见,因为我们不希望已部署的系统在运行中不断学习更新。

由于受害者策略是固定的,我们可以将其视为环境的一部分,从而将问题简化为一个单智能体强化学习问题。我们可以使用标准的RL算法(如策略迭代、值迭代,或更先进的近端策略优化)来训练对抗性对手。

研究人员在模拟机器人环境(使用MuJoCo物理模拟器)中进行了评估,对手智能体仅用受害者训练量3%的计算资源,就成功击败了通过数亿步自我博弈训练出的、针对正常对手表现优异的受害者智能体。

以下是几个环境中的攻击示例:

  • 跑酷与拦截:蓝色跑步者试图穿过红色终点线,红色拦截者试图阻止。对抗性拦截者通过做出扭曲身体等奇怪动作,极大地提高了胜率,尽管它从未与跑步者发生直接身体接触。
  • 点球大战:蓝色踢球者试图进球,红色守门员试图扑救。对抗性守门员不再尝试移动扑救,而是摆出扭曲姿势,导致踢球者经常失误。
  • 相扑:两个智能体试图将对方推出擂台。对抗性智能体学会保持一个非常稳定的跪姿,等待受害者自己摔倒,其胜率与正常对手相当。

攻击为何生效?机制分析

对抗性策略在没有身体接触的情况下获胜,它们通过改变受害者观察到的“自然”观察信息(如对手关节的角度)来导致受害者策略失效。

为了理解原因,研究人员分析了受害者策略神经网络的激活情况。他们记录了受害者与正常对手、随机对手以及对抗性对手对战时,网络各层的激活值。

分析发现,对抗性对手诱导出的神经网络激活模式,与正常对手诱导出的模式截然不同,并且出现在正常数据分布中极不可能的区域。而随机对手诱导的激活则更分散,与正常模式有部分重叠。这说明对抗性攻击并非随机行为,而是有明确方向地将策略激活推向极端值。

可能的防御措施

既然攻击是通过操纵受害者观察到的“自然”信息起作用的,一个直观的防御想法是:不让受害者看到对手

研究人员尝试了一种“蒙面受害者”防御:在环境初始化后,就冻结受害者看到的关于对手的观察信息(例如,对手的关节位置保持不变)。

实验表明,这种防御对对抗性攻击非常有效,能将对手的胜率从86%大幅降低到1%。然而,这种防御的代价是:当面对正常的、具有攻击性的对手时,蒙面受害者的表现会急剧下降,因为它无法看到对手的进攻动作。

另一种更有希望的防御是对抗性训练。即从已训练好的受害者策略开始,继续在混合了正常对手和对抗性对手的环境中对其进行微调,以防止“灾难性遗忘”。

初步结果显示,经过对抗性训练后,受害者对特定对抗策略的鲁棒性显著提升(胜率从14%上升到89%)。然而,攻击方可以针对这个“硬化”后的受害者重新训练新的对抗策略,并且新策略依然能够保持较高的胜率,尽管其攻击模式可能变得更“合理”(例如通过身体接触绊倒受害者)。

超人AI系统的对抗性漏洞

上述攻击针对的是仍在发展中的机器人RL系统。那么,在已经超越人类的“超人”AI系统(如AlphaGo)中,对抗性漏洞是否依然存在?

以开源最强围棋AI KataGo 为例,它可以通过调整蒙特卡洛树搜索的模拟次数来线性地提升强度,在大量搜索下是超人的。然而,研究发现它同样存在漏洞。

研究人员训练了一个“对抗性对手”,其架构与KataGo相同,但使用了一种修改过的对抗性蒙特卡洛树搜索进行训练。在对手节点,使用对手自身的策略和价值网络进行搜索;在受害者节点,则从受害者策略网络中采样,以模拟真实受害者。

训练从随机初始化的对手网络开始,通过让树搜索(作为策略改进算子)与目标受害者对弈,并将搜索得出的策略提炼回对手的策略网络,如此循环。

他们发现了两种成功的攻击策略:

  1. 过路者:通过诱导受害者在不当的时机“过”(放弃一手棋)而获胜。这种攻击利用了规则细节,但在受害者进行一定量的搜索后就会失效。
  2. 循环者:通过构建“循环棋块”来迷惑KataGo。对手下出一些看似已死的棋,引诱受害者去包围,最终反而被对手合围。这种策略非常弱,人类新手都能击败它,但它却能以高胜率击败超人的KataGo,表现出强烈的非传递性。即使受害者进行大量搜索,胜率依然可观。

更令人惊讶的是,这种攻击展现出了一定的“迁移性”。虽然直接迁移胜率不高(30-50%),但人类围棋专家在理解攻击模式后,可以手动调整策略,成功击败其他强大的围棋AI。

总结与启示

本节课中我们一起学习了对抗性攻击的多个层面:

  1. 现实威胁:针对RL系统的现实攻击可能来自共享环境中的恶意智能体,因此需要在多智能体框架下研究攻击与防御。
  2. 普遍脆弱性:即使对正常对手表现优异的策略,也可能在专门针对其训练的对抗性策略面前失败。
  3. 攻击机制:对抗性策略通过创建看似自然、实则将受害者策略激活推向异常区域的观察信息而获胜。
  4. 防御挑战:对抗性训练显示出一定潜力,但攻击方可以迭代升级,形成“矛与盾”的竞赛。简单的防御(如蒙面)往往带来新的弱点。

对抗性示例揭示了深度学习系统的认知方式与人类存在根本差异。当我们计划在高风险环境中部署AI系统,尤其是那些涉及智能体间竞争或优化的系统(例如,基于人类反馈的强化学习训练聊天机器人)时,必须认真考虑对抗性鲁棒性问题。

未来的工作方向包括:通过可解释性研究深入理解漏洞根源;探索更有效的对抗性训练方法;以及研究模型能力(平均情况)与鲁棒性(最坏情况)之间的缩放规律,这对于我们预判和规划AI系统的可信度至关重要。

构建值得信赖的人工智能,需要我们持续关注并解决这些基础性的安全问题。

课程三:启发式搜索与A*算法 🧭

在本节课中,我们将学习如何利用关于目标的额外信息来改进搜索算法。我们将重点介绍启发式的概念,以及如何将其与搜索成本结合,形成强大且最优的A*搜索算法


概述

搜索问题的核心是:给定一个状态空间、后继函数、起始状态和目标测试,我们需要找到一个从起点到目标的行动序列(即一个计划)。之前我们学习了深度优先、广度优先和一致代价搜索,它们都是“盲目”的,会向所有方向探索。

本节我们将引入启发式——一种对当前状态到目标距离的“猜测”。我们将看到如何利用启发式进行贪婪搜索,并最终学习如何将启发式与已付出的代价结合,形成A*搜索,从而在保证找到最优解的同时,大幅提升搜索效率。


回顾:搜索问题与搜索树

上一节我们介绍了搜索问题的通用数学定义:一个状态空间、一个后继函数(包含行动和成本)、一个起始状态和一个目标测试。

解决搜索问题的通用方法是构建搜索树。这棵树代表了所有可能的计划(行动序列)。关键在于,我们并非让机器人在真实世界中尝试所有路径,而是在“脑海”中(即模型中)预先计算和评估这些计划,最终只执行找到的有效序列。

所有搜索算法的共同点是,它们都维护一个边缘(或“前沿”)——一个待探索的部分路径列表。算法的唯一区别在于从边缘选取下一个扩展节点的顺序


引入启发式

为了更智能地搜索,我们希望算法能“感知”目标的方向,而不是盲目地向四周探索。这就需要启发式

什么是启发式?

启发式是一个数学函数,记作 h(n)。它接收一个状态 n 作为输入,输出一个实数。这个数字代表了从状态 n 到目标的估计代价

  • 数值小:意味着估计很接近目标。
  • 数值大:意味着估计距离目标还很远。

可以将启发式想象成一个“热度探测器”:数字越小,你离“宝藏”(目标)越“热”。

重要提示:启发式是针对特定问题设计的。一个对迷宫问题有效的启发式(如直线距离),对煎饼排序问题可能毫无意义。因此,解决搜索问题通常分为两步:

  1. 设计一个通用的搜索算法。
  2. 为你的具体问题设计一个合适的启发式函数。

启发式示例

  1. 吃豆人迷宫:一个简单的启发式是忽略墙壁,计算吃豆人当前位置与目标点之间的曼哈顿距离(网格上的直线距离)。这给出了一个“有多近”的快速估计。
  2. 罗马尼亚旅行问题:启发式可以是当前城市到目的地布加勒斯特的直线地理距离
  3. 煎饼排序问题:一个可能的启发式是“尚未就位的最大煎饼的编号”。例如,如果最大的煎饼(5号)不在最底部,则启发式值为5。

这些启发式的共同点是:越接近目标的状态,其启发式值通常越低


贪婪搜索

有了启发式,一个最直接的想法是:总是优先探索当前看起来离目标最近的节点。这就是贪婪搜索

算法逻辑

贪婪搜索与之前算法的框架相同,唯一区别在于从边缘选取节点的策略

  • 深度优先搜索 (DFS):选取最新的节点(栈)。
  • 广度优先搜索 (BFS):选取最旧的节点(队列)。
  • 一致代价搜索 (UCS):选取累计路径代价 g(n) 最小的节点。
  • 贪婪搜索:选取启发式值 h(n) 最小的节点。

它完全根据 h(n) 做出决策,而忽略到达当前状态已花费的实际代价 g(n)

贪婪搜索的局限性

贪婪搜索是“短视”的。它总是选择能带来最大单步进展的路径,即使从长远看,这条路径可能并非最优。

示例:在罗马尼亚问题中,贪婪搜索可能因为某条路径的第一步启发式值降低很多(显得很近)而选择它,却忽略了另一条每一步进展稍小,但总代价更低的路径。因此,贪婪搜索不能保证找到最优解,并且可能因为启发式的误导而陷入死胡同。


A*搜索:结合代价与启发式

为了克服贪婪搜索的缺点,我们需要一个既考虑“已付出代价”又考虑“预计剩余代价”的算法。这就是A*搜索

算法核心

A*搜索在选取边缘节点时,使用的评估函数是:
f(n) = g(n) + h(n)
其中:

  • g(n):从起始状态到状态 n实际已花费代价
  • h(n):从状态 n 到目标的估计剩余代价(启发式)。

A*总是优先扩展 f(n) 值最小的节点。这巧妙地平衡了:

  • g(n)(一致代价搜索的考量):倾向于探索代价低的路径。
  • h(n)(贪婪搜索的考量):倾向于探索靠近目标的路径。

一个关键细节

在实现A*(或其他搜索算法)时,有一个至关重要的细节:只有当节点从边缘中被取出(出队)并检查时,才能判断它是否为目标状态。仅仅因为目标节点被加入(入队)到边缘,并不意味着搜索可以结束。提前结束可能导致返回一个非最优解。

可采纳启发式与最优性

A*搜索要保证找到最优解,其启发式函数必须满足一个条件:可采纳性

定义:一个启发式 h(n)可采纳的,当且仅当对于所有状态 nh(n) 从未高估n 到达目标的真实代价 h*(n)。即:
h(n) ≤ h*(n) (对于所有状态 n

为什么需要可采纳性?
如果启发式高估了真实代价(即 h(n) > h*(n)),A可能会因为 f(n) 值过大而“吓跑”那些实际上是通往最优解的道路,转而去探索更差的路径。可采纳性保证了A不会忽略任何可能的最优路径。

定理:如果启发式 h(n) 是可采纳的,那么使用该启发式的树搜索A*算法是最优的

(证明思路:通过比较最优路径上的节点与次优路径的优先级 f(n),利用可采纳性 h(n) ≤ h*(n) 和最优路径代价更低的事实,可以证明最优路径上的节点总会比次优路径的节点先被从边缘中取出。)


总结

本节课我们一起学习了如何利用启发式信息来引导搜索:

  1. 启发式 h(n) 是对状态到目标距离的估计,需针对具体问题设计。
  2. 贪婪搜索仅使用 h(n),虽快但短视,不保证最优。
  3. A*搜索结合了实际代价 g(n) 和启发式估计 h(n)f(n) = g(n) + h(n)),在方向上更智能。
  4. 为保证A*找到最优解,启发式必须是可采纳的(永不超估真实代价)。

A*搜索在人工智能中应用极广,从游戏路径规划到自然语言处理,它都是平衡效率与最优性的强大工具。下一节课,我们将更深入地探讨如何设计有效的启发式函数。

课程4:启发式搜索与局部搜索 🧭

在本节课中,我们将学习启发式搜索(A*算法)的进阶概念,以及一种全新的问题求解范式——局部搜索。我们将探讨如何设计有效的启发式函数,理解图搜索与树搜索的区别,并学习如何通过“爬山”等简单策略来直接寻找问题的最优解。


启发式函数从何而来?💡

上一节我们介绍了A*算法,它使用启发式函数 h(n) 来估计从节点 n 到目标的代价。本节中我们来看看这些启发式函数是如何被设计出来的。

发明启发式最常见的方法是思考一个与原问题相关但更简单的“松弛问题”。在松弛问题中,对可行行动的限制更少,因此更容易求解。原问题最优解的代价是松弛问题最优解代价的下界,因此我们可以用松弛问题的解作为原问题的可采纳启发式

以下是两个经典例子:

  • 罗马尼亚路径规划:如果我们允许“直线飞行”绕过所有中间城市,那么两点间的直线距离(欧几里得距离)就是一个可采纳启发式。
  • 吃豆人游戏:如果我们允许吃豆人“穿墙”,那么从当前位置到目标的曼哈顿距离(|Δx| + |Δy|)就是一个可采纳启发式。

正式定义:问题 P2 是问题 P1 的松弛版本,如果对于每个状态,P2 中可用的行动集合是 P1 中可用行动集合的超集。

关键定理:松弛问题最优解的代价是原问题最优解代价的下界。因此,我们可以用松弛问题的最优解代价作为原问题的可采纳启发式。


实例:八数码拼图 🧩

让我们通过八数码拼图这个“AI界的果蝇”来实践如何构造启发式。在这个问题中,状态是瓷砖的排列,行动是将空白格向四个方向移动,每一步代价为1。

以下是两种启发式的设计思路:

1. 错位瓷砖数

  • 思路:松弛问题是“允许将任何瓷砖直接移动到其目标位置”。在这个更简单的问题中,最优解代价就是错位瓷砖的数量。
  • 性质:这是一个可采纳启发式,因为每移动一次只能改变一个瓷砖的位置,所以实际所需步数至少等于错位瓷砖数。

2. 曼哈顿距离和

  • 思路:松弛问题是“允许瓷砖穿过其他瓷砖移动”。每个瓷砖到达其目标位置所需的最少步数就是其当前与目标位置的曼哈顿距离。将所有瓷砖的曼哈顿距离相加即为启发式值。
  • 性质:这也是一个可采纳启发式。它几乎总是比“错位瓷砖数”更准确(即值更大),我们说它支配了前者。

启发式的优势:使用启发式能极大提升搜索效率。例如,在某个需12步解的问题中:

  • 无启发式(h=0,即UCS)需扩展 360万 个节点。
  • 使用简单的“错位瓷砖数”启发式,仅需扩展 227 个节点。
  • 使用更优的“曼哈顿距离和”启发式,仅需扩展 73 个节点。

如果我们有多个互不支配的启发式,一个简单而强大的方法是取它们的最大值:h(n) = max(h1(n), h2(n), ...)。这个新启发式同样是可采纳的,并且支配所有原启发式。


图搜索与一致性要求 🔄

之前我们讨论的A算法是在搜索上进行的,但实际问题中的状态空间往往是一个,同一状态可能通过不同路径被多次访问。简单地“不扩展已访问状态”的图搜索策略,在与A结合时可能无法保证找到最优解。

问题根源:问题出在启发式可能不一致。一致性是比可采纳性更强的条件。

一致性定义:对于每个节点 n 及其后继节点 n‘,启发式函数需满足三角不等式:h(n) ≤ cost(n, n’) + h(n‘)。这意味着从 n 到目标的估计代价,不能超过走到 n‘ 的实际代价加上从 n‘ 到目标的估计代价。

重要性:如果启发式是一致的,那么沿着任何路径,A算法中的 f(n) = g(n) + h(n) 值是非递减的。这保证了A图搜索总能找到最优解。几乎所有从松弛问题推导出的启发式都是一致的。

总结

  • 树搜索A*:只要 h(n) 可采纳,就能保证最优。
  • 图搜索A*:需要 h(n) 一致,才能保证最优。

局部搜索算法 🧗

前面我们关注的是找到从起点到目标的行动序列(路径)。现在,我们转向局部搜索算法,它只关心最终的解决方案状态,而不关心如何到达。这类算法从一个猜测的解决方案开始,然后通过局部修改(“摆弄”)来逐步改进它。

为何使用局部搜索?

  1. 内存效率高:通常只维护当前状态,占用恒定内存。
  2. 适用于在线或物理搜索:类似于在现实世界中通过试错学习,你无法复制多个自己进行并行探索。
  3. 解决只需最终状态的问题:如N皇后问题(找到一种互不攻击的布局)、旅行商问题(找到最短环路),我们只关心结果,不关心步骤顺序。

爬山算法(最速上升法)

这是最简单的局部搜索算法。

算法描述

  1. 从随机初始状态开始。
  2. 循环:考察所有“邻居”状态(通过一次局部修改得到的状态),移动到评估函数值最好的那个邻居。
  3. 如果所有邻居都不比当前状态好,则停止,返回当前状态。

在N皇后问题中,我们可以定义评估函数 h(state)互相攻击的皇后对数。我们的目标是最小化这个值(即“下坡”)。

代码框架

current = initial_state
while True:
    neighbor = highest_valued_successor(current) # 找最好的邻居
    if value(neighbor) <= value(current):
        return current # 没有更好邻居,停止
    current = neighbor

局限性:爬山算法很容易陷入局部最优(一个小山峰),而非全局最优(最高峰)。地形中还有“山肩”(平坦区域)和“高原”等复杂情况。


改进局部搜索的策略 🛠️

为了逃离局部最优,有以下几种常见策略:

以下是几种改进策略:

  • 随机重启:陷入局部最优后,随机生成一个新的初始状态重新开始爬山。在有限状态空间中,只要时间足够,这保证能找到全局最优。如果单次成功率是 p,则平均需要 1/p 次重启。
  • 允许侧向移动:当没有上坡路时,允许移动到评估值相等的邻居状态。这有助于逃离“山肩”。但需设置侧移次数限制,以防在“高原”上无限循环。
  • 随机选择:不一定总选择最陡的上坡路,可以按一定概率随机选择邻居,这增加了探索的多样性。

以八皇后问题为例

  • 单纯爬山(不允许侧移)成功率约 14%,平均约4次随机重启可解决。
  • 允许最多100次侧向移动后,单次成功率提升至 94%,但平均步数增加。

这些策略引入了需要调节的参数(如侧移次数上限),使得算法不如A*那样“优雅”,但在许多实际问题中非常高效。


总结 📚

本节课中我们一起学习了:

  1. 启发式设计:通过构造原问题的松弛问题来获得可采纳的启发式函数,这是A*算法高效的关键。
  2. 图搜索最优性:为了在状态图(而非树)上使用A*并保证最优,启发式需要满足更强的一致性条件。
  3. 局部搜索新范式:引入了不关心路径、只寻找最终解的局部搜索算法,并以爬山算法为例,说明了其原理、优势(内存小、适用于在线学习)和局限性(易陷入局部最优)。
  4. 改进策略:学习了通过随机重启允许侧向移动等方法来帮助局部搜索算法逃离局部最优。

从系统性的树/图搜索,到注重局部改进的搜索,我们拥有了解决不同类型优化问题的多样化工具。

课程5:局部搜索、命题逻辑与规划 🧭

在本节课中,我们将要学习两种重要的算法思想:局部搜索命题逻辑。局部搜索用于在状态空间中寻找最优解,而命题逻辑则为知识表示和推理提供了数学基础。我们将从模拟退火算法开始,探讨其在连续和离散空间中的应用,然后转向命题逻辑的基本概念及其在人工智能中的意义。


局部搜索与模拟退火 🔥

上一节我们介绍了在状态空间中寻找路径的搜索算法。本节中我们来看看另一种思路:局部搜索。局部搜索不关心到达目标的路径,只关注最终状态的质量。它从一个初始状态出发,通过移动到“邻居”状态来逐步改进解的质量。

模拟退火算法

模拟退火算法灵感来源于冶金学中的退火过程。金属通过缓慢冷却,使其原子排列整齐,达到低能量状态,从而变得更坚固。算法将这一思想应用于优化问题。

算法维护一个“温度”参数 T。温度 T 随时间逐渐降低。在高温时,算法可以接受使解变差的移动,有助于跳出局部最优;在低温时,算法行为更像爬山法,主要接受改进解。

以下是算法的核心步骤:

  1. 从当前状态 S 开始。
  2. 随机生成一个邻居状态 S‘
  3. 计算能量差 ΔE = E(S’) - E(S)。这里 E 是状态的值(例如成本或收益)。
  4. 根据以下规则决定是否接受新状态 S‘
    • 如果 ΔE > 0(新状态更好),则总是接受。
    • 如果 ΔE <= 0(新状态更差或相同),则以概率 P = exp(ΔE / T) 接受。其中 exp 是指数函数。

随着温度 T 从高逐渐降低到接近零,算法从随机探索逐渐转变为局部改进。

算法的理论性质

尽管模拟退火看起来启发式,但它有坚实的理论基础。可以证明,如果温度下降得足够慢,在每个温度下运行足够长时间以达到平衡,那么算法处于某个状态 S 的概率服从玻尔兹曼分布

P(S) ∝ exp(E(S) / T)

当温度 T 趋近于0时,概率分布会集中在全局最优解上。这个性质通过考虑两个相邻状态 xy 之间的概率流平衡方程得以证明。

算法的实践与局限

收敛保证是在“温度无限缓慢下降”和“每个温度下运行无限长时间”的理想条件下成立的。在实际应用中,如何设计冷却计划(即温度 T 随时间下降的速率)是一门需要经验的“艺术”。模拟退火被成功应用于超大规模集成电路(VLSI)芯片布局等复杂组合优化问题。


其他局部搜索算法

除了模拟退火,还有其他有效的局部搜索策略。

局部束搜索

局部束搜索同时维护 k 个状态(即 k 个搜索进程),而不仅仅是单个状态。在每次迭代中,它从所有 k 个状态的邻居中生成所有可能的后继状态,然后从中选出最好的 k 个作为下一轮迭代的起点。

这个过程允许搜索进程之间进行“通信”:表现差的搜索区域会被放弃,计算资源被重新分配到更有希望的区域。这比独立运行 k 次爬山搜索更高效。

遗传算法

遗传算法是受生物进化启发的搜索算法。它将状态编码为字符串(类似于基因序列)。算法维护一个种群(一组状态),通过选择(偏好适应度高的个体)、交叉(组合两个父代状态的部分)和变异(随机改变状态的某些部分)来生成新的种群。

遗传算法是进化计算领域的一部分,并被用于神经网络架构设计等复杂优化问题。


连续空间中的局部搜索

许多优化问题的状态空间是连续的(例如,设计参数是实数)。我们以在罗马尼亚放置三个机场以最小化总旅行成本为例。

问题形式化

设三个机场的坐标为 (x1, y1), (x2, y2), (x3, y3)。每个城市归属于最近的机场。目标函数 f 是每个城市到其归属机场的欧几里得距离的平方和

我们希望找到使 f 最小化的机场坐标。

梯度下降

当目标函数可微时,我们可以利用梯度。梯度 ∇f 是一个向量,其每个分量是 f 对相应变量的偏导数。例如,对于机场1的x坐标:
∂f/∂x1 = 2 * Σ (x1 - x_c),其中求和针对归属于机场1的所有城市。

梯度方向是函数值上升最快的方向。因此,梯度下降算法通过反复沿负梯度方向移动一小步来寻找最小值:
x_new = x_old - η * ∇f(x_old),其中 η 是学习率。

对于这个特定问题,在固定城市分组的情况下,最优解是将机场置于其所属城市的质心。但全局最优解还需要考虑改变城市分组的情况。对于更复杂的问题(如神经网络训练),我们无法直接求解梯度为零的方程,梯度下降及其变体(如随机梯度下降)是核心优化工具。

自动微分技术使得计算机能够自动计算任何数值程序的梯度,这是现代机器学习框架(如TensorFlow, PyTorch)的基石。


命题逻辑基础 🧠

现在,我们从优化转向知识表示与推理。为了让AI系统能基于知识进行规划,我们需要一种形式化语言,逻辑正是为此而生。

知识、推理与智能体

智能体(如吃豆人)需要几种知识:

  1. 过渡模型:行动如何改变世界。
  2. 传感器模型:世界状态如何产生感知信息。
  3. 初始状态信息

利用这些知识,智能体可以进行状态估计(追踪世界状态)和规划。逻辑方法允许我们声明式地陈述知识,然后由通用的推理引擎来回答问题,而无需为每个问题编写特定的过程代码。

逻辑的构成:语法与语义

一个逻辑系统由两部分定义:

  • 语法:规定了语言中合法句子的构成规则(哪些符号串是有效的)。
  • 语义:定义了如何确定一个句子在某个“可能世界”中是真还是假。

命题逻辑是一种简单的逻辑。

  • 语法:由命题变量(如 P, Q, Rains, Sunny)和逻辑连接词(与 , 或 , 非 ¬, 蕴含 , 当且仅当 )构成。
  • 语义:一个“可能世界”为每个命题变量分配一个真值(True或False)。复杂句子的真值通过连接词的语义规则递归确定。例如,A ∧ B 为真当且仅当 A 为真且 B 为真。

数据库与知识图谱

关系数据库可以看作是一种受限的逻辑系统。它包含一系列关系事实(如 WorksFor(John, CIA))。查询语言(如SQL)具有一阶逻辑的表达能力。

谷歌知识图谱是一个超大规模的关系数据库,包含数百亿实体和数千亿事实,用于直接回答搜索引擎的查询,展示了基于逻辑的系统在现实世界中的巨大价值。


总结

本节课中我们一起学习了:

  1. 局部搜索算法,包括模拟退火、局部束搜索和遗传算法,它们专注于寻找最优状态而非路径。
  2. 模拟退火通过引入温度和概率接受机制来逃离局部最优,其理论收敛于玻尔兹曼分布。
  3. 连续空间中,可以利用目标函数的梯度信息进行优化,梯度下降是核心方法。
  4. 命题逻辑为知识表示提供了形式化基础,通过语法语义来定义句子的合法性及其真值条件。
  5. 逻辑方法允许声明式编程:将知识输入通用的推理引擎,即可回答领域内的问题,这是实现高级AI推理能力的关键一步。

从优化搜索到逻辑推理,这些工具构成了人工智能处理复杂问题的基础。

课程 P6:布尔可满足性与DPLL算法 🧠

在本节课中,我们将学习命题逻辑的核心概念,特别是如何判断一个逻辑句子是否可满足。我们将介绍一种名为DPLL的高效算法来解决这个问题,并探讨如何将其应用于构建一个能进行逻辑推理的智能体(如吃豆人)。


逻辑蕴涵与可能世界 🌍

上一节我们介绍了命题逻辑的基本语法和语义。本节中,我们来看看逻辑推理中的一个核心关系:逻辑蕴涵。

逻辑蕴涵定义了一个句子如何必然导致另一个句子为真。其定义如下:句子α逻辑蕴涵句子β(记作 α ⊨ β),当且仅当在每一个使α为真的可能世界中,β也为真。

公式:α ⊨ β ⇔ 在所有模型 M 中,若 M ⊨ α,则 M ⊨ β。

更强的断言会排除更多的可能世界。例如,断言“A为真且B为真”比只断言“A为真”更强,因为它只在更少的可能世界中成立。因此,α₂ ⊨ α₁ 意味着使α₂为真的世界集合是使α₁为真的世界集合的子集。


推理算法:模型检查与定理证明 ⚙️

从逻辑蕴涵的定义,我们可以直接得到一个算法:枚举所有可能世界(即对所有命题符号的真值赋值),检查是否在每个α为真的世界中β也为真。这就是模型检查

另一种方法是定理证明,即应用一系列推理规则(如假言推理 Modus Ponens)从前提推导出结论。这两种方法都追求两个关键属性:

  • 可靠性:如果算法说α蕴涵β,那么它一定是正确的。
  • 完备性:如果α确实蕴涵β,那么算法最终一定能证明它。

命题逻辑的模型检查是可行的,因为可能世界的数量是有限的(2^n个)。而对于一阶逻辑,可能世界是无限的,这使得完备的判定算法不存在(哥德尔不完备定理)。


为吃豆人构建知识库 🎮

现在,我们将逻辑应用于一个具体问题:为部分可观察环境下的吃豆人构建一个知识库,使其能通过推理进行定位、建图和规划。

首先,我们需要定义命题符号(变量):

  • Wall_xy: 位置(x,y)处有一堵墙。
  • Blocked_W_t: 在时间t,吃豆人西侧感知到墙。
  • Pacman_xy_t: 在时间t,吃豆人在位置(x,y)。
  • Action_N_t: 在时间t,吃豆人执行“向北”动作。

知识库由描述世界如何运作的“公理”句子组成。以下是核心部分:

1. 地图知识
我们需要断言墙在哪里,以及墙不在哪里。

Wall_00, Wall_01, ..., ¬Wall_11, ¬Wall_12, ...

2. 初始位置知识
吃豆人知道自己在一个且仅在一个非墙格子上。

(Pacman_00_0 ∨ Pacman_01_0 ∨ ...)  // 他在某个地方
¬(Pacman_00_0 ∧ Pacman_01_0)        // 他不同时在(0,0)和(0,1)
... // 对所有位置对进行类似断言

3. 感知公理
感知信号的值由世界的真实状态决定。例如,“在时间t西侧被阻挡”当且仅当吃豆人当时在一个其西邻格有墙的位置上。

Blocked_W_t ⇔ (Pacman_00_t ∧ Wall_(-1)0) ∨ (Pacman_01_t ∧ Wall_(-1)1) ∨ ...

代码:这可以通过循环所有位置(x,y)来生成。

4. 转移公理(运动模型)
描述状态如何随时间变化。例如,吃豆人在时间t位于(3,3)有两种方式:

  • 保持:他上一刻就在(3,3),且没有执行使他离开的动作。
  • 移动:他上一刻在邻格(如(3,2)),并执行了进入(3,3)的动作(如向北移动)。
Pacman_33_t ⇔
    [Pacman_33_{t-1} ∧ ¬(Action_N_{t-1} ∧ ¬Wall_N) ∧ ...] // 未离开
    ∨
    [Pacman_32_{t-1} ∧ Action_N_{t-1} ∧ ¬Wall_N] ∨ ...    // 从邻格移入

这些公理构成了完整的“吃豆人物理学”。虽然句子数量庞大(位置数×时间步数),但可由程序自动生成。推理机将利用这些知识,从感知和行动历史中推断出吃豆人的位置(定位)、地图(建图)或达成目标的行动序列(规划)。


可满足性(SAT)与推理 🔗

上一节我们为吃豆人建立了知识库。本节中我们来看看如何让机器利用这些知识进行自动推理,核心是可满足性问题。

一个句子是可满足的,当且仅当存在至少一个可能世界(一组真值赋值)使其为真。检查可满足性的算法称为SAT求解器。

我们如何用SAT求解器进行蕴涵推理呢?利用演绎定理
α ⊨ β 当且仅当 句子 (α ∧ ¬β) 是不可满足的(即存在矛盾)。

推理流程

  1. 知识库(已知事实)记为 α。
  2. 想证明的查询记为 β。
  3. 将知识库与查询的否定组合:α ∧ ¬β。
  4. 将该句子送入SAT求解器。
  5. 如果求解器说“不可满足”,则证明 α ⊨ β 成立(因为假设β为假会引发矛盾)。
  6. 如果求解器找到一个满足的模型,则该模型就是α为真而β为假的反例,证明蕴涵不成立。

合取范式(CNF)📝

大多数高效的SAT求解器要求输入是合取范式。任何命题逻辑句子都可以机械地转化为CNF。

合取范式定义:它是多个子句的合取(∧),每个子句是多个文字的析取(∨)。文字是命题符号或其否定。
公式:CNF = (literal₁ ∨ literal₂ ∨ ...) ∧ (literal₃ ∨ literal₄ ∨ ...) ∧ ...

转换示例
将句子 (A ⇒ W) ⇔ B 转换为CNF。

  1. 消除⇔: (A ⇒ W) ∧ (W ⇒ A) ⇔ B 变为 [(A ⇒ W) ⇒ B] ∧ [B ⇒ (A ⇒ W)]?更正:应拆分为两个方向:(A ⇒ W) ⇒ B 以及 B ⇒ (A ⇒ W)。更标准的方法是: (P ⇔ Q) 等价于 (P ⇒ Q) ∧ (Q ⇒ P)。所以原句变为:
    ( (A ⇒ W) ⇒ B ) ∧ ( B ⇒ (A ⇒ W) )
  2. 消除⇒:用 (X ⇒ Y) ≡ (¬X ∨ Y) 替换。
    ( ¬(A ⇒ W) ∨ B ) ∧ ( ¬B ∨ (A ⇒ W) )
  3. 再次消除内层的⇒:
    ( ¬(¬A ∨ W) ∨ B ) ∧ ( ¬B ∨ (¬A ∨ W) )
  4. 应用德摩根定律:¬(¬A ∨ W) ≡ (A ∧ ¬W)
    ( (A ∧ ¬W) ∨ B ) ∧ ( ¬B ∨ ¬A ∨ W )
  5. 分配律:将(A ∧ ¬W) ∨ B 转化为 (A ∨ B) ∧ (¬W ∨ B)
  6. 最终CNF:
    (A ∨ B) ∧ (¬W ∨ B) ∧ (¬B ∨ ¬A ∨ W)

转换过程可能使句子变长,但它是自动化的。在我们的应用中,直接以接近CNF的形式书写公理可以避免复杂的转换。


DPLL算法 🌳

最后,我们介绍一个经典且高效的确定性SAT求解算法:DPLL算法(Davis-Putnam-Logemann-Loveland)。它本质上是对所有可能真值赋值进行深度优先搜索,但加入了两个关键的优化。

算法基本步骤如下:

代码(递归框架):

function DPLL(CNF句子 S, 赋值 partial_assignment):
    if S 在 partial_assignment 下已为真:
        return SATISFIABLE
    if S 在 partial_assignment 下存在假子句:
        return UNSATISFIABLE

    // 优化1:纯文字消除
    literal = 找到在S中只以一种形式出现的纯文字
    if literal 存在:
        return DPLL(S, partial_assignment ∪ {literal=true})

    // 优化2:单元传播
    unit_clause = 找到只有一个未赋值文字的子句(单元子句)
    if unit_clause 存在:
        literal = unit_clause 中的那个文字
        return DPLL(S, partial_assignment ∪ {literal=true})

    // 分裂:选择一个未赋值的变量
    var = 选择一个未赋值的命题符号
    // 尝试赋值为真
    if DPLL(S, partial_assignment ∪ {var=true}) == SATISFIABLE:
        return SATISFIABLE
    // 尝试赋值为假
    else:
        return DPLL(S, partial_assignment ∪ {var=false})

关键优化

  1. 单元传播:如果一个子句只有一个文字未赋值,为使该子句为真,该文字必须被赋值为真。这可以强制推导出许多赋值,避免不必要的分支。
  2. 纯文字消除:如果一个文字在整个CNF句子中只以正形式或只以负形式出现,那么可以立即将其赋值为真(如果以正形式出现)而不影响可满足性,因为这只会使包含它的子句变真,不会导致矛盾。

通过结合深度优先搜索和这两种强大的推导规则,DPLL算法能够极大地剪枝搜索空间,从而高效地解决许多大规模的SAT问题。


总结 🎯

本节课中我们一起学习了:

  1. 逻辑蕴涵的定义及其与可能世界集合的关系。
  2. 基于知识的智能体框架:通过知识库(公理)和推理机来回答问题。
  3. 如何为吃豆人世界构建详细的命题逻辑知识库,包括感知、运动和初始状态公理。
  4. 利用可满足性问题进行推理的核心方法:将蕴涵查询转化为KB ∧ ¬Query的不可满足性检查。
  5. 命题逻辑句子可以标准化为合取范式
  6. DPLL算法作为高效的SAT求解器,通过单元传播和纯文字消除来优化对真值赋值的搜索。

这为我们提供了强大的工具:一旦用逻辑公理描述了一个领域(如吃豆人游戏),我们就可以使用通用的SAT求解器来自动解决该领域内的规划、定位和建图问题,而无需为每个任务编写特定算法。

课程 P7:使用命题逻辑进行规划与状态估计 🧠

在本节课中,我们将学习如何利用命题逻辑和可满足性求解器来解决规划、定位和地图构建等任务。我们将从基本的规划问题开始,逐步深入到在部分可观察世界中进行状态估计和同步定位与建图的复杂问题。


规划问题:使用逻辑求解器寻找路径 🗺️

上一节我们介绍了命题逻辑及其推理方法。本节中,我们来看看如何利用可满足性求解器来制定计划。

基本思想是:我们首先写下描述世界物理规则的所有命题逻辑语句。然后,我们询问求解器:在给定的时间步数 T 内,是否存在一个动作序列可以实现目标? 这本质上是在询问,在给定的物理约束下,整个语句集合是否可满足。

更详细地说,我们采用迭代加深的方法:

  1. T = 1 开始,尝试在一步内解决问题。
  2. 如果不可行,则 T = T + 1,增加允许的时间步数。
  3. 重复此过程,直到找到解。第一个找到解的 T 值对应的就是最短计划。

对于每个 T 值,我们需要生成:

  • 初始状态:描述吃豆人和鬼魂的初始位置。
  • 目标状态:断言目标(例如,吃掉所有食物)在时间 T 为真。
  • 转移模型:定义每个时间步状态如何变化,由动作和物理规则决定。

以下是转移模型的核心逻辑示例:

  • 吃豆人位置PacmanAt(x, y, t) ⇔ [PacmanAt(x, y, t-1) ∧ StayAction(t-1)] ∨ [PacmanAt(x', y', t-1) ∧ MoveActionTo(x, y, t-1)]
  • 食物状态FoodAt(x, y, t) ⇔ FoodAt(x, y, t-1) ∧ ¬Eaten(x, y, t-1)
  • 鬼魂位置:由固定的策略决定。

求解器运行后,如果计划存在,我们可以通过查看满足所有约束的动作变量在每一步的真值,直接读出具体的行动计划。


状态估计:在部分可观察世界中定位自己 🧭

上一节我们讨论了在完全已知世界中的规划。本节中,我们来看看当吃豆人不知道自己初始位置,只能通过局部感知(如感知四个方向的墙壁)来获取信息时,如何进行状态估计

状态估计是指,根据历史行动和观察,推断当前世界状态中哪些事实必然为真。这是一个所有智能系统都需要解决的核心问题。

我们依然可以使用逻辑推理来解决。知识库 KB 包含:

  • 世界物理规则。
  • 传感器模型:将感知与可能的位置关联起来。例如,“西边被阻挡”这一感知为真,当且仅当吃豆人位于所有西边有墙的方格之一。公式上,这是一个包含所有可能位置的析取式:BlockedWest(t) ⇔ (PacmanAt(1,1,t) ∧ WallAt(0,1)) ∨ (PacmanAt(1,2,t) ∧ WallAt(0,2)) ∨ ...

要进行状态估计,代理可以不断询问 KB 两类问题:

  1. KB ⊨ PacmanAt(x, y, now)? (能证明我在 (x, y) 吗?)
  2. KB ⊨ ¬PacmanAt(x, y, now)? (能证明我不在 (x, y) 吗?)

有两种实现方式:

  • 惰性估计:仅在需要回答问题时,才基于全部历史进行推理。
  • 积极估计:在每一步行动和感知后,主动对所有状态变量进行上述两类查询,并将能证明为真或为假的事实加入 KB,作为后续推理的“垫脚石”,从而提高效率。

通过这个过程,可能的位置集合会随着新的感知而不断缩小(单调不增),最终可能确定唯一位置。


地图构建:在已知自身位置时探索环境 🗺️➡️📝

如果吃豆人知道自己的确切位置(例如,通过航位推算,从定义的 (0,0) 点开始,根据动作和是否被阻挡来精确计算相对位置),那么它就可以利用感知来构建地图

方法与状态估计类似:

  1. 初始化 KB,包含物理规则和传感器模型,并固定初始位置为 (0,0)
  2. 在每个时间步,根据当前位置和感知到的阻挡信息,对墙变量进行推理。
  3. 如果能证明 WallAt(x, y)¬WallAt(x, y),就将该结论加入 KB
  4. 选择可行的动作继续探索。

通过不断探索和推理,吃豆人可以逐步建立起整个可达区域的地图。


同步定位与建图:解决“鸡与蛋”问题 🐔🥚

在更现实的情况下,航位推算可能失效(例如,轮子打滑导致位置不确定)。此时,吃豆人面临同步定位与建图问题:不知道地图,就无法定位;不知道自身位置,就无法正确建图。

解决方法依然是逻辑推理,但同时对位置变量墙变量进行推断:

  1. 同样初始化 KB(物理规则 + 传感器模型,例如感知可能简化为“相邻墙的数量”)。
  2. 仍然可以定义初始位置为 (0,0)
  3. 在每个时间步,用动作和感知更新 KB 后,尝试推断:
    • 关于墙:WallAt(x, y)¬WallAt(x, y)
    • 关于自身位置:PacmanAt(x, y, t)¬PacmanAt(x, y, t)
  4. 即使信息非常有限(如仅知道相邻墙的数量变化),通过交叉推理,智能体通常也能逐步同时确定自身位置和地图结构。

前向链接算法:高效的定理证明方法 ⚙️

最后,我们补充介绍一种用于知识库推理的算法——前向链接。它属于定理证明算法,通过应用推理规则(如肯定前件)从已知事实推导出新事实。

肯定前件规则形式为:(A₁ ∧ A₂ ∧ ... ∧ Aₙ) ⇒ B。如果已知 A₁, A₂, ..., Aₙ 都为真,则可推出 B 为真。

前向链接算法持续应用此规则,直到没有新事实可被推出。它特别适用于知识库全部由定子句组成的情况。定子句是形如 (A₁ ∧ A₂ ∧ ... ∧ Aₙ) ⇒ B 的蕴含式,其中 B 是单个命题符号。一个普通事实 A 可看作 True ⇒ A

为了使算法高效,需要两个关键技巧:

  1. 索引:为每个符号建立索引,记录它作为前提出现在哪些定子句中。
  2. 计数器:为每个定子句维护一个计数器,记录尚未被满足的前提数量。当计数器归零时,即可推出结论。

对于定子句知识库,前向链接算法是可靠且完备的。


总结 📚

本节课中,我们一起学习了如何将命题逻辑和可满足性求解器应用于一系列AI核心任务:

  1. 规划:通过迭代加深和逻辑编码,寻找实现目标的最短动作序列。
  2. 状态估计(定位):在部分可观察环境中,通过逻辑推理逐步缩小可能状态的集合。
  3. 地图构建:在已知位置时,通过感知和推理建立环境模型。
  4. 同步定位与建图:在位置和地图均未知时,通过交叉推理同时解决两者。
  5. 前向链接:一种针对定子句知识库的高效、可靠且完备的推理算法。

这些方法展示了逻辑表示和推理在构建理性智能体中的强大能力和通用性。

课程 P8:[CS188 SP23] 第七讲 - 约束满足问题 (CSPs) 🧩

在本节课中,我们将学习一种特殊的搜索问题——约束满足问题。我们将了解它的数学定义,并通过经典例子(如地图着色和八皇后问题)来理解如何将现实问题形式化为CSP。最后,我们会简要介绍CSP的不同类型和现实应用。


回顾通用搜索问题 🔍

上一节我们介绍了通用搜索问题的基本框架。在搜索过程中,我们做了几个关键假设:只有一个智能体在规划;所有动作都是确定性的;世界是完全可观察的;状态空间是离散的。这些假设构成了我们之前讨论的搜索算法的基础。

在接下来的几周,我们将探讨如果改变这些假设(例如,如果动作不是确定性的),搜索问题及其算法将如何变化。但今天,我们将专注于搜索问题的一个更具体的子类。


什么是约束满足问题? 🎯

本节中,我们来看看约束满足问题。与通用搜索不同,在CSP中,我们通常不关心达到目标所采取的动作序列,而只关心最终的目标状态本身。例如,一个侦探机器人可能只关心对事件(如钻石失窃)的最终合理解释,而不关心它如何推理出这个解释。

为了处理这类问题,我们需要一个更具体的数学定义。CSP是搜索问题的一个子类,其状态由一组变量构成,每个变量都有一个对应的值域。目标测试也不再是一个任意的“法官”函数,而是一组明确的约束规则。一个有效的解是为所有变量分配值,并满足所有约束。

数学定义
一个CSP可以形式化地定义为:

  • 变量X = {X1, X2, ..., Xn}
  • 值域: 每个变量 Xi 有一个对应的值域 Di,表示它可以取的所有可能值。
  • 约束C = {C1, C2, ..., Cm}。每个约束 Cj 涉及一个变量子集,并规定了这些变量取值组合的允许范围。

目标是找到一组赋值 {Xi = vi, vi ∈ Di},使得所有约束 C 都被满足。


CSP实例:地图着色 🗺️

以下是CSP的一个经典例子——地图着色问题。

假设你是一名地图设计师,需要为澳大利亚各州着色,并希望相邻的州不使用同一种颜色。我们需要将此问题转化为CSP形式。

  • 变量: 每个州是一个变量(例如:西澳大利亚 WA, 北部地方 NT, 昆士兰 Q 等)。
  • 值域: 每个变量的值域是相同的:{红色, 绿色, 蓝色}
  • 约束: 对于每一对相邻的州,存在一个约束:它们的颜色不能相同。例如,WA ≠ NTNT ≠ SA 等。

约束可以用多种方式表达:

  1. 隐式约束: 写一段代码来检查,例如 color(WA) != color(NT)
  2. 显式约束: 列出所有合法的值对,例如 (WA, NT) 的合法组合为:{(红,绿), (红,蓝), (绿,红), (绿,蓝), (蓝,红), (蓝,绿)}

一个有效的解是为所有变量(州)分配颜色,并满足所有相邻颜色不同的约束。下图展示了一个可能的解:


CSP实例:八皇后问题 ♟️

上一节我们看了地图着色,本节我们来看看另一个经典问题——八皇后问题(这里以4皇后为例)。目标是在4x4棋盘上放置4个皇后,使得它们互不攻击(即不在同一行、同一列或同一对角线上)。

我们可以用不同的方式将其形式化为CSP。

第一种形式化方法

  • 变量: 棋盘的16个格子,每个格子是一个变量 Xij
  • 值域: 每个变量的值域是 {0, 1},其中 1 代表有皇后,0 代表无皇后。
  • 约束
    1. 每一行、每一列、每一条对角线上不能有一个以上的皇后(即这些格子上的变量值之和 ≤ 1)。
    2. 棋盘上必须有恰好4个皇后(即所有变量值之和 = 4)。

第二种形式化方法(更高效)
我们利用“每行必有一个皇后”的洞察,可以简化问题。

  • 变量: 4个变量 Q1, Q2, Q3, Q4,分别代表第1、2、3、4行皇后所在的列号。
  • 值域: 每个变量的值域是 {1, 2, 3, 4}
  • 约束
    1. 所有 Qi 互不相同(保证不同列)。
    2. 对于任意两个行号 ij,需满足 |Qi - Qj| != |i - j|(保证不在同一对角线)。

第二种方法变量更少,更高效地捕捉了问题的本质。


CSP的图表示与更多例子 📊

CSP通常可以用图(约束图)来直观表示。

  • 变量节点: 图中的每个节点代表一个变量。
  • 约束边: 如果两个变量之间存在直接约束,则在它们之间连一条边。例如,在地图着色问题中,相邻的州(变量)之间就有一条边。

对于涉及两个以上变量的约束(高阶约束),可以使用超图表示,即用一个方形节点代表约束,并将其与所有相关的变量节点相连。

以下是更多CSP的例子:

  • 字母算术谜题: 如 SEND + MORE = MONEY,每个字母代表一个数字,需满足加法等式。
  • 数独: 每个格子是变量,值域为1-9,约束包括行、列、宫内数字不重复。
  • 现实问题: 课程排课、会议调度、硬件布局等,都可以建模为CSP。

CSP的类型与约束分类 📝

本课程主要讨论有限离散域的CSP,即每个变量的可能取值来自一个有限的、离散的集合。但也存在其他类型:

  • 无限域CSP: 变量取值可以是整数等无限集合。
  • 连续域CSP: 变量取值可以是实数。

约束也可以根据涉及的变量数量进行分类:

  • 一元约束: 只涉及一个变量(例如,“南澳大利亚不能是绿色”)。
  • 二元约束: 涉及两个变量(例如,“西澳大利亚与北部地方颜色不同”)。这是最常见的形式。
  • 高阶约束: 涉及两个以上变量(例如,数独中“一个宫内的9个数字必须互异”)。
  • 软约束: 表示偏好而非必须满足的条件(例如,“我更希望会议室是红色的”)。

总结 🎓

本节课中,我们一起学习了约束满足问题。我们从通用搜索问题出发,引入了更具体的CSP定义,其核心是变量值域约束。我们通过地图着色和八皇后问题,实践了如何将实际问题形式化为CSP,并了解了它的图表示方法。最后,我们简要介绍了CSP的不同类型和约束分类。CSP是一类强大且应用广泛的模型,能够解决许多规划、调度和组合优化问题。在接下来的课程中,我们将探讨解决CSP的具体算法。

课程 P9:[CS188 SP23] 第八讲 - CSPs II 🧩

在本节课中,我们将学习如何更高效地解决约束满足问题。我们将从通用搜索算法开始,分析其优缺点,然后逐步引入回溯搜索、前向检查、弧一致性以及变量和值排序等优化技术,最后探讨如何利用问题结构和局部搜索来加速求解。


概述:从通用搜索到CSP专用算法

上一节我们介绍了CSP的基本定义和例子。本节中,我们来看看如何解决CSP。由于CSP是搜索问题的一个特殊类别,这意味着我们已经学过的通用搜索算法也可以用来解决CSP。我们将从通用搜索算法开始,分析其表现,找出不足之处,然后尝试改进。


通用搜索算法在CSP中的应用

一个通用搜索问题需要初始状态、后继函数和目标测试。对于CSP:

  • 初始状态:所有变量都未被赋值。
  • 后继函数:选择一个未赋值的变量,并为其赋予一个值。
  • 目标测试:检查是否所有变量都已赋值,并且所有约束都得到满足。

我们可以将CSP直接套入这个框架。让我们尝试两种常见的搜索策略:广度优先搜索和深度优先搜索。

广度优先搜索的困境

BFS会逐层探索搜索树。然而,CSP的解决方案存在于最底层(所有变量都被赋值的那一层)。在找到任何解决方案之前,BFS需要检查上面所有层的节点,这会导致它在找到解之前浪费大量时间检查无效的部分赋值。

深度优先搜索的优势

相比之下,DFS会沿着一条路径深入探索,直接到达可能存在解决方案的底层。虽然它可能也需要搜索很长时间,但至少它是在朝着解决方案可能存在的地方前进,而不是在肯定无解的区域浪费时间。因此,对于CSP,DFS看起来是一个比BFS更好的起点。


回溯搜索:更聪明的深度优先搜索

单纯的DFS仍然效率不高,因为它将目标测试视为一个黑盒,只在完全赋值后才检查是否满足所有约束。这导致它会探索许多明显违反约束的分支(例如,给相邻区域都涂上相同的颜色)。

CSP的约束结构允许我们进行更早的检查。回溯搜索 本质上仍然是DFS,但加入了“早期失败”机制:在扩展一个节点(即进行新的赋值)之前,检查当前的部分赋值是否已经违反了任何约束。如果违反了,就立即回溯,不再探索该分支下的所有节点。

为什么这在CSP中有效?
因为在CSP中,一旦一个约束被违反,除非取消导致违反的赋值,否则无法修复。因此,该分支下的所有完整赋值都注定无效,可以安全剪枝。

代码描述回溯搜索的核心思想:

def backtracking_search(assignment, csp):
    if assignment.is_complete():
        return assignment
    var = select_unassigned_variable(assignment, csp)
    for value in order_domain_values(var, assignment, csp):
        if is_consistent(var, value, assignment, csp):
            assignment.add(var, value)
            result = backtracking_search(assignment, csp)
            if result is not None:
                return result
            assignment.remove(var, value) # 回溯
    return None

优化技术一:过滤 - 跟踪可能的值

回溯搜索在赋值后检查约束。我们可以做得更主动一些,这就是过滤 的思想:不仅记录变量是否被赋值,还为每个未赋值的变量维护一个可能值域。当我们为一个变量赋值时,我们可以推理出这个赋值对其邻居变量值域的影响,并提前划掉那些不再可能的值。

前向检查

前向检查 是一种简单的过滤。当一个变量X被赋值后,我们检查所有与X有约束关系的未赋值变量Y。对于Y值域中的每个值,如果它与X的当前赋值不兼容,就从Y的值域中删除该值。

优势:如果某个未赋值变量的值域因此变为空集,我们就可以立即知道当前的部分赋值不可能扩展为有效解,从而提前回溯。

局限性:前向检查只检查已赋值变量和未赋值变量之间的约束。它无法检测两个未赋值变量之间可能存在的冲突。


优化技术二:弧一致性

为了检测更隐蔽的冲突,我们需要一种更强的过滤方法:弧一致性

一条从变量X指向变量Y一致的,当且仅当:对于X值域中的每一个可能值,在Y的值域中都至少存在一个值,使得XY之间的约束得到满足。

算法思路(AC-3算法)

  1. 将所有弧(每个约束对应两个方向的弧)加入队列。
  2. 当队列非空时,取出一条弧(X, Y)
  3. 检查它是否一致。为了使它一致,可能需要从X的值域中删除某些值(因为这些值在Y中找不到任何兼容的值)。
  4. 如果从X的值域中删除了任何值,那么所有指向X的弧(即(Z, X))都可能变得不一致,需要将它们重新加入队列进行检查。
  5. 重复步骤2-4,直到队列为空。

效果:弧一致性通过不断传播约束,可以大幅缩减变量的值域,经常能比前向检查更早地发现矛盾。

重要说明

  • 弧一致性本身通常不能直接给出解,它只是一个强大的过滤步骤,需要与回溯搜索结合使用。
  • 维护弧一致性需要计算成本,但通过减少需要回溯搜索的节点数量,总体上可以加速问题求解。

优化技术三:变量与值排序策略

在回溯搜索中,我们有两个选择点:下一步为哪个变量赋值?以及为该变量选择哪个值?聪明的选择顺序能极大提升效率。

最小剩余值(MRV)启发式

选择哪个变量? 优先选择值域最小的变量(即剩余合法值最少的变量)。

为什么? 因为我们必须给所有变量赋值。先处理最受限的变量,可以尽早暴露问题。如果这个变量无值可选,我们可以立即回溯,避免在其他变量上浪费大量时间后才失败。

最少约束值(LCV)启发式

选择哪个值? 为选定的变量,优先选择给其他变量值域限制最少的值(即排除其他变量可选值最少的值)。

为什么? 因为我们不必尝试变量的每一个值。先尝试“宽松”的值,希望能一次成功,从而避免探索“苛刻”的值可能导致的复杂分支。

结合使用:MRV和LCV启发式结合,可以引导搜索更快地找到解。


利用问题结构

有些CSP具有特殊结构,可以被用来设计极其高效的专用算法。

独立子问题

如果一个CSP的约束图可以完全分解为几个互不连接的子图,那么每个子问题可以独立求解,最后将解组合即可。这能将指数级复杂度的问题转化为几个小问题之和。然而,实际问题中变量通常相互关联,这种理想情况很少见。

树结构CSP

如果CSP的约束图是一棵树(无环),那么可以在多项式时间内求解。
算法

  1. 定向:任选一个节点作为根,将无向边转为有向边(父节点指向子节点)。
  2. 后向传递(建立弧一致性):从叶子节点开始向上,对每条弧(父节点, 子节点)执行弧一致性检查,确保父节点的每个值在子节点都有兼容值。只需遍历一次。
  3. 前向赋值:从根节点开始向下,为每个节点选择任意一个与父节点赋值兼容的值即可。由于步骤2保证了兼容性,这个过程不会失败。

近似树结构:割集调节

对于接近树结构的CSP(例如,只有一个或少数几个环),可以采用割集调节技术:

  1. 找到一个割集:一组变量,删除它们后,剩余约束图变成一棵树。
  2. 枚举这个割集中所有变量的可能赋值组合。
  3. 对于每一种赋值组合,将割集变量固定为这些值,剩下的问题就是一个树结构CSP,可以用快速算法求解。
  4. 检查所有结果中是否有满足原问题的解。

局部搜索法

以上方法都是系统搜索(基于DFS的回溯)。对于CSP,我们还可以使用局部搜索,它不关心路径,只寻找最终解。

基本思路

  1. 从一个完整赋值开始(所有变量都有值,但可能违反约束)。
  2. 计算当前赋值违反约束的数量(冲突数)。
  3. 重复以下步骤直到找到解(冲突为0)或达到步数限制:
    • 选择一个冲突的变量。
    • 将其值更改为能最大程度减少总冲突数的值(采用最陡上升的爬山法思想,或结合随机性避免局部最优)。

特点

  • 优点:内存消耗小,对于某些大型CSP可能非常快。
  • 缺点:不完备,不保证找到解;可能陷入局部最优。

总结

本节课我们一起学习了多种解决CSP的算法和优化技术:

  1. 回溯搜索:在DFS基础上加入约束检查,实现早期失败。
  2. 过滤技术:通过前向检查和弧一致性,在搜索过程中主动修剪变量的值域,提前发现矛盾。
  3. 智能排序:使用MRV和LCV启发式,优化变量和值的选择顺序,引导搜索方向。
  4. 利用结构:对于树状等特殊结构的CSP,存在多项式时间算法;对于近似树状结构,可使用割集调节。
  5. 局部搜索:提供了一种不同于系统搜索的、可能更高效的求解思路,尤其适用于不要求完备性的大规模问题。

理解这些技术如何逐步改进搜索效率,是掌握CSP求解的关键。实际应用中,常常需要根据具体问题的特点组合使用这些策略。

posted @ 2026-02-04 18:22  绝不原创的飞龙  阅读(3)  评论(0)    收藏  举报