博舍

人工智能的三要素 人工智能搜索过程的三大要素

人工智能的三要素

业界普遍认为人工智能在技术层面的竞争主要决定于3个要素:数据资源、算法和算力,下面佳恒小编为您简单介绍。

1、数据资源

大数据技术为人工智能提供强大的分布式计算能力和知识库管理能力,是人工智能深度学习、分析预测、自主完善的重要支持支撑。数据挖掘是人工智能发挥真正价值的核心,利用机器学习算法自动开展多种分析计算,探究数据资源中的规律和异常点,辅助用户以更快、更精准的手段找到有效的可用资源,并进行风险预测和评估。

2、算法

从过去的神经网络开始,一直到近年的深度学习,尤其是多层神经网络技术的飞速发展,算法进步将看似不可能的运算带入认知、拟人的学习推理领域。早在2015年,微软ResNet系统采用152层的神经网络架构,让计算机对影像进行辨识并对物体开展监测,错误率降低到3.5%,正式超越人类的5.1%水平。而谷歌的X实验室采用了参数多大17亿的神经网络,斯坦福大学做了更大的神经网路,采用参数多达112亿个神经网络。人工神经元整在步步逼近人脑神经元,多层架构深度神经网络算法正在迈入超高速的发展时代。

3、算力

有了算法,也要有足够的运算能力,才能做到相应的效果。算力的核心是芯片技术,目前应用于人工智能领域的芯片有常用的计算机CPU,图形计算处理器GPU及神经网络处理器NPU,而用作神经网络处理器的芯片类型有两类:FPGA与ASIC,FPGA芯片能够重复编写程序,因此可以根据用户的需要来制作针对性的算法设计。ASIC即专用集成电路,同FPGA类似,但ASIC一旦出厂就不可以被再编写程序,而ASIC的稳定性能更优秀,而且成本远低于FPGA。

在机器学习领域,特别是深度学习依赖于进行重复的大量的计算,就需要定制特殊芯片进行加速运算。随着芯片技术快速发展,GPU替代CPU,而目前NPU则为人工智能技术提供了有力的支撑。

实现人工智能的三要素

人工智能,一个熟悉又陌生的名词。对于外行人员来说,人工智能就是所看到的应用产品,比如人脸识别、智能语音、智能机器人等,但是对于业内人员来讲,人工智能的本质是数据、算力、算法这些必须的元素所构成的。数据、算力、算法已经构成了目前实现人工智能的三要素,并且缺一不可。接下来,我们就来逐一分析构成人工智能的这三个要素。

数据——人工智能的粮食

实现人工智能的首要因素是数据,数据是一切智慧物体的学习资源,没有了数据,任何智慧体都很难学习到知识。自从有记录以来,人类社会发展了数千年,在这期间,人类社会不断发展变化,从最早的原始社会到奴隶社会,再到封建社会、资本主义社会、社会主义社会,未来还会发展到共产主义社会,在这漫长的发展过程中,都少不了数据做为人类社会发展的动力。

人类社会之所以发展的越来越高级文明,离不开学习知识,而知识的传播流传越快,则社会发展也越快,在封建社会以前,知识的传播从口口相传到甲骨文,再到竹简记录,就算是封建社会后期的纸质记录,其知识的传播速度也无法和今天的互联网知识的传播速度相提并论。

一般来说,知识的获取来自两种途径,一种是通过他人的经验而获得的知识,也就是他人将知识整理成册,然后供大家学习,这也是目前的主流学习方式;另一种就是通过自己的探索而获得的知识,这种学习方式目前只存在高精尖领域的知识学习,由于在已有的开放社会资源中,找不到可以学习的知识,只有自我探索获取。

无论哪种学习方式,都要通过学习载体来传播知识,无论是面对面讲述,实践操作,还是书本记录,或是电子刊物,亦或者影像资料等,这些都是学习载体,我们都可以称其为数据,学习数据的质量从根本上影响了学习的效果,所以对于人类学习而言,找一个好的老师,有一本好的书籍都是非常重要的学习选择。

既然人类的学习非常依赖于数据的质量,那么AI学习知识的时候,是否也会存在同样的问题呢?答案当然是肯定的,不仅如此,而且AI学习知识的时候对于数据的依赖还要高于人类。人类相比目前的AI而言,是具有推理能力的,在学习某些具有关联性知识的时候,通过推理联想可以获得更多的知识。从另一角度来讲,在某种特定场景下,即使数据不够完整全面,对于人类的学习影响也不会太大,因为人类会利用推理和想象来完成缺失的知识。而目前AI的推理能力还处于初级研究阶段,更多的难题还等着业内技术人员来攻克。

由此可见,目前AI学习知识大部分基本都是依赖于数据的质量的,在这种情况下,连人工智能专家吴恩达都发出人工智能=80%数据+20%算法模型的感慨,可见人工智能的“粮食安全”问题还是非常紧迫的,如果“粮食”出现了质量安全问题,那么最终将会导致人工智能“生病”。可见数据的好坏基本上大概率的决定了智能化的高低,有人会说,我可以通过提高算法模型来提高效果啊,不幸的是,在数据上稍微不注意造成了质量问题,需要在算法上历尽千辛万苦来提高效果,而且还不一定弥补得上,数据对于人工智能最终的发展结构可见一斑。

算力——人工智能的身体

算力是实现人工智能的另一个重要因素,算力在一定程度上体现了人工智能的速度和效率。一般来说算力越大,则实现更高级人工智能的可能性也更大。算力是依附于设备上的,所以一般谈论算力,都是在说具体的设备,比如CPU、GPU、DPU、TPU、NPU、BPU等,都是属于算力设备,只是他们有各自不同的能力而已。具体介绍可以阅读上一篇文章:CPU、GPU、DPU、TPU、NPU...傻傻分不清楚?实力扫盲——安排!一文,介绍相当全面,从APU到ZPU,各种PU全部介绍完了,扫盲是够了。

算力设备除了上面的各种PU之外,每一种设备下面还会分不同的系列,比如英伟达的GPU在PC端有消费级的GeForce系列,专业制图的Quadro 系列、专业计算的Tesla系列等,而GeForce系列细分还可以分为GT、GTX、RTX等,当然每种子系列下还可以继续细分,比如GTX下面有GTX1050、GTX1050Ti......GTX1080、GTX1080Ti,还有GTXTitan等更强大的系列,RTX下面也一样包括了更详细的等级划分,具体选择哪个系列要看具体使用场景而定,当然还和自身的消费实力相关,算力性能越强大也意味着更多的真金白银。

下面是RTX20系列的各种显卡的性能对比:

RTX30系列的各种显卡的对比:

此外,英伟达还有嵌入式端的各种显卡系列,比如适用于自主机器AI平台的JetSon系列、DRIVEAGX系列、ClaraAGX系列等,以及云端的一些计算资源。同样每种系列还是做了进一步的细分,比如Jetson下面就根据其算力核心数就分成了JetsonNano、JetsonTX2、JetsonXavierNX、JetsonAGXXavier等四款设备。

对于厂家而言,产品分的越细,越利于宣传和推广,对于消费者而言,可选择性也大大增加,但是也对消费者的基本知识也有了要求,如果不清楚各种产品的差异,那么就很容易选择错误,而现在的显卡市场就是如此,需要一些专业的知识才能够选对自己所需的显卡类型。希望大家经过科普后都能够选对自己的显卡型号,是打游戏、制图、还是计算,心里要有一个对应的系列型号才行,不然可要陷入选择困难症中了。

以目前人工智能主流技术深度学习为例,它的学习过程就是将需要学习的数据放在在算力设备上运行,经过神经网络亿万次的计算和调整,得到一个最优解的过程。如果把数据当成人工智能的“粮食”,那么算力就是撑起人工智能的“身体”,所有的吃进去的“粮食”都需要“身体”来消化,提取“营养”帮助成长。同样,人工智能的数据也是需要经过算力来逐一运算,从而提取数据的特征来作为智能化程度的标志的。

算法——人工智能的大脑

算法是人工智能程序与非人工智能程序的核心区别,可以这么理解,就算有了数据、有了算力,但是如果没有核心算力,也只能算是一个看起来比较高大上的资源库而已,由于没有算法的设计,相当于把一大堆的资源堆积了起来,而没有有效的应用。而算法就是使得这对资源有效利用的思想和灵魂。

算法和前两者比起来,算法更加的依赖于个人的思想,在同一家公司里,公司可以给每个算法工程师配备同样的数据资料和算力资源,但是无法要求每个算法工程师设计出来的算法程序的一致性。而算法程序的不一致性,也导致了最终智能化的程度千差万别。

相对于数据是依赖于大众的贡献,算力是依赖于机构组织的能力,而算法更加的依赖于个人,虽然很多公司是算法团队,但是真正提出核算算法思想的也就是那么一两个人,毫不夸张的说其他人都是帮助搬砖的,只是这种算法层面的搬砖相对纯软件工程的搬砖,技能要求要更高而已。这点和建筑设计一样,很多著名的建筑设计,其思想都是来自于一个人或者两个人,很少见到一个著名的设计其思想是由七八个人想出来的。

由于算法设计的独特性,和数据与算力相比,在人工智能的三个要素中,算法对人工智能的影响更大,这是因为在平时的工作当中,只要大家花上时间和费用,基本都可以找到好一些的数据和算力设备,但是算法由于其独特性,很多的算法是有专利或者没有向外界开源的,这个时候的差异就要在算法上体现出来了。

现在的大学和培训机构的人工智能专业,其学习方向也主要是以算法为主。因为数据是由大众产生,又由一些互联网大厂存储的,一般个人很少会去做这一块;而算力设备是由芯片公司控制着的;做为独立的个人最能够发挥效力的就在人工智能的算法方向了。培养优秀的算法人才对于人工智能的发展至关重要。目前市场上关于图像视觉、语音信号、自然语言、自动化等方向的算法工程师供不应求,薪资水平也是远超其他互联网软件行业的岗位。

后记:

当前,国内人工智能发展正处于高速成长期,未来将会进入爆发期,无论从业者是处于人工智能的数据处理方向,还是人工智能的算力设备研发方向,或者是人工智能的算法研发方向,都将会迎来巨大的行业红利和丰厚的回报。而人工智能算法方向又是学习回报比最高的一个方向,做为没有背景的个人,是进入人工智能行业的最佳选择。

最后希望想进入人工智能的朋友都能愿望成真,关注微信公众号深度人工智能学院,我们长期致力于人工智能的技术传播和人才发展计划。

关注微信公众号:深度人工智能学院,获取更多人工智能方面的知识!

        

        官方公众号                          官方微信号

传统人工智能中的三大问题

基于神经网络和大样本统计规律的深度学习越来越走入瓶颈,人工智能的发展越来越向基于符号推理和因果推理的传统人工智能回归。AI算法工程师不能把眼光仅仅局限在海量样本的统计规律上,而应该学习并掌握基于符号推理和小样本学习的传统人工智能技术。否则,当深度学习的热点一过,你很可能无法适应企业和市场对AI的新的需求。

本文介绍了传统人工智能要解决的三大问题:问题求解、博弈和谓词逻辑。它们都是基于符号推理和白盒推理的。了解相应的解决方案和算法有助于算法工程师开拓眼界,加深对算法本质的理解,增加解决问题、适应未来需求的能力。

1.传统人工智能的三大问题

人工智能包括传统人工智能和现代人工智能两部分。机器学习、深度学习、遗传算法和强化学习是现代人工智能的主要分支。他们主要解决分类、回归、聚类、关联和生成等问题。而传统人工智能主要解决问题求解、博弈和谓词逻辑三大问题。

传统人工智能之所以重要是因为:

传统人工智能的算法比较成熟、可靠、有效。很多能够用传统人工智能解决的问题就不应该使用复杂且成本高昂的现代人工智能方法。比如求上海到北京之间的最短路径问题,用A*算法就要比深度神经元网络高效得多;传统人工智能更基础。很多应用场景中,现代人工智能方法必须在传统人工智能基础上发挥作用。比如战胜围棋世界冠军李世石的AlphaGo其基础部分仍然是博弈算法,而残差神经元网络(深度学习技术之一)只不过在评价棋局优劣时发挥了作用。作为一个算法工程师,如果你只懂深度学习不懂博弈算法,是很难编写出高效的围棋程序的;深度学习是基于黑盒推理的,往往知其然而不知其所以然。也就是说,它能解决问题,但是我们不知道它为什么能解决问题。而传统人工智能的各种算法一般都是基于白盒推理的,知其然更知其所以然;更重要的是,我们不能以“有没有用”为标准来评价传统人工智能。就像数学中某些当时看来“没有用”的理论和方法一样,当它“有用”时你再去研究它就迟了。2.问题求解2.1状态和状态转化

这里的问题是指可以用状态来描述的,且起始状态和终止状态明确的问题。比如,八数码问题的一个可能的起始状态如下图所示:

 在一个3*3的网格中随机放置了1-8八个数码。其中有一个网格是空着的。这个空网格可以跟上下左右四个方向的任何一个临近的数码交换。但不能跟斜方向上的数码交换。比如上图中空网格可以和右边的那个数码3相交换,得到的子状态就是: 

八数码问题就是研究如何用最少的次数移动空网格,从而使得八个数码最终呈现出如下所示的终止状态:

 

2.2搜索树

问题求解的一个最简单的方法就是构造搜索树。方法是:

把初始状态看成是根结点,构成仅含有一个结点的搜索树T;任选T中的一个候选结点a,把它的所有可能的子结点都挂在a之下。这个过程称为对a的扩展。所谓候选结点就是没有被扩展过的结点;不断重复2)直到找到终止状态,或者没有候选结点为止。

下图就是一个搜索树的例子(其中排除了重复的结点)。尽管上述算法并不能保证给出最少移动次数,甚至我们都不能保证它一定能终止(如果我们不排除重复结点的话),但是它仍然给出了问题求解算法的最基本框架。问题求解的各种算法(比如宽度优先、深度优先、爬山法、分支定界法和A*算法等)就是在这个框架基础上按照不同思路进行优化的结果。

比如宽度优先搜索,就是在算法的第2)步选择距离根结点最近的候选结点优先扩展。这个方法找到的第一个解一定也是最优解。所谓解就是从根结点到终止结点的一个路径。

所谓分支定界法就是在找到一个解之后,就把这个解的路径长度与以前找到的解的路径长度相比较,只保留路径短的那个。以后我们在扩展任何一个结点时,都要看看当前路径的长度是否短于解的路径长度。如果回答是“否“,则当前这个结点就没有必要扩展下去了。

至于其他更高明的算法,比如A*,这里就不再赘述。感兴趣的同学请关注方老师博客http://fanglin.blog.csdn.net。

与八数码问题类似的著名问题还有:

华容道问题:见上图,一个4*5的棋盘上有曹操、卒、马云、......大小不同的棋子。4个卒的大小都是1*1,黄忠、赵云、张飞和马超的大小是1*2,关羽的大小是2*1,曹操最大,大小是2*2。棋盘上还有两个1*1的空格以便棋子移动。游戏的目的是把曹操移到下方关口位置处,从而逃出华容道;八皇后问题:在8*8的国际象棋棋盘上(见下图)如何放置八个皇后使得任意两个皇后都不在同一行、同一列或者同一斜线上;求两个城市之间的最短路径问题;背包问题:给定有限个物品以及每个物品的重量以及价值,比如罐头200克6元,手机125克5000元,等等。另外再给你一个最大负重为2000克的背包。问在不超过最大负重的情况下应该在背包中放置哪些物品从而获得最大的价值?路径规划问题,怎样规划一个或者多个快递小哥的路径使得他们跑最少的路把一堆快递送到客户手中。这个问题还可以扩展到物流规划、船舶航运规划上。

 八皇后问题

 解决这些问题的关键在于如何描述问题的状态以及父状态如何生成子状态。比如最短路径问题中,状态就可以用当前所在的城市表示。城市与城市之间有道路直接连通的就可以构成父子状态的转换。由于道路一般是双向的,则父子状态的转换也是双向的。

而背包问题的状态可以用背包里当前所拥有的所有物品的集合表示。所谓子状态就是往父状态背包里添加任意一个不超重的物品构成的。

3.博弈3.1博弈树

我们通常所说的博弈其实是博弈的最简单形式,即信息全透明的封闭环境下的两人零和博弈。围棋、象棋、国际象棋等都是这样的博弈。而扑克、麻将、多人跳棋等就不是。以下除非特指,所谓博弈都是指这种两人零和博弈。

博弈要解决的问题是:当人类棋手下一步棋之后,电脑该如何应对呢?跟搜索树一样,博弈所采用算法也是从当前的根结点出发构建博弈树。以井字棋为例,井字棋是一种两人轮流在一个3*3的棋盘上下棋的游戏。目的是看谁先把自己的棋连成了一行、一列或者一条斜线。与中国的五子棋类似。以下是井字棋博弈树的部分结构:

井字棋的博弈树  

与搜索树不同的是:

博弈树在扩展过程中,是双方轮流下棋的。而搜索树无需这样的考虑;搜索树通常要考虑从根结点到当前结点的耗费,而A*算法甚至还要考虑从当前结点到可能的终止结点的预期耗费。耗费越小越好。而博弈树通常只考虑当前状态对双方的价值。价值越大越好,价值也称为得分。得分可以小于0(这表示对对方有利);由于我们考虑的仅仅是两人零和博弈,所以当一个状态对一方的价值(或者说得分)是v的话,则同一个状态对另一方的价值就是-v;如果某个状态下,当前走棋的一方已经获胜的话(比如井字棋中己方有三个棋子已经连成一条线),则他的得分就是正无穷大或接近无穷大,而另一方的得分就是负无穷大或接近负无穷大;由于结点的数目会呈几何指数增加,所以博弈树和搜索树一样,都要解决组合爆炸问题。3.2简单博弈算法

简单博弈算法主要思想是:

博弈树上所有结点的得分都相对于当前下棋的一方计算。正得分表示对他有利,负得分表示对对方有利;采用深度优先方法扩展候选结点。也就是说,优先扩展离根结点远的结点;为了避免组合爆炸,当博弈树的高度达到一定高度h时,就停止扩展。此时当前结点的得分采用估算法或者深度学习方法获得。这个问题下面还要谈;当一个结点的所有子结点的得分都确定之后,就可以确定该结点的得分。结点的得分总是等于所有子结点得分中最大得分的相反数。比如,假设所有子结点的得分分别是-3,12,7,-10,则当前结点的得分就是-12。这是因为,博弈算法假设对方是理性的,总是会走对他自己最有利的一步棋。而这一步的得分如果是v的话,对当前下棋的一方就是-v。因为是两人零和博弈嘛!有意思的是,这个方法也可以用来计算当前结点的父结点的得分。包括当前结点在内的所有兄弟节点中最大得分的相反数就是父结点的得分。所谓兄弟结点就是父结点相同的结点。这个过程可以不断地向上传播直到根结点;根结点的所有子结点中得分最大的那个就是计算机的解。

假设下图是一个限高4层的博弈树,其中所有叶子结点的得分都已经估算出来了:

 

    博弈树(叶子结点的得分已被估算出来)

我们的问题是:A、B、C三个结点中,电脑会选择哪个下棋呢?我们只需沿着叶子结点向上,一层一层计算各个结点的得分即可。记住:每个非叶子结点的得分等于其所有子结点中最大得分的相反数。下面是计算结果:

从叶子结点出发向上一层层计算得分 

根据上述结果我们显然知道,电脑应该选择结点A作为自己的应对。

3.3估算得分

可能有人会问,我怎么估算结点的得分呢?这要看你们下的是什么棋。如果是井字棋,一般来说正中间的那个位置特别重要,谁占据了那个位置应该给谁高分。给多少分您就自己看着办吧。如果是象棋,可以计算一下双方的剩余棋力,比如“车”给100分,“兵”给1分。然后以双方的棋力差作为得分。这个方法没有考虑棋子的位置。其他棋类游戏都可以以此类推。

值得一提的是,深度学习方法可以在估算得分时发挥重要作用。AlphaGo等就是采用这个方法解决了围棋的组合爆炸问题。由于这个问题比较复杂,并且超出了本文的讨论范围,这里不再赘述。有兴趣的读者可以参考我以后的文章。

3.4Alpha-Beta剪裁

绝大多数博弈游戏都面临组合爆炸问题。即随着结点的指数级扩展,博弈树的规模很快就达到天文数字。围棋的博弈程序就是基于这个原因才长期得不到解决直到引入深度学习方法。

Alpha-Beta剪裁算法可以部分地解决这个问题。它的核心思想就是:如果当前结点的某个兄弟结点的得分是v,则当前结点的所有子结点的得分都必须小于-v。只要其中有一个子结点的得分大于或者等于-v,则当前结点及其以它为根结点的整个子树都可以从博弈树上删除。如下图:

 Alpha-Beta剪裁示例 

假设D的得分是4,E是D的兄弟结点。则E的子结点F和G的得分都必须小于-4。否则就应该把以E为根结点的子树从博弈树上删除。为什么呢?假设F的得分是-3,这意味着E和所有兄弟结点的最大得分至少是-3即:

max_value>=-3

前面我们讲过,E的得分应该等于-max_value。根据上面公式,我们得出E的得分必然小于等于3,从而小于D的得分4。这意味着我们根本就没有必要去扩展E的任何其他子结点了(比如G),因为即使扩展了G,E的得分也不会大于4。这就是Alpha-Beta剪裁的原理!

所以,使用Alpha-Beta剪裁算法时,博弈树的扩展常采用深度优先策略。这不仅更节省空间(因为没有必要保存整棵博弈树,只需把当前路径上的结点保存在一个堆栈中即可),更重要的是,深度优先策略有助于算法快速找到一个叶子结点,从而能把该结点的得分用来对相关结点进行剪裁。

关于Alpha-Beta剪裁的更多细节请关注方老师的博客。我在实践中使用这个方法实现了包括井字棋、五子棋、黑白棋等游戏的开发,证明了它的有效性。

4.谓词逻辑4.1命题、谓词和规则

谓词逻辑主要研究如何进行逻辑推理。逻辑推理的基础是事实和规则。“张三和李四是朋友”,“太阳总是从东方升起”等就是事实。事实在谓词逻辑中是以命题的形式给出的。比如上述两个事实对应的命题分别是:

Is_Friend(“张三”,“李四”)

Rise_From(“Sun”,”Oriental”)

这里Is_Friends和Rise_From就是谓词,双引号扩起来的是字符串型逻辑常量。

规则形如:

If 条件 then 结论

其中条件和结论都是命题。比如:

IfIs_Friend(X,Y)thenIs_Friend(Y,X)

这个规则的含义是:如果X是Y的朋友,那么Y也是X的朋友。言下之意:朋友是相互的,不存在X是Y的朋友而Y却不是X朋友的情况。其中X和Y都是逻辑变量。

4.2逻辑运算和复合命题

两个谓词之间可以用“and”或者“or”连接,分别表示“与”运算和“或”运算。比如,Is_Father(X,Y)andIs_Father(Y,Z)表示X是Y的父亲,Y是Z的父亲。这样由多个命题经过逻辑运算构成的命题称为复合命题。。

第三个逻辑运算是“not”,表示逻辑“非”操作。它是一个一元运算符。含义自明。

这样我们就可以用复合命题构成复杂的规则。比如:

IfIs_Father(X,Y)andIs_Father(Y,Z)thenIs_Grandpa(X,Z)

这个规则的意思是说:如果X是Y的父亲,Y是Z的父亲,则X是Z的爷爷。

4.3自动逻辑推理

当我们把已知的命题和规则罗列在一起时,就能进行逻辑推理。逻辑推理的方法主要有两种,第一种是著名的三段式。比如,所有的猫都是哺乳动物,凯蒂是一只猫,所以凯蒂是哺乳动物。

第二种是利用规则进行反向推导。比如,假设我们想知道Tom的爷爷是谁。这实际上是求解命题Is_Grandpa(X, “Tom”)中X的值。怎么做呢?首先我们可以寻找所有结论是谓词Is_Grandpa的规则,这样的规则目前只有一条那就是:

IfIs_Father(X,Y)andIs_Father(Y,Z)thenIs_Grandpa(X,Z)

然后把Z=“Tom”代入其条件部分,则原命题Is_Grandpa(X, “Tom”)被替换为求解两个命题:

Is_Father(X,Y)andIs_Father(Y,“Tom”)

而求解这两个命题的方法是递归地调用上述步骤,直到所有命题都可以用三段式解决为止。

我们可以开发一个系统自动完成上述推理过程,这就是自动推理系统。事实上逻辑程序设计语言Prolog就是干这事的。如果你想自己开发一个这样的自动逻辑推理系统,你一定要注意:满足当前命题的规则可能不止一个,你应该在找到第一个答案前把所有可能的路径都走一遍而不是一旦一条路径走不通就下结论说原命题不成立。

递归显然不能满足这个要求,所以自动推理系统通常采用的是回溯法。如果你对如何构建自动推理系统感兴趣,请关注我以后的文章。

4.4高阶谓词逻辑

我们前面所说的谓词逻辑实际是一阶谓词逻辑,也就是说,谓词的参数要么是变量,要么是常量。如果谓词的参数也是谓词,则这样的谓词就是二阶谓词。这已经超出了本文的讨论范围,本文不再赘述。

4.5谓词逻辑的应用

谓词逻辑特别适合构建基于规则的专家系统、决策支持系统和规则系统。这与深度学习基于大量样本的黑盒推理完全不同。深度学习是从特殊(的样本)出发归纳出一般性的结论,谓词逻辑则是从一般性的规则出发推导出特殊情况下的结论,这是两个截然相反的过程。人脑就是这两个过程的完美结合体。

5.结束语

本文简单介绍了传统人工智能的问题求解、博弈和谓词逻辑,目的是帮助非计算机专业的算法工程师开拓眼界增加认知的。要想了解更多的详情还需要你系统学习《人工智能》课程,或者关注我的博客。

人工智能大作业

基于搜索策略的八数码问题求解

大作业题目:

基于搜索策略的八数码问题求解

大作业目的:

加深对搜索策略的理解,尤其是对启发式搜索的基本原理的理解,使学生能够通过编程实现图搜索的基本方法和启发式搜索算法,并能够解决一些应用问题。

 

大作业要求:

使用盲目搜索中的宽度优先搜索算法或者使用启发式搜索中的全局择优搜索或A*算法。每人提交一份大作业报告,该报告包括设计、实现、测试、实验对比结果分析、结论、个人体会与总结,具体见格式要求。大作业程序需验收通过。

大作业提交内容:课程大作业纸质报告1份;将课程大作业电子报告和课程大作业程序及代码压缩包提交至网络教学综合平台。

大作业提交截止时间:以网络教学综合平台中的截止时间为准。

对任意的八数码问题,给出求解结果。例如:对于如下具体八数码问题:

 

 

1

3

2

 

 

 

1

2

3

4

 

5

8

 

4

6

7

8

 

 

 

7

6

5

 

 

通过设计启发函数,编程实现求解过程,如果问题有解,给出数码移动过程,否则,报告问题无解。

250123

873804

641765

求解步骤:

步骤一.设计八数码格局的隐式存储的节点结构:

将表示棋局的状态用如下向量表示:

A=(X0,X1,X2,X3,X4,X5,X6,X7,X8)

约束条件:Xi{0,1,2,3,4,5,6,7,8}

XiXj,当ij时。

初始状态:S0=(1,3,2,4,0,5,6,7,8)

目标状态:Sg=(1,2,3,8,0,4,7,6,5)

步骤二.计算两个节点之间的可达性。

(1)可以通过限定时间阈值或步骤阈值,判定两个节点之间的可达性。

(2)通过计算八数码节点的逆序数判断。如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。计算八数码节点的逆序数时将代表空格的0去除,如初始状态排列为

(1,3,2,4,5,6,7,8)逆序数为:0+1+0+0+0+0+0+0=1即为奇排列

目标状态排列为(1,2,3,8,4,7,6,5)逆序数为:0+0+0+4+0+2+1+0=7即为奇排列,具有同奇或同偶排列的八数码才能移动可达,否则不可达。

步骤三. 设计估计函数与启发函数,估计函数f(n)定义为:f(n)=d(n)+h(n)其中,d(n)表示节点深度。

启发函数h(n)可参考如下定义方法:

(1)启发函数h(n)定义为当前节点与目标节点差异的度量:即当前节点与目标节点格局相比,位置不符的数字个数。

(2)启发函数h(n)定义为当前节点与目标节点距离的度量:当前节点与目标节点格局相比,位置不符的数字移动到目标节点中对应位置的最短距离之和。

启发函数可参考如下定义方法:

(3)启发函数h(n)定义为每一对逆序数字乘以一个倍数。

(4)为克服了仅计算数字逆序数字数目策略的局限,启发函数h(n)定义为位置不符数字个数的总和与3倍数字逆序数目相加。

步骤四.选择并设计搜索算法(至少选择1个)

(1)使用盲目搜索中的宽度优先搜索算法。

(2)使用启发式搜索中的全局择优搜索算法。

(3)使用A*算法。

步骤五 设计输入输出

输入:初始节点,目标节点格式:132405678

123804765

可采取以下三种方式输入:命令行、文件start.txt、GUI输入。

输出:如果无解在屏幕输出"目标状态不可达"

如果有解请在屏幕输出"最少移动n步到达目标状态",n为最少移动的步骤数,并记录从初始状态到目标状态的每一步中间状态,并将这些状态保存至result.txt文件中。

以上过程可采取以下三种方式输出:命令行、文件result.txt、GUI输出。

步骤六 编写代码,调试程序。

至少给出5组初始节点和目标节点对,并记录程序运算结果。节点对要包括以下三种情况:不可达;最少移动步骤数≥10;最少移动步骤数≤6

 

 

拓展实验:(可任选1个完成)

1.记录步骤四中3个搜索算法的执行时间,并比较3者的效率。

2.在启发式搜索中,分别采用步骤三中启发式函数(1)(2)(3)(4),并比较四者的效率,思考如何进一步改进启发式函数。

3.试分析在所有可能的初始状态和目标状态之间最长的最小移动步骤数是多少?

 

 

我准备采用A*算法来解决这个问题,拓展实验选的是2

作者水平有限,如有问题,欢迎留言交流

 

PS:笔者一开始觉得第一个太麻烦,要写三个算法。而且当时对全局择优算法和A*算法的差别并没有太明显的认知,后来知道了,虽然在选择扩展OPEN结点时,全局择优和A*都是选择Open表中F值小的那一个,但是A*有一个查重过程(即查找即将扩展的结点是否在open表或者closed表中已经存在过),全局择优算法并无这个查重过程。这个查重过程的意义在于,同一个状态序列可能通过多个路径到达的,在F=G+H这个启发函数中,G是结点拓展深度,H是当前序列到目标序列的评估函数,所以对于同样的排列,H肯定是相同的,只是G不同罢了。所以在全局择优算法中,closed表中可能有两个结点的序列state相同,但是f不同,但是A*算法中closed表不会存在两个结点的state序列相同。

一、知识准备 1.1何为A*算法

    A*算法是对启发式算法A算法的一种改进,启发式算法,就是给每一种子状态一个F=G+H的函数评估,取F值小的(到目标路径代价最小的路径值)的一种情况进行拓展。这里的F是单调函数

    启发式算法是对盲目搜索策略算法的一种改进,能够大幅提高搜索效率,但是关键在于启发式函数的选择,这一点跟剪枝法中剪枝函数的选择有些类似的思想。

介绍A算法,需要引入两个重要概念,open表和close表

 1.2何为open、close表?

  open表:记录已经生成但未扩展的状态,open表中状态的排列顺序至关重要,默认先从表头选择状态扩展

  close表:记录已经扩展过的状态(应该还包含路径)

     根据书上的定义,在深度优先和广度优先的遍历中,也引入了open表和close表,在不同的搜索策略中,open表的结构是不同的。在深度优先中,open表是一个先进后出的堆栈(说白了,就是对子状态按生成次序排列后,插入到open表头,与编译原理里面LL算法中的预测分析法的堆栈结构还有所不同,后者是先生成的结点先进栈,这个是先生成一个次序,将次序放入表头)

    在A*算法中,open表是按照f值由小到大排序的表,比较特殊。

二、编程思路:

    我不喜欢直接贴上代码,因为学习代码就是一个学习思路的过程,编程重在思考,学习别人的思路和思考问题的方式。

  2.1 根据要求解的问题特征、定义一个新的基础元素结构体   

     首先这个A*问题是一个比较复杂的算法实现问题,应该定义一个新的结构体来作为基础元素

    基础元素应该包含一个3*3的矩阵(八数码的排列形式),而且这个矩阵还要能查到它的前驱路径,对于前驱这个概念,学过数据结构的应该都不陌生,二叉树就有父节点、子节点的概念,所以对基础元素的定义里面,应该也有childparent结点这些元素,好了,现在可以确定三个因素了:3*3矩阵、child结点、parent结点。还有一点就是启发函数F=G+H的因素,上文也提到了,对于相同的状态序列,它的H值肯定相同,G值可能有所不同(主要是通过不路径到达的,路径深度不同),那么也应该包含G和H这两个元素,F值要不要包含进去呢?因为F=G+H,我认为结构体冗余,F最好不要加进去。现在一个状态序列由:3*3的矩阵序列、child、parent、G、H这5个因素唯一确定了,其中child和parent代表了它的路径存储信息,应该也是要求中请求的。

    题目中要求输出从初始状态到目标状态的路径过程(实际上就是一个动态规划问题),在初始结构体定义中,child和parent是寻找路径时候要用到的,这个问题是从初始状态到目标状态的路径,如果最后我们输出最佳路径的时候,还是从初始状态开始找,找它的child结点,那肯定会有许多无用查找,因为有很多child结点最终不会生成目标状态。因此,输出最佳路径的时候,应该从生成的最后路径往前倒推,后序遍历得到结果(与动态规划的问题不谋而合)。这样在搜索过程中,只需要用到parent结点就可以了,child结点就失去了它存在的意义,故舍弃(因为我要解决的问题,不关心哪个路径是哪个路径的child,指关心哪个路径是哪个路径的pre,如果一个八数码问题有解,这个解的路径的起始点和终止点是已经确定的)

    继续深入,在二叉树的学习中,child值应该是唯一确定的,它不应该是指一个结点的data值,而是它的下标(即唯一标识确定的),那么在我们已经定义的四个元素里面,3*3矩阵、G、H、parent可以唯一标识一个结点吗?(这个问题类似于数据库中的候选码的定义问题)显然,parent是指向它的父的标识值,这个标识值如果是这四个元素组合值(3*3,G,H,pre)确实可以唯一确定,但显然有些复杂了。不如对每一个生成的结点,都给它从0,1,2,3,4……这样编个序号,这样pre值指向的是序号编码,也达到了唯一标识的作用。于是再引入一个新的元素,current,current的值是在新的基础元素放进open时,依次+1,作为序号,parent指向的是该路径的父节点的序号。

    这样初始结构体就应该有:3*3的矩阵序列(数字0-8排列,0代表空格)、G、H、current、parent。

    再看看这样的定义,满足搜索路径是满足了,那能不能满足open和closed表的存储过程呢?在新结点的生成过程中,肯定有空格(在八数码问题中用0代表)移动这一过程,这个结构体中,G、H、Current、parent都可以用int值,3*3是一个二维数组,为了方便作为传递参数,满足耦合性,可以用一个一维的数字序列来代表二维数组,之后进行解压即可,即:

   123

   456

   70 9 可以用123456709来代表,需要输出路径时进行解压操作即可了。(别问我怎么想到的,我是站在巨人的肩膀上知道的)

 2.2代码函数编辑

  那么,讲到这,结构体定义很好写了(不过这个不是完全体,后面会遇到具体问题,进一步完善)

StructSnode{intstate;//3*3的矩阵的一维数组表示intg;//遍历深度g值inth;//启发函数H值intcur;//当前结点的编号intpre;//当前结点的前驱结点的编号Snode(constintstate,intg,inth,intcur,intpre):state(state),g(g),h(h),cur(cur),pre(pre){};//对产生的新结构体的便捷赋初始值,与对类的初始化函数类似,是个小技巧};

    

顺手推舟,将一维数字的解压函数和返回F值的函数写出来:

typedefintArc[4][4];voidstate_toArc(intstate,Arcarc){for(inti=3;i>=1;i--)for(intj=3;j>=1;j++){arc[i][j]=state%10;state/=10;}}intF(constSnode&node)//为什么传递参数变量前选const,建议百度一下{returnnode.g+node.h;}

     typedef让int[4][4]变成一个新的变量名,也是处理二维数组作为形式参数的一个便捷方法,同学们可以学习一下。

    解决完基础的元素结构体的定义,那么接下来对这个基础元素的所有操作都在open和closed表上进行,那么接下来就是对open和closed表的定义了。在a*算法中,open表是按照f值(>0)从小到大排列,这不禁让人联想到STL容器中map,map是一个pair数据类型的容器,有值,并且按照key值从小到大排列,于是用map来存储open,close也可以使用map

    attention:map中明确定义,一个key值只能对应一个value值,但是在open表中,不同的Snode可能它们的f值相同,于是采用multimap来解决这个问题。

    考虑到后面有对open表的元素查重问题,即查找open表中的value值是否与生成结点相同,在map中查找value值,可以通过建立key-value的一一对应的value-key表(即把value值作为key值)来解决这个问题,map中直接查找key值要方便的多。但是由于value是一个Snode类型,在map的value-key查询key值时,需要比较大小,即比较Snode的大小,因此需要重载“"

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

上一篇

下一篇