实现图的宽度优先遍历_人工智能和经典图搜索问题之间有什么关系?

全文共5764字,预计学习时长11分钟
ce11f5b3871032f9893849cc1492a91c.png

人工智能与图搜索

通常,我们在浏览一些与人工智能相关的话题、教程、或者文章时会发现,作者为了解释人工智能代理的工作原理,常会用图搜索问题作为例子。这是为什么呢?人工智能和经典的图搜索问题之间有什么关系呢?

aaf661c99f3edec64edd73b3f3c3fb83.png

什么是人工智能

查找各种资料后你会发现,对于人工智能并没有一个清晰而明确的定义。部分人认为“人工智能就是对理性主体的研究,此处的理性主体指任何能够作出决策的主体,可以是一个人、一个公司,也可以是机器或者软件”。在分析了过去和现在的感知经历和背景信息之后(即主体在某一特定环境中的感知输入),理性主体能够选择执行会产生最佳结果的行为。此外,对于人工智能还有其他一些定义,但它们主要从哲学的角度来探讨人类智能与机器智能之间的界限问题。

然而,所有这些定义在谈的都是,当你不知道怎么做而又想知道怎么做的时候,人工智能就是能够给予你帮助的一门研究学科。理性主体会通过一些传感器来感知目前的环境,在分析过去已执行的行为之后,选择执行会带来最佳结果的行为。

接下来,一起来了解一下经典的最佳路径问题。给出一幅图,上面有许多节点,你需要找出两个节点间总代价最小的路径。这个时候,人工智能代理就可以发挥作用了。当然,你自己不知道哪条是最佳路径;但是理性主体可以,它通过感知周围环境(此处也就是这幅图),快速找出最佳路径。

但大家知道,能够解决图搜索问题的算法多种多样,比如深度优先搜索(DFS)、宽度优先搜索(BFS)、迪杰斯特拉算法(Dijkstra)和A星算法。一些人在高中可能就已经学过了,因此稀奇之处在哪呢?难道这就是人工智能代理的工作方式吗?的确是这样的,但也不全是。人工智能不仅仅包括图搜索算法这类编程模式,正如上文提到的,它依旧是对理性主体的研究,即通过对环境的分析,执行某一动作以取得最佳结果。

人工智能代理是一个涵盖面比较宽泛的术语,它可以是机器学习、神经网络和深度学习等。此外,它也在金融、医疗和安保等领域得到广泛应用。所以,图搜索不过是人工智能的一个子领域。

对于经典的图搜索算法与能够找出两节点间最短路径的人工智能代理之间的区别,不过是其各自使用的术语不同而已。如果你想要构建一个人工智能代理,其实这和构建一个传统的算法没什么区别,理解好这一点非常重要。

aaf661c99f3edec64edd73b3f3c3fb83.png

传统算法

能够进行图搜索的方法诸多,比较经典的算法有宽度优先搜索和深度优先搜索,这两种算法能够找到目标节点但无法计算最佳路径;此外还有一致代价搜索(Uniform Cost Search)、迪杰斯特拉算法和A星算法,这三类算法都能够计算出从源节点到目标节点之间的最短路径。总的来说,以上几类算法都属于生成树算法,唯一一点值得注意的是,图搜索可能包含回路,因此树形或许不会很明显。

对于以上所有算法来说,最重要的一点是当我们在访问完一个节点之后,必须选择下一个未访问的节点继续访问,从而确认是否已经到达目标节点。

宽度优先搜索

正如上文所说,宽度优先搜索也是一种生成树算法。它之所以叫做宽度优先搜索,是因为整个图的遍历是逐层进行的。从源节点开始,首先访问它的邻接点(即同一层的节点),然后以此类推,继续访问下一层的节点。

让我们来具体分析一下以下这幅图:

08b76c0278d854b50b417d7e62a8f3ac.png

从节点A开始,看看它是如何长成“一棵树”的。

3e1a86d5dbbf9510d86ae7f4e309d785.png

A作为初始节点,处于0层,B和C处于1层,D和E处于2层。而这,正是宽度优先搜索将遍历整个图的顺序。

即如果用宽度优先搜索算法遍历整个图,那么其访问顺序为:A -> B -> C -> D -> E。

仔细观察整棵树,会发现B、C、E、D之间是连通的。之所以会这样,是因为这个图本身包含回路。但是,如果要以最优的方式遍历整个图,那么已经访问过的节点就不能再访问。因此在选择要访问的节点时,条件之一就是该节点未被访问过。

宽度优先搜索算法的工作原理

在访问了源节点之后,需要继续访问它所有的邻接点,然后再访问下一层的节点,所以此处需要一个队列。在访问一个节点之后,我们需要搜索它的邻接点,如果这些邻接点还未被访问,那么就需要将其加入到队列之中。然后,从队列中选出下一个节点继续访问。另一件非常重要的事,就是要记得标记已访问过的节点,避免重复访问。通过这种方式,我们就能遍历图中所有的节点,确保每个节点仅访问一次。

一起来学习下面的这组伪代码:

BFS(G, s, goal) Let Q be queue Q.enqueue(s) Mark s as visited while (Q is not empty) //Removing that vertex from queue v = Q.dequeue() If v is goal  return “found the goal” //processing all the neighbours of v  for all neighbours w of v in Graph G if w is not visited  //Stores w in Q to further visit its neighbour Q.enqueue(w)  mark w as visited

因此通过这种算法,只要源节点和目标节点之间有至少一条路径,那么我们就能找到任何目标节点。

寻找最小代价路径

现在改变一下这幅图,在其每条边上都加上一定的代价值。

656eea9361fdfd48883609446d22a1b3.png

假设要从A到D,寻找出一条总代价最小的路径。要想从A到D,可选择的路径有许多。我们可以选择A - > B -> D,总代价是20;或者选择A -> C -> B -> D,而这条路的总代价低一点,但也要16。实际上,存在一条总代价为3的最优路径,即A -> C -> E -> D。但是,我们该如何找到这一路径呢?此刻我们需要改变选取下一个访问节点的方式。在使用经典的宽度优先搜索算法时,我们通常使用先进先出队列(FIFO)的方式来选择下一个访问的节点。通过这种方式,我们最终的确能找到目标节点,但是却并不一定是最小代价路径。因此,为了找到能到达目标节点的最小代价路径,我们需要改变一下从队列中选取访问节点的方式。

接下来要介绍的这种算法叫做“一致代价搜索算法”(Uniform Cost Search),它其实算是迪杰斯特拉算法的改良版,因为在使用迪杰斯特拉算法时,一旦找到目标节点,搜索就会立即停止。在经典的迪杰斯特拉算法中,为了找到源节点到图中其他所有节点的最小代价路径,该算法会访问完图中所有节点,直至队列穷尽。此外,一致代价搜索与宽度优先搜索的不同之处就在于,在一致代价搜索中,从源节点到目前访问的节点的总代价值都会被储存起来。

并且,队列中的顺序也不再是根据先进先出原则,而是基于目前的总代价值。也就是说,该算法会优先选择队列中未被访问、且当前代价值最低的节点进行访问。

一起来看一下以下这组代码:

UniformCostSrearch(G, s) s.costSoFar = 0; for all nodes w in G except s w.costSoFar = Int.maxInt Let Q be a priority queue ordered by cost_so_far Q.enqueue(s) while (Q is not empty) //Removing that vertex from queue v = Q.dequeue() If v is goal return “found the goal”  //processing all the neighbours of v  for all neighbours w of v in Graph G currentCost = dist[v,w] newCost = v.costSoFar + currentCost; If (newCost < w.costSoFar) w.costSoFar = newCost ; Q.enqueue(w)

因此,基于最低代价原则,我们就能选出下一个继续访问的节点。

但是,当前的最低代价需要不断更新,因为在继续遍历整个图的过程中,我们总是能找到更优的路径。因此,在访问某个节点时,需要了解一下它所有的邻接点,并且将它们目前的代价与新的代价进行比较,新的代价也就是目前所访问的节点的总代价和该节点与其邻接点间的距离。

currentCost = dist[v,w]newCost = v.costSoFar + currentCost;If (newCost < w.costSoFar) { w.costSoFar = newCost ; Q.enqueue(w);}

如果新的代价更低,那么这意味着我们找到了一条抵达目标节点更好的路径,所以需要继续更新当前的代价。进一步了解该算法的更多细节:https://dzone.com/articles/from-dijkstra-to-a-star-a,并且通过使用估价函数,也能将该算法转换为A星算法。

aaf661c99f3edec64edd73b3f3c3fb83.png

图搜索与人工智能的关系

现在,我们再来总结一下人工智能到底是什么。正如上文所给出的定义,人工智能就是对理性主体的研究,此处的理性主体指任何能够作出决策的主体,可以是一个人、一个公司,也可以是机器或者软件”。在分析了过去和现在的感知经历和背景信息之后(即主体在某一特定环境中的感知输入),理性主体能够选择执行对自己有最佳结果的行为。

但是通过图搜索算法,我们能获得什么呢?能获得一个函数、一个程序、一个理性主体。因此,如果给出一幅图,一个环境,以及一个源节点,那么通过使用图搜索算法,在分析了过去和当前对环境的感知经验之后,便能计算出一系列的行动以找到目标节点。

以上我们可以看出,图搜索算法的功能是符合人工智能代理的定义的。因此,我们也完全可以将其视为一种初级的人工智能。所以说,人工智能也并不是什么高深莫测、不可企及的科学。人工智能的定义是非常宽泛的,甚至包括像图搜索这种简单算法。通过这些例子,我们也能大概了解一下人工智能的基本概念。

了解了人工智能的概念之后,我们可以试着来构建一个人工智能代理来分析周围环境,并且计算出一系列行动以帮助我们达到某一特定目的(在这里本质上使用的还是图搜索算法,只是借助了人工智能的术语)。

以下是一幅罗马尼亚(Romania)地图。

8a3d65c1b2ba4fe9cdbf45c7fdfc14c0.png

假设我们目前正处于Arad,想要走一条最近的路前往Bucharest。很明显,我们有很多条路线可以选择,比如可以从Arad先到Timisoara,然后经过Lugoj等城市最后到达Bucharest;或者,也可以选择经过Sibiu和Fagaras后直接到达目的地。但是,我们仍然不知道哪条路径的代价最低。

罗马尼亚问题的定义

该问题可以分解为几个部分:

· 初始状态:位于Arad。

· 函数行动(s):当我们处于某一状态,则会有一系列的可能行动。例如:我们位于Arad,则可能会前往Zerind、Sibiu,或者Timisoara。

· 函数结果(s,a) -> s’:如果我们处于状态s,执行行动a就会到达s’。

· 函数目标测试 (s) -> t/f:它能告诉我们是否已经到达目的地。

· 步骤代价 (s,a,s’) -> 行动代价:当我们执行行动a,从s到s'时,它能告诉我们该过程中每一步的代价。

· 代价 (S1 -> S2 -> … -> Sn) -> n (路径代价):该路径的总代价。

现在,让我们来分析一下这幅罗马尼亚地图是如何在该路径问题中体现出来的。我们的初始状态是在Arad,当我们到达Bucharest,则目标测试函数回溯。该过程中,所有可能的状态叫做状态空间,并且我们必须通过执行行动来逐个搜索状态空间。初始状态于Arad并且执行函数行动 (“Arad”),会产生三种可能的行动,即去往Zerind,Timisoara,或者Sibiu。现在,记住这一点,接下来我们将把状态空间分为三部分:

· 已扩展的状态:目前仅指Arad。

· 前驱节点:目前已扩展的最远的状态(也就是Zerind、Timisoara,以及Sibiu)。

· 尚未扩展的状态:剩下的所有城市。

因此,当处于已扩展的状态时,我们就需要从前驱节点中选择一个新状态,执行一个行动,然后进入这个新状态,这样前驱节点也得以扩展。

TreeSearch(G, s) s.costSoFar = 0; for all nodes w in G except s w.costSoFar = Int.maxInt Let frontier be a priority queue ordered by the cost_so_far frontier.enqueue(s) while (frontier is not empty) //Removing that vertex from frontier,whose neighbour will be visited now v = frontier.dequeue() If v is goal return “found the goal”  //processing all the neighbours of v  for all neighbours w of v in Graph G currentCost = dist[v,w] newCost = v.costSoFar + currentCost; If (newCost < w.costSoFar) { w.costSoFar = newCost ; frontier.enqueue(w)

因此在初始阶段,前驱节点中只有一个源节点。在之后的每一次迭代过程中,我们从前驱节点中获取一个节点,然后进入下一个状态。一旦我们到达目标状态,就会发出信息“已找到目标”并随即结束搜索。我们也可以选择打印路径,或者将新状态添加到前驱节点中。

因此,根据你从前驱节点中选择新状态的不同方式,相应地也会执行不同的算法,比如可以执行经典的宽度优先搜索、一致代价搜索,或者A星算法。

想要更加清楚地了解这些算法之间的区别,并且找到最适合的算法来搜索从Arad到Bucharest的最短路径:https://dzone.com/articles/from-dijkstra-to-a-star-a

aaf661c99f3edec64edd73b3f3c3fb83.png

结语

当然,人工智能代理也不只是应用于图搜索,相关的人工智能算法也广泛应用于面部识别、机器学习、神经网络和统计算法领域,但要理解这些需要一定的数学基础。实际上,也不必过多担心或者被它们的难度吓到,因为总的来说,它们的基本概念还是不难理解的。

e5b50d01fda831822ff6c820c7db0a5d.png

留言 点赞 关注

我们一起分享AI学习与发展的干货

如需转载,请后台留言,遵守转载规范

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值