上篇回顾,无信息搜索算法比较:
启发式搜索(informed search)策略
使用关于目标位置的特定领域线索——如何比无信息搜索策略更有效地找到解, 线索以启发式函数(heuristic function)的形式出现,记为h(n):
贪婪最佳优先搜索GBFS(Greedy Best-First Search)
贪心最佳优先搜索(greedy best-first search)是最佳优先搜索的一种形式,它首先扩展h(n)值最小的节点——看起来最接近目标的节点,因为这样可能可以更快找到解。因此,评价函数f(n) =h(n)。
在每次迭代中,它都会做出在当前看来最优的(即可以最接近目标的)选择,但这也会导致贪心法在全局意义上可能产生比谨慎的算法更糟糕的结果。
完备性
有限空间 | 无限空间 | |
GBFS树搜索 | 否 | 否 |
GBFS图搜索 | 完备 | 否 |
最优性
非最优
复杂性
最坏情况下的时间复杂性和空间复杂性是O(b^m) 。然而,使用一个好的启发式函数,复杂性可以大大降低,对于某些问题可以达到O(bm)。
A*搜索
最常见的有信息搜索算法是A*搜索(A* search)(读为“A星搜索”),这是一种最佳优先搜索,评价函数为
其中g(n)是从初始状态到节点n的路径代价,h(n)是从节点n到一个目标状态的最短路径的代价估计值,因此我们有
f(n) = 经过n到一个目标状态的最优路径的代价估计值
完备性:完备
最优性:对于可容许的启发式函数,A*是代价最优的
复杂性
最优化问题与局部搜索
局部搜索(local search)算法的操作是从一个起始状态搜索到其相邻状态,它不记录路径,也不记录已达状态集。这意味着它们不是系统性的——可能永远不会探索问题的解实际所在的那部分搜索空间。但是,它们有两个主要优点:
(1)使用很少的内存;
(2)通常可以在系统性算法不适用的大型或无限状态空间中找到合理的解。
局部搜索算法也可以求解最优化问题(optimization problem),其目标是根据目标数(objective function)找到最优状态。
为了理解局部搜索,我们考虑在状态空间地形图(state-space landscape)中布局的问题状态,如图所示。地形图中的每个点(状态)都有一个“标高”,由目标函数值定义。
如果标高对应于目标函数,那么目的就是找到最高峰——全局极大值(global maximum)——我们称这个过程为爬山(hill climbing);
如果标高对应于代价,那么目的就是找到最低谷——全局极小值(global minimum)——我们称之为梯度下降(gradient descent)。
爬山法
最陡爬山法
记录当前状态并在每次迭代中移动到值最大的相邻状态,也就是说,它朝最陡上升(steepest ascent)的方向前进。当它到达一个没有邻居具有更高值的“峰值”时,算法终止。爬山法不会考虑超出当前状态的直接邻居之外的状态。
“就像一个健忘的人在大雾中试图找到珠穆朗玛峰的顶峰”
爬山法可能会由于以下原因而陷入困境:
- 局部极大值(local maxima):局部极大值是一个比它每个相邻状态都高但比全局极大值低的峰顶。爬山法到达局部极大值附近就会被向上拉向峰顶,但随后将困在局部极大值处无路可走。
- 岭(ridge):如图所示。岭的存在将导致一系列局部极大值,对于贪心算法,这是很难处理的。
- 平台区(plateau):平台区是指状态空间地形图中的平坦区域。它可能是一块平坦的局部极大值,不存在上坡的出口;也可能是一个山肩(shoulder),从山肩出发还有可能继续前进。爬山搜索可能会迷失在平台区上。
随机爬山法(stochastic hill climbing)
在上坡行动中随机选择一个;被选中的概率随着上坡陡度的变化而变化。比最陡爬山法收敛慢,但是在某些状态空间中可以找到更好的解
- 随机行走:在所有后继中随机选择一个
- 随机爬山:在所有好的后继中随机选择一个
首选爬山法(first-choice hill climbing)
通过不断随机地生成后继直到生成一个比当前状态更好的后继为止来实现随机爬山。当一个状态存在众多(如数千个)后继时,这是一个很好的策略。
随机重启爬山法(random-restart hillclimbing)
它来自于一句格言:“如果一开始没有成功,那么尝试,再尝试。”它从随机生成的初始状态开始,执行一系列爬山搜索,直到找到目标。算法完备的概率为1,因为它最终会生成一个目标状态作为初始状态。如果每一次爬山搜索成功的概率为p,那么需要重启的期望次数为1 / p。
爬山法是否能成功在很大程度上取决于状态空间地形图的形状:如果几乎不存在局部极大值和平台区,那么随机重启爬山法可以很快找到一个好的解。但是,许多实际问题的地形图看起来更像是平地上散布着一群秃顶豪猪,每个豪猪的刺上还住着微型豪猪。NP困难问题通常存在指数级数量的局部极大值。尽管如此,在几次重启后,通常也可以找到相当好的局部极大值。
模拟退火法
从不“下坡”,即从不向值较低(或代价较高)的状态移动的爬山算法总是很容易陷入局部极大值。相比之下,纯粹的随机游走算法不考虑状态值,而是随机移动到一个后继状态,它最终能够找到全局极大值,但它的效率非常低。因此,尝试将爬山法和随机游走结合起来以同时获得高效性和完备性,似乎是合理的。
模拟退火(simulated annealing)就是这样一种算法。在冶金学中,退火(annealing)是一种通过将金属或玻璃加热到高温然后逐渐冷却的方法使材料达到低能量结晶态以进行回火或硬化的过程。为了更好地解释模拟退火,我们将关注点从爬山转换为梯度下降(gradient descent)(即,最小化代价)。
模拟退火算法的总体结构与爬山法类似,然而它不是选择最佳移动,而是选择随机移动。
- 如果该移动使得情况改善,那么它总是会被接受。
- 否则,算法以小于1的概率接受该移动。
概率随着该移动的“坏的程度”——评估值变差的量 ——呈指数级下降。如果schedule所设置的T降到0的速度足够慢,那么玻尔兹曼分布的一个性质是所有概率都集中在全局极大值上,即算法将以接近1的概率找到全局极大值。
局部束搜索
局部束搜索(local beam search)算法记录k个状态而不是只记录一个。它从k个随机生成的状态开始。
- 在每一步中,生成全部k个状态的所有后继状态。
- 如果其中任意一个是目标状态,那么算法停止。
- 否则,它将从完整列表中选择k个最佳后继并重复上述操作。
从第一印象来看,具有k个状态的局部束搜索似乎只不过是并行(而非串行)地运行k次随机重启。事实上,这两种算法是完全不同的。
- 在随机重启搜索中,每个搜索进程独立运行。
- 而在局部束搜索中,有用信息将在并行的搜索线程之间传递。
实际上,生成最佳后继的那些状态会对其他状态说:“过来,这里的草更绿!”。算法将很快放弃那些没有效果的搜索并把资源转移到取得最大进展的路径上。
如果k个状态之间缺乏多样性,局部束搜索可能会受到影响——k个状态可能聚集在状态空间的一块小区域内,导致搜索只不过是k倍慢版本的爬山法。
随机束搜索(stochastic beam search)可以帮助缓解这个问题,它类似于随机爬山法。随机束搜索不是选择最佳的k个后继状态,而是选择概率与它对应的目标函数值成正比的后继状态,从而增加了多样性。
遗传算法
进化算法(evolutionary algorithm)可以看作随机束搜索的变体,算法的动机明显来自生物学中自然选择的隐喻:一个由个体(状态)组成的种群,其中最适应环境(值最高)的个体可以生成后代(后继状态)来繁衍下一代,这个过程被称为重组(recombination)。
遗传算法类似于随机束搜索,但增加了杂交操作。如果存在可以执行有用功能的区域,杂交操作是有利的。