《麻省理工学院公开课:人工智能》笔记三

《04 搜索: 深度优先,爬山,束搜索》视频链接

【内容简介】

由地图的例子讲述了关于搜索的几个算法的原理,包括:大英博物馆算法(British Museum Algorithm),深度优先搜索(Depth first search),广度优先搜索(Breadth first search),爬山算法(Hill climbing),束搜索算法(Beam)

【笔记】

因为实际的地图非常复杂,所以我们就假设一个简单的地图来解释上述搜索算法。假设我们有这么一张地图,如下图,我们打算从S点移动到***,请你规划出一条最近的路线。

如果让我们来规划的话,我们肯定选择 S>A>D>G 这条路线,因为我们人脑运行的是基于视觉的算法,但是机器没有视觉,如果让机器来选择,它会如何选择呢?

大英博物馆算法(British Museum Algorithm)

大英博物馆算法的思路就是:找出所有可能的路径。让我们用 树 来表示就是下图:

当处理这种问题时我们有两个 惯例 需要了解:

  1. 要求你画出来的搜索树使用词典顺序。(意思是S下的这些节点都需要按照字母顺序来)
  2. 搜索树不能在原地打转。(意思是:从S去了A,就不能再从A回到S,不允许有路径绕回到原来到过的地方,否则我们会无止境的原地打转)

如图所示,大英博物馆算法就是在树上列出了所有的路径。当地图很复杂的时候,这个算法就显得非常愚蠢了。

有一点要强调,虽然我们用地图来解释搜索算法,但实际上 搜索是关于选择的,这节课的内容也就是在讲探索地图时所面临的选择。

深度优先搜索(Depth First Search)

按照深度优先和从左开始的原则,我们将会拓展出 S>A>B>C>E 这条道路,这时就会进入死胡同。

Tip 1:
处理办法就是回到上次做出选择的地方,选择另一个分支进行深度拓展,这个过程称为回溯(Backup/Backtracking)*

所以搜索树的演变就如下图:

搜索算法的深度优先大致流程图如下:

解释:
假设我们有一个队列来存储所有的路径。
刚开始队列里面存储的是(S),因为并不是想要的结果,所以我们拓展队列中的第一个。
这时队列里面存储就是( S>A,S>B ),这也不是想要的结果,所以我们拓展队列中的第一个路径,并删除原来第一个的路径。
这时队列里面存储就是( S>A>B,S>A>D,S>B ),这也不是想要的结果,所以我们拓展队列中的第一个路径,并删除原来第一个路径。

所以队列的变化就为:
(S)
(S>A, S>B)
(S>A>B, S>A>D, S>B)
(S>A>B>C, S>A>D, S>B)
(S>A>B>C>E, S>A>D, S>B)
(S>A>D, S>B)
(S>A>D>G, S>B)

广度优先搜索

工作方式:你一层一层的建立这棵树,在某一层横向扫描时发现自己得到了目标的路径。

搜索树的变化为:

广度优先的算法与深度优先的算法流程图区别在于:将拓展结果方放到队列末端,这样的话队列就会同时拓展所有的路径。

但是广度优先也是比较蠢的?

  • 路径重复考虑了(比如说A到D,B到C被重复考虑了,如果路径够复杂,会影响效率)

Tip 2:
为了解决路径重复考虑的问题,我打算修改算法流程图中的规则:不拓展队列中的第一个路径,除非末端节点之前从未被扩展过。因此我们需要一个列表来存储之前已经拓展过的所有路径。

在广度优先的基础上加入 拓展位置列表 就对搜索算法进行了优化。

爬山算法(hill climb)

与深度优先搜素算法相似,只是不再使用字典顺序进行选择。

当我们起点放到地图中间(如下图所示),此时不管我们用上面讲述过的任何一种算法,它都会往左寻找路径,但我们人眼可以看到往右才离目标更近。所以我们在搜索算法中加入哪些节点离得目标近的思路来优化它。

Tip 3:
怎么才能让机器知道哪些节点离目标更近?
用一些启发式的方法。就比如我们最初的地图上(下图)就标注了距离长度,这是一般地图上都会有的。
启发式方法有就用,没有就算了。

所以用爬山算法解决这个地图,它的搜索树就如下图所示:

爬山法对搜素算法流程图的改动在于:在深度优先的基础上,将路径按照知情启发式信息,及远近信息进行排序后,放到队列前面。

但是爬山法会有一些问题:

束搜索(Beam search)

是广度优先的改良,将知情启发式信息加到了广度优先搜素中。

我们将每一层中考虑拓展的路径数字进行限制,取一个较小固定数字(比如说我们这里假设束搜素的束宽 (Beam Width) w 为 2),再加上知情启发式信息,我们的搜素树就如下图:

束搜索对搜素算法流程图的改动在于:在广度优先的基础上,将路径放到队列之前,要 keep w best。

最后有一个表格整理这节内容:

Backup use extended list informed search
British Museum NO NO NO
Depth First Yes Yes NO
Breadth First NO Yes NO
Hill climb Yes Yes Yes
Beam NO Yes Yes
全部评论

相关推荐

昨天 12:06
已编辑
华侨大学 测试开发
最近看到很多 92 的,甚至是硕士,开始往测开赛道卷,说实话有点看不懂。先把话说清楚,大厂里的测开,绝大多数时间干的还是测试的活,只是写点自动化脚本、维护测试平台、接接流水线,真正像开发一样做系统、做架构、做核心平台的测开少得可怜,基本都集中在核心提效组,而且人很少,外面进去的大概率轮不到你,我想真正干过人都清楚。很多人被洗脑了,以为测开也是开,和后端差不多,只是更简单、更轻松、还高薪。现实情况是,测开和开发的职业路径完全不一样。开发的核心是业务和系统能力,测开的核心是稳定性和覆盖率,前者是往上走,后者天花板非常明显。你可以见到很多开发转测开,但你很少见到干了几年测开还能顺利转回开发的。更现实一点说,92 的高学历如果拿来做测开,大部分时间就是在做重复性很强的杂活,这种工作对个人能力的放大效应非常弱。三年下来,你和一个双非的,甚至本科的测开差距不会太大,但你和同龄的后端、平台开发差距会非常明显。这不是努不努力的问题,是赛道问题。所谓测开简单高薪,本质上是把极少数核心测开的上限,当成了整个岗位的常态来宣传。那些工资高、技术强的测开,本身就是开发水平,只是挂了个测开的名。普通人进去,99% 做的都是项目兜底型工作,而不是你想象中的平台开发。测开不是不能做,但它绝对不是开发的平替,也不是性价比最优解。如果你是真的不想做开发,追求稳定,那测开没问题。但如果你只是觉得测开比后端容易,还能进大厂,那我劝你冷静一点,这只是在用短期安全感换长期天花板。有92的学历,如果你连测开这些重复性工作都能心甘情愿接受,那你把时间精力用在真正的开发、系统、业务深度上,回报大概率比卷测开要高得多。想清楚再下场,别被岗位名和话术带偏了,就算去个前端客户端也是随便占坑的,测开是一个坑位很少赛道,反而大面积学历下放,不用想也能知道会是什么结果,我想各位在JAVA那里已经看到了
烤点老白薯:测测你的
点赞 评论 收藏
分享
bg双非本科,方向是嵌入式。这次秋招一共拿到了 8 个 offer,最高年包 40w,中间也有一段在海康的实习经历,还有几次国家级竞赛。写这篇不是想证明什么,只是想把自己走过的这条路,尽量讲清楚一点,给同样背景的人一个参考。一、我一开始也很迷茫刚决定走嵌入式的时候,其实并没有一个特别清晰的规划。网上的信息很零散,有人说一定要懂底层,有人说项目更重要,也有人建议直接转方向。很多时候都是在怀疑:1.自己这种背景到底有没有机会2.现在学的东西到底有没有用3.是不是已经开始晚了这些问题,我当时一个都没答案。二、现在回头看,我主要做对了这几件事第一,方向尽早确定,但不把自己锁死。我比较早就确定了嵌入式这个大方向,但具体做哪一块,是在项目、竞赛和实习中慢慢调整的,而不是一开始就给自己下结论。第二,用项目和竞赛去“证明能力”,而不是堆技术名词。我不会刻意追求学得多全面,而是确保自己参与的每个项目,都能讲清楚:我负责了什么、遇到了什么问题、最后是怎么解决的。第三,尽早接触真实的工程环境。在海康实习的那段时间,对我触动挺大的。我开始意识到,企业更看重的是代码结构、逻辑清晰度,以及你能不能把事情说清楚,而不只是会不会某个知识点。第四,把秋招当成一个需要长期迭代的过程。简历不是一次写完的,面试表现也不是一次就到位的。我会在每次面试后复盘哪些问题没答好,再针对性补。三、我踩过的一些坑现在看也挺典型的:1.一开始在底层细节上纠结太久,投入产出比不高2.做过项目,但前期不会总结,导致面试表达吃亏3.早期有点害怕面试,准备不充分就去投这些弯路走过之后,才慢慢找到节奏。四、给和我背景相似的人一点建议如果你也是双非,准备走嵌入式,我觉得有几件事挺重要的:1.不用等“准备得差不多了”再投2.项目一定要能讲清楚,而不是做完就算3.不要只盯着技术,多关注表达和逻辑很多时候,差的不是能力,而是呈现方式。五、写在最后这篇总结不是标准答案,只是我个人的一次复盘。后面我会陆续把自己在嵌入式学习、竞赛、实习和秋招中的一些真实经验拆开来讲,希望能对后来的人有点帮助。如果你正好也在这条路上,希望你能少走一点弯路。
x_y_z1:蹲个后续
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务