您的位置:首页 > 大数据 > 人工智能

《人工智能——一种现代方法》(第二版)【第3章 用搜索法对问题求解】小结

2012-07-29 12:07 711 查看
这章是第二部分问题求解的开篇,主讲运用搜索法解决问题。然后介绍常用无信息搜索策略(BFS,DFS,IDS……),还强调了下避免重复状态,最后提到了下使用不完全信息的搜索。

开章提到:当没有单独的行动可以解决问题的时候,智能体如何找到一个行动序列达到它的目标,是讨论的重点。然后会描述一种基于目标的智能体,称为问题求解智能体。问题求解智能体通过寻找达到所希望的状态的行动序列来决策要做什么。从精确地定义组成“问题”和它的“解”的元素开始,并且给出一些例子来详细介绍这些定义。

智能化智能体被认为是能使自己的性能度量达到最大化的智能体。

基于当前的情形和智能体的性能度量的目标形式化是问题求解的第一个步骤。

我们将考虑的目标是一个世界状态集合——正是在那些状态中,该目标是可满足的。智能体的任务是找出能够使它达到目标状态的行动序列。在能作这个之前,它需要决策所要考虑的行动和状态的种类。而在很多的细节水平上,世界的不确定因素太多,问题的解也将包含过多的步骤。问题形式化是决策对于给定的目标需要考虑哪些行动和状态的过程。

如果智能体不知道哪个可能的行动学列是最好的,那是因为它对由每个行动产生的状态了解得不够多。如果智能体没有得到额外的知识,就只能停滞不前了。这时它能做的最好决策就是随机选择一个行动。

一般来说,一个智能体有多个评价未知直接选项的时候,可以首先检验各个不同的能导致已知评价的状态的可能行动序列,然后选择最佳序列。寻找这样一个序列的过程被称为搜索。

搜索算法把问题作为输入,并以行动序列的形式返回问题的解。一旦找到一个解,那么它所建议的行动就可以付诸实施。这被称为执行阶段。从而,我们有了一个对智能体的简单设计,即“形式化,搜索,执行”。在把目标和待求解的问题形式化之后,智能体通过调用搜索过程对它求解。然后智能体用得到的解来引导行动,按照解的建议去作下一步事情。一旦解被执行,智能体将形式化新的目标。

这里,我们的智能体设计假定环境是静态的,可观察的,确定性的,离散的。

1,静态的,是因为完成问题形式化和求解的时候不再注意可能发生在环境中的任何变化;2,可观察的,了解初始化状态是最简单的;3,离散的,是为了枚举“可选的行动过程”的思想;4,确定性的(无二义性?)。

问题求解有两部分,一是定义明确的问题及解;二是把问题形式化。

1,一个问题可以形式化地定义为四个组成部分:智能体起始时的初始状态,对智能体可采纳的可能行动的描述(最常见的形式化是使用一个后继函数,给定一个特殊状态x,SUCCESSOR-FN(x)返回一个由有序对<action, successor>组成的集合。总之,初始状态和它的后继函数隐含地定义了问题的状态空间,即是从初始状态可以达到的所有状态的集合。),目标测试(用来确定给定的状态是不是目标状态),路径耗散函数为每条路径分配一个数值化的耗散值。

上述元素定义了一个问题,可以把他们集合在一起成为单一的数据结构,作为问题求解算法的输入。问题的解就是从初始状态到目标状态的路径。解的质量由路径耗散函数度量,而最优解是所有解里路径耗散值最小的解。

去除表象中的细节的过程被称为抽象化。除了对状态描述抽象化之外,还要对行动本身进行抽象化。

选择一个好的抽象化方法,涉及在保持有效性和保证抽象化的行动能够容易完成的同时去除尽可能多的细节。如果缺乏能力去构造游泳的抽象化,智能体将会被现实世界完全淹没。

然后提到了几个问题实例,都是抽象出状态,初始状态,后继函数,目标测试和路径消耗。

重点是对解的搜索。该章讨论的搜索技术使用显式的搜索树,搜索树是由初始状态和后继函数共同产生的,同时也定义了状态空间。一般来说,当同一个状态可以从多条路径达到时,我们会得到一个搜索图而不是搜索树。

搜索的基本做法是:先追随一个选择,把其它的暂且放在一边,等到以后万一发现第一个选择不能通向问题的解的时候再考虑。而对要被扩展的状态的选择是由搜索策略决定的。

见图3.7中一般的生成搜索树算法的非形式化描述。(循环是否有节点,根据不同策略选择一个节点进行判断,判断节点是否为目标节点,是结束,否继续拓展增加)

节点的表示有很多方式,不过我们假设节点是一个包含五个元素的数据结构:

STATE:状态空间中与该节点相对应的节点;

PARENT-NODE:搜索树中产生该节点的节点(即父节点);

ACTION:由父节点产生该节点所用的行动;

PATH-COST:从初始状态到到达该节点的路径消耗,传统上记为g(n),路径由父指针表示;

DEPTH:从初始状态到达该节点所经路径上的步数。

记住节点和状态的差别是很重要的。节点是用来表示搜索树的记录型数据结构。状态对应于世界的格局。

已经生成出来但还未被扩展的节点集合被称为边缘。边缘的每个元素都是叶节点,即在搜索树中没有后继的节点。因此可以更加形式化一般的树搜索算法。见图3.9。从FRINGE中取节点,判断是否目标,不是扩展所有后继节点加入FRINGE中。循环。

度量问题求解的性能,问题求解算法的输出不是失败就是解。(当然除掉一些陷入无限循环而永远不会返回输出的)通过一下四种途径来评价一个算法的性能。

1,完备性:当问题有解时,这个算法是否能够保证找到一个解?

2,最优性:这个搜索策略是否能找到最优解?

3,时间复杂性:找到一个解需要花费多长时间?

4,空间复杂性:在执行搜索的过程中需要多少内存?

时间和空间的复杂度往往要与问题难度的某种度量一起考虑。在AI领域,状态空间图是由初始状态和后继函数隐含地表示的,经常是无限的,它的复杂度根据下列三个值来表达。

b,分支因子,或者说是任何节点的后继的最大个数;

d,最浅的目标节点的深度;

m,状态空间中任何路径的最大深度。

时间复杂度常常根据搜索过程中产生的节点数目来度量,而空间复杂度则根据在内存中存储的最大节点数来度量。

在评价一个搜索算法的有效性的时候,可以只考虑搜索耗散——它通常取决于时间复杂度,不过也可以包括内存的使用情况——或者我们可以使用总耗散,它把找到的解的搜索耗散和路径耗散结合起来。(解耗散,举例说明,书中的例子是到Bucharest城市,这里搜索耗散就是找到解的时间,而解耗散就是汽车到达B城市的时间,需要考虑公里数加上车速等因素)

无信息的搜索策略介绍了广度优先,代价一致,深度优先,深度有限,迭代深入深度优先,双向这六种。那三个名字听起来有点陌生的策略只是对广度和深度优先的改进优化。

广度优先搜索是简单的搜索策略,首先先扩展根节点,接着扩展根节点的所有后继,然后再扩展它们的后继,以此类推。一般来讲,在下一层的任何节点扩展之前搜索树上本层深度的所有节点都已经扩展过。(用FIFO实现上面的FRINGE集合即可实现)(维基百科上面的:广度优先搜索算法(Breadth-First-Search),又译作宽度优先搜索,或横向优先搜索,简称BFS,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索的实现一般采用open-closed表。)

复杂度方面,维基百科给出的是O(b^d),而该书给出的是O(b^(d+1))。这个差异应该是对d的定义不同。维基上面对于树的介绍如下http://zh.wikipedia.org/wiki/%E6%A0%91_(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84),其中其深度定义d是层次的。而该书中的d定义为到根节点的距离,即是两者定义上就相差1了。至于这个d+1怎么来的的问题,按照本书上面提到的“时间复杂度常常根据搜索过程中产生的节点数目来度量,而空间复杂度则根据在内存中存储的最大节点数来度量。”来衡量的话,给出d+1的结论是OK的。这个b^(d+1)指数是由目标节点所在层的节点扩展出来的未被扩展的节点数量产生的。

另外要提到的完备性和最优性。完备性很容易理解,如果最浅的目标节点处于一个有限的深度d。不过,最浅的目标节点不一定就是最优的目标节点。这个要注意,必须要有“路径耗散是节点深度的非递减函数”的前提才能成立。

代价一致搜索,其实就是一个贪心搜索,取代扩展深度最浅的节点,代价一致搜索扩展的是路径消耗最低的节点n。如果所有单步耗散都相等的话,这种算法就和广度优先搜索算法是一样的。不过,这样在扩展到一个具有能返回到同一状态的零耗散行动的节点时就会陷入无限循环(例如NoOp行动,即无操作行动)。

完备性方面,如果每一步的耗散都大于等于某个小的正值常数r。这个条件可以有效地保证最优性。因为这意味着路径的耗散总是增加的。即是最开始扩展到的节点一定耗散不大于后面扩展到的节点。

复杂度方面,由于代价一致搜索是由路径的耗散引导而不是深度,所以不能简单地使用b和d来刻画。替代地,用C*表示最优解的耗散值,并且假设每个行动的耗散至少为r。那么这个算法最坏情况下的时间和空间复杂度为O(b^ceil(C*/r)),要比b^d大得多。当单步消耗都相等的时候,两者相等。

深度优先搜索,总是扩展搜索树的当前边缘中最深的节点。其对内存的需求很少。只需要存储一条从根节点到叶节点的路径,以及该路径每个节点的所有未被扩展的兄弟节点即可。(一旦一个节点被扩展,当它的所有后代都被完全搜索过后这个节点就可以从内存中删除。)

因此,DFS只需要存储bm+1个节点。其另一种变形称为回溯搜索,所用的内存空间更少。在回溯搜索中,每次只产生一个后继节点而不是所有的后继节点:每个被部分扩展的节点要记住下一个要生成的节点是哪个。用这种方法,内存只需要O(m)而不是O(bm)。其还推动了另一个节省内存(和节省时间)的技巧:通过直接修改当前的状态描述而不是先对它进行复制来生成后继节点的思想。

完备性方面,是不能保证的。因为如果所左子树深度没限制又不包含目标节点,那么DFS永远不会停止。另外,最优也明显不能保证。时间复杂度方面,搜索O(b^m)数量级节点。

下面还介绍了两个对DFS优化的搜索策略。

深度有限搜索,这个,在DFS的基础上面预先设定了一个深度限制l。搜索过程和DFS一样,只是深度为l的节点被当作没有后继的节点对待。虽然这种方法解决了无穷路径的问题,但是如果我们选择的l<d的话,这会导致不完备性。

实际上,对状态空间的研究,我们会发现状态空间的直径,从而用来限制DFS,可以得到优化。

迭代深入深度优先搜索,简称为迭代深入搜索,是一个用来寻找最合适的深度限制的通用策略。它的做法是不断地增大深度限制,直到找到目标节点。空间需求明显和DFS一样,也为O(bd)。虽然深度较低的节点多次重复,但是总的来说,还是不算多。也只是到达O(b^d),比BFS快。

一般来讲,当搜索空间很大而且解的深度未知的时候,迭代深入搜索是一个首选的无信息搜索方法。

最后介绍的双向搜索,同时运行两个搜索,一个从初始状态空间向前搜索,另一个从目标状态先后搜索。其思想是b^(d/2)+b^(d/2)要比b^d小得多。(通过哈希表检测一个节点是否属于另一颗搜索树只需要固定的时间)时间复杂度为O(b^(d/2))……最困难的地方是,目标测试只给出对可能很大的目标状态集合的一个隐性描述——象棋中的将死。

避免重复状态是很重要的,一般用closed表和open表。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: