Oasis's Cloud

一个人的首要责任,就是要有雄心。雄心是一种高尚的激情,它可以采取多种合理的形式。
—— 《一个数学家的辩白》

智能体

《人工智能现代方法》读书笔记

作者:oasis


本章节的逻辑:

首先提出智能体和环境这个主题是为了给处智能体的基本抽象:智能体=感知序列 -> 动作。同时引入环境的概念,强调智能体与环境之间的交互式人工智能的基本单位。

有了智能体与环境的框架,自然要问:什么样的行为是好的?于是引出理性这个概念,用“性能度量”来定义良好行为。然后作者明确区分了“理性”与“完美”或“全知”,强调理性取决于智能体已有的知识。

理性行为的具体实现高度依赖于环境的特点,在讨论智能体设计前,要分析环境的各种属性(完全可观测 vs 部分可观测、确定性 vs 随机性、静态 vs 动态、离散 vs 连续、单智能体 vs 多智能体)

对智能体的前提条件(基本定义、理性标准、以及所处环境)有了理解后,就可以讨论如何构建智能体。

智能体这一章节构成了一条清晰的链路:

  1. 智能体和环境:定义研究对象的基本元素(智能体、环境、感知序列、动作)
  2. 良好行为:确立评价标准(理性 = 最大化期望性能度量)
  3. 环境的本质:分析约束条件(环境属性决定了理性行为的复杂性和所需信息)
  4. 智能体的结构:设计解决方案(针对不同环境或组合适当的结构)

智能体定义

任何通过传感器(sensor)感知环境并通过执行器(actuator)作用于该环境的事物都可以被视为智能体(agent)。

智能体这个概念核心目标是用于系统分析,而不是用来划分智能体和非智能体。

感知序列

感知序列是智能体所感知的一切的完整历史。一个智能体在任何给定时刻的动作选择可能取决于其内置知识和迄今为止观察到的整个感知序列,而不是它未感知到的任何事物。

智能体函数

智能体函数描述智能体的行为,该函数将任意给定的感知序列映射到一个动作。智能体函数是一种抽象的数学描述,智能体程序是一个具体的实现。

理性智能体

理性智能体是做正确事情的事物。怎么定义正确事情?人工智能对正确事情的定义是结果主义的概念,通过结果评估智能体的行为。

  1. 性能度量

评估任何给定序列导致环境经历一系列的状态。怎么评估这一系列的状态是不是好的?

性能度量设计原则

一般是根据一个人在环境中真正想要实现的目标,而不是根据一个人认为智能体应该如何表现来设计性能度量。这个判断标准反应了评价是让机器向人的行为靠拢。

  1. 理性

理性智能体的定义

对于每个可能的感知序列,给定感知序列提供的证据和智能体所拥有的任何先验知识,理性智能体应该选择一个期望最大化其性能度量的动作。

这里是不是可以理解为最优解的搜索?

与传统的最优解相比有一些差异:

传统最优解搜索通常假设:目标已知且明确,模型完全已知且确定,评价函数是达到目标的代价。而理性智能体的最优解更宽泛:性能度量可以是任意指标(不是目标),环境可能随机、部分观测、多智能体,先验知识可以是不完备的模型,“期望”意味着需要处理不确定性,不是单纯找一条确定路径。

  1. 全知、学习和自主

对于最优解的差异,所以智能体需要具有全知、学习和自主。智能体需要收集信息,需要依赖自身的感知和学习过程。

智能体的结构

人工智能的工作是设计一个智能体程序(agent program)实现智能体函数,即从感知到动作的映射。

智能体 = 架构 + 程序

什么是架构?假设该程序运行在某种具有物理传感器和执行器的计算设备上,我们称之为智能体架构(agent architecture)

表驱动智能体

js
function Table-Driven-Agent(percept) returns 一个动作
  persistent: percepts, 初始为空的序列
              table感知序列为索引的动作表初始为完全确定

 percept 添加到 percepts 的末尾
  action<-Lookup(percepts, table)
  return action

表驱动的智能体构建方法会面临巨大的表查找。所以人工智能面临的关键挑战是找出编写程序的方法,尽可能从一个小程序而不是一个大表中产生理性行为。

四种基本的智能体程序

  1. 简单反射型智能体
  2. 基于模型的反射型智能体
  3. 基于目标的智能体
  4. 基于效用的智能体

percept: 当前感知

persistent: 当智能体函数被环境反复调用(每次传入新的感知,返回一个动作)时,persistent 变量不会被重新初始化,而是保留上一次调用结束时的值。

简单反射型智能体

根据当前感知选择动作,忽略感知历史的其余部分。

这里的例子是扫地机器人。

js
function Reflex-Vacuum-Agent([location, status]) returns 一个动作
  if status = Dirty then return Suck
  else if location = A then return Right
  else if location = B then return Left

通用结构的简单反射型智能体

js
function Simple-Reflex-Agent(percept) returns 一个动作
  persistent: rules一组条件-动作规则
  state <- Interpret-Input(percept) // 根据 percept 生成当前状态的抽象描述,这一步是将世界具有的复杂性简化,简化为一条程序可用的环境状态
  rule <- Rule-Match(state, rules) // 给定状态描述,返回规则集中匹配的第一条规则。这里是从条件-动作规则中筛选
  action <- rule.action
  return action

简单反射型智能体适合于:完全可观测的环境下。这种智能体完全依赖条件-动作规则。当环境部分可观测时,只靠当前感知时不够的。为了能处理这种环境,智能体需要维护内部状态,记录哪些无法直接感知到的信息。

例如:简单吸尘吸智能体看到当前位置有灰尘就吸尘,看到前方有墙就转向。但它无法区分自己是不是已经去过哪些房间,也不知道当前房间是否已经干净。

内部状态就是要表示哪些房间去过,当前房间是否已经干净,这些不可观测的环境。其实是一种间接观察的方法。人类在打扫房间的时候也会有这种内部记录,我们清楚的记得哪些房间打扫过,当前房间打扫了多少,当要转向的时候,我们根据这些内部状态做出动作的判断。

基于模型的反射型智能体

基于模型的反射型智能体在内部构建了三个关键成分:内不状态、转移模型、传感器模型。

内部状态是根据历史感知和动作维护的信息,用于支持当前决策。

转移模型描述智能体某个动作后,世界状态如何变化。转移模型是对世界演化规律的内部知识。例如,吸尘器在位置A执行向右动作后,转移模型会推断新位置是位置B;如果吸尘器有清洁功能,模型还会预测灰尘状态的变化。

传感器模型描述给定世界状态,智能体会得到什么样的感知,它让智能体能够从当前感知反推或更新自己对状态的信念。例如:当吸尘器看到有灰尘时,传感器模型告诉它:如果当前状态时房间脏,则很可能观察到灰尘;如果当前状态时房间干净,则不会观察到灰尘。

运行过程:

用传感器模型解释当前感知:结合内部状态,判断这次感知是否和状态一直,或者需要修正状态

更新内部状态:利用转移模型先预测动作后的状态,再结合传感器模型和实际感知来修正这个状态。这个过程本质是维护一个对世界状态的信念。

根据内部状态选择动作,通过预设的反射规则(或更负责的决策逻辑)选择动作。

js
function Model-Based-Reflex-Agent(percept) returns 一个动作
  persistent: state, 智能体对世界状态的当前理解 // 内部状态
              transition_model, 关于下一个状态如何决定于当前状态和动作的描述 // 转移模型
              sensor_model, 关于当前世界状态如何反映到智能体感知的描述 // 传感器模型
              rules一组条件-动作规则
              action最近的动作初始为空
  state <- Update-state(state, action, percept, transition_model, sensor_model)
  rule <- Rule-Match(state, rules)
  action <- rule.action
  return action

基于目标的智能体

基于目标的智能体在结构上扩展了基于模型的反射智能体。它包含一个目标信息,用来描述“世界状态中哪些情况是期望的”,基于目标的智能体本质上是在执行一种规划(planning),它不再仅仅根据当前状态做出瞬时反应,而是选择那些有助于在未来达到目标状态的动作。

瞬时反应这个词很精确,就像人的植物神经反应,例如膝跳反应。实际人类在活动中,常常以目标为导向,所做的一系列动作旨在实现其目标。

在最简单的环境(完全可观测、静态)中,反射足以实现理性;但随着环境复杂化,智能体必须引入更复杂的内部机制。支持其决策的知识是显示表示的,并且可以修改。

js
function Goal-Based-Agent(percept) returns action
  persistent: state,              // 智能体对当前世界状态的信念(内部状态)
              transition_model,   // 转移模型:给定状态和动作,描述后继状态的函数
              sensor_model,       // 传感器模型:给定状态,描述可能感知的函数
              goal                // 目标:描述哪些世界状态是期望的

  // 利用上一个动作、当前感知以及两个模型,更新内部状态
  stateUpdate-State(state, action, percept, transition_model, sensor_model)

  // 基于当前信念、目标和转移模型,选择能够达成目标的首个动作
  // 这一步通常涉及规划(planning),即搜索动作序列以找到能实现目标的路径
  // 具体算法(如A*搜索、启发式搜索)将在第3章及以后详细介绍
  actionChoose-Action-That-Achieves-Goal(state, goal, transition_model)

  return action

基于效用的智能体

仅仅通过目标不足以产生高质量的行为。通过效用评价搜索或规划,从而选择能够最大化其动作结果期望效用的动作。

js
function Utility-Based-Agent(percept) returns action
  persistent: state,                // 当前世界状态的信念(内部状态)
              transition_model,     // 转移模型:P(s' | s, a)
              sensor_model,         // 传感器模型:P(percept | s)
              utility_function,     // 效用函数 U(s),将状态映射为实数
              action_history        // 最近执行的动作(用于更新状态)

  // 1. 更新信念状态
  stateUpdate-State(state, action_history, percept, transition_model, sensor_model)

  // 2. 决策:选择最大化期望效用的动作
  //    对于每个可能的动作 a,计算在当前信念状态下执行 a 的期望效用
  //    期望效用的计算依赖于转移模型和效用函数
  actionargmax_a Expected-Utility(a, state, transition_model, utility_function)

  // 3. 记录当前动作,供下一次更新使用
  action_historyaction

  return action

学习型智能体

任何类型的智能体(基于模型、基于目标、基于效用等)都可以构建(或不构建)成学习型智能体。学习型智能体分为四个概念:

  1. 性能元素:决策模块——负责根据当前感知和内部状态选择动作,学习的目标就是改进这个模块
  2. 学习元素:负责根据评判者提供的反馈,对性能元素进行修改(例如调整规则权重、更新模型参数、改进搜索启发式等)。它体现了学习的具体机制(例如监督学习、强化学习、模型学习等)
  3. 评判者:为学习元素提供评价信号,告诉学习元素:当前决策好还是不好,以及程度如何。评判者通常依赖于一个固定的性能度量标准(与理性定义中的性能度量一一致),用来衡量智能体行为的质量。注意:评判者与性能元素不同——性能元素产生动作,评判者评价动作的长期效果。
  4. 问题生成器:负责提出探索性动作,帮助智能体获取新的经验,从而发现更好的策略。如果没有问题生成器,智能体可能只依赖已有的知识,陷入局部最优。问题生成器是学习型智能体实现“探索与利用权衡”的关键。

模块之间的关系与工作流程:

  • 智能体与环境的交互由性能元素完成:它接收感知,输出动作,环境反馈新的感知和(可能隐含的)奖励/代价。
  • 评判者观察性能元素产生的动作序列及其结果(例如累积奖励、是否达到目标等),根据固定的性能度量生成一个评价信号(例如“好”或“坏”,或者一个数值评分)。
  • 学习元素接收这个评价信号,结合当前性能元素的状态,修改性能元素的内部结构(例如更新规则集、调整效用函数的参数、优化转移模型等)。
  • 问题生成器有时会绕过性能元素,主动建议一些探索性动作(如“尝试一条新路径”),以便让学习元素获得更多样化的训练数据。

智能体程序的组件如何工作

智能体程序的组件如何工作一节中提到了 原子表示、因子化表示、结构化表示,他们是什么,关系如何?为什么要这么划分?

当我们讨论智能体程序如何表示它所处理的信息时,引入了原子表示、因子化表示和结构化表示这三个层次。它们描述了智能体对世界状态(是智能体对“当前世界状况”的内部表示)的描述精细程度,直接影响智能体能够执行哪些类型的推理。

原子表示、因子化表示、结构化表示是在表达智能体中世界模型的状态。

**原子表示:**智能体将世界状态表示为一个不可分割的整体符号。例如,一个真空吸尘器智能体可能用 “状态A” 表示“机器人在房间1且有污渍”,用 “状态B” 表示“机器人在房间2且无污渍”。智能体知道自己在哪个状态,但不知道这个状态由哪些属性构成——它无法回答“我在哪个房间”这个问题,除非预先在状态名称中编码。

**因子化表示:**智能体将世界状态表示为一组“属性-值”对(或特征向量)。例如:[位置=房间1, 污渍=有, 电量=高]。智能体不仅可以知道当前状态,还可以独立地查询或修改某个属性。这种表示让智能体能够利用属性之间的独立性和结构进行推理和学习。

结构化表示:智能体将世界状态表示为对象、关系和事实的集合。例如 In(机器人, 房间1), Dirty(房间1), Connected(房间1, 房间2), ∀x (Dirty(x) → NeedsCleaning(x))。这种表示允许智能体处理数量可变的对象(如任意数量的房间)、表达一般性规律,并进行基于逻辑的推理。

原子表示、因子化表示、结构化表示的关系:

这三种表示构成了一个表示能力的层级,每一层都建立在前一层的基础上,并增加了表达力:

原子表示是最基本的,把世界当作一堆无结构的符号。它足以解决完全可观测、确定性的简单问题,但无法处理复杂的结构或不确定性。

因子化表示将状态拆解成独立的特征,使得智能体能够对部分信息进行推理、利用概率模型、学习与泛化。这是当前大多数机器学习和规划方法的基础。

结构化表示进一步突破因子化表示中“固定变量集合”的限制,允许变量数量变化、对象之间存在关系,从而能够表达无限域和复杂知识。它更接近自然语言和真实世界的复杂结构。