书名:人工智能:现代方法(第4版)(上下册)
ISBN:978-7-115-59810-3
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [美] 斯图尔特•罗素(Stuart Russell) 彼得•诺维格(Peter Norvig)
译 张博雅 陈坤 田超 顾卓尔 吴凡 赵申剑
责任编辑 杨海玲
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
读者服务:
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
本书全面、深入地探讨了人工智能(AI)领域的理论和实践,以统一的风格将当今流行的人工智能思想和术语融合到引起广泛关注的应用中,真正做到理论和实践相结合。全书分7个部分,共28章,理论部分介绍了人工智能研究的主要理论和方法并追溯了两千多年前的相关思想,内容主要包括逻辑、概率和连续数学,感知、推理、学习和行动,公平、信任、社会公益和安全;实践部分完美地践行了“现代”理念,实际应用选择当下热度较高的微电子设备、机器人行星探测器、拥有几十亿用户的在线服务、AlphaZero、人形机器人、自动驾驶、人工智能辅助医疗等。
本书适合作为高等院校人工智能相关专业本科生和研究生的教材,也可以作为相关领域专业人员的参考书。
Authorized translation from the English language edition, entitled ARTIFICIAL INTELLIGENCE: A MODERN APPROACH, 4th Edition by RUSSELL, STUART; NORVIG, PETER, published by Pearson Education, Inc, Copyright © 2021, 2010, 2003 by Pearson Education, Inc. or its affiliates.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc.
CHINESE SIMPLIFIED language edition published by POSTS AND TELECOM PRESS CO., LTD., Copyright © 2022.
本书中文简体字版由Pearson Education Inc授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。
本书封面贴有Pearson Education(培生教育出版集团)激光防伪标签,无标签者不得销售。
版权所有,侵权必究。
献给洛伊、戈登、露西、乔治和艾萨克。——斯图尔特·罗素
献给克丽丝、伊莎贝拉和朱丽叶。——彼得·诺维格
(按姓氏拼音字母排序)
这是一本关于人工智能的百科全书,堪称人工智能教材的典范。本科时我曾在人工智能课上学过这本书的第3版。很多年过去了,深度学习给世界带来了惊喜,推动了自然语言处理、计算机视觉、机器人学的快速发展,也为社会带来了伦理、公平性和安全性的新挑战。我很欣喜地看到第4版引入了这些领域大量最新研究成果。如果你想了解人工智能的全貌,不要错过这本书。
阿斯顿·张(Aston Zhang)
亚马逊资深科学家
《动手学深度学习》作者、ICLR杰出论文奖
这是人工智能领域世界范围内最经典、最全面、最具影响力的教材,覆盖了人工智能领域所有重要子领域的核心问题、算法思想和现实应用。第4版加入了深度学习、多智能体系统、机器人、人工智能伦理等前沿领域的最新进展和挑战,更适合作为不同层次和领域的研究人员及学生的人工智能入门教材。
安波
新加坡南洋理工大学教授
这本书以智能体为主题思想,在统一的大框架下全面系统地阐述了人工智能的理论方法和技术。本书第4版内容丰富,资料翔实,理论结合实践,延续了作为人工智能领域国际经典教材的风范。同时,第4版也与时俱进,增加了包括深度学习在内的人工智能最新进展的内容,做到了经典与前沿并存,共展人工智能之魅力。
邓志鸿
北京大学智能学院教授
《人工智能:现代方法》是一本经典教材。“现代方法”选择从当下的角度讲述人工智能的故事,而贯穿全书的核心方法论是“智能体”。以计算机为载体的人工智能,揭开了机器智能大幕的一角,制造更复杂的机器,实现更强大的智能,机器智能将为科学研究创造无穷无尽的新对象。在这个意义上,智能是“科学的无尽疆域”,而人工智能这个“现代方法”,正是开疆拓土的动力之源。方法不止,智能无疆,“人工智能:现代方法”这个书名可以永远延续下去。
黄铁军
北京智源人工智能研究院院长
北京大学计算机学院教授
本书是享誉世界的人工智能经典教材,我在读博期间就学习过其第3版,内容全面翔实,介绍深入浅出,既是初学者理想的入门教材,也是人工智能从业者的案头参考书。很高兴这本书的第4版被译介到国内,新版增加了2010年以来深度学习等最新前沿技术动态,新章节的贡献者有朱迪亚·珀尔(Judea Pearl)和伊恩·古德费洛(Ian Goodfellow)等知名学者。期待这本新版教材更好地推动我国人工智能的发展。
刘知远
清华大学计算机科学与技术系长聘副教授
这是一本不可多得的全面介绍人工智能基本方法的教科书,自20世纪90年代中期出版以来,至今已经出版了4版,被全球很多大学作为教科书使用。本人曾经组织本组教师和学生翻译过这本书的第2版。本书最大的特点是系统性强,涉及人工智能的方方面面,是学习人工智能、全面了解人工智能的优秀教科书。
马少平
清华大学计算机科学与技术系教授
中国人工智能学会副监事长
中国中文信息学会副理事长
广义上讲,人类所发现的规律、提出的思想、发明的工具,都是人工智能的一部分,最终都是为了认识世界和改造世界。面对复杂的现实世界,人类智者长期苦苦探索,特别是第二次世界大战之后,产生了繁杂的规律、思想、工具。因此,对人类在人工智能方方面面的探索进行有效总结,形成百科全书式的教材,是一项非常必要且具有挑战性的工作。作者不仅需要深厚的学术素养,还需要宽广的学术视野,如果还有一流的文笔,那就更难得了。幸运的是,本书的作者,正是这样的学者。
毛先领
北京理工大学副教授
人工智能领域的特点是知识点散、前置知识多、技术迭代快,因此写一本全面深入的人工智能教材是一件很难的事。本书是人工智能领域的经典教材,全方位描述了人工智能的主要分支和技术方向,提供了人工智能领域的全景图。经过20多年的不断优化,目前本书已经是第4版。和第3版相比,本书增加了深度学习、人工智能伦理等近年来的热点研究内容,非常适合对人工智能技术感兴趣的读者阅读。强烈推荐!
邱锡鹏
复旦大学计算机科学技术学院教授
本书是在世界范围内广受欢迎的人工智能教材之一,其最鲜明的特点有二:第一,一卷在手,人工智能方方面面的主要知识被系统性地一网打尽,经典知识内容与前沿知识内容取舍剪裁别具匠心,深具章法,驾轻就熟,相得益彰,颇有一种“包藏人工智能宇宙之机,吞吐人工智能天地之志”的架势;第二,文字阐述深入浅出,言简意赅,旁征博引,详略得当,同时适合初学者以及在人工智能领域已有一定经验和造诣者这两大类人群阅读和学习,各取所需,甘之若饴。本书冠以人工智能的“现代方法”,可谓实至名归。特别是在以勃兴于2011年的深度学习模型为基本表征的人工智能走到山重水复、柳暗花明的当前形势下,其中的“现代”二字就显得更为重要。人们正呼唤着下一代人工智能新境界的到来。2022年10月,包括两位图灵奖得主约书亚·本吉奥(Yoshua Bengio)和杨立昆(Yann LeCun)在内的一批学者撰文提出了“具身图灵测试”的概念,强调机器系统与世界环境的具身交互研究是开拓下一代人工智能创新方法的关键要义,而这一点与本书从“智能体”的视角总揽全篇的前瞻性思路不谋而合。显然,深度学习远不能包打天下,复杂开放环境下智能任务的解决离不开多种理论、方法和技术手段在“具身智能”条件下的兼包并蓄、融会贯通,这就对人工智能研究者在知识结构体系上提出了更高的要求,而本书恰好具备能够满足这种要求缺一不可的广博性和深刻性。
孙茂松
清华大学计算机科学与技术系教授
清华大学人工智能研究院常务副院长
欧洲科学院外籍院士
在炒作和质疑声中,人工智能技术不断倔强而真实地成长。可以预见并且逐渐成为现实的是,智能化革命就如同当年的信息化革命一样,会给很多领域和行业带来革命性的变化。人工智能也从一门选修型前沿学科,逐渐演化成一门必修型基础学科。要了解人工智能,一本全面的人工智能教材必不可少,眼前的这本书出自名家,是一本享誉世界的经典教材,翻译质量也非常高。相信这本经典之作能带你踏入人工智能之门。
王斌
小米集团技术委员会主席、人工智能实验室主任
本书是人工智能的经典之作,覆盖启发式搜索、知识表示、统计机器学习、强化学习等模型和算法,为读者呈现领域全景图。人工智能涉及的知识门类广,而且各部分相对独立,作者凭借渊博的学识和对学科深入的理解,系统化编排各个知识点,提供了成体系的人工智能学习路径,实在是大师级的作品。更难能可贵的是,本书行文流畅、样例丰富,知识点还附带背景和拓展,作为课内外读物的阅读体验都很棒。
我个人与这本书也有很深的缘分。在学生时代,这是我学习人工智能的教材,带我入门。从教之后,我又以本书为教材讲授人工智能,反复翻看,常读常新。我从学生到老师,整个时间跨度超过十年,而这本书也出了新的版本。希望它可以陪伴更多读者探索人工智能的世界。
魏忠钰
复旦大学大数据学院长聘副教授
本书是继“西瓜书”和“花书”之后又一部大师之作。本书简称为AIMA,其历史其实更为久远,几乎可以认为是国际上关于人工智能的标准教材。两位作者斯图尔特·罗素和彼得·诺维格是打通学术和产业“任督二脉”的大师。相比于“花书”的作者,本书的两位作者可以被归类为“传统派”,他们认为机器智能并不一定要学习生物智能,机器可以通过更擅长的计算、更完美的数学模型以及大数据下的去模型化来实现智能。因此,在2009年出版第3版时,彼得·诺维格无法预测到近10年深度学习在诸多领域(特别是他擅长的自然语言处理、机器翻译)的快速进展,而作为强化学习的高手,斯图尔特·罗素也不会预想到深度强化学习在决策应用中的流光溢彩。第4版中融入了两位大师基于人工智能近10年最新进展的深度思考。同时,作者也是人工智能伦理和哲学的思想家,他们在最后一章中回答了人工智能未来走向和关乎人类命运的几乎所有问题。这是一本大部头的书,若能日拱一卒,势必功不唐捐。
吴甘沙
驭势科技董事长/CEO
这本书长期以来都是美国大部分知名大学人工智能课程的教科书,今天也已经被全世界1500多所大学采用为教材,其内容覆盖了到每一版出版时为止世界人工智能的主流技术和方法。说它权威,是因为这本书是几乎所有人工智能从业者的参考书,但凡人们对某些人工智能的概念发生争议时,就会以这本书的讲述为准。
这本书版本更新的过程与人工智能的发展过程是相一致的。通过这本书,读者不仅能够掌握与人工智能相关的理论和技术,还能把握人工智能发展的规律。因此,这是一本适合各类人群的专业好书。
吴军
人工智能专家、畅销书作家
人工智能与计算机技术几乎同时起步,但与计算机技术几乎线性的发展路径不同,人工智能的发展路径经历了几次大的转向,目前越来越依赖于数据科学和高性能计算机器的发展,因而知识和技术覆盖范围非常广泛。作为一本经典教材,本书提纲挈领,像百科全书一样涵盖了人工智能的大部分领域,每章几乎都对应了一个人工智能问题或技术分支,甚至可以单独成为一门课程。本书的特色是不纠缠于技术和工程细节,直击问题的本质和方法的底层逻辑,在帮助读者形成人工智能领域知识的整体大框架的基础上,增强读者对人工智能基础问题和技术方法的理解和进一步学习的能力。
肖睿
北大青鸟研究院院长
课工场创始人
这是一本教材,但不是传统意义上的教材,它用现代思想凸显人工智能及相关工作的发展脉络,用“智能体”贯穿全书知识点的诠释,各章内容自然衔接,易于理解与掌握。
这不仅是一本教材,还是一本“大”百科全书,它全方位探讨了人工智能领域的方方面面,涵盖了从基础知识、模型方法、工具技术、社会伦理到应用专题等各个层面,是一本人工智能的高级工具书。
这是一本面向人工智能大领域的“大”书,作者也是大学者,连译者都是大学者领衔的团队,堪称经典之作,非常值得初学者、从业者、教师及科研工作者等专业人员阅读。
俞勇
上海交通大学特聘教授
上海交通大学ACM班创始人
首批“国家高层次人才特殊支持计划”教学名师
人工智能是一个大领域,该书是一本“大”书,作者是大学者。该书全方位探究了人工智能这一领域,涵盖了从基础知识、模型方法、社会伦理到应用专题等各个层面。正如作者在前言中所提到的,本版中约25%的内容是全新的,剩下的75%也做了大量修改,以呈现出更加完整的人工智能领域图景,且本版中22%的参考文献是2010年以后发布的。此外,作者邀请了9位相关方向最有代表性的学者撰写了部分内容……此外,书中还讨论了人工智能面临的哲学、伦理和安全等社会问题。书中也蕴含了作者对人工智能的理解和思考,处处闪烁着思想的光辉,耐人回味……我本人在阅读时受到的启发良多,获益颇丰。
张志华
北京大学数学科学学院教授
本书可谓是一流学者撰写一流教材的典范,作者是国际人工智能领域知名专家、ACM/AAAI会士、曾获IJCAI卓越研究奖、AAAI费根鲍姆奖、AAAI/EAAI杰出教育家奖、ACM杰出教育家奖等荣誉,自1995年第1版出版以来,已被全球1500多所大学用作人工智能入门教科书。人民邮电出版社隆重推出第4版中文版,无疑是中文读者的福音。
周志华
南京大学计算机科学与技术系主任兼人工智能学院院长
ACM/AAAI会士
欧洲科学院外籍院士
斯图尔特·罗素教授和彼得·诺维格博士的《人工智能:现代方法》一书,是美国最为经典、最具权威性的大学教科书。说它经典,是因为这本书长期以来都是美国大部分知名大学人工智能课程的教科书,今天也已经被全世界1500多所大学采用为教材,其内容覆盖了到每一版出版时为止世界人工智能的主流技术和方法。说它权威,是因为这本书是几乎所有人工智能从业者的参考书,但凡人们对某些人工智能的概念发生争议时,就会以这本书的讲述为准。
2002年,我有幸成为诺维格博士的下属,先后在谷歌公司的搜索部门以及研究部门从事与机器学习相关的工作。诺维格博士是作为人工智能专家和科技管理者,被谷歌公司请来负责研发工作的。在我和他共事的十多年里,我们在研究工作中和私底下有很多交流。诺维格博士是一个卓有远见的管理者,也是一名基础极为扎实的技术专家。他并没有因为繁忙的管理工作而放松对新技术的学习和研究。
罗素教授是诺维格博士的同事和朋友,他一直活跃在人工智能学术研究的第一线,并曾经担任加利福尼亚大学伯克利分校计算机系主任。罗素教授的研究横跨人工智能的很多领域,包括机器学习、统计模型、知识表示、实时决策、计算机视觉,以及近年来比较热门的强化学习。
可以讲,这两位作者是近20年来世界人工智能领域最权威的学者,他们每过一段时间都会更新这本已经非常畅销的教科书,将最新的研究成果和理论方法增补进去。而我有幸见证了他们每一次版本升级的过程。
《人工智能:现代方法》的第1版出版于1995年,当时虽然已经有了基于数据的方法,但是从20世纪60年代到20世纪80年代,传统的人工智能方法依然在学术界占主导地位。因此本书第1版的主要内容只包含了这次出版的第4版的第二部分和第三部分,即智能问题的求解和有关知识表示与推理的部分。20世纪90年代其实是人工智能发展的转折点,传统的基于规则和推理的人工智能发展走到了今天,数据驱动的人工智能方法变得越来越重要。因此,在2003年,两位作者更新了这本书,加入了与统计有关的内容,即这次出版的第4版的第四部分和第五部分。在21世纪的前10年,人工智能中的机器学习、自然语言处理和计算机视觉三个领域发展迅猛,因此,几年后,诺维格和罗素决定再次更新升级这本书。在那几年里,诺维格博士和我们这些一线的研究人员有着密切的沟通和讨论,而罗素教授一直在伯克利教学和做科研,因此他们掌握着最新的人工智能发展动态。但是,由于当时他们都在各自的机构担任要职,非常繁忙,写书的事情一拖再拖。最后,诺维格博士为了专心写书,申请了三个月的学术休假,在远离喧嚣的加拉帕戈斯群岛专心写作。两位作者最终在2009年完成了本书的第3版,第3版加入了当时全世界最新的人工智能研究成果,并且构建了这本书今天的结构。
进入21世纪的第二个十年,人工智能的发展进入到一个黄金期。人工智能以大数据、深度学习、增强学习为基础方法,在很多领域取得了重大突破,不仅解决了众多科研问题,还将数据挖掘、计算机视觉、自然语言处理、机器人、机器学习等技术应用到了更广泛的领域。这期间,诺维格博士也不再承担谷歌公司的管理工作,他在大学里潜心教学,和罗素教授一道,把他们在课堂上所讲授的人工智能的前沿知识增加到现在的第4版中,同时他们在全书的第一部分和最后一部分加入了关于对人工智能历史和全貌的详细描述,以及他们对人工智能社会意义的理解。虽然从结构上看,第3版和第4版相差不大,但是第4版增加了大约四分之一的新内容,特别是与深度学习和强化学习有关的内容。同时,他们更新了之前版本中已有章节的部分内容,删除了一些过时的内容(主要是那些曾经使用过的,现在不再重要的人工智能方法和技术)。因此,可以讲目前这本书的第4版几乎涵盖了人工智能从业者需要了解的人工智能领域的所有基本内容。对比第1版,第4版的厚度几乎是它的两倍。
由于这是一本近千页的“巨著”,内容非常多,信息量极大,不同的读者在阅读这本书时可能需要采用不同的方式。第一类读者应该是正在从事人工智能研究的人,包括高校的研究生、教师和公司里的研究人员。我建议这一类读者从头到尾认真阅读每一章,如果有必要,还需要阅读其中一些参考文献,这样才能对人工智能有完整的、深刻的理解。第二类读者是大学的本科生。他们应该在任课老师的指导下系统阅读每一部分中的重点内容。相比较而言,从第四部分开始的内容更新也更重要,需要重点阅读,当然第一部分是对人工智能的全面描述,对每一个人了解这个领域大有裨益。第三类读者是已经对人工智能有了一定了解,在工作中需要用到人工智能技术的人,如公司里的工程师或者做研究的博士生。他们可以把这本书作为参考书阅读,用到哪一部分内容直接阅读即可。这本书的好处是,每一部分,甚至每一章都相对独立,跳过前面的内容不影响阅读后面的内容。当然,如果还有一些非计算机专业的读者对人工智能感兴趣,重点阅读第一部分和最后一部分就好了。如果这些读者依然有兴趣阅读全书也是没有问题的,因为这本书语言浅显易懂,逻辑性强,并不需要读者具有很强的技术背景,大家只要跟随作者的思路从每一章的开始阅读即可。如果遇到不懂的地方,可以直接跳过去。相比书中的一些公式和算法,更重要的是读懂书中的概念,并且了解每一种方法的来龙去脉。
《人工智能:现代方法》一书版本更新的过程与人工智能的发展过程是相一致的。通过这本书,读者不仅能够掌握与人工智能相关的理论和技术,还能把握人工智能发展的规律。因此,这是一本适合各类人群的专业好书。
吴军
2022年11月于巴尔的摩
《人工智能:现代方法》是一本经典教材。我和作者斯图尔特·罗素教授相识,和译者团队的张志华教授相熟,特别高兴为最新中文版写几句话。
书名中的“现代方法”,罗素教授的标准解释是“选择从当下的角度讲述人工智能的故事”。从初版到现在的第4版,确实如此。比如,这一版的第五部分“机器学习”就重点介绍了过去十年的热点,特别是深度学习和强化学习,如果再加上第六部分“沟通、感知和行动”中的自然语言处理、计算机视觉和机器人学,这两部分似乎就是“现代”人工智能的全部,为什么还要前面四个部分呢?
要回答这个问题,需要对“现代方法”做另一个层次的解读,这关乎人工智能这门学科的性质。
我认为,人工智能首先是一门技术,和计算机、互联网等技术类似,不同于物理学和生命科学那样的科学。科学是寻求事物和现象背后的规律,例如揭示宇宙奥秘的万有引力定律、相对论和量子力学,揭示生命奥秘的进化论和基因。技术是创造新事物和新现象,例如以指南针为代表的中国四大发明,以飞机和计算机为代表的现代技术。
技术发明和科学发现是两种独立的原始创新活动,把科学视为技术的基础,这是偏见。有些技术确实是基于既有科学原理,例如原子弹是核物理发展到一定阶段的产物,但原理只提供了可能性,没有链式反应和内爆技术等一系列技术发明,原子弹不会成为必然。有些技术并不基于科学原理,例如计算机的基础是图灵可计算理论,这是“人工”理论。更多技术在发明时并不明白背后的原理,例如指南针发明时并无电磁学,飞机发明时并无空气动力学。人工智能也一样,深度学习成功应用后,可解释性成为热点,至今理论还在探索中。如果没有深度学习的发明和实践,可解释性理论又从何而来呢?
人工智能研究是应该寻求理论基础,还是应该探索实现更强智能的新方法?两者都该做,但后者是主旋律:先有方法和实现,后有理论解释,先有智能技术,后有智能科学,如此迭代发展。智能技术无止境,智能科学也无止境,可以有解释现有人工智能的专门理论,没有指导未来人工智能的通用理论。
经典人工智能时代,我国的最大贡献是机器定理证明的“吴方法”。吴方法提出前一年,吴文俊院士曾撰文指出:“西方数学史家往往以希腊式的严密推理相标榜,并以中国数学从来没有达到演绎科学的形式相指责。然而, 我们已经看到, 在微积分的发明上希腊形式的那种脆弱性以及与之相较中国式数学的生命力。”后来,他更明确地指出:“它(中国数学)重视计算,是计算性,构造性,也是算法性的。大部分的重要结果都以‘术’的形式表示,而‘术’通常相当于现代的算法。”算法不是数学推理,而是人构造问题解决方案,就是方法。
从探索实现智能的方法论角度看这本书,就容易看出“大而有序”:第二部分“问题求解”是人在设计搜索、博弈和约束满足问题的解决方案;第三部分“知识、推理和规划”是人定义逻辑推理、人整理知识以及人设计的“自动规划”;第四部分“不确定知识和不确定推理”引入了不确定性和概率方法,以实现更强智能,但所有智能仍然是人设计决定的;第五部分“机器学习”,人类后退一步,只设计学习方法,让机器自己“学习”,特别是强化学习,只定义基本规则,智能主要来自与环境的交互,智能实现重大跃升。然而,深度学习和强化学习虽然更强大,但学到的知识是隐式的,获得的智能不可解释,要打开机器学习的“黑盒”,还需要前四部分的传统方法,当然也可能需要探索全新方法。就此而言,没有比“现代方法”更好的词来概括这本书了。
贯穿全书的核心方法论是“智能体”。罗素教授把人工智能定义为“对从环境中接受感知并执行行动的智能体的研究”。这个概念稍加扩展,就既能概括以机器为载体的人工智能,也能概括以有机体为载体的生物智能——生物就是感知环境并适应环境的有机智能体。更一般地,我认为“智能是系统通过获取和加工信息而获得的一种能力,从而实现从简单到复杂的演化”,这当然也同时涵盖了生物智能和机器智能。
在自然界已知的事物和现象中,人和人脑是最复杂的系统,人类智能是最复杂的现象,因此,脑科学被视为“自然科学的最后疆域”。然而,没有理由相信,人类是生物进化的最后阶段,人类智能是最高水平的智能,有机体是智能的唯一载体。以计算机为载体的人工智能,揭开了机器智能大幕的一角,制造更复杂的机器,实现更强大的智能,机器智能将为科学研究创造无穷无尽的新对象。在这个意义上,智能是“科学的无尽疆域”,而人工智能这个“现代方法”,正是开疆拓土的动力之源。
方法不止,智能无疆,“人工智能:现代方法”这个书名可以永远延续下去。
黄铁军
2022年10月15日
深度学习是机器学习最前沿的领域,它促进了人工智能技术产生了革命性进展,特别是给计算机视觉、语音识别、自然语言处理、棋牌游戏以及某些科学领域带来了颠覆性的突破。深度学习同时驱动了新的机器学习范式产生,比如生成对抗学习、元学习等;并使强化学习和因果学习得以“复兴”,展示更为强大的潜力。斯图尔特·罗素(Stuart Russell)和彼得·诺维格(Peter Norvig)两位教授的这本书在这一背景下于2021年年初出版正应其时。
人工智能是一个大领域,该书是一本“大”书,作者是大学者。该书全方位探究了人工智能这一领域,涵盖了从基础知识、模型方法、社会伦理到应用专题等各个层面。正如作者在前言中所提到的,本版中约25%的内容是全新的,剩下的75%也做了大量修改,以呈现出更加完整的人工智能领域图景,且本版中22%的参考文献是2010年以后发布的。此外,作者邀请了9位相关方向最有代表性的学者撰写了部分内容。本书主要包括5方面的内容:问题求解的搜索方法,基于知识的推理和规划方法(逻辑和知识表示),知识和推理中的不确定性(概率推理、概率编程和多智能体决策),机器学习(概率方法、深度学习和强化学习),应用专题(自然语言处理、计算机视觉和机器人学)。此外,书中还讨论了人工智能面临的哲学、伦理和安全等社会问题。书中也蕴含了作者对人工智能的理解和思考,处处闪烁着思想的光辉,耐人回味。比如,本版的封面展示了人工智能各个发展阶段的部分重要事件和人物,体现了作者的别具匠心。第1章关于人工智能的思想、历史发展等的论述深刻、透彻和精辟。第28章讨论某些具有前瞻性的想法和方向。我本人在阅读时受到的启发良多,获益颇丰。
“南朝四百八十寺,多少楼台烟雨中。”人工智能试图模拟人类的行为和思维,是一个最富有期待和遐想的学科,其发展波澜壮阔、起伏跌宕。她经历了热情高涨和期望无限的早期(1952—1969),通用搜索机制局限所导致的回落期(1966—1973),以专家系统为代表的基于规则学习的崛起期(1969—1986),神经网络联结主义的回归期(1986—1995),统计机器学习的复兴期(1995—现在),以及大数据驱动的深度学习的突破期(2006—现在)。[1]人工智能从哲学、数学、经济学、神经科学、心理学、计算机科学、控制科学、语言学等诸多学科中汲取思想、观点和技术,滋养并发展自身。机器学习试图从数据或经验中学习进而提升机器的能力或性能,这不同于人工智能,但她是目前趋向人工智能的一个最重要或有效的途径。
[1] 列举的人工智能发展的各个阶段非严格划分,之间或有重叠。
人工智能是思想发轫、观点争鸣、技术创新的汇集地,是学术英雄辈出的荟萃地。人工智能的发展历程告诉我们:发展人工智能技术需要高度的想象力、创造力和执行力,需要务实、理性、严谨的求是态度。人工智能未来仍会经历波折,各种潮流、观点也会纷争喧嚣,但沉淀下来的是隽永的思想。
我非常感谢人民邮电出版社杨海玲编辑的信任,邀请我的学生来承担该书的中文翻译。译稿的初稿是由我的博士生张博雅、陈坤,已毕业的硕士田超、吴凡和赵申剑,以及博士后顾卓尔完成的。博雅和陈坤对全书译稿进行了统一审校,我的其他在读博士生也参与了相关章节的审校。他们的背景分别是统计学、数据科学和计算机科学,这有益于他们合作翻译该书。然而他们在人工智能领域仍都是新人,知识结构还不全面,但是他们勤于学习、执行力极强、工作专注。在半年左右的时间内完成了译著的初稿,之后又经过自校对、交叉校对等环节力图使译著保持正确性和一致性。我为他们的责任心和独立工作能力感到自豪。
由于我们深感自己的中英文能力都有限,译文还是比较生涩,难免出现不当之处,而且我们特别担心未能完整地传达出原作者的真实思想和观点。因此,我们强烈地建议有条件的读者去阅读英文原著,也非常期待大家继续指正译著,以便今后进一步修订完善。我恳请读者多给予译者以鼓励。请把你们的批评留给我,这是我作为他们的导师必须要承担的。
最后,我希望我的学生们能享受其翻译过程,翻译和阅读这么一部大书得以领略艾伦·图灵、冯·诺依曼、诺伯特·维纳、理查德·贝尔曼、库尔特·哥德尔、约翰·麦卡锡、马文·明斯基、唐纳德·米奇、爱德华·费根鲍姆、艾伦·纽厄尔、赫伯特·西蒙等在人工智能领域中的工作,感悟他们的思想、领略他们的智慧,何其美哉!我们当谦卑再谦卑,勤奋更勤奋。是以代写此序为勉!
张志华
2022年9月12日
首先,我们要感谢原作者在本书翻译时给予我们的帮助,感谢人民邮电出版社对我们的信任和支持。
这是一本“大”书,涵盖了人工智能的广泛领域。我们几位译者来自不同专业,能力有限且工作量巨大。在翻译过程中,许多老师和同学给予我们很大的帮助。在此我们一一列出,以表示我们衷心的感谢!
特别感谢韩燮教授审校了全书的第三部分(即第7章~第11章)。赵融和郭新东同学审校了第26章。
我们实验室的其他同学帮助我们进行了校对:陈雨静(第1章和第2章),崔圣宇(第3章部分),罗维俭(第3章部分和第4章),彭洋(第5章和第6章),韩雨泽(第12章),张宇航(第13章),梁家栋(第14章),谢广增(第15章),王迩东(第16章),李翔(第17章),金昊(第18章),谢楚焓(第20章),林大超(第21章),杨文昊(第22章),程昊(第23章和第24章),胡一征(第25章),林诗韵、赵悦楷和张良宇(第27章和第28章)。我们还要感谢邓辉、李威、秦钢、王晓雷、魏太云、肖睿、姚远和张淞等专家进行了专业性审读。
他们对译文中的专业术语、中文语句、算法、公式以及原文中可能存在的问题等提出了很多宝贵的修改意见,增强了译文的准确性和可读性。当然,现在的译文仍存在一些没有及时发现的问题,因此修订工作仍将继续。我们恳请读者能提供反馈,以便我们在后续版本中修正问题。
此外,我们还要感谢刘艳云老师,感谢她帮助我们与出版社沟通交流,处理相关事务。
最后,感谢我们的导师张志华教授,感谢老师在翻译过程中的指导和对译文的审校。
张博雅(北京大学前沿交叉学科研究院)
陈坤(北京大学数学科学学院)
2022年9月15日
人工智能(artificial intelligence,AI)是一个大领域,本书也是一本“大”书。我们试图全方位探索这一领域。书中内容涵盖逻辑、概率和连续数学,感知、推理、学习和行动,以及公平、信任、社会公益和安全,应用范围从微电子设备到机器人行星探测器,再到拥有几十亿用户的在线服务。
本书的副书名是“现代方法”。这意味着我们选择从当下的角度讲述人工智能的故事。我们使用当今流行的思想和术语重新构建早期的工作,将现有已知的内容融合到统一的框架中。对那些因为研究领域不是本书所及而没有受到本书重视的人,我们深表歉意。
第4版反映了自2010年第3版面世以来人工智能领域发生的下列变化。
● 由于数据、计算资源和新算法的可用性增强,我们更关注机器学习而不是人工设计的知识工程。
● 我们增加了专门的章节介绍深度学习、概率编程和多智能体系统的相关内容。
● 我们修订了自然语言理解、机器人学和计算机视觉的内容,以反映深度学习的影响。
● 我们在第26章“机器人学”中包括了与人类互动的机器人以及强化学习在机器人学中的应用。
● 之前,我们将人工智能的目的定义为创建一些试图最大化期望效用的系统,其中具体效用信息——目标——由系统的人类设计师提供。现在我们不再假设目标是固定的,也不再假设人工智能系统知道目标,相反,人工智能系统可能不确定人类的真正目标。它必须学习到要最大化的内容,必须在不确定目标的情况下也能适当地发挥作用。
● 我们增加了人工智能对社会影响的相关内容,包括道德、公平、信任和安全等重要问题。
● 我们把习题从每章末尾移到了网站。这让我们能够不断添加、更新和改进习题,以满足教师的需求并反映这一领域和人工智能相关软件工具的进展。
● 书中约25%的内容是全新的,剩下的75%也做了大量修改,以呈现出更加统一的人工智能领域图景。本版中22%的参考文献是2010年以后发布的。
智能体(intelligent agent)的概念是贯穿整本书的主题思想。我们将人工智能定义为对从环境中接收感知并执行动作的智能体的研究。每个这样的智能体都要实现一个将感知序列映射为动作的函数,我们介绍了表示这些函数的不同方法,如反应型智能体、实时规划器、决策论系统和深度学习系统。我们强调,学习既是构造良好系统的方法,也是将设计者的影响范围扩展到未知环境的方法。我们没有把机器人学和视觉看作独立定义的问题,而是将其看作实现目标的服务。我们强调任务环境在确定合适的智能体设计中的重要性。
我们的主要目标是传达在过去70多年的人工智能研究和过去2000多年的相关工作中涌现出来的思想。在表达这些思想时,我们在保持准确性的前提下尽量避免过于拘泥于形式。书中提供了数学公式和伪代码算法,让关键思想具体化;附录A中给出了数学概念和符号,附录B中给出了伪代码。
本书主要用作本科人工智能课程或课程序列的教科书。全书共28章,每章大约需要一周的课时,因此完成整本书的教学需要两个学期。如果课程只有一个学期,可以按教师和学生的兴趣选择部分章节进行教学。本书也可用于研究生课程(可能需要增加参考文献中建议的一些主要资料),或者用于自学或作为参考书。
在本书中,定义了新术语的地方都会以灰色粗体显示,术语的后续重要用法也以黑色粗体显示。
阅读本书唯一的先修要求是对计算机科学基本概念(算法、数据结构、复杂性)的熟悉程度达到大学二年级的水平。大学一年级的微积分和线性代数知识对一些主题的阅读很有帮助。
在线资源可通过培生教育集团的官方网站或本书的配套网站获得。本书的配套网站上有以下内容。
● 习题、编程项目和研究项目。这些不再放在每章末尾,只在网站提供。在本书中,我们将使用“习题6.NARY”之类的名称引用在线习题。网站的说明允许读者按名称或主题查找习题。
● 使用Python、Java和其他编程语言实现的本书中的算法(目前托管在GitHub上)。
● 1500多所使用过本书的学校名单,其中许多都附有在线课程材料和教学大纲的链接。
● 供学生和教师使用的补充材料及其链接。
● 书中可能存在的错误以及关于如何报告书中错误的说明。
封面描绘了加里·卡斯帕罗夫(Garry Kasparov)与IBM的“深蓝”(Deep Blue)计算机在1997年国际象棋对抗赛中第六盘决胜局的最终局面。在这场比赛中,“深蓝”击败了卡斯帕罗夫(执黑棋),这是计算机首次在国际象棋比赛中战胜人类世界冠军。卡斯帕罗夫位于封面顶部,他的右边是前世界冠军李世石和DeepMind的AlphaGo进行历史性围棋比赛的第二局的关键局面。AlphaGo的第37手违背了几个世纪以来的围棋正统观念,人类专家认为这是一个令人尴尬的错误,但结果证明这一走法是正确的。封面上,左上角是由波士顿动力公司制造的Atlas人形机器人,埃达·洛芙莱斯(Ada Lovelace,世界上第一位计算机程序员)和艾伦·图灵(Alan Turing,他的基础工作定义了人工智能)之间的是自动驾驶汽车感知环境的画面,棋盘底部是火星探测漫游者机器人和逻辑学研究先驱亚里士多德的雕像,英文书名背后是亚里士多德的《论动物的运动》(De Motu Animalium)中的规划算法,棋盘面上的文字是联合国全面禁止核试验条约组织(UN Comprehensive Nuclear-Test-Ban Treaty Organization)使用的用于从地震信号中检测核爆炸的概率编程模型。
制作一本书需要无数人的帮助。600多人阅读了本书的部分内容,并提出了改进意见。我们感谢他们所有人。在这里,我们只列出几位特别重要的贡献者。首先是撰稿人:
● 朱迪亚·珀尔(Judea Pearl)(13.5节);
● 维卡什·曼辛卡(Vikash Mansinghka)(15.4节);
● 迈克尔·伍尔德里奇(Michael Wooldridge)(第18章);
● 伊恩·古德费洛(Ian Goodfellow)(第21章);
● 雅各布·德夫林(Jacob Devlin)和张明伟(Ming-Wei Chang)(第24章);
● 吉滕德拉·马利克(Jitendra Malik)和戴维·福赛思(David Forsyth)(第25章);
● 安卡·德拉甘(Anca Dragan)(第26章)。
然后是本书出版过程中的关键角色:
● 辛西娅·杨(Cynthia Yeung)和玛莉卡·坎托(Malika Cantor)(项目管理);
● 朱莉·萨斯曼(Julie Sussman)和汤姆·加洛韦(Tom Galloway)(文字加工和写作建议);
● 奥马里·斯蒂芬斯(Omari Stephens)(插图);
● 特蕾西·约翰逊(Tracy Johnson)(编辑);
● 埃琳·奥尔特(Erin Ault)和罗丝·克南(Rose Kernan)(封面设计和颜色转换);
● 纳林·奇伯(Nalin Chhibber)、萨姆·戈托(Sam Goto)、雷蒙·拉卡兹(Raymond de Lacaze)、拉维·莫汉(Ravi Mohan)、夏兰·奥赖利(Ciaran O’Reilly)、阿米特·帕特尔(Amit Patel)、德拉戈米尔·拉迪夫(Dragomir Radiv)和萨马格拉·夏尔马(Samagra Sharma)(在线代码开发和指导);
● Google Summer of Code students(在线代码开发)。
斯图尔特想要感谢他的妻子洛伊·谢弗洛特(Loy Sheflott),感谢她无尽的耐心和无限的智慧。他希望戈登(Gordon)、露西(Lucy)、乔治(George)和艾萨克(Isaac)能很快读到本书,并原谅他在本书上花了这么长时间。感谢RUGS(Russell’s Unusual Group of Students)一如既往地提供了非同寻常的帮助。
彼得想要感谢他的父母托尔斯滕(Torsten)和格尔达(Gerda)让他迈出第一步,感谢他的妻子克丽丝(Kris)、孩子伊莎贝拉(Isabella)和朱丽叶(Juliet)、同事、老板以及朋友在他漫长的写作和修改过程中鼓励和包容他。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
您还可以扫码右侧二维码, 关注【异步社区】微信公众号,回复“e59810”直接获取,同时可以获得异步社区15天VIP会员卡,近千本电子书免费畅读。
本书提供全书彩图、伪代码、各章的参考文献与历史注释及完整的参考文献。您可以扫描下方二维码,发送“59810”,添加异步助手,获取本书配套资源。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的积分。积分可用于在异步社区兑换优惠券、样书或奖品。
扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频或者参与技术审校等工作,可以通过邮件与本书责任编辑联系(yanghailing@ptpress.com.cn)。
如果您来自学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
图1-3 积木世界的场景。Shrdlu(Winograd, 1972)刚刚完成了一个命令——“找到一块比你所持有的积木块更高的积木块,并把它放进盒子里”
图2-16 表示状态及其之间转移的3种方法:(a)原子表示一个状态(如B或C)是没有内部结构的黑盒;(b)因子化表示状态由属性值向量组成,值可以是布尔值、实值或一组固定符号中的一个;(c)结构化表示状态包括对象,每个对象可能有自己的属性以及与其他对象的关系
图3-4 3棵部分搜索树,用于寻找从Arad到Bucharest的路线。已扩展节点用淡紫色和粗体字母表示;边界上已生成但未被扩展的节点用绿色表示;对应于这两种类型节点的状态集被称为已达。接下来可能生成的节点用虚线表示。注意,在最下面的树中,有一个从Arad到Sibiu再到Arad的环,这不可能是最优路径,因此搜索不应该从那里继续
图3-4 3棵部分搜索树,用于寻找从Arad到Bucharest的路线。已扩展节点用淡紫色和粗体字母表示;边界上已生成但未被扩展的节点用绿色表示;对应于这两种类型节点的状态集被称为已达。接下来可能生成的节点用虚线表示。注意,在最下面的树中,有一个从Arad到Sibiu再到Arad的环,这不可能是最优路径,因此搜索不应该从那里继续(续)
图3-5 由图3-1中的罗马尼亚问题的图搜索生成的搜索树序列。在每一阶段,我们扩展边界上的每个节点,使用所有不指向已达状态的可用动作延伸每条路径。需要注意的是,在第三阶段,最高位置的城市(Oradea)有两个后继城市,这两个城市都已经有其他路径到达,所以没有路径可以从Oradea延伸
图3-6 以矩形网格问题为例说明图搜索的分离性质。边界(绿色)分离了内部(淡紫色)和外部(虚线)。边界是已达但尚未扩展的节点(及相应的状态)的集合;内部是已被扩展的节点(及相应的状态)的集合;外部是尚未到达的状态的集合。在(a)中,只有根节点被扩展。在(b)中,上面的边界节点被扩展。在(c)中,按顺时针顺序扩展根节点的其他后继节点
图3-8 简单二叉树上的广度优先搜索。每个阶段接下来要扩展的节点用三角形标记表示
图3-11 二叉树的深度优先搜索过程中,从开始状态A到目标M,共12步(从左到右,从上到下)。边界节点为绿色,用三角形表示下一步要扩展的节点。已扩展的节点为淡紫色,潜在的未来节点用模糊的虚线表示。边界中没有后继的已扩展节点(用非常模糊的线表示)可以丢弃
图3-13 二叉树上的迭代加深搜索的4次迭代(目标为M),深度界限从0到3。注意,内部节点形成了一条路径。三角形标记下一步要扩展的节点,边界为加粗轮廓的绿色节点,非常模糊的节点可被证明不可能是这种深度界限下的解的一部分
图3-13 二叉树上的迭代加深搜索的4次迭代(目标为M),深度界限从0到3。注意,内部节点形成了一条路径。三角形标记下一步要扩展的节点,边界为加粗轮廓的绿色节点,非常模糊的节点可被证明不可能是这种深度界限下的解的一部分(续)
图3-17 基于直线距离启发式函数hSLD的贪心最佳优先树状搜索的各个阶段(目标为Bucharest)。节点上标有h值
图3-18 A*搜索的各个阶段(目标为Bucharest)。节点上标有,h值为图3-16中得到的到Bucharest的直线距离
图3-21 同一网格上的两种搜索:(a)A*搜索,(b)加权A*搜索,权重W = 2。灰色线条表示障碍,紫色线是一条从绿色起始点到红色目标点的路径,较小的点是每次搜索到达的状态。在这个特定问题上,加权A*搜索探索的状态数不到A*搜索探索的状态数的七分之一,找到的路径的代价只比最优代价大了5%
图3-23 使用RBFS搜索到Bucharest的最短路线的各个阶段。每次递归调用的f_limit值标注在每个当前节点的上方,每个节点上都标有它的f代价。(a)沿着经过Rimnicu Vilcea的路径前进,直到当前最优叶节点(Pitesti)的值比最优备选路径(Fagaras)差。(b)递归回溯,被遗忘子树的最优叶节点值(417)被备份到Rimnicu Vilcea;接着扩展Fagaras,得到最优叶节点值450。(c)递归回溯,被遗忘子树的最优叶节点值(450)被备份到Fagaras;然后扩展Rimnicu Vilcea。这一次,因为最优备选路径(经由Timisoara)的代价至少为447,所以继续扩展Bucharest
图3-23 使用RBFS搜索到Bucharest的最短路线的各个阶段。每次递归调用的f_limit值标注在每个当前节点的上方,每个节点上都标有它的f代价。(a)沿着经过Rimnicu Vilcea的路径前进,直到当前最优叶节点(Pitesti)的值比最优备选路径(Fagaras)差。(b)递归回溯,被遗忘子树的最优叶节点值(417)被备份到Rimnicu Vilcea;接着扩展Fagaras,得到最优叶节点值450。(c)递归回溯,被遗忘子树的最优叶节点值(450)被备份到Fagaras;然后扩展Rimnicu Vilcea。这一次,因为最优备选路径(经由Timisoara)的代价至少为447,所以继续扩展Bucharest(续)
图4-4 岭为爬山法带来困难的示意图。状态网格(蓝色圆点)叠加在从左到右上升的岭上,形成了一个彼此不直接相连的局部极大值序列。从每个局部极大值出发,所有可选动作都指向下坡。这样的拓扑在低维状态空间中很常见,例如二维平面中的点。但是在具有成百上千个维度的状态空间中,这种直观图并不成立,而且通常至少存在几个维度使得算法有可能漏掉岭和平台区
图4-7 对应于图4-6c中前两个亲本和图4-6d中第一个后代的8皇后状态。在杂交步中,丢弃绿色列,保留红色列。(图4-6中数字的解释:第1行是最下面一行,第8行是最上面一行)
图4-23 一维状态空间上LRTA*的5次迭代。每个状态都标有H(s),即到达目标的当前代价估计值,每个连接的动作代价为1。红色状态表示智能体的位置,每次迭代所更新的代价估计值以双圈标记
图5-4 三人博弈的博弈树的前三层,3个玩家为A、B、C。每个节点都标有3个玩家各自的效用值。最佳移动标示在根节点上
图5-10 使用蒙特卡罗树搜索(MCTS)选择移动的算法的一次迭代,该算法使用“应用于树搜索的置信上界”法(UCT)作为选择度量,此时已完成了100次迭代。(a)选择移动,沿着树一直向下,到标记为27/35(35次模拟中黑方赢了27次)的叶节点结束。(b)扩展所选节点并进行模拟,最终黑方获胜。(c)将模拟结果沿树反向传播
图6-6 图6-1中地图着色问题的部分搜索树
图6-7 带前向检验的地图着色搜索过程。首先赋值WA = red;然后前向检验从其相邻变量NT和SA的域中删除red。赋值Q = green后,从NT、SA和NSW的域中删除green。赋值V = blue后,从NSW和SA的域中删除blue,此时SA没有合法值
图7-6 语句是智能体的物理结构,而推理是从旧结构构建新结构的过程。逻辑推理应当确保新结构所表示的部分世界确实能够从旧结构所表示的部分世界推得
图9-10 归结证明韦斯特有罪。每个归结步骤中,合一文字用加粗字体表示,带有正文字的子句用蓝底表示
图9-11 好奇心害死猫的归结证明。注意,在推导子句Loves(G(Jack), Jack)时使用了因子分解。还要注意,在右上角,合一Loves(x, F(x))和Loves(Jack, x)只有在变量标准化分离后才可以进行
图11-6 使用忽略删除列表启发式方法的规划问题的两个状态空间。底部平面以上的高度是一个状态的启发式得分;底部平面的状态是目标。由于不存在局部极小值,所以搜索目标很简单直接。图片来自(Hoffmann, 2005)
图11-9 可达集的语义示例。目标状态集用紫色阴影表示。黑色和红色箭头分别表示h1和h2的可能实现。(a)在状态s中HLA h1的可达集。(b)序列[h1, h2]的可达集。因为它与目标集相交,所以序列实现了目标
图11-10 具有近似描述的高层规划的目标达成。目标状态集用紫色阴影表示。对于每个规划将显示悲观(实线,浅蓝色)和乐观(虚线,浅绿色)可达集。(a)黑色箭头所指的规划的确达成了目标,而红色箭头所指的规划完全没有达成目标。(b)可能达成目标(乐观可达集相交的目标)但未必会达成目标(悲观可达集与目标不相交)的规划。该规划需要进一步细化,以确定它是否真的达成了目标
图13-4 (a)给定父节点(浅紫色区域中所示的Ui),节点X条件独立于它的非子孙节点(例如,Zi j)。(b)给定它的马尔可夫毯(浅紫色区域),节点X条件独立于网络中的所有其他节点
图13-9 用于评估汽车保险申请的贝叶斯网络
图13-14 3-CNF语句的贝叶斯网络编码
图14-14 (a)红色曲线:除t = 21和t = 22为0外,其他观测都为5的观测序列的Batteryt期望值轨迹,采用简单高斯误差模型。绿色曲线:从t = 21开始观测值维持在0的轨迹。(b)瞬时故障模型运行了同样的实验。瞬时故障处理良好,但持续故障导致对电池电量的过度悲观
图14-15 (a)一个显示建模电池传感器持续故障要求的传感器状态变量的动态贝叶斯网络片段。(b)上方曲线为对“瞬时故障”与“持续故障”的Batteryt的期望值轨迹,下方曲线为给定两个观测序列的BMBroken的概率轨迹
图14-18 N=10的雨伞动态贝叶斯网络的粒子滤波更新循环,显示每个状态的样本总体。(a)在时刻t,有8个样本表示rain,有2个样本表示。每个状态通过转移模型采样下一个状态向前传播。在时刻t+1,有6个样本表示rain,有4个样本表示
。(b)在时刻t+1观测到
。每个样本通过这个观测的似然来进行加权,权重如圆的大小所示。(c)从当前的集合中通过加权随机选择产生一个新的集合,共有10个样本,其中2个样本表示rain,8个样本表示
图14-21 (a)具有1000个粒子的标准粒子滤波算法的性能,在不同的灰尘持久性p下,显示与精确推断相比边际灰尘概率的均方根(RMS)误差。(b)Rao-Blackwellized粒子滤波(100个粒子)性能与真实情况的比较,包含精确的位置传感和噪声墙传感,灰尘是确定性的。数据是超过20次运行的平均值
图15-1 (a)在一阶逻辑的标准语义下,具有两个常量符号R和J以及一个二元关系符号的语言的全部可能世界的集合的部分成员。(b)数据库语义下的可能世界。常量符号的解释是固定的,每个常量符号都对应唯一的对象
图15-7 (a)上图:在澳大利亚艾利斯斯普林斯市记录的地震波形实例。下图:用于检测地震波到达时间的处理后的波形。蓝线是自动检测的地震波到达,红线是真正的地震波到达。(b) 2013年2月12日朝鲜核试验地点估计:联合国CTBTO最新事件公报(左上角绿色三角形),NET-VISA(中间蓝色方块)。地下试验设施的入口(以“x”标记)距离NET-VISA的估计0.75公里。轮廓线显示NET-VISA的后验位置分布。图片由CTBTO筹备委员会提供
图16-3 选择k个选项中的最佳选项引起的不合理的乐观:我们假设每个选项的真实效用为0,但效用估计是单位正态分布(棕色曲线)。其他曲线展示了k = 3、10和30时估计最大值的分布
图17-5 (a)俄罗斯方块游戏。位于顶部中心的T型块可以落在任何方向和任何水平位置。如果某一行被补全,则该行消失,上方的行向下移动,智能体得1分。下一块(这里是右上方的L形块)成为当前的一块,并出现一个新的下一块,从7种类型中随机选择。如果棋盘被填满,游戏结束。(b)俄罗斯方块MDP的DDN
图17-7 (a)显示被选择状态使用价值迭代的效用演变的图。(b)对于c不同的值,为保证误差最多为所需的价值迭代次数,作为折扣因子
的函数
图17-12 (a)一个简单的有两个臂的确定性老虎机问题。臂可以以任何顺序拉动,每个臂产生所示的奖励序列。(b)关于(a)中的老虎机的一个更普遍的情况,其中第一个臂给出任意奖励序列,第二个臂给出一个固定的奖励λ
图17-14 (a)伯努利老虎机的状态、奖励与转移概率。(b)伯努利老虎机过程的状态的基廷斯指数
图17-17 具有均匀初始信念状态的4×3 POMDP的最大化期望树的一部分。信念状态用与存在于每个位置的概率成正比的深浅来描述
图17-18 墙传感误差的4×3 POMDP中感知、信念状态和动作的序列。注意,之前的Left是安全的,它们不太可能落入(4, 2),并迫使智能体的位置变成少量的可能位置。Up移动后,智能体认为它可能在(3, 3)中,但也可能在(1, 3)中。幸运的是,Right在这两种情况下都是一个好主意,所以它选择Right,发现它之前在(1, 3),现在在(2, 3),然后继续Right,达到目标
图19-3 决定是否在餐厅等待的决策树
图19-4 通过测试属性来对样例进行分割。在每一个节点中我们给出剩余样例的正(绿色方框)负(红色方框)情况。(a)根据Type分割样例,没有为我们分辨正负带来帮助。(b)根据Patrons分割样例,很好地区分了正负样例。在根据Patrons进行分类之后,Hungry是相对较好的第二个测试属性
图19-6 根据12样例训练集推断出的决策树
图19-9 两个不同问题上不同复杂性模型的训练误差(下方绿线)和验证误差(上方橙色线)。模型选择算法Model-Selection将选择验证误差最小的模型对应的超参数值。(a)模型类是决策树,超参数是节点数量。数据来自餐厅等待问题。最佳的超参数大小为7。(b)模型类是卷积神经网络(见21.3节),超参数是网络中常规参数的数量。数据是数字图像的MNIST数据集,任务是识别手写数字的照片。效果最好的超参数是1 000 000(注意坐标的对数刻度)
图19-15 (a)两种类型地震数据,包含体波震级x1和面波震级x2,数据来源于1982~1990年在亚洲和中东发生的地震(橙色空心圆)和地底爆炸(绿色实心圆)(Kebeasy et al., 1998)。图中还绘制了类之间的决策边界。(b)同一个领域,有比之前更多的数据点。此时地震和爆炸不再是线性可分的
图19-19 (a)一个k近邻模型,该图显示了图19-15中数据的爆炸一类的范围,其中k = 1。可以明显看到有过拟合现象。(b)当k = 5时,该数据集上的过拟合现象消失了
图19-21 支持向量机分类器:(a)两类点(橙色空心圆和绿色实心圆)和3个候选线性分离器。(b)极大边距分离器(粗线)位于边距(虚线之间的区域)的中间。支持向量(带有大黑圈的点)是最靠近分离器的,本图中有3个
图19-22 (a)一个二维训练集,其中正样例为绿色实心圆,负样例为橙色空心圆。图中还给出了真实的
决策边界。(b)映射到三维输入空间
后的相同数据。(a)中的圆形决策边界变成
三维空间中的线性决策边界。图19-21b给出了(b)中分离器的特写
图19-27 MNIST数据集上的二维t-SNE平面图,该数据集收集了60 000幅手写数字图像,每幅28像素×28像素,因此是784维。可以清楚地看到10个数字的聚类簇,每个聚类簇之间都存在一些混淆;例如,顶部是数字0的聚类簇,但是在聚类簇的范围内有一些表示数字3和6的数据点。t-SNE算法找到了一种突出聚类簇间差异的表示
图20-1 (a)根据式(20-1)得到的后验概率。观测数量N为1~10,且每一个观测都是酸橙味的糖果。(b)基于式(20-2)的贝叶斯预测
图20-4 (a)高斯线性模型,它表述为加上固定方差的高斯噪声。(b)由该模型生成的50个数据点,以及它的最佳拟合直线
图20-5 不同(a, b)下Beta(a, b)分布的例子
图20-7 贝叶斯线性回归模型,它被约束为经过原点且噪声方差固定为。误差为±1、±2和±3个标准差的密度预测等高线也在图中给出。(a)其中3个数据点距离原点较近,因此斜率相当不确定,其方差
。注意,当离观测到的数据点距离增大时,预测的不确定性也逐渐增大。(b)相比前一幅图多出两个距离较远的数据点,此时斜率
被较严格地约束,其方差为
。密度预测中剩余的方差几乎完全来源于噪声的固定方差
图20-8 (a)图20-12a中所给出的混合高斯模型的三维样貌。(b)从混合高斯模型中采样的128个数据点、两个查询点(小方块)以及它们的10近邻(大圆圈以及右边的小圆圈)
图20-9 应用k近邻进行密度估计,所用的数据为图20-8b中的数据,分别对应k = 3、10和 40。k = 3的结果过于尖锐,40的结果过于光滑,而10的结果接近真实情况。最好的k值可以通过交叉验证进行选择
图21-3 (a)具有两个输入、一个包含两个单元的隐藏层和一个输出单元的神经网络,其中虚拟输入及其权重没有在图中给出。(b)将(a)中的网络分解为完整的计算图
图21-9 生成模型如何使用空间中的不同方向来表示人脸不同方面的信息。实际上我们可以在
空间中进行运算。这里的图像都是从学习到的模型中生成的,并且图像解释了当我们解码
空间中的不同点时会发生什么。我们从“戴眼镜的男人”这个对象的坐标出发,减去“男人”的坐标,再加上“女人”的坐标,得到“戴眼镜的女人”的坐标。图像经许可摘自(Radford et al., 2015)
图22-3 在给定图22-1所示的最优策略情况下,关于4×3世界问题的被动自适应动态规划的学习曲线。(a)选定某个状态子集,其效用估计值与试验次数的关系。注意,对于很少被访问的状态(2, 1)和(3, 2),它们分别在第14次和第23次试验才被“发现”连接到位于(4, 3)处的+1退出状态。(b)U(1, 1)估计的均方根误差(见附录 A),所示的结果为50组,每组执行100次试验的平均值
图22-5 4×3世界问题中,TD的学习曲线。(a)选定的状态子集的效用估计与试验次数的关系。此为单组执行500次试验的结果。可以与图22-3a中的每组执行100次试验的结果进行比较。(b)U(1, 1)估计的均方根误差,所示结果为50组、每组执行100次试验的平均值
图25-4 这张照片展示了各种照明的效果。不锈钢佐料壶上发生镜面反射。洋葱和胡萝卜是亮的漫反射表面,因为它们面向光照射的方向。阴影部分出现在根本看不到光源的表面点上。在锅中存在一些暗的漫反射表面,光线沿着切线角度照射进来(锅内还有一些其他阴影)。该照片由Ryman Cabannes/Image Professionals GmbH/Alamy Stock Photo拍摄
图25-10 (a)原始图像。(b)图像的边界轮廓,其中Pb值越高,轮廓颜色越深。(c)通过对图像精细划分得到的各个分割区域,其中每个区域使用区域中的平均颜色进行填充。(d)通过对图像进行较粗糙的分割得到的各个分割区域,粗糙分割将导致得到的区域更少(图片由Pablo Arbelaez、Michael Maire、Charless Fowkes和Jitendra Malik提供)
图25-12 最左侧是MNIST数据集中的一些图像。中间图的左侧为3个卷积核。它们以实际大小(图中的小方块)给出,并放大以显示其内容:中度灰色的值为0,浅色表示正值,深色表示负值。中间图的右中侧给出了将左侧这些核应用于图像的结果。最右侧给出了响应大于阈值(绿色)与小于阈值(红色)的像素。注意,这里(从上到下)给出了一个水平条检测器、一个竖条检测器和(更难注意到的)一个尾端检测器。这些检测器关注条的对比度,因此(例如)顶部亮底部暗的水平条产生正(绿色)响应,顶部暗底部亮的水平条产生负(红色)响应。这些检测器有一定的效果,但它们不是完美的
图25-13 快速RCNN使用两个网络。一张年轻时的纳尔逊·曼德拉的照片被输入物体检测器。一个网络用于计算候选图像框(称为“锚框”)的物体检测得分,这些框以网格上的点为中心。每个网格点对应着9个锚框(3种尺寸,每种尺寸包含3种纵横比)。对于示例图像,内部的绿色框和外部的蓝色框通过了物体检测。第二个网络是一个特征栈,用于计算适合分类的图像表示。具有最高得分的框将从特征图中分割出来,通过ROI池化进行尺寸标准化,再传给分类器。注意,蓝色框的得分高于绿色框,并且与绿色框重叠,因此绿色框将被非极大值抑制算法拒绝。最后,我们对蓝色框进行边框回归,使其符合人脸的形状。这意味着对位置、比例和纵横比的相对粗粒度的采样不会降低预测准确率。照片由Sipa/Shutterstock提供
图25-16 从单一的图像中重建人类模型目前已经可以实现。两行图片都展示了基于单个图像的三维身体形状重建。这些重建是有可能的,因为一些方法可以估计关节的位置、关节在三维中的角度、身体的形状以及身体相对于图像的位姿。每行包括以下内容:最左图为一张图片,中左图为原图与重建出的身体叠加的图片,中右图为重建出的身体的另一个视图,最右图是重建出的身体的另一个不同视图。考查身体的不同视图使得在重建中隐藏错误变得更加困难。图由Angjoo Kanazawa提供,并用(Kanazawa et al., 2018a)中提出的系统加以处理
图25-17 同一个动作看起来很不一样,不同的动作看起来很相似。这些例子是来自一个数据集中的自然动作,其标签由数据集的管理员进行选择,而不是由算法预测的。上面3幅图表示标签为“打开冰箱”的样本,有的是特写,有的是远处拍摄。下面3幅图表示标签为“从冰箱里拿东西”的样本。注意,在两排图像中,图像里的人的手是如何靠近冰箱门的——若要区分不同的情况,就需要对手的位置和门的位置做出相当微妙的判断。图由David Fouhey提供,摘自(Fouhey et al., 2018)中给出的数据集
图25-18 我们所说的动作取决于时间尺度。对于最上面的单幅图像,最好的描述是“打开冰箱”(当你打算关上冰箱时,你不会盯着里面的东西)。但是,如果你看完了一段视频短片(由中间一行图像表示),关于这个动作的最佳描述就是“从冰箱里拿牛奶”。如果你看完了一段较长的视频(由最下面一行图像表示),关于这个动作的最佳描述是“准备点心”。这说明了行为的一种构成方式:从冰箱中拿牛奶有时是准备点心的一部分,而打开冰箱通常是从冰箱中拿牛奶的一部分。图由David Fouhey提供,摘自(Fouhey et al., 2018)中给出的数据集
图25-19 自动图像标题系统给出了一些好的结果和一些失败的结果。左边的两个标题很好地描述了各自的图像,尽管“eating … in his mouth”是一个不流畅的表达,这是早期标题系统所使用的循环神经网络语言模型的一个相当典型的特点。根据右边的两个标题,我们认为标题系统似乎不了解松鼠,所以从环境猜测该动物;它也没有意识到这两只松鼠在吃东西。图片来源:geraine/Shutterstock、ESB Professional/Shutterstock、BushAlex/Shutterstock、Maria.Tem/Shutterstock。所示图像与用于生成标题的原始图像相似但不完全相同。原始图像见(Aneja et al., 2018)
图25-20 视觉问答系统产生关于图像的自然语言问题的答案(通常从多项选择中选择)。顶部:该系统对有关图像的一些相当棘手的问题给出了非常合适的答案。底部:不太令人满意的答案。例如,系统被要求猜测比萨饼上的洞的个数,但系统并不知道什么算洞,而且洞本身很难计数。类似地,系统认为猫的腿的颜色是棕色,这是因为图片背景是棕色的,并且系统不能正确定位猫的腿。图片来源:(顶部)Tobyanna/Shutterstock、679411/Shutterstock、ESB Professional/Shutterstock、Africa Studio/Shutterstock,(底部)Stuart Russell、Maxisport/Shutterstock、Chendongshan/Shutterstock、Scott Biales DitchTheMap/Shutterstock。所示的图像与用于问答系统的原始图像相似但不完全相同,原始图像见(Goyal et al., 2017)
图25-21 多视图立体算法根据运动结构图像生成的建筑工地的三维模型。它们可以帮助建筑公司通过比较目前三维模型实际搭建的进度与建筑计划来协调大型建筑工作。左图:基于无人机拍摄图像重建出的可视化几何模型。重建出的三维点以彩色呈现,因此结果看起来像是目前的真实进度(注意用起重机完成的部分建筑)。这些小金字塔表示无人机拍摄图像时的位姿,以便对飞行轨迹进行可视化。右图:这些系统实际上是施工队所使用的;作为协调会议的一部分,该团队正在查看竣工场地的模型,并将其与建筑平面图进行比较。图由Derek Hoiem、Mani Golparvar-Fard和Reconstruct提供,模型由商业系统制作
图25-22 如果你已经看过很多鸟类物种的图片(上图),你可以利用它们从一个新的图片(下图)中生成一个三维重建模型。你需要确保所有的物体都有一个相当类似的几何结构(所以如果你看到的是麻雀,那么鸵鸟的图片将对你没有任何帮助),但分类方法可以解决这个问题。你可以从许多图像中估计出图像中的纹理是如何分布在物体上的,从而完成对你尚未观察到的鸟的纹理估计(下图)。图由Angjoo Kanazawa提供,模型用(Kanazawa et al., 2018b)中提供的系统生成。上方图片来源于Satori/123RF,左下图来源于Four Oaks/Shutterstock
图25-23 左图为真实场景的图像。在右图中,计算机图形物体已插入场景中。你可以看到光线看上去来自正确的方向,并且物体看起来也投射了效果不错的阴影。尽管生成的图像在光线和阴影方面有较小的误差,但这个图像仍是令人信服的,因为人类并不擅长分辨这些误差。图由Kevin Karsch提供,模型用(Karsch et al., 2011)中提供的系统生成
图25-24 成对图像的转换,其中输入由航空影像和相应的道路图组成,我们的目标是训练一个从航空影像生成道路图的网络(该系统还可以学习从道路图生成航空影像。)网络通过比较(X型样本xi的输出)和Y型的正确输出yi进行训练。在测试时,网络必须从新的X型输入中生成新的Y型图像。图由Phillip Isola、Jun-Yan Zhu和Alexei A. Efros提供,模型用(Isola et al., 2017)中提供的系统生成。地图数据©2019 Google
图25-25 未配对图像转换:给定两组图像(X型是马,Y型是斑马),但没有对应的配对,我们要学习将马转换成斑马。该方法训练两个预测器:一个将X型映射为Y型,另一个将Y型映射为X型。如果第一个网络将马xi映射为斑马,那么第二个网络应当把
映射回原始的xi。两个网络利用xi和
之间的差进行训练。从Y型到X型再回到Y型的循环必须是封闭的。这样的网络可以成功地对图像进行丰富的变换。图由Alexei A. Efros提供,见(Zhu et al., 2017)。正在奔跑的马的照片由Justyna Furmanchyk Gibaszek/Shutterstock拍摄
图25-26 风格转换:将内容为猫的照片与抽象绘画的风格相结合,生成经过抽象风格渲染的猫的新图像(右图)。中间这幅画为Wassily Kandinsky绘制的Lyrisches或The Lyrical(公共领域),左图猫的照片为Cosmo
图25-28 MobileEye研发的基于摄像头的自动车辆传感装置。顶部:两张来自前置摄像头的照片,照片的拍摄相隔几秒。绿色区域为自由空间——车辆在不久的将来可以实际移动到的区域。系统使用表示侧面的三维边框来表示物体(红色表示后部,蓝色表示右侧,黄色表示左侧,绿色表示前部)。其中物体包括车辆、行人、自行车道内边缘标志(横向控制所需)、其他标线道路和人行横道标志、交通标志和交通信号灯。动物、路杆和锥桶、人行道、护栏和其他一般物体(例如,从卡车后面掉下来的沙发)没有在图中给出。然后用三维位置和速度对每个物体进行标记。底部:根据检测到的物体刻画的环境的完整物理模型(图中所示为MobileEye的仅基于视觉的系统产生的结果)。图像由MobileEye提供
图25-29 导航功能通过分解成地图构建:和路径规划两个问题来实现。在每一个连续的时间步中,来自地图构建传感器的信息将用来逐步地建立一个关于世界的不确定的模型。该模型连同其规范目标一起传入路径规划器,路径规划器输出机器人为实现目标应该采取的下一个动作。关于世界的模型可以是纯粹的几何模型(如经典的SLAM),也可以是语义模型(通过学习得到),甚至可以是拓扑模型(基于地标)。我们在右图中给出实际的机器人的图片。图由Saurabh Gupta提供
图26-1 (a)具有定制末端效应器的工业机器人。图片来源:Macor/123RF。(b)安装在轮椅上的Kinova® JACO® Assistive Robot 机械臂。Kinova和JACO是Kinova股份有限公司的商标
图26-2 (a)美国国家航空航天局的好奇号巡视器在火星上自拍。图片来自美国国家航空航天局。(b)Skydio无人机伴随一家人骑行。图片由Skydio提供
图26-7 蒙特卡罗定位,这是一种用于移动机器人定位的粒子滤波算法。(a)起初,全局具有不确定性。(b)在导航到(对称的)走廊后形成近似双峰的不确定性。(c)在进入到特定的房间后形成单峰不确定性
图26-10 使用适应性视觉取得的一系列“可行驶表面”分类。(a)只有路面被分类为可行驶的(粉色区域)。蓝色的V形线表示车辆的行驶方向。(b)车辆被迫驶离路面,分类器开始将部分草地分类为可行驶的。(c)车辆更新了它的可行驶表面模型,以将草地视作路面。图片由Sebastian Thrun提供
图26-12 (a)有两个自由度的机械臂的工作空间表示。工作空间是一个盒子,其中扁平障碍物悬挂在天花板上。(b)同一个机器人的构形空间。只有空间中的白色区域是没有碰撞的构形。图中的点对应左图所示的机器人构形
图26-13 工作空间和构形空间中的3个机器人构形
图26-15 沃罗诺伊图式展示了构形空间中与周围两个或多个障碍物等距的点的集合(红色线)
图26-19 RRT生成并经过“走捷径”后期处理的截图。图片由Anca Dragan提供
图26-21 用轨迹优化器解决了伸手抓住瓶子的任务。左图:为末端效应器绘制的初始轨迹。中图:优化后的最终轨迹。右图:目标构形。图片由Anca Dragan提供,见(Ratliff et al., 2009)
图26-26 训练健壮的策略。(a)在一个操作物体的机械手上多次运行模拟,物理学参数和照明情况是随机的。图片由Wojciech Zaremba提供。(b)真实世界环境中,单个机械手处于笼子中央,周围有摄像头和测距器。(c)模拟和真实世界训练产生了多个抓住物体的策略,此处有捏住和四指握两种。图片由OpenAI提供,见(Andrychowicz et al, 2018a)
图26-27 假设人类在给定目标的情况下的理性带有噪声时进行预测:机器人使用过往动作来更新对人类目标的信念,并使用这个信念预测未来动作。(a)房间的地图。(b)看到小部分人类轨迹时的预测(白色路径)。(c)看到更多人类动作时的预测:机器人现在知道人类没有走向左边的走廊,因为如果那是人类的目标,到目前为止的行进路径就是一条糟糕的路径。图片由Brian D. Ziebart提供,见(Ziebart et al., 2009)
图26-28 (a)左图:自主驾驶汽车(中间车道)预测人类司机(左侧车道)要继续前进,并规划了减速并入该车后方的轨迹。右图:自主驾驶汽车考虑了它的动作对人类动作的影响,发觉它可以依靠人类司机的减速来并入前方。(b)在交叉路口,同样的算法产生了不寻常的策略:自主驾驶汽车发觉它可以通过稍稍后退来使人类司机(底部)更快地通过路口。图片由Anca Dragan提供,见(Sadigh et al., 2016)
图26-29 (a)向移动机器人展示保持在土路上的演示。(b)机器人推断所需的代价函数,将其用于新场景中,且知道使道路上的代价较低。(c)机器人对新场景规划了一条同样在道路上的路径,重现了演示中隐含的偏好。图片由Nathan Ratliff and James A. Bagnell提供,见(Ratliff et al., 2006)
图26-30 人类教学者把机器人向下拽来教它离桌子更近一些。机器人正确地更新了它对所需代价函数的理解,并开始对代价函数进行优化。图片由Anca Dragan提供,见(Sefidgar et al., 2017)
图26-31 一个编程接口,在机器人的工作空间中放置专门设计的程序块,以选择物体并指定高层级动作。图片由Maya Cakmak提供,见(Sefidgar et al., 2017)
图26-32 (a)六足机器人Genghis。图片由Rodney A. Brooks提供。(b)用于控制一条腿的增强有限状态机(AFSM)。AFSM对传感器反馈进行反应:如果腿在前摆阶段卡住,则会逐渐增加高度
图26-33 (a)一位用脑机接口控制机械臂抓取饮料的患者。图片由布朗大学提供。(b)吸尘器机器人Roomba。照片来自HANDOUT/KRT/Newscom
图26-34 (a)手术室内的外科手术机器人。照片来自Patrick Landmann/科学图片库。(b)医院运输机器人。照片来自Wired
图26-35 (a)赢得DARPA城市挑战赛的自主汽车Boss。照片由 Tangi Quemener/AFP/Getty Images/Newscom拍摄,由Sebastian Thrun提供。(b)展示Waymo自主汽车(绿色轨迹上的白车)的感知和预测的空中视角。其他车辆(蓝色方块)和行人(橙色方块)及其预期轨迹也展示在图中。道路/人行道边界为黄色。照片由Waymo提供
图26-36 (a)机器人为废弃煤矿绘制地图。(b)机器人获取的该煤矿三维地图。图片由Sebastian Thrun提供
在本章中,我们将解释为什么我们认为人工智能是一个最值得研究的课题,并试图定义人工智能究竟是什么。这是开启人工智能学习之旅之前不错的准备。
我们称自己为智人(有智慧的人),因为智能(intelligence)对我们来说尤其重要。几千年来,我们一直试图理解我们是如何思考和行动的,也就是不断地了解我们的大脑是如何凭借它那小部分物质去感知、理解、预测并操纵一个远比其自身更大更复杂的世界。人工智能(artificial intelligence,AI)领域不仅涉及理解,还涉及构建智能实体。这些智能实体机器需要在各种各样新奇的情况下,计算如何有效和安全地行动。
人工智能经常被各种调查列为最有趣、发展最快的领域之一,现在每年创造的价值超过一万亿美元。人工智能专家李开复预测称,人工智能对世界的影响“将超过人类历史上的任何事物”。此外,人工智能的研究前沿仍是开放的。学习较古老科学(如物理学)的学生可能会认为最好的想法都已经被伽利略、牛顿、居里夫人、爱因斯坦等人发现了,但当下人工智能仍然为专业人员提供了许多机会。
目前,人工智能包含大量不同的子领域,从学习、推理、感知等通用领域到下棋、证明数学定理、写诗、驾车或诊断疾病等特定领域。人工智能可以与任何智能任务产生联系,是真正普遍存在的领域。
我们声称人工智能很有趣,但是我们还没有描述它是什么。历史上研究人员研究过几种不同版本的人工智能。有些根据对人类行为的复刻来定义智能,而另一些更喜欢用“理性”(rationality)来抽象正式地定义智能,直观上的理解是做“正确的事情”。智能主题的本身也各不相同:一些人将智能视为内部思维过程和推理的属性,而另一些人则关注智能的外部特征,也就是智能行为。[1]
[1] 公众有时会将“人工智能”和“机器学习”这两个术语混淆。机器学习是人工智能的子领域,研究基于经验提升表现的能力。有些人工智能系统使用机器学习方法来获得能力,有些则不然。
从人与理性[2]以及思想与行为这两个维度来看,有4种可能的组合,而且这4种组合都有其追随者和相应的研究项目。他们所使用的方法必然是不同的:追求类人智能必须在某种程度上是与心理学相关的经验科学,包括对真实人类行为和思维过程的观察和假设;而理性主义方法涉及数学和工程的结合,并与统计学、控制理论和经济学相联系。各个研究团体既互相轻视又互相帮助。接下来,让我们更细致地探讨这4种方法。
[2] 我们并不是在暗示人类是“非理性的”,不是像字典上所说的“被剥夺了正常的心智清晰度”。我们只是承认人类的决策在数学上并不总是完美的。
图灵测试(Turing test)是由艾伦·图灵(Alan Turing)提出的(Turing, 1950),它被设计成一个思维实验,用以回避“机器能思考吗?”这个哲学上模糊的问题。如果人类提问者在提出一些书面问题后无法分辨书面回答是来自人还是来自计算机,那么计算机就能通过测试。在第27章中,我们会讨论图灵测试的细节,以及一台通过图灵测试的计算机是否真的具备智能。目前,为计算机编程使其能够通过严格的应用测试尚有大量工作要做。计算机需要具备下列能力:
● 自然语言处理(natural language processing),以使用人类语言成功地交流;
● 知识表示(knowledge representation),以存储它所知道或听到的内容;
● 自动推理(automated reasoning),以回答问题并得出新的结论;
● 机器学习(machine learning),以适应新的环境,并检测和推断模式。
图灵认为,没有必要对人进行物理模拟来证明智能。然而,其他研究人员提出了完全图灵测试(total Turing test),该测试需要与真实世界中的对象和人进行交互。为了通过完全图灵测试,机器人还需要具备下列能力:
● 计算机视觉(computer vision)和语音识别功能,以感知世界;
● 机器人学(robotics),以操纵对象并行动。
以上6个学科构成了人工智能的大部分内容。然而,人工智能研究人员很少把精力用在通过图灵测试上,他们认为研究智能的基本原理更为重要。当工程师和发明家停止模仿鸟类,转而使用风洞并学习空气动力学时,对“人工飞行”的探索取得了成功。航空工程学著作并未将其领域的目标定义为制造“能像鸽子一样飞行,甚至可以骗过其他真鸽子的机器”。
我们必须知道人类是如何思考的,才能说程序像人类一样思考。我们可以通过3种方式了解人类的思维:
● 内省(introspection)——试图在自己进行思维活动时捕获思维;
● 心理实验(psychological experiment)——观察一个人的行为;
● 大脑成像(brain imaging)——观察大脑的活动。
一旦我们有了足够精确的心智理论,就有可能把这个理论表达为计算机程序。如果程序的输入/输出行为与相应的人类行为相匹配,那就表明程序的某些机制也可能在人类中存在。
例如,开发通用问题求解器(General Problem Solver,GPS)的艾伦·纽厄尔(Alan Newell)和赫伯特·西蒙(Herbert Simon)并不仅仅满足于让他们的程序正确地求解问题,他们更关心的是将推理步骤的顺序和时机与求解相同问题的人类测试者进行比较(Newell and Simon, 1961)。认知科学(cognitive science)这一跨学科领域汇集了人工智能的计算机模型和心理学的实验技术,用以构建精确且可测试的人类心智理论。
认知科学本身是一个引人入胜的领域,值得用多本教科书和至少一部百科全书(Wilson and Keil, 1999)来介绍。我们会偶尔评论人工智能技术和人类认知之间的异同,但真正的认知科学必须建立在对人类或动物实验研究的基础上。这里,我们假设读者只有一台可以做实验的计算机,因此我们将把这方面的内容留给其他书籍。
在人工智能发展的早期,这两种方法经常会混淆。有作者认为,如果算法在某个任务中表现良好,就会是建模人类表现的良好模型,反之亦然。而现代作者将这两种主张分开,这种区分使人工智能和认知科学都得到了更快的发展。这两个领域相互促进,值得一提的是计算机视觉领域,它将神经生理学证据整合到了计算模型中。最近,将神经影像学方法与分析数据的机器学习技术相结合,开启了“读心”能力(即查明人类内心思想的语义内容)的研究。这种能力反过来可以进一步揭示人类认知的运作方式。
希腊哲学家亚里士多德是最早试图法则化“正确思维”的人之一,他将其定义为无可辩驳的推理过程。他的三段论(syllogism)为论证结构提供了模式,当给出正确的前提时,总能得出正确的结论。举个经典的例子,当给出前提苏格拉底是人和所有人都是凡人时,可以得出结论苏格拉底是凡人。[这个例子可能是塞克斯都·恩披里柯(Sextus Empiricus)提出的而不是亚里士多德提出的。]这些思维法则被认为支配着思想的运作,他们的研究开创了一个称为逻辑(logic)的领域。
19世纪的逻辑学家建立了一套精确的符号系统,用于描述世界上物体及其之间的关系。这与普通算术表示系统形成对比,后者只提供关于数的描述。到1965年,任何用逻辑符号描述的可解问题在原则上都可以用程序求解。人工智能中所谓的逻辑主义(logicism)传统希望在此类程序的基础上创建智能系统。
按照常规的理解,逻辑要求关于世界的认知是确定的,而实际上这很难实现。例如,我们对政治或战争规则的了解远不如对国际象棋或算术规则的了解。概率(probability)论填补了这一鸿沟,允许我们在掌握不确定信息的情况下进行严格的推理。原则上,它允许我们构建全面的理性思维模型,从原始的感知到对世界运作方式的理解,再到对未来的预测。它无法做到的是形成智能行为。为此,我们还需要关于理性行为的理论,仅靠理性思考是不够的。
智能体(agent)就是某种能够采取行动的东西(agent来自拉丁语agere,意为“做”)。当然,所有计算机程序都可以完成一些任务,但我们期望计算机智能体能够完成更多的任务:自主运行、感知环境、长期持续存在、适应变化以及制定和实现目标。理性智能体(rational agent)需要为取得最佳结果或在存在不确定性时取得最佳期望结果而采取行动。
基于人工智能的“思维法则”方法重视正确的推断。做出正确的推断有时是理性智能体的一部分,因为采取理性行为的一种方式是推断出某个给定的行为是最优的,然后根据这个结论采取行动。但是,理性行为的有些方式并不能说与推断有关。例如,从火炉前退缩是一种反射作用,这通常比经过深思熟虑后采取的较慢的动作更为成功。
通过图灵测试所需的所有技能也使智能体得以采取理性行为。知识表示和推理能让智能体做出较好的决策。我们需要具备生成易于理解的自然语言句子的能力,以便在复杂的社会中生存。我们需要学习不仅是为了博学多才,也是为了提升我们产生高效行为的能力,尤其是在新环境下,这种能力更加重要。
与其他方法相比,基于人工智能的理性智能体方法有两个优点。首先,它比“思维法则”方法更普适,因为正确的推断只是实现理性的几种可能机制之一。其次,它更适合科学发展。理性的标准在数学上是明确定义且完全普适的。我们经常可以从这个标准规范中得出可以被证明能够实现的智能体设计,而把模仿人类行为或思维过程作为目标的设计在很大程度上是不可能的。
由于上述这些原因,在人工智能领域的大部分历史中,基于理性智能体的方法都占据了上风。在最初的几十年里,理性智能体建立在逻辑的基础上,并为了实现特定目标制定了明确的规划。后来,基于概率论和机器学习的方法可以使智能体在不确定性下做出决策,以获得最佳期望结果。简而言之,人工智能专注于研究和构建做正确的事情的智能体,其中正确的事情是我们提供给智能体的目标定义。这种通用范式非常普遍,以至于我们可以称之为标准模型(standard model)。它不仅适用于人工智能,也适用于其他领域。控制理论中,控制器使代价函数最小化;运筹学中,策略使奖励的总和最大化;统计学中,决策规则使损失函数最小;经济学中,决策者追求效用或某种意义的社会福利最大化。
然而在复杂的环境中,完美理性(总是采取精确的最优动作)是不可行的,它的计算代价太高了,因此需要对标准模型做一些重要的改进。第5章和第17章会探讨有限理性(limited rationality)的问题,也就是在没有足够时间进行所有可能的计算的情况下,适当地采取行动。但是,完美理性仍然是理论分析的良好出发点。
[3] 根据beneficial insect的翻译“益虫”,将beneficial machine翻译成“益机”。——译者注
自标准模型被提出以来,其一直是人工智能研究的指南,但从长远来看,它可能不是一个正确的模型,原因是标准模型假设我们总是为机器提供完全指定的目标。
人为定义的任务,如国际象棋或最短路径计算之类的,都附带固有的目标,因此标准模型是适用的。然而,在真实世界中,我们越来越难以完全正确地指定目标。例如,在设计自动驾驶汽车时,我们可能会认为目标是安全到达目的地。但是,由于存在其他司机失误、设备故障等原因,在任何道路上行驶都有可能受伤,因此,严格的安全目标是要求待在车库里而不要上路驾驶。向目的地前进和承担受伤风险是需要权衡的,应该如何进行这种权衡?此外,我们能在多大程度上允许汽车采取会惹恼其他司机的行动?汽车应该在多大程度上调控其加速、转向和刹车动作,以避免摇晃乘客?这类问题很难预先回答。在人机交互的整个领域,这些问题尤其严重,自动驾驶只是其中一个例子。
在我们的真实需求和施加给机器的目标之间达成一致的问题称为价值对齐问题(value alignment problem),即施加给机器的价值或目标必须与人类的一致。如果我们在实验室或模拟器中开发人工智能系统(就像该领域的大多数历史案例一样),就可以轻松地解决目标指定不正确的问题:重置系统、修复目标然后重试。随着人工智能的发展,越来越强大的智能系统需要部署在真实世界中,这种方法不再可行。部署了错误目标的系统将会导致负面影响,而且,系统越智能,其负面影响就越严重。
回想看似没有问题的国际象棋案例,想象一下,如果机器足够智能,可以推断并采取超出棋盘限制的动作,会发生什么。例如,它可能试图通过催眠或勒索对手,或贿赂观众在对手思考时发出噪声等手段来增加获胜的机会。[4]它也可能会为自己劫持额外的计算能力。这些行为不是“愚蠢”或“疯狂”的,这些行为是将获胜定义为机器唯一目标的逻辑结果。
[4] 鲁伊·洛佩兹(Ruy Lopez)在最早的一本关于国际象棋的书(Lopez, 1561)中写道:“把棋盘放好,让阳光晃进对手的眼睛。”
一台实现固定目标的机器可能会出现很多不当行为,要预测所有不当行为是不可能的。因此,我们有足够理由认为标准模型是不充分的。我们不希望机器“聪明”地实现它们的目标,而是希望它们实现我们的目标。如果我们不能将这些目标完美地传达给机器,就需要一个新的表述,也就是机器正在实现我们的目标,但对于目标是什么则是不确定的。当一台机器意识到它不了解完整的目标时,它就会有谨慎行动的动机,会寻求许可,并通过观察来更多地了解我们的偏好,遵守人为控制。最终,我们想要的是对人类可证益的(provably beneficial)智能体。我们将在1.5节中讨论这个主题。
在本节中,我们将简要介绍为人工智能提供思想、观点和技术的学科的历史。像任何历史一样,本书只关注少数人物、事件和思想,而忽略其他同样重要的。我们围绕一系列问题来组织这段历史。我们不希望带给读者这样一种印象:这些问题是各个学科唯一要解决的问题,或者各个学科都将人工智能作为最终成果而努力。
● 可以使用形式化规则得出有效结论吗?
● 思维是如何从物质大脑中产生的?
● 知识从何而来?
● 知识如何导致行为?
亚里士多德(Aristotle,公元前384—公元前322)制定了一套精确的法则来统御思维的理性部分,他是历史上第一位这样做的哲学家。他发展了一套非正式的三段论系统进行适当的推理,该系统原则上允许人们在给定初始前提下机械地得出结论。
拉蒙·鲁尔(Ramon Llull,约1232—1315)设计了一种推理系统,发表为Ars Magna(即The Great Art)(Llull, 1305)[5]。鲁尔试图使用实际的机械设备——一组可以旋转成不同排列的纸盘——实现他的系统。
[5] Ars Magna为拉丁文书名,翻译成英文的书名为The Great Art。——编者注
大约在1500年,列奥纳多·达·芬奇(Leonardo da Vinci,1452—1519)设计了一台机械计算器,虽然当时并未制造,但最近的重构表明该设计是可行的。第一台已知的计算器是在1623年前后由德国科学家威廉·席卡德(Wilhelm Schickard,1592—1635)制造的。布莱兹·帕斯卡(Blaise Pascal,1623—1662)于1642年建造了滚轮式加法器(Pascaline),并写道:“它产生的效用似乎比动物的所有行为更接近思维。”戈特弗里德·威廉·莱布尼茨(Gottfried Wilhelm Leibniz,1646—1716)制造了一台机械设备,旨在根据概念而非数值进行操作,但其应用范围相当有限。托马斯·霍布斯(Thomas Hobbes,1588—1679)在《利维坦》(Leviathan)一书中提出了会思考的机器的想法,用他的话说就是一种“人造动物”,设想“心脏无非就是发条,神经只是一些游丝,而关节不过是一些齿轮”。他还主张推理就像是数值计算,认为“推理就是一种计算,也就是相加减”。[6]
[6] 此处对《利维坦》一书中的引用采用了商务印书馆1985年9月出版的由黎思复、黎廷弼翻译的《利维坦》版本中的译文。——编者注
有观点认为,思维至少在某种程度上是根据逻辑或数值规则运作的,可以建立模仿其中的一些规则的物理系统。也有观点说,思维本身就是这样一个物理系统。勒内·笛卡儿(René Descartes,1596—1650)首次清晰地讨论了思维与物质之间的区别。他指出,思维的纯粹物理概念似乎没有给自由意志留下多少空间。如果思维完全受物理法则支配,那么它拥有的自由意志不会比一块“决定”往下掉的石头多。笛卡儿是二元论(dualism)的支持者。他认为,人类思维(灵魂或者精神)的一部分处于自然之外,不受物理定律的约束。但是,动物不具备这种二元特性,它们可以被视为机器。
唯物主义(materialism)是二元论的一种替代,它认为大脑根据物理定律的运作构成了思维。自由意志仅仅是实体对可选决策的感知。物理主义(physicalism)和自然主义(naturalism)这两个术语也被用于描述这类与超自然观点相反的观点。
如果给定可以操纵知识的实体思维,接下来的问题就是建立知识的来源。经验主义(empiricism)运动始于弗朗西斯·培根(Francis Bacon,1561—1626)的《新工具》(Novum Organum)[7]一书,并以约翰·洛克(John Locke,1632—1704)的名言“知识归根到底都来源于经验”为特征。
[7] 培根的《新工具》(Novum Organum)是亚里士多德的《工具论》(Organon)的更新。
大卫·休谟(David Hume,1711—1776)的《人性论》(A Treatise of Human Nature)(Hume, 1739)提出了现在称为归纳法(induction)的原则:通过暴露要素之间的重复联系获得一般规则。
以路德维希·维特根斯坦(Ludwig Wittgenstein,1889—1951)和伯特兰·罗素(Bertrand Russell,1872—1970)的工作为基础,著名的维也纳学派(Sigmund, 2017)——一群在20世纪20年代及20世纪30年代聚集在维也纳的哲学家和数学家——发展了逻辑实证主义(logical positivism)学说。该学说认为,所有知识都可以通过逻辑理论来描述,逻辑理论最终与对应于感知输入的观察语句(observation sentence)相联系。因此,逻辑实证主义结合了理性主义和经验主义。
鲁道夫·卡纳普(Rudolf Carnap,1891—1970)和卡尔·亨佩尔(Carl Hempel,1905—1997)的确证理论(confirmation theory)试图通过量化应分配给逻辑语句的信念度来分析从经验中获取知识,信念度的取值基于逻辑语句与确证或否定它们的观察之间的联系。卡纳普的《世界的逻辑构造》(The Logical Structure of the World)(Carnap, 1928)也许是最先提出将思维视为计算过程这一理论的著作。
思维的哲学图景中最后一个要素是知识与动作之间的联系。这个问题对人工智能来说至关重要,因为智能不仅需要推理,还需要动作。而且,只有理解了怎样的行为是合理的,才能理解如何构建行为是合理的(或理性的)智能体。
亚里士多德在《论动物的运动》(De Motu Animalium)中指出,动作的合理性是通过目标和动作结果的知识之间的逻辑联系来证明的:
但是,思考有时伴随着行为,有时却没有,有时伴随着行动,有时却没有,这是如何发生的?这看起来和对不变的对象进行推理和推断时发生的情况几乎是一样的。但是在那种情况下,结局是一个推测性的命题……而在这里,由两个前提得出的结论是一个行为……我需要覆盖物;斗篷是一种覆盖物。我需要一件斗篷。我需要什么,我必须做什么;我需要一件斗篷。我必须做一件斗篷。结论是,“我必须做一件斗篷”,这是一个行为。
在《尼各马可伦理学》(Nicomachean Ethics)(第三卷第3章,1112b)中,亚里士多德进一步阐述了这个主题,并提出了一个算法:
我们考虑的不是目的,而是实现目的的手段。医生并不考虑是否要使一个人健康,演说家并不考虑是否要去说服听众……他们是先确定一个目的,然后考虑用什么手段和方式来达到目的。如果有几种手段,他们考虑的就是哪种手段最能实现目的。如果只有一种手段,他们考虑的就是怎样利用这一手段去达到目的,这一手段又需要通过哪种手段来获得。这样,他们就在所发现的东西中一直追溯到最初的东西……分析的终点也就是起点。如果恰巧遇到不可能的事情,例如需要钱却得不到钱,那么就放弃这种考虑。而所谓可能的事情,就是以我们自身能力可以做到的那些事情。[8]
[8] 此处对《尼各马可伦理学》一书中的引用采用了商务印书馆2017年8月出版的廖申白翻译的《尼各马可伦理学》版本中的译文。——编者注
2300年后,纽厄尔和西蒙在他们的通用问题求解器(General Problem Solver)程序中实现了亚里士多德的算法。我们现在将其称为贪婪回归规划系统(见第11章)。在人工智能理论研究的前几十年中,基于逻辑规划以实现确定目标的方法占据主导地位。
纯粹从行为的角度来思考实现目标通常是有用的,但在某些情况是不适用的。例如,如果有几种不同的方法可以实现目标,我们就需要某种方法来进行选择。更重要的是,确定性地实现一个目标可能是无法做到的,但某些行为仍然必须被实施。那该如何决策呢?安托万·阿尔诺(Antoine Arnauld)(Arnauld, 1662)分析了赌博中的理性决策概念,提出了一种量化公式,可以最大化期望收入的货币价值。后来,丹尼尔·伯努利(Daniel Bernoulli)(Bernoulli, 1738)引入了更普适的效用(utility)概念,可以体现结果的内在主观价值。如第16章所述,在不确定性下,理性决策的现代概念涉及最大化期望效用。
在道德和公共政策方面,决策者必须考虑多个个体的利益。杰里米·边沁(Jeremy Bentham)(Bentham, 1823)和约翰·斯图尔特·穆勒(John Stuart Mill)(Mill, 1863)提出了功利主义(utilitarianism)思想:基于效用最大化的理性决策应该适用于人类活动的所有领域,包括代表许多个体做出公共政策的决策。功利主义是一种特殊的结果主义(consequentialism),行为的预期结果决定了正确与否。
相反,伊曼努尔·康德(Immanuel Kant)在1785年提出了一种基于规则或义务伦理学(deontological ethics)的理论。在该理论中,“做正确的事”不是由结果决定的,而是由管理可行行为的普适社会法则所决定的,可行行为包括“不要撒谎”“不要杀人”等。因此,如果期望的好处大于坏处,那么功利主义者可以撒一个善意的谎言,但康德主义者则不能这样做,因为撒谎本质上就是错误的。穆勒承认规则的价值,但将其理解为基于第一性原理对结果进行推理的高效决策程序。许多现代人工智能系统正是采用了这种方法。
● 得出有效结论的形式化规则是什么?
● 什么可以被计算?
● 如何使用不确定的信息进行推理?
哲学家们提出了人工智能的一些基本理念,但人工智能要成为正规科学,需要逻辑和概率的数学化,并引入一个新的数学分支——计算。
形式化逻辑(formal logic)的思想可以追溯到古希腊、古印度和古代中国的哲学家,但它的数学发展真正始于乔治·布尔(George Boole,1815—1864)的工作。布尔提出了命题和布尔逻辑的细节(Boole, 1847)。1879年,戈特洛布·弗雷格(Gottlob Frege,1848—1925)将布尔逻辑扩展到包括对象和关系,创建了沿用至今的一阶逻辑[9]。一阶逻辑除了在人工智能研究的早期发挥核心作用外,还激发了哥德尔和图灵的工作,这些工作支撑了计算本身。
[9] 弗雷格提出的一阶逻辑符号(文本和几何特征的神秘组合)从未流行起来。
概率(probability)论可以视为信息不确定情况下的广义逻辑,这对人工智能来说是非常重要的考虑。吉罗拉莫·卡尔达诺(Gerolamo Cardano,1501—1576)首先提出了概率的概念,并根据赌博事件的可能结果对其进行了刻画。1654年,布莱兹·帕斯卡(Blaise Pascal,1623—1662)在给皮埃尔·费马(Pierre Fermat,1601—1665)的信中展示了如何预测一个未完成的赌博游戏的结局,并为赌徒分配平均收益。概率很快成为定量科学的重要组成部分,用于处理不确定的度量和不完备的理论。雅各布·伯努利(Jacob Bernoulli,1654—1705,丹尼尔·伯努利的叔叔)、皮埃尔·拉普拉斯(Pierre Laplace,1749—1827)等人发展了这一理论,并引入了新的统计方法。托马斯·贝叶斯(Thomas Bayes,1702—1761)提出了根据新证据更新概率的法则。贝叶斯法则是人工智能系统的重要工具。
概率的形式化结合数据的可用性,使统计学(statistics)成为了一个新研究领域。最早的应用之一是1662年约翰·格兰特(John Graunt)对伦敦人口普查数据的分析。罗纳德·费舍尔(Ronald Fisher)被认为是第一位现代统计学家,他汇总了概率、实验设计、数据分析和计算等思想(Fisher, 1922)。在1919年,他坚称,如果没有机械计算器“百万富翁”(Millionaire,第一个可以做乘法的计算器),他就无法进行工作,尽管这台计算器的成本远远超过了他的年薪(Ross, 2012)。
计算的历史与数字的历史一样古老,但用于计算最大公约数的欧几里得算法被认为是第一个非平凡的算法(algorithm)。“算法”一词源自一位9世纪的数学家穆罕默德·本·穆萨·阿尔·花剌子模(Muhammad ibn Musa al-Khwarizmi),他的著作还将阿拉伯数字和代数引入了欧洲。布尔等人讨论了逻辑演绎的算法,到19世纪末,人们开始努力将一般的数学推理形式化为逻辑演绎。
库尔特·哥德尔(Kurt Gödel,1906—1978)表明,虽然存在一种有效方法能够证明弗雷格和罗素的一阶逻辑中的任何真实陈述,但是一阶逻辑无法满足表征自然数所需的数学归纳原理。1931年,哥德尔证明关于演绎的限制确实存在。哥德尔的不完全性定理(incompleteness theorem)表明,在任何像皮亚诺算术(Peano arithmetic,自然数的基本理论)这样强的形式化理论中,必然存在一些没有证明的真实陈述。
这个基本结果也可以解释为作用于整数上的某些函数无法用算法表示,即它们无法被计算。这促使艾伦·图灵(Alan Turing,1912—1954)试图准确地描述哪些函数是可计算的,即能够通过有效的过程进行计算。丘奇-图灵论题(Church-Turing thesis)提出将图灵机(Turing, 1936)可计算的函数作为可计算性的一般概念。图灵还表明,存在某些任何图灵机都无法计算的函数。例如,没有一台机器能够在广义上判断给定程序是会根据给定的输入返回答案,还是永远运行下去。
尽管可计算性(computability)对理解计算很重要,但易处理性(tractability)的概念对人工智能的影响更大。粗略地说,如果解决一个问题实例所需的时间随着问题规模呈指数增长,那么这个问题就是难处理的。在20世纪60年代中期,复杂性的多项式增长和指数增长之间的区别首次被强调(Cobham, 1964; Edmonds, 1965)。因为指数级增长意味着即使是中等规模的问题实例也无法在合理的时间内解决,所以易处理性很重要。
由斯蒂芬·库克(Stephen Cook)(Cook, 1971)和理查德·卡普(Richard Karp)(Karp, 1972)开创的NP完全性(NP-completeness)理论为分析问题的易处理性提供了基础:任何可以归约到NP完全的问题都可能是难处理的。(尽管尚未证明NP完全问题一定是难处理的,但大多数理论家都相信这一点。)这些结果与大众媒体对第一台计算机的乐观态度——“比爱因斯坦还快的电子超级大脑!”——形成了鲜明对比。尽管计算机的速度在不断提高,但对资源的谨慎使用和必要的缺陷将成为智能系统的特征。粗略地说,世界是一个极大的问题实例!
● 我们应该如何根据自己的偏好做出决定?
● 当其他人可能不支持时,我们应该怎么做?
● 当收益可能在很遥远的未来时,我们应该怎么做?
经济学起源于1776年,当时亚当·斯密(Adam Smith,1723—1790)发表了《国富论》(全名为《国民财富的性质和原因的研究》,An Inquiry into the Nature and Causes of the Weallth of Nations)。斯密建议将经济视为由许多关注自身利益的独立主体组成,但他并不主张将金融贪婪作为道德立场。他在较早的著作《道德情操论》(The Theory of Moral Sentiments)(Smith, 1759)开篇就指出,对他人福祉的关注是每个个体利益的重要组成部分。
大多数人认为经济学就是关于钱的,而实际上第一个对不确定性下的决策进行数学分析的是安托万·阿尔诺(Arnauld, 1662)的最大期望值公式,而这一分析也的确是与赌注的货币价值相关。丹尼尔·伯努利(Bernoulli, 1738)注意到,这个公式似乎不适用于更大规模的金钱,例如对海上贸易远征的投资。于是,他提出了基于期望效用最大化的原则,并指出额外货币的边际效用会随着一个人获得更多货币而减少,从而解释了大众的投资选择。
里昂·瓦尔拉斯(Léon Walras,1834—1910)为效用理论提供了一个更为普适的基础,即对任何结果(不仅仅是货币结果)的投机偏好。弗兰克·拉姆齐(Frank Ramsey)(Ramsey, 1931)以及后来约翰·冯·诺伊曼(John von Neumann)和奥斯卡·摩根斯特恩(Oskar Morgenstern)在他们的著作《博弈论与经济行为》(The Theory of Games and Economic Behavior)(Neumann and Morgenstern, 1944)中对这一理论进一步改进。经济学不再是研究金钱的学科,而是对欲望和偏好的研究。
决策论(decision theory)结合了概率论和效用理论,为在不确定性下做出个体决策(经济的或其他的)提供了一个形式化完整的框架,也就是说,概率适当地描述了决策者所处的环境。这适用于“大型”经济体,在这种经济体中,每个主体都无须关注其他独立主体的行为。对“小型”经济体而言更像是一场博弈(game):一个参与者的行为可以显著影响另一个参与者的效用(积极或消极的)。冯·诺依曼和摩根斯特恩对博弈论(game theory)的发展[也可以参考(Luce and Raiffa, 1957)]得出了令人惊讶的结果,即对于某些博弈,理性智能体应该采用随机(或至少看起来是随机)的策略。与决策论不同,博弈论并没有为行为的选择提供明确的指示。人工智能中涉及多个智能体的决策将在多智能体系统(multiagent system)的主题下探讨(第18章)。
经济学家(除了一些例外)没有解决上面列出的第三个问题:当行为的收益不是立即产生的,而是在几个连续的行为后产生时,应该如何做出理性的决策。这个课题在运筹学(operations research)的领域探讨,运筹学出现在第二次世界大战期间英国对雷达安装的优化工作中,后来发展出了无数民用应用。理查德·贝尔曼(Richard Bellman)(Bellman, 1957)的工作将一类序贯决策问题进行了形式化,称为马尔可夫决策过程(Markov decision process),我们将在第17章研究该问题,并在第22章以强化学习(reinforcement learning)的主题研究该问题。
经济学和运筹学的工作对理性智能体的概念做出了很大贡献,但是多年来的人工智能研究是沿着完全独立的道路发展的。原因之一是做出理性决策显然是复杂的。人工智能的先驱赫伯特·西蒙(Herbert Simon, 1916—2001)凭借其早期工作在1978年获得了诺贝尔经济学奖,他指出基于满意度(satisficing)的决策模型(做出“够好”的决策,而不是费力地计算最优决策)可以更好地描述实际的人类行为(Simon, 1947)。自20世纪90年代以来,人工智能的决策理论技术重新引起了人们的兴趣。
● 大脑如何处理信息?
神经科学(neuroscience)是对神经系统(尤其是对大脑)的研究。尽管大脑进行思考的确切方式是科学的奥秘之一,但大脑确实是能思考的现实已经被人们接受了数千年,因为有证据表明,对头部的强烈打击会导致精神丧失。人们也早就知道人的大脑在某种程度上是不同的,大约在公元前335年,亚里士多德写道:“在所有动物中,人类的大脑与身体大小的比例最大。”[10]然而,直到18世纪中叶,大脑才被广泛认为是意识的所在地。在此之前,意识所在地的候选位置包括心脏和脾脏。
[10] 后来人们发现树鼩和一些鸟类的脑体比超过了人类的脑体比。
1861年,保罗·布罗卡(Paul Broca,1824—1880)对脑损伤患者中的失语症(语言缺陷)进行了调查研究,他在大脑左半球发现一个局部区域(现在被称为布罗卡氏区域)负责语音的产生,从而开始了对大脑功能组织的研究。[11]那时,人们已经知道大脑主要由神经细胞或神经元(neuron)组成,但直到1873年,卡米洛·高尔基(Camillo Golgi,1843—1926)才发明了一种可以观察单个神经元的染色技术(见图1-1)。圣地亚哥·拉蒙-卡哈尔(Santiago Ramon y Cajal,1852—1934)在神经组织的开创性研究中使用了该技术。[12]现在人们普遍认为认知功能是由这些结构的电化学反应产生的。也就是说,一组简单的细胞就可以产生思维、行为和意识。如约翰·希尔勒(John Searle)(Searle, 1992)的精辟名言所说:大脑产生思想。
[11] 许多人引用亚历山大·胡德(Alexander Hood)(Hood, 1824)的论文作为可能的先验资料。
[12] 卡哈尔提出了“神经元学说”,高尔基则坚持他的信念,认为大脑的功能主要是在神经元嵌入的连续介质中发挥的。虽然两人共同获得1906年的诺贝尔奖,但发表的获奖感言却是相互对立的。
图1-1 神经细胞或神经元的部分。每个神经元都由一个包含神经核的细胞体或体细胞组成。许多从细胞体中分支出来的纤维状被称为树突,其中的长纤维被称为轴突。轴突伸展的距离很长,比这张图上显示的要长得多。轴突一般长1厘米(是细胞体直径的100倍),但也可以达到1米。一个神经元在称为突触的连接处与其他10~100 000个神经元建立连接。信号通过复杂的电化学反应从一个神经元传递到其他神经元。这些信号可以在短期内控制大脑活动,还可以长期改变神经元的连通性。这些机制被认为是大脑学习的基础。大多数信息都在大脑皮质(大脑的外层)中处理的。基本的组织单元似乎是直径约0.5毫米的柱状组织,包含约20 000个神经元,并延伸到整个皮质(人类皮质深度约4毫米)
现在,我们有了一些关于大脑区域和身体部位之间映射关系的数据,这些部位是受大脑控制或者是接收感官输入的。这样的映射可以在几周内发生根本性的变化,而有些动物似乎具有多个映射。此外,我们还没有完全理解当一个区域受损时其他区域是如何接管其功能的。而且,关于个人记忆是如何存储的,或者更高层次的认知功能是如何运作的,目前几乎没有任何相关理论。
1929年,汉斯·伯杰(Hans Berger)发明脑电图仪(EEG),开启了对完整大脑活动的测量。功能磁共振成像(fMRI)的发展(Ogawa et al., 1990; Cabeza and Nyberg, 2001)为神经科学家提供了前所未有的大脑活动的详细图像,从而使测量能够以有趣的方式与正在进行的认知过程相对应。神经元活动的单细胞电记录技术和光遗传学(optogenetics)方法的进展(Crick, 1999; Zemelman et al., 2002; Han and Boyden, 2007)增强了这些功能,从而可以测量和控制被修改为对光敏感的单个神经元。
用于传感和运动控制的脑机接口(brain-machine interface)的发展(Lebedev and Nicolelis, 2006)不仅有望恢复残疾人的功能,还揭示了神经系统许多方面的奥秘。这项工作的一项重要发现是,大脑能够自我调整,使自己成功与外部设备进行交互,就像对待另一个感觉器官或肢体一样。
大脑和数字计算机有不同的特性。如图1-2所示,计算机的周期时间比大脑快一百万倍。虽然与高端个人计算机相比,大脑拥有更多的存储和互连,但最大的超级计算机在某些指标上已经与大脑相当。未来主义者充分利用这些数字,指出了一个即将到来的奇点(singularity),在这个奇点上计算机达到了超越人类的性能水平(Vinge, 1993; Kurzweil, 2005; Doctorow and Stross, 2012),然后会进一步迅速提高。但是比较原始数字并不是特别有用。即使计算机的容量到达无限也无济于事,在理解智能方面仍然需要进一步的概念突破(见第28章)。粗略地说,如果没有正确的理论,更快的机器只会更快地给出错误的答案。
图1-2 领先的超级计算机Summit(Feldman, 2017)、2019年的典型个人计算机和人类大脑的粗略对比。数千年来,人类大脑的能力并没有发生太大变化,而超级计算机的计算能力已经从20世纪60年代的百万次浮点运算(MFLOP)提高到了20世纪80年代的十亿次浮点运算(GFLOP)、20世纪90年代的万亿次浮点运算(TFLOP)、2008年的千万亿次浮点运算(PFLOP)以及2018年的百亿亿次浮点运算(exaFLOP,1 exaFLOP = 1018次浮点运算/秒)
● 人类和动物是如何思考和行为的?
科学心理学的起源通常可以追溯到德国物理学家赫尔曼·冯·赫尔姆霍茨(Hermann von Helmholtz,1821—1894)和他的学生威廉·温特(Wilhelm Wundt,1832—1920)的工作。赫尔姆霍茨将科学方法应用于人类视觉的研究,他的Handbook of Physiological Optics被描述为“关于人类视觉的物理学和生理学的最重要的专著”(Nalwa, 1993, p.15)。1879年,温特在莱比锡大学开设了第一个实验心理学实验室。温特坚持严格控制的实验,他实验室的工作人员在进行感知或联想任务的同时,内省他们的思维过程。严格的控制在很大程度上帮助心理学成为了一门科学,但是数据的主观性质使得实验者不太可能会推翻自己的理论。
另外,研究动物行为的生物学家缺乏内省的数据,于是发展了一种客观的方法,赫伯特·詹宁斯(Herbert S. Jennings)(Jennings, 1906)在他有影响力的著作Behavior of the Lower Organisms中对此进行了描述。约翰·沃森(John Watson,1878—1958)领导的行为主义(behaviorism)运动将这一观点应用于人类,以内省无法提供可靠证据为由,拒绝任何涉及心理过程的理论。行为主义者坚持只研究施加动物的感知(或刺激)及其产生的行为(或反应)的客观度量。行为主义发现了很多关于老鼠和鸽子的知识,但是在理解人类方面却不太成功。
认知心理学(cognitive psychology)认为大脑是一个信息处理设备,这至少可以追溯到威廉·詹姆斯(William James,1842—1910)的著作。赫尔姆霍茨也坚持认为感知涉及一种无意识的逻辑推断形式。在美国,认知观点在很大程度上被行为主义所掩盖,但在弗雷德里克·巴特利特(Frederic Bartlett,1886—1969)所领导的剑桥大学应用心理学系,认知模型得以蓬勃发展。巴特利特的学生和继任者肯尼斯·克雷克(Kenneth Craik)(Craik, 1943)所著的The Nature of Explanation强有力地重新确立了诸如信念和目标之类的“精神”术语的合法性,认为它们就像用压力和温度来讨论气体一样科学,尽管气体是由既不具有压力又不具有温度的分子组成。
克雷克指出了知识型智能体的3个关键步骤:(1)刺激必须转化为一种内在表示;(2)认知过程处理表示,从而产生新的内部表示;(3)这些过程反过来又被重新转化为行为。他清晰地解释了为什么这是一个良好的智能体设计:
如果有机体拥有一个“小规模的模型”,建模了外部现实及其在脑海中可能采取的行为,那么它就能够尝试各种选择,得出哪个是最好的,并在未来出现情况之前加以应对。有机体可以利用过去的知识处理现在和未来的情况,并在各方面以更全面、更安全、更有力的方式应对紧急情况。(Craik, 1943)
继1945年克雷克死于自行车事故之后,唐纳德·布劳德本特(Donald Broadbent)继续从事这一工作。布劳德本特的Perception and Communication(Broadbent, 1958)是最早将心理现象建模为信息处理的著作之一。与此同时的美国,计算机建模的发展导致了认知科学(cognitive science)领域的诞生。这个领域可以说是开始于1956年9月麻省理工学院的一次研讨会上,并且仅仅两个月后,人工智能本身就“诞生”了。
在研讨会上,乔治·米勒(George Miller)发表了“The Magic Number Seven”,诺姆·乔姆斯基(Noam Chomsky)发表了“Three Models of Language”,艾伦·纽厄尔和赫伯特·西蒙发表了“The Logic Theory Machine”。这3篇影响广泛的论文分别展示了如何使用计算机模型处理记忆、语言和逻辑思维的心理学问题。现在心理学家普遍认为“认知理论应该就像一个计算机程序”(Anderson, 1980),也就是说,认知理论应该从信息处理的角度来描述认知功能的运作。
为了综述目的,我们将人机交互(human-computer interaction,HCI)领域归于心理学下。人机交互的先驱之一道格·恩格巴特(Doug Engelbart)倡导智能增强(intelligence augmentation)的理念(IA而非AI)。他认为,计算机应该增强人类的能力,而不是完全自动化人类的任务。1968年,在恩格巴特的“所有演示之母”(mother of all demos)上首次展示了计算机鼠标、窗口系统、超文本和视频会议,所有这些都是为了展示人类知识工作者可以通过某些智能增强来共同完成工作。
今天,我们更倾向于将IA和AI视为同一枚硬币的两面,前者强调人类控制,而后者强调机器的智能行为,都是机器有利于人类所必需的。
● 如何构建高效的计算机?
现代数字电子计算机是由陷入第二次世界大战中的3个国家的科学家们独立且几乎同时发明的。第一台可操作的计算机是由艾伦·图灵的团队于1943年建造的机电希思·罗宾逊(Heath Robinson[13]),它的唯一目的是破译德国的情报。1943年,同一小组开发了Colossus,这是一款基于真空管的强大通用机器。[14]第一台可操作的可编程计算机是Z-3,是德国工程师康拉德·楚泽(Konrad Zuse)在1941年发明的。楚泽还发明了浮点数和第一个高级编程语言Plankalkül。第一台电子计算机ABC是约翰·阿塔纳索夫(John Atanasoff)和他的学生克利福德·贝里(Clifford Berry)在1940年至1942年间在爱荷华州立大学组装的。阿塔纳索夫的研究很少得到支持或认可,而ENIAC作为宾夕法尼亚大学秘密军事项目的一部分被证明是现代计算机最有影响力的先驱。ENIAC的开发团队包括了约翰·莫奇利(John Mauchly)和约翰·普雷斯伯·埃克特(J. Presper Eckert)等工程师。
[13] 以一位英国漫画家的名字命名的复杂机器。这位漫画家描绘了一些古怪而又荒唐的复杂装置来完成日常任务,如给面包涂黄油。
[14] 在第二次世界大战后,图灵想把这些计算机用于人工智能研究,例如,他创建了第一个国际象棋程序的框架(Turing et al., 1953),但英国政府阻止了这项研究。
从那时起,每一代计算机硬件更新都带来了速度和容量的提升以及价格的下降,这是摩尔定律(Moore’s law)所描述的趋势。直到2005年之前,大约每18个月CPU的性能就会翻一番,但功耗问题导致制造商开始增加CPU的核数而不是提高CPU的时钟频率。目前的预期是,未来性能的增加将来自于大量的并行性,这体现了与大脑特性奇妙的一致性。在应对不确定的世界时,基于这一理念设计硬件:不需要64位的数字精度,只需16位(如bfloat16
格式)甚至8位就足够了,这可以使处理速度更快。
已经出现了一些针对人工智能应用进行调整的硬件,如图形处理单元(GPU)、张量处理单元(TPU)和晶圆级引擎(WSE)。从20世纪60年代到大约2012年,用于训练顶级机器学习应用的计算能力遵循了摩尔定律。从2012年开始,情况发生了变化:从2012年到2018年,这一数字增长了30万倍,大约每100天翻一番(Amodei and Hernandez, 2018)。在2014年花一整天训练的机器学习模型在2018年只需两分钟就可以训练完成(Ying et al., 2018)。尽管量子计算(quantum computing)还不实用,但它有望为人工智能算法的一些重要子方向提供更显著的加速。
毋庸置疑,在电子计算机出现之前计算设备就已经存在了。最早的自动化机器可追溯到17世纪(见1.2.1节的讨论)。第一台可编程机器是由约瑟夫·玛丽·雅卡尔(Joseph Marie Jacquard,1752—1834)于1805年发明的提花织布机,它使用打孔卡片来存储编织图案的指令。
19世纪中期,查尔斯·巴贝奇(Charles Babbage,1792—1871)设计了两台计算机,但都没有完成。差分机的目的是为工程和科学项目计算数学表。它最终于1991年建成并投入使用(Swade, 2000)。巴贝奇的分析机更有雄心:它包括可寻址内存、基于雅卡尔打孔卡的存储程序以及有条件的跳转。这是第一台能够进行通用计算的机器。
巴贝奇的同事埃达·洛芙莱斯(Ada Lovelace,诗人拜伦勋爵的女儿)理解了计算机的潜力,将其描述为“一种能思考或者……能推理的机器”,能够对“宇宙中所有事物”进行推理(Lovelace, 1843)。她还预测到了人工智能的技术成熟度曲线,并提出:“我们最好防范可能夸大分析机能力的想法。”遗憾的是,巴贝奇的机器和洛芙莱斯的思想已基本被遗忘了。
人工智能还得益于计算机科学软件方面的发展,后者提供了编写现代程序所需的操作系统、编程语言和工具(以及有关它们的论文)。而这也是人工智能对其有回馈的领域:人工智能工作开创的许多想法正重归主流计算机科学,包括分时、交互式解释器、使用窗口和鼠标的个人计算机、快速开发环境、链表数据类型、自动存储管理,以及符号式编程、函数式编程、说明性编程和面向对象编程的关键概念。
● 人造物如何在它们自己的控制下运行?
居住在亚历山大城的古希腊工程师克特西比乌斯(Ktesibios,约公元前250年)建造了第一个自我控制的机器:一台水钟,其特点是拥有一个可以保持恒定水流速度的调节器。这一发明改变了人造物可以做什么的定义。在此之前,只有生物才能根据环境的变化来改变自己的行为。其他自调节反馈控制系统的示例工作包括由詹姆斯·瓦特(James Watt,1736—1918)创建的蒸汽机调节器以及科内利斯·德雷贝尔(Cornelis Drebbel,1572—1633,潜艇发明者)发明的恒温器。詹姆斯·克拉克·麦克斯韦(James Clerk Maxwell)(Maxwell, 1868)开创了控制系统的数学理论。
第二次世界大战后,控制理论(control theory)发展的核心人物是诺伯特·维纳(Norbert Wiener,1894—1964)。维纳是一位杰出的数学家,在对生物和机械控制系统及其与认知的联系产生兴趣之前,曾与伯特兰·罗素等人合作。像克雷克(把控制系统作为心理模型)一样,维纳和他的同事阿图罗·罗森布鲁斯(Arturo Rosenblueth)以及朱利安·毕格罗(Julian Bigelow)挑战了行为主义正统派(Rosenblueth et al., 1943)。他们认为具有目的的行为源于试图最小化“错误”的调节机制,即当前状态和目标状态之间的差异。20世纪40年代后期,维纳与沃伦·麦卡洛克(Warren McCulloch)、沃尔特·皮茨(Walter Pitts)和约翰·冯·诺伊曼一起组织了一系列有影响力的会议,探索关于认知的新数学和计算模型。维纳的《控制论》(Cybernetics)(Wiener, 1948)成为畅销书,使大众意识到了人工智能机器的可能性。
与此同时,英国控制论专家罗斯·艾什比(W. Ross Ashby)开创了类似的思想(Ashby, 1940)。艾什比、图灵、沃尔特和其他一些学者为“那些在维纳的书出现之前就有维纳想法的人”组织了推理俱乐部[15]。艾什比在《大脑设计》(Design for a Brain)(Ashby, 1948, 1952)一书中详细阐述了他的想法,即可以通过自我平衡(homeostatic)设备来实现智能,该设备使用恰当的反馈回路来实现稳定的自适应行为。
[15] 推理俱乐部(Ratio Club)。Ratio取自推理演算器(calculus ratiocinator),因此此处翻译为“推理俱乐部”。——编者注
现代控制理论,特别是被称为随机最优控制的分支,其目标是设计随时间最小化代价函数(cost function)的系统。这与人工智能的标准模型——设计性能最优的系统大致相符。尽管人工智能和控制理论的创始人之间有着密切的联系,为什么它们却是两个不同的领域呢?答案在于参与者所熟悉的数学技术与每种世界观所包含的对应问题是紧密结合的。微积分和矩阵代数是控制理论的工具,它们适用于固定的连续变量集描述的系统,而人工智能的建立在一定程度上是为了避开这些可感知的局限性。逻辑推理和计算工具使人工智能研究人员能够考虑语言、视觉和符号规划等问题,而这些问题完全超出了控制理论家的研究范围。
● 语言是如何与思维联系的?
1957年,斯金纳(B. F. Skinner)发表了Verbal Behavior,包含该领域最著名的专家对语言学习的行为主义方法的全面详细的描述。但奇怪的是,一篇对这本书的评述也像这本书一样广为人知,几乎扼杀了大众对行为主义的兴趣。评述的作者是语言学家诺姆·乔姆斯基,彼时他刚刚出版了一本关于他自己理论的书《句法结构》(Syntactic Structure)。乔姆斯基指出,行为主义理论并没有解决语言创造力的概念,它没有解释孩子们如何理解并造出他们从未听过的句子。乔姆斯基以句法模型为基础的理论可以追溯到古印度语言学家波你尼(Panini,约公元前350年)。该理论可以解释语言创造力,而且与以前的理论不同,它足够形式化,原则上可以被程序化。
现代语言学和人工智能几乎同时“诞生”,并一起成长,交叉于一个称为计算语言学(computational linguistics)或自然语言处理(natural language processing)的混合领域。相比1957年,理解语言复杂了许多。理解语言需要理解主题和上下文,而不仅仅是理解句子结构。这似乎是显而易见的,但直到20世纪60年代才得到广泛认可。知识表示(knowledge representation)(关于如何将知识转化为计算机可以推理的形式的研究)的大部分早期工作与语言相关联,并受到语言学研究的启发,而语言学研究反过来又与数十年的语言哲学分析工作有关联。
总结人工智能历史里程碑的快速方法是列出图灵奖得主:马文·明斯基(Marvin Minsky)(1969年图灵奖得主)和约翰·麦卡锡(John McCarthy)(1971年图灵奖得主)定义了基于表示和推理的领域基础;艾伦·纽厄尔(Allen Newell)和赫伯特·西蒙(Herbert Simon)(1975年图灵奖得主)提出了关于问题求解和人类认知的符号模型;爱德华·费根鲍姆(Ed Feigenbaum)和劳伊·雷迪(Raj Reddy)(1994年图灵奖得主)开发了通过对人类知识编码来解决真实世界问题的专家系统;朱迪亚·珀尔(Judea Pearl)(2011年图灵奖得主)提出了通过原则性的方式处理不确定性的概率因果推理技术;最近的是约书亚·本吉奥(Yoshua Bengio)、杰弗里·辛顿(Geoffrey Hinton)和杨立昆(Yann LeCun)(2018年图灵奖得主)[16],他们将“深度学习”(多层神经网络)作为现代计算的关键部分。本节的其余部分将更详细地介绍人工智能历史的每个阶段。
[16] 此书英文原著将约书亚·本吉奥、杰弗里·辛顿和杨立昆记录为获得了2019年图灵奖,他们实则获得的是2018年图灵奖。——编者注
现在普遍认为由沃伦·麦卡洛克和沃尔特·皮茨(McCulloch and Pitts, 1943)完成的工作是人工智能的第一项研究工作。他们受到皮茨的顾问尼古拉斯·拉舍夫斯基(Nicolas Rashevsky)(1936, 1938)对数学建模工作的启发,选择了3方面的资源构建模型:基础生理学知识和大脑神经元的功能,罗素和怀特海(Whitehead)对命题逻辑的形式化分析,以及图灵的计算理论。他们提出了一种人工神经元模型,其中每个神经元的特征是“开”或“关”,并且会因足够数量的相邻神经元受到刺激而切换为“开”。神经元的状态被认为是“事实上等同于提出其充分激活的命题”。例如,他们证明任何可计算的函数都可以通过一些神经元互相连接的网络来计算,以及所有的逻辑联结词(AND、OR、NOT等)都可以通过简单的网络结构来实现。麦卡洛克和皮茨还表明适当定义的网络可以学习。唐纳德·赫布(Donald Hebb)(Hebb, 1949)示范了用于修改神经元之间连接强度的简单更新规则。他的规则,现在称为赫布型学习(Hebbian learning),至今仍是一种有影响力的模式。
哈佛大学的两名本科生马文·明斯基(Marvin Minsky,1927—2016)和迪安·埃德蒙兹(Dean Edmonds)在1950年建造了第一台神经网络计算机——SNARC。SNARC使用了3000个真空管和B-24轰炸机上一个多余的自动驾驶装置来模拟由40个神经元组成的网络。后来,明斯基在普林斯顿大学研究了神经网络中的通用计算。他的博士学位委员会对这类工作是否应该被视为数学持怀疑态度,但据说冯·诺伊曼评价:“如果现在还不能被视为数学,总有一天会的。”
还有许多早期工作可以被描述为人工智能,包括1952年由曼彻斯特大学的克里斯托弗·斯特雷奇(Christopher Strachey)和IBM公司的亚瑟·塞缪尔(Arthur Samuel)分别独立开发的西洋跳棋程序。然而,还是图灵的观点最有影响力。早在1947年,他就在伦敦数学协会(London Mathematical Society)就这一主题发表了演讲,并在其1950年的文章“Computing Machinery and Intelligence”中阐明了有说服力的议程。在论文中,他介绍了图灵测试、机器学习、遗传算法和强化学习。如第27章所述,也回答了许多针对人工智能的质疑。他还认为,通过开发学习算法然后教会机器,而不是手工编写智能程序,将更容易创造出人类水平的人工智能。他在随后的演讲中警告说,实现这一目标对人类来说可能不是最好的事情。
1955年,达特茅斯学院的约翰·麦卡锡说服明斯基、克劳德·香农(Claude Shannon)和纳撒尼尔·罗切斯特(Nathaniel Rochester)帮助他召集对自动机理论、神经网络和智能研究感兴趣的美国研究人员。他们于1956年夏天在达特茅斯组织了为期两个月的研讨会。这场研讨会共有10位与会者,其中包括来自卡内基理工学院[17]的艾伦·纽厄尔和赫伯特·西蒙、普林斯顿大学的特伦查德·摩尔(Trenchard More)、IBM的亚瑟・塞缪尔以及来自麻省理工学院的雷·所罗门诺夫(Ray Solomonoff)和奥利弗·赛弗里奇(Oliver Selfridge)。该提案指出:[18]
[17] 现在是卡内基梅隆大学(CMU)。
[18] 这是麦卡锡的术语“人工智能”被第一次正式使用。也许“计算理性”会更精确、威胁更小,但“人工智能”一直存在。在达特茅斯会议50周年纪念会上,麦卡锡表示,他反对使用“计算机”或“可计算”等术语,以表达对诺伯特·维纳的敬意,因为维纳倡导模拟控制设备,而不是数字计算机。
1956年夏天,我们提议在新罕布什尔州汉诺威的达特茅斯学院进行为期两个月共10人参与的人工智能研讨。这次研讨是基于这样的假设:理论上可以精确描述学习的每个方面或智能的任何特征,从而可以制造机器来对其进行模拟。我们将试图寻找让机器使用语言,形成抽象和概念,解决人类特有的各种问题并改进自身的方法。我们认为,如果一个精心挑选的科学家团队在一整个夏天里共同研究这些问题,则可以在一个或多个方面取得重大进展。
尽管有这种乐观的预测,但达特茅斯的研讨会并没有带来任何突破。纽厄尔和西蒙提出了也许是最成熟的工作——一个称为“逻辑理论家”(Logic Theorist,LT)的数学定理证明系统。西蒙声称:“我们已经发明了一种能够进行非数值思维的计算机程序,从而解决了神圣的身心问题。”[19]研讨会结束后不久,这个程序就已经能证明罗素和怀特海的Principia Mathematica第2章中的大多数定理。据报道,当罗素被告知LT提出了一个比Principia Mathematica书中更精巧的证明时,罗素感到很高兴。但《符号逻辑杂志》(The Journal of Symbolic Logic)的编辑们没被打动,他们拒绝了由纽厄尔、西蒙和逻辑理论家合著的论文。
[19] 纽厄尔和西蒙还发明了一种链表处理语言IPL来编写LT。他们没有编译器,只能手动将其翻译为机器代码。为了避免错误,他们并行工作,在编写每条指令时相互大声喊出二进制数,以确保他们是一致的。
20世纪50年代的知识界总体上倾向于相信“机器永远不能做X”。(见第27章中图灵收集的X的详细列表。)人工智能研究人员自然而然地一个接一个地演示X以回应。他们特别关注那些被认为能够显示人类智能的任务,包括游戏、谜题、数学和智商测试。约翰·麦卡锡将这段时期称为“瞧,妈,不需要人动手操控!”(Look,Ma,no hands!)时代。
纽厄尔和西蒙继LT成功之后又推出了通用问题求解器,即GPS。与LT不同,GPS从一开始就被设计为模仿人类求解问题的协议。结果表明,在它可以处理的有限类型的难题中,该程序考虑的子目标和可能采取的行为的顺序与人类处理相同问题的顺序类似。因此,GPS可能是第一个体现“人类思维”方式的程序。作为认知模型,GPS和后续程序的成功使得纽厄尔和西蒙(1976)提出了著名的物理符号系统(physical symbol system)假说,该假说认为“物理符号系统具有进行一般智能动作的必要和充分方法”。意思是,任何显示出智能的系统(人类或机器)必须通过操作由符号组成的数据结构来运行。之后我们会看到这个假说已经受到了多方面的挑战。
在IBM,纳撒尼尔·罗切斯特和他的同事开发了首批人工智能程序。赫伯特·盖伦特(Herbert Gelernter)(Gelernter, 1959)构造了几何定理证明程序(Geometry Theorem Prover),它能够证明许多数学学生认为相当棘手的定理。这项工作是现代数学定理证明程序的先驱。
从长远来看,这一时期所有探索性工作中,最有影响力的可能是亚瑟·萨缪尔对西洋跳棋的研究。通过使用现在称之为强化学习的方法(见第22章),萨缪尔的程序可以以业余高手的水平进行对抗。因此,他驳斥了计算机只能执行被告知的事情的观点:他的程序很快学会了玩游戏,甚至比其创造者玩得更好。该程序于1956年在电视上演示,给人留下了深刻的印象。和图灵一样,萨缪尔也很难找到使用计算机的机会,他只能晚上工作,使用仍在IBM制造工厂测试场地上还未出厂的计算机。萨缪尔的程序是许多后继系统的前身,如TD-Gammon(Tesauro, 1992)和AlphaGo(Silver et al., 2016)。TD-Gammon是世界上最好的西洋双陆棋棋手之一,而AlphaGo因击败人类世界围棋冠军而震惊世界(见第5章)。
1958年,约翰·麦卡锡为人工智能做出了两项重要贡献。在麻省理工学院人工智能实验室备忘录1号中,他定义了高级语言Lisp,Lisp在接下来的30年中成为了最重要的人工智能编程语言。在一篇题为“Programs with Common Sense”的论文中,麦卡锡为基于知识和推理的人工智能系统提出了概念性议案。这篇论文描述了“建议接受者”(Advice Taker),这是一个假想程序,它包含了世界的一般知识,并可以利用它得出行动规划。这个概念可以用简单的逻辑公理来说明,这些逻辑公理足以生成一个开车去机场的规划。该程序还被设计为能在正常运行过程中接受新的公理,从而实现无须重新编程就能够在新领域中运行。因此,“建议接受者”体现了知识表示和推理的核心原则:对世界及其运作进行形式化、明确的表示,并且通过演绎来操作这种表示是很有用的。这篇论文影响了人工智能的发展历程,至今仍有意义。
1958年也是马文·明斯基转到麻省理工学院的一年。然而,他与麦卡锡的最初合作并没有持续。麦卡锡强调形式逻辑中的表示和推理,而明斯基则对程序工作并最终形成反逻辑的观点更感兴趣。1963年,麦卡锡在斯坦福大学建立了人工智能实验室。1965年亚伯拉罕·鲁滨逊(J. A. Robinson)归结原理(一阶逻辑的完备定理证明算法;见第9章)的发现推进了麦卡锡使用逻辑来构建最终“建议接受者”的计划。麦卡锡在斯坦福大学的工作中强调了逻辑推理的通用方法。逻辑的应用包括柯德尔·格林(Cordell Green)的问答和规划系统(Green, 1969b)以及斯坦福研究所(SRI)的Shakey机器人项目,后者(将在第26章中进一步讨论)是第一个展示逻辑推理和物理活动完全集成的项目。
在麻省理工学院,明斯基指导了一批学生,他们选择了一些似乎需要智能才能求解的有限问题。这些有限的领域被称为微世界(microworld)。詹姆斯·斯莱格尔(James Slagle)的Saint程序(Slagle, 1963)能够求解大学一年级课程中典型封闭形式的微积分问题。托马斯·埃文斯(Thomas Evans)的Analogy程序(Evans, 1968)能够解决智商测试中常见的几何类比问题。丹尼尔·博布罗(Daniel Bobrow)的Student项目(Bobrow, 1967)能够求解代数故事问题,例如:
如果汤姆获得的客户数量是他投放的广告数量的20%的平方的两倍,已知他投放的广告数量是45,那么汤姆获得的客户数量是多少?
最著名的微世界是积木世界(blocks world),由一组放置在桌面上的实心积木组成(或者更常见的是模拟桌面),如图1-3所示。在这个世界中,一个典型的任务是用机械手以某种方式重新排列积木,这个机械手一次可以拿起一块积木。积木世界孕育了戴维·哈夫曼(David Huffman)(Huffman, 1971)的视觉项目、戴维·沃尔茨(David Waltz)(Waltz, 1975)的视觉和约束传播工作、帕特里克·温斯顿(Patrick Winston)(Winston, 1970)的学习理论、特里·温诺格拉德(Terry Winograd)(Winograd, 1972)的自然语言理解程序以及斯科特·法尔曼(Scott Fahlman)(Fahlman, 1974)的规划器。
图1-3 积木世界的场景。Shrdlu(Winograd, 1972)刚刚完成了一个命令——“找到一块比你所持有的积木块更高的积木块,并把它放进盒子里”
建立在麦卡洛克和皮茨提出的神经网络上的早期工作也蓬勃发展。什穆埃尔·温诺格拉德(Shmuel Winograd)和杰克·考恩(Jack Cowan)的研究(Winograd and Cowan, 1963)展示了大量元素如何共同代表一个独立的概念,同时提升稳健性和并行性。赫布的学习方法分别得到了伯尼·维德罗(Bernie Widrow)(Widrow and Hoff, 1960; Widrow, 1962)和弗兰克·罗森布拉特(Frank Rosenblatt)(Rosenblatt, 1962)的改进,他们的网络分别被称为线性自适应神经网络(adaline)和感知机(perceptron)。感知机收敛定理(perceptron convergence theorem)(Block et al., 1962)指出,学习算法可以调整感知机的连接强度来拟合任何输入数据(前提是存在这样的拟合)。
从一开始,人工智能研究人员对未来成功的预测毫不避讳。下面这句1957年赫伯特·西蒙的名言经常被引用:
我的目的不是使大家感到惊讶或震惊,我可以总结出的最简单的说法是,现在世界上存在着能够思考、学习和创造的机器。此外,它们的这些能力将迅速提高,在可见的未来内,它们能够处理的问题范围将与人类思维的应用范围一样广泛。
虽然“可见的未来”这个词是模糊的,但西蒙也做出了更具体的预测:10年内,计算机将成为国际象棋冠军以及机器将能证明重要的数学定理。实际上,这些预测的实现(或近似实现)用了40年时间,远远超过10年。当初西蒙的过度自信来自于早期人工智能系统在简单示例任务上的出色表现。但是,在几乎所有情况下,这些早期系统在更困难的问题上都失败了。
失败有两个主要原因。第一个主要原因是许多早期人工智能系统主要基于人类如何执行任务的“知情内省型”,而不是基于对任务、解的含义以及算法需要做什么才能可靠地产生解的仔细分析。
第二个主要原因是对人工智能要求解的问题的复杂性缺乏认识。大多数早期的问题求解系统都会尝试组合不同的步骤,直到找到解为止。这一策略最初奏效是因为微世界所包含的对象非常少,因此可能的动作非常少,解的动作序列也非常短。在计算复杂性理论发展完备之前,人们普遍认为“扩展”到更大的问题仅仅是需要更快的硬件和更大的内存。但是当研究人员无法证明涉及几十个事实的定理时,伴随着归结定理证明发展而来的乐观情绪很快就受到了打击。一般而言,程序可以找到解的事实并不意味着该程序具备任何在实践中找到解所需的机制。
无限计算能力的幻想并不局限于求解问题的程序。早期的机器进化(machine evolution)[现在称为遗传编程(genetic programming)]实验(Friedberg, 1958; Friedberg et al., 1959)基于绝对正确的信念,即通过对机器代码程序进行一系列适当的小变异,就可以为任何特定任务生成表现良好的程序。这个想法就是通过选择过程来尝试随机突变,并保留似乎有用的突变。尽管使用了长达数千小时的CPU时间,但几乎没有任何进展。
未能处理“组合爆炸”是莱特希尔报告(Lighthill, 1973)中对人工智能的主要批评之一,基于这份报告,英国政府决定在除两所大学外的所有大学中停止支持人工智能研究。(口述传说描绘了一幅稍有不同、更加丰富多彩的画面,但带有政治野心和个人好恶的描述都不是本书的话题。)
此外,产生智能行为的基础结构存在一些根本限制也是导致失败的原因。例如,明斯基和派珀特的著作Perceptrons(Minsky and Papert, 1969)证明,尽管感知机(一种简单的神经网络形式)被证明可以学习它们能够表示的任何事物,但它们能表示的事物很少。举例来说,我们无法训练双输入感知机来判断它的两个输入是否相同。尽管他们的研究结果并不适用于更复杂的多层网络,但用于神经网络研究的经费很快就减少到几乎为零。讽刺的是,在20世纪80年代和21世纪10年代再次引起神经网络研究巨大复兴的新反向传播学习算法,早在20世纪60年代初已经在其他情景下得到了发展(Kelley, 1960; Bryson, 1962)。
在人工智能研究的前十年提出的问题求解是一种通用搜索机制,试图将基本的推理步骤串在一起,找到完整的解。这种方法被称为弱方法(weak method),这种方法虽然很普适,但它不能扩展到大型或困难的问题实例上。弱方法的替代方案是使用更强大的领域特定的知识,这些知识允许更大规模的推理步骤,并且可以更轻松地处理特定专业领域中发生的典型案例。有人可能会说,必须已经差不多知道答案才能解决一个难题。
Dendral程序(Buchanan et al., 1969)是这种方法的早期例子。它是在斯坦福大学开发的,爱德华·费根鲍姆(曾是赫伯特·西蒙的学生)、布鲁斯·布坎南(Bruce Buchanan,从哲学家转行的计算机科学家)和乔舒亚·莱德伯格(Joshua Lederberg,诺贝尔生理学或医学奖得主,遗传学家)联手解决了从质谱仪提供的信息推断分子结构的问题。该程序的输入包括分子的基本分子式(如C6H13NO2)和质谱,其中质谱给出了分子被电子束轰击时产生的各种碎片的质量。例如,质谱可能在m = 15处有一个峰,这对应于甲基(CH3)碎片的质量。
朴素版本的程序生成所有可能的符合分子式的结构,然后预测每个结构在质谱仪中的观测结果,并将其与实际质谱进行比较。正如人们所预期的,这对中等规模的分子来说也是难以处理的。Dendral的研究人员咨询了分析化学家,并发现他们通过寻找质谱中已知的峰模式来工作,这些峰表明分子中的常见子结构。例如,以下规则用于识别酮(C=O)结构(分子量28):
如果M是整个分子的质量,且在x1和x2处有两个峰,并且
(a)x1 + x2 = M + 28;(b)x1 − 28 是一个高峰;(c)x2 − 28 是一个高峰;(d)x1和 x2中至
少有一处是高峰,
则该分子含有酮基。
认识到分子包含特定的子结构,可以极大地减少可能候选项的量级。据作者称,Dendral之所以强大,是因为它不是以第一性原理的形式,而是以高效“食谱”的形式体现了质谱的相关知识(Feigenbaum et al., 1971)。Dendral的意义在于它是第一个成功的知识密集型系统:它的专业知识来源于大量专用规则。1971年,费根鲍姆和斯坦福大学的其他研究人员开启了启发式编程项目(heuristic programming project,HPP),以此来研究专家系统(expert system)的新方法可以在多大程度上应用到其他领域。
接下来的一个主要工作是用于诊断血液感染的Mycin系统。Mycin有大约450条规则,它能够表现得和一些专家一样好,甚至比初级医生要好得多。Mycin与Dendral有两个主要区别。首先,不像Dendral规则,不存在可以推导出Mycin规则的一般理论模型,Mycin规则不得不从大量的专家访谈中获得。其次,规则必须反映与医学知识相关的不确定性。Mycin引入了一种称为确定性因子(certainty factor)的不确定性计算(见第13章),这在当时似乎与医生评估证据对诊断影响的方式非常吻合。
第一个成功的商用专家系统R1在数字设备公司(Digital Equipment Corporation,DEC)投入使用(McDermott, 1982),该程序帮助公司配置新计算机系统的订单。截至1986年,它每年为公司节省约4000万美元。到1988年,DEC的人工智能小组已经部署了40个专家系统,而且还有更多的专家系统在开发中。同时期,杜邦公司有100个专家系统在使用,500个在开发。当时几乎每家美国大公司都有自己的人工智能团队,不是在使用专家系统,就是在研究专家系统。
领域知识的重要性在自然语言理解领域也很突出。尽管特里·温诺格拉德的Shrdlu系统取得了成功,但它的方法并没有扩展到更一般的任务:对于歧义消解之类的问题,它使用了依赖于积木世界中微小范围的简单规则。
包括麻省理工学院的尤金·查尔尼克(Eugene Charniak)和耶鲁大学的罗杰·尚克(Roger Schank)在内的几位研究人员一致认为,强大的语言理解需要关于世界的一般知识以及使用这些知识的一般方法。(尚克进一步声称,“根本就没有语法这回事”,这让很多语言学家感到不安,但确实引发了一场有益的讨论。)尚克和他的学生们建立了一系列的程序(Schank and Abelson, 1977; Wilensky, 1978; Schank and Riesbeck, 1981),这些程序都用于理解自然语言。但是,重点不在于语言本身,而在于用语言理解所需的知识来表示和推理问题。
在真实世界中的广泛应用引发了表示和推理工具的广泛发展。有些是基于逻辑的,例如,Prolog语言在欧洲和日本流行,而Planner家族在美国流行。其他人则遵循明斯基的框架(frame)思想(Minsky, 1975),采用了一种更结构化的方法,将有关特定对象和事件类型的事实组合起来,并将这些类型组织成类似于生物分类法的大型分类层次结构。
1981年,日本政府宣布了“第五代计算机”计划,这是一个十年计划,旨在建造运行Prolog的大规模并行智能计算机。按现在的货币系统衡量,预算将超过13亿美元。作为回应,美国成立了微电子与计算机技术公司(Microelectronics and Computer Technology Corporation,MCC),这是一个旨在确保国家竞争力的联盟。在这两个项目中,人工智能都是广泛努力的一部分,包括芯片设计和人机界面研究。在英国,阿尔维(Alvey)报告恢复了被莱特希尔报告取消的资助资金。然而,这些项目都没有在新型的人工智能能力或经济影响方面下实现其宏伟目标。
总的来说,人工智能行业从1980年的几百万美元增长到1988年的数十亿美元,还产生了数百家构建专家系统、视觉系统、机器人以及专门服务于这些目的的软硬件的公司。
但此后不久,经历了一段被称为“人工智能冬天”的时期,许多公司因未能兑现夸张的承诺而停滞。事实证明,为复杂领域构建和维护专家系统是困难的,一部分原因是系统使用的推理方法在面临不确定性时会崩溃,另一部分原因是系统无法从经验中学习。
在20世纪80年代中期,至少有4个不同的团队重新发明了最早在20世纪60年代初期发展起来的反向传播(back-propagation)学习算法。该算法被应用于计算机科学和心理学中的许多学习问题,Parallel Distributed Processing合集(Rumelhart and McClelland, 1986)中的结果的广泛传播引起了极大的轰动。
这些所谓的联结主义(connectionist)模型被一些人视为纽厄尔和西蒙的符号模型以及麦卡锡和其他人的逻辑主义方法的直接竞争对手。人类在某种程度上操纵符号似乎是显而易见的——事实上,人类学家特伦斯·迪肯(Terrence Deacon)在其著作《符号化动物》(The Symbolic Species)(Deacon, 1997)中指出,这是人类的决定性特征。与此相反,20世纪80年代和21世纪10年代神经网络复兴的领军人物杰弗里·辛顿将符号描述为“人工智能的光以太”(19世纪许多物理学家认为电磁波传播的介质是光以太,但其实这种介质不存在)。事实上,我们在语言中命名的许多概念,经过仔细检查后,都未能获得早期人工智能研究人员希望以公理形式描述逻辑定义的充要条件。联结主义模型可能以一种更流畅和不精确的方式形成内部概念,更适配真实世界的混乱。它们还具备从样本中学习的能力,它们可以将它们的预测输出值与问题的真实值进行比较,并修改参数以减少差异,使它们在未来的样本中更有可能表现良好。
专家系统的脆弱性导致了一种新的、更科学的方法,结合了概率而不是布尔逻辑,基于机器学习而不是手工编码,重视实验结果而不是哲学主张。[20]现在更普遍的是,基于现有理论而不是提出全新的理论,基于严格的定理或可靠的实验方法(Cohen, 1995)而不是基于直觉的主张,以及展示与真实世界应用的相关性而不是虚拟的示例。
[20] 一些人将这种变化描述为整洁派(neat,认为人工智能理论应该以数学的严谨性为基础的人)战胜了邋遢派(scruffy,那些宁愿尝试大量的想法,编写一些程序,然后评估哪些似乎可行的人)。这两种方法都很重要。向整洁派的转变意味着该领域已经达到了稳定和成熟的水平。目前对深度学习的重视可能代表着邋遢派的复兴。
共享的基准问题集成为了展示进度的标准,包括加利福尼亚大学欧文分校的机器学习数据集库、用于规划算法的国际规划竞赛、用于语音识别的LibriSpeech语料库、用于手写数字识别的MNIST数据集、用于图像物体识别的ImageNet和COCO、用于自然语言问答的SQuAD、机器翻译的WMT竞赛以及布尔可满足性求解器国际SAT竞赛。
人工智能的创立在一定程度上是对控制理论和统计等现有领域局限性的反抗,但在这一时期,它吸纳了这些领域的积极成果。正如戴维·麦卡莱斯特(David McAllester)(McAllester, 1998)所说:
在人工智能早期,符号计算的新形式(例如框架和语义网络)使大部分经典理论过时,这似乎是合理的。这导致了一种孤立主义,即人工智能在很大程度上与计算机科学的其他领域分离。这种孤立主义目前正在被摒弃。人们认识到,机器学习不应该独立于信息论,不确定推理不应该独立于随机建模,搜索不应该独立于经典优化和控制,自动推理不应该独立于形式化方法和静态分析。
语音识别领域对这种模式进行了说明。20世纪70年代,研究人员尝试了各种不同的架构和方法,许多是相当暂时和脆弱的,并且只能处理几个精心挑选的例子。在20世纪80年代,使用隐马尔可夫模型(hidden Markov model,HMM)的方法开始主导这一领域。HMM有两个相关的方面。首先,它们基于严格的数学理论。这使得语音研究人员能够在其他领域数十年数学成果的基础上进行开发。其次,它们是在大量真实语音数据的语料库上训练而产生的。这确保了健壮性,并且在严格的盲测中,HMM的分数稳步提高。因此,语音技术和手写体字符识别的相关领域向广泛的工业和消费级应用过渡。注意,并没有科学证据表明人类使用HMM识别语音,HMM只是为理解和求解问题提供了一个数学框架。然而,在1.3.8节中我们将看到,深度学习已经破坏了这种舒适的叙述。
1988年是人工智能与统计学、运筹学、决策论和控制理论等其他领域相联系的重要一年。朱迪亚·珀尔的Probabilistic Reasoning in Intelligent Systems(Pearl, 1988)使概率和决策论在人工智能中得到了新的认可。珀尔对贝叶斯网络的发展产生了一种用于表示不确定的知识的严格而有效的形式体系,以及用于概率推理的实用算法。第12~16章涵盖了这个领域,此外最近的发展大大提升了概率形式体系的表达能力,第20章描述了从数据中学习贝叶斯网络(Bayesian network)和相关模型的方法。
1988年的第二个主要贡献是理查德·萨顿(Rich Sutton)的工作,他将强化学习(20世纪50年代被用于亚瑟·塞缪尔的西洋跳棋程序中)与运筹学领域开发的马尔可夫决策过程(Markov decision processe,MDP)联系起来。随后,大量工作将人工智能规划研究与MDP联系起来,强化学习领域在机器人和过程控制方面找到了应用,并获得了深厚的理论基础。
人工智能对数据、统计建模、优化和机器学习的新认识带来的结果是,计算机视觉、机器人技术、语音识别、多智能体系统和自然语言处理等子领域逐渐统一,此前这些子领域在某种程度上已经脱离了核心人工智能。重新统一的过程在应用方面(例如,在此期间实用机器人的部署大大扩展)和关于人工智能核心问题更好的理论理解方面都产生了显著的效用。
计算能力的显著进步和互联网的创建促进了巨大数据集的创建,这种现象有时被称为大数据(big data)。这些数据集包括数万亿字的文本、数十亿的图像、数十亿小时的语音和视频,以及海量的基因组数据、车辆跟踪数据、点击流数据、社交网络数据等。
这导致了专为利用非常大的数据集而设计的学习算法的开发。通常,这类数据集中的绝大多数例子都没有标签。例如,在雅让斯基关于词义消歧的著作(Yarowsky, 1995)中,出现的一个词(如“plant”),并没有在数据集中标明这是指植物还是工厂。然而,如果有足够大的数据集,合适的学习算法在识别句意的任务上可以达到超过96%的准确率。此外,班科和布里尔认为,将数据集的规模增加两到三个数量级所获得的性能提升会超过调整算法带来的性能提升(Banko and Brill, 2001)。
类似的现象似乎也发生在计算机视觉任务中,例如填补照片中的破洞(要么是由损坏造成的,要么是挖除前朋友造成的)。海斯和埃弗罗斯(Hays and Efros, 2007)开发了一种巧妙的方法,从类似的图像中混合像素。他们发现,该技术在仅包含数千幅图像的数据库中效果不佳,但在拥有数百万幅图像的数据库中,该技术超过了质量阈值。不久之后,ImageNet数据库(Deng et al., 2009)中可用的数千万幅图像引发了计算机视觉领域的一场革命。
大数据的可用性和向机器学习的转变帮助人工智能恢复了商业吸引力(Havenstein, 2005; Halevy et al., 2009)。大数据是2011年IBM的Watson系统在《危险边缘》(Jeopardy!)问答游戏中战胜人类冠军的关键因素,这一事件深深影响了公众对人工智能的看法。
深度学习(deep learning)是指使用多层简单的、可调整的计算单元的机器学习。早在20世纪70年代,研究人员就对这类网络进行了实验,并在20世纪90年代以卷积神经网络(convolutional neural network)(LeCun et al., 1995)的形式在手写数字识别方面取得了一定的成功。然而,直到2011年,深度学习方法才真正开始流行起来,首先是在语音识别领域,然后是在视觉物体识别领域。
在2012年的ImageNet竞赛中,需要将图像分类为1000个类别之一(犰狳、书架、开瓶器等)。多伦多大学杰弗里·辛顿团队开发的深度学习系统(Krizhevsky et al., 2013)比以前基于手工特征的系统有了显著改进。从那时起,深度学习系统在某些视觉任务上的表现超过了人类,但在其他一些任务上还显落后。在语音识别、机器翻译、医疗诊断和博弈方面也有类似的进展。AlphaGo(Silver et al., 2016, 2017, 2018)之所以能够战胜人类顶尖的围棋棋手,是因为它使用了深度网络来表示评价函数。
这些非凡的成功使学生、公司、投资者、政府、媒体和公众对人工智能的兴趣重新高涨。似乎每周都有新的人工智能应用接近或超过人类表现的消息,通常伴随着加速成功或人工智能新寒冬的猜测。
深度学习在很大程度上依赖于强大的硬件,一个标准的计算机CPU每秒可以进行109或1010次运算。运行在特定硬件(例如GPU、TPU或FPGA)上的深度学习算法,每秒可能进行1014~1017次运算,主要是高度并行化的矩阵和向量运算。当然,深度学习还依赖于大量训练数据的可用性,以及一些算法技巧(见第21章)。
斯坦福大学的人工智能百年研究(也称为AI100)召集了专家小组来提供人工智能最先进技术的报告。2016年的报告(Stone et al., 2016; Grosz and Stone, 2018)总结:“未来人工智能的应用将大幅增加,包括更多的自动驾驶汽车、医疗诊断和针对性的治疗,以及对老年人护理的物理援助”,并且“社会现在正处于关键时刻,将决定如何以促进而不是阻碍自由、平等和透明等民主价值观的方式部署基于人工智能的技术”。AI100还在其网站上创建了一个人工智能指数(AI Index),以帮助跟踪人工智能的进展。以下列举了与2000年基线相比(除非另有说明),2018年和2019年报告的一些亮点。
● 出版物:人工智能论文数量在2010年至2019年间增长了20倍,达到每年约2万篇。最受欢迎的类别是机器学习(2009年至2017年,arXiv.org上的机器学习论文数量每年都会翻一番)。其次是计算机视觉和自然语言处理。
● 情绪:大约70%的人工智能新闻文章是中性的,但正面基调的文章从2016年的12%上升到2018年的30%。最常见的问题是道德问题——数据隐私和算法偏见。
● 学生:与2010年基线相比,课程注册人数在美国增加了5倍,全球增加了16倍。人工智能是计算机科学中最受欢迎的专业。
● 多样性:全球人工智能领域的教授中,大约80%是男性,20%是女性。博士生和行业招聘也有类似的数字。
● 会议:NeurIPS的参会人数比2012年增加了8倍,达到13 500人。其他会议的参会人数年增长率约为30%。
● 行业:美国的人工智能初创公司数量增长了20倍,达到800多家。
● 国际化:中国每年发表的论文多于美国,与整个欧洲一样多。但是,在引用加权影响方面,美国作者领先中国作者50%。从人工智能招聘人数看,新加坡、巴西、澳大利亚、加拿大和印度是增长最快的国家。
● 视觉:物体检测的错误率(大规模视觉识别挑战,LSVRC)从2010年的28%下降到2017年的2%,超过了人类的表现。自2015年以来,开放式视觉问答(VQA)的准确率从55%提高到68%,但仍远落后于人类83%的表现。
● 速度:在过去两年中,图像识别任务的训练时间减少了100倍。顶级人工智能应用使用的计算能力每3.4个月就会翻一番。
● 语言:以斯坦福问答数据集(SQuAD)的F1分数衡量的问答准确率,自2015年到 2019年从60分提升到95分,在SQuAD2版本上进展更快,仅在一年内从62分提升到90分。这两个分数都超过了人类表现。
● 人类基准:截至2019年,人工智能系统在多个领域达到或超越人类表现,包括国际象棋、围棋、扑克、《吃豆人》(Pac-Man)、《危险边缘》(Jeopardy!)、ImageNet物体检测、有限域中的语音识别、约束域中的英文翻译、《雷神之锤3》(Quake III)、《刀塔2》(Dota 2)、《星际争霸II》(StarCraft II)、Atari的各种游戏、皮肤癌检测、前列腺癌检测、蛋白质折叠、糖尿病视网膜病变诊断等。
人工智能系统何时(如果可以的话)能够在各种任务中达到人类水平的表现?马丁·福特(Martin Ford)(Ford, 2018)通过对人工智能专家的访谈发现这一目标时间的范围很广,从2029年到2200年,均值为2099年。在一项类似的调查中(Grace et al., 2017),50%的受访者认为这可能在2066年发生,有10%的人认为这最早可能在2025年发生,少数人则认为“不可能”。对于我们是需要根本性的新突破,还是仅仅对现有方法进行改进,专家们也存在分歧。但是不要过于严肃对待他们的预测,正如菲利普·泰洛克(Philip Tetlock)(Tetlock, 2017)在预测世界事件领域所证明的那样,专家并不比业余爱好者预测得更准。
未来的人工智能系统将如何运作?我们还不能确定。正如本节所详述的,这个领域采用了几个关于它本身的故事:首先是一个大胆的想法,即机器的智能是可能的,然后是它可以通过将专家知识编码成逻辑来实现,接着是建模世界的概率模型将成为主要工具,以及最近的机器学习将产生可能根本不基于任何易于理解的理论的模型。未来将揭示接下来会出现什么模式。
人工智能现在能做什么?也许不像一些更乐观的媒体文章让人相信的那样多,但仍然很多,以下是一些例子。
自动驾驶:自动驾驶的历史可以追溯到20世纪20年代的无线电遥控汽车,而在20世纪80年代首次展示了没有特殊向导的自动道路驾驶(Kanade et al., 1986; Dickmanns and Zapp, 1987)。在2005年的212公里沙漠赛道DARPA挑战赛(Thrun, 2006)和 2007 年繁忙城市道路的城市挑战赛上,自动驾驶汽车成功展示之后,自动驾驶汽车的开发竞赛正式开始。2018年,Waymo的测试车辆在公共道路上行驶超过1600万公里,没有发生严重事故,其中人类司机每9650公里才介入一次接管控制。不久之后,该公司开始提供商业机器人出租车服务。
自2016年以来,自动固定翼无人机一直在为卢旺达提供跨境血液输送服务。四轴飞行器可以进行出色的特技飞行,可以在构建三维地图的同时探索建筑,并进行自主编队。
腿足式机器人:雷伯特等人制作的四足机器人BigDog(Raibert et al., 2008),颠覆了我们对机器人如何行动的概念——不再是好莱坞电影中机器人缓慢、僵硬、左右摇摆的步态,而是类似于动物,并且能够在被推倒或在结冰的水坑上滑倒时恢复站立。类人机器人Atlas不仅能在崎岖不平的路况中行走,还可以跳到箱子上,做后空翻后可以稳定落地(Ackerman and Guizzo, 2016)。
自动规划和调度:在距离地球1.6亿公里的太空,美国国家航空航天局(NASA)的“远程智能体”程序成为第一个控制航天器操作调度的机载自动规划程序(Jonsson et al., 2000)。远程智能体根据地面指定的高级目标生成规划,并监控这些规划的执行(在出现问题时检测、诊断和恢复)。现在,Europa规划工具包(Barreiro et al., 2012)被用于NASA火星探测器的日常操作,而Sextant系统(Winternitz, 2017)允许航天器在全球GPS系统之外进行深空自主导航。
在1991年海湾危机期间,美国军队部署了动态分析和重新规划工具Dart(Cross and Walker, 1994),为运输进行自动化的后勤规划和调度。规划涉及的交通工具、货物和人员达5万之多,并且必须考虑起点、目的地、路线、运输能力、港口和机场能力以及解决所有参数之间的矛盾。美国国防高级研究计划局(Defense Advanced Research Project Agency,DARPA)表示,这一应用取得的效果足以回报DARPA过去30年在人工智能领域的投资。
每天,优步(Uber)等网约车公司和谷歌地图等地图服务为数亿用户提供行车向导,在考虑当前和预测未来交通状况的基础上快速规划最佳路线。
机器翻译:在线机器翻译系统现在可以阅读超过100种语言的文档,涵盖99%的人类使用的母语,每天为数亿用户翻译数千亿词语。虽然翻译结果还不完美,但通常足以理解。对于具有大量训练数据的密切相关的语言(如法语和英语),在特定领域内的翻译效果已经接近于人类的水平(Wu et al., 2016b)。
语音识别:2017年,微软表示其会话语音识别系统的单词错误率已降至5.1%,与人类在Switchboard任务(转录电话对话)中的表现相当(Xiong et al., 2017)。现在全世界大约三分之一的计算机交互是通过语音而不是键盘完成的,另外Skype提供了10种语言的实时语音翻译。Alexa、Siri、Cortana和谷歌都提供了可以回答用户问题和执行任务的助手。例如,谷歌Duplex服务使用语音识别和语音合成为用户预订餐厅,它能够代表用户进行流畅的对话。
推荐:Amazon、Facebook、Netflix、Spotify、YouTube、Walmart等公司利用机器学习技术,根据用户过去的经历和其他类似的人群为用户推荐可能喜欢的内容。推荐系统领域有着悠久的历史(Resnick and Varian, 1997),但由于分析内容(文本、音乐、视频)以及历史和元数据的新深度学习方法的出现,推荐系统正在迅速发生变化(van den Oord et al., 2014; Zhang et al., 2017)。垃圾邮件过滤也可以被认为是推荐(或不推荐)的一种形式。目前的人工智能技术可以过滤掉99.9%以上的垃圾邮件,电子邮件服务还可以推荐潜在收件人以及可能回复的文本。
博弈:1997年,当“深蓝”(Deep Blue)击败国际象棋世界冠军加里·卡斯帕罗夫(Garry Kasparov)后,人类霸权的捍卫者把希望寄托在了围棋上。当时,天体物理学家、围棋爱好者皮特·赫特(Piet Hut)预测称:“计算机在围棋上击败人类需要一百年的时间(甚至可能更久)。”但仅仅20年后,AlphaGo就超过了所有人类棋手(Silver et al., 2017)。世界冠军柯洁说:“去年的AlphaGo还比较接近于人,现在它越来越像围棋之神。”AlphaGo得益于对人类棋手过去数十万场棋局的研究以及对团队中围棋专家的知识提炼。
后继项目AlphaZero不再借助人类输入,只通过游戏规则就能够自我学习并击败所有对手,在围棋、国际象棋和日本将棋领域击败了包括人类和机器在内的对手(Silver et al., 2018)。与此同时,人类冠军在各种游戏中被人工智能系统击败,包括《危险边缘》(Ferrucci et al., 2010)、扑克(Bowling et al., 2015; Moravčík et al., 2017; Brown and Sandholm, 2019),以及电子游戏《刀塔2》(Fernandez and Mahlmann, 2018)、《星际争霸II》(Vinyals et al., 2019)、《雷神之锤3》(Jaderberg et al., 2019)。
图像理解:计算机视觉研究人员不再满足于在具有挑战性的ImageNet物体识别任务上超越人类的准确性,他们开始研究更困难的图像描述问题。一些令人印象深刻的例子包括“一个人在土路上骑摩托车”“两个比萨饼放在炉顶的烤箱上”和“一群年轻人在玩飞盘”(Vinyals et al., 2017b)。然而,目前的系统还远远不够完善,一个“装满大量食物和饮料的冰箱”原来是一个被许多小贴纸遮挡住部分的禁止停车的标志。
医学:现在,人工智能算法在多种疾病的诊断方面(尤其是基于图像的诊断)已经达到或超过了专家医生的水平。例如,对阿尔茨海默病(Ding et al., 2018)、转移性癌症(Liu et al., 2017; Esteva et al., 2017)、眼科疾病(Gulshan et al., 2016)和皮肤病(Liu et al., 2019c)的诊断。一项系统回顾和汇总分析(Liu et al., 2019a)发现,人工智能程序的平均表现与医疗保健专业人员相当。目前医疗人工智能的重点之一是促进人机合作。例如,Lyna系统在诊断转移性乳腺癌方面达到了99.6%的总体准确性,优于独立的人类专家,但两者联合的效果仍然会更好(Liu et al., 2018; Steiner et al., 2018)。
目前,限制这些技术推广的不是诊断准确性,而是需要证明临床结果的改善,并确保透明度、无偏见和数据隐私(Topol, 2019)。2017年,只有两项医疗人工智能应用获得FDA批准,但这一数字在2018年增至12项,并在持续上升。
气候科学:一个科学家团队凭借深度学习模型获得了2018年戈登·贝尔奖,该模型发现了之前隐藏在气候数据中的极端天气事件的详细信息。他们使用了一台具有专用GPU硬件,运算性能超过exaop级别(每秒1018次运算)的超级计算机,这是第一个实现这一目标的机器学习程序(Kurth et al., 2018)。Rolnick等人(Rolnick et al., 2019)提供了一个60页的目录,其中列举了机器学习可用于应对气候变化的方式。
这些只是几个目前存在的人工智能系统的例子。这不是魔法或科幻小说,而是科学、工程和数学,本书将对此进行介绍。
弗朗西斯·培根是一位被誉为创造科学方法的哲学家,他在《论古人的智慧》(The Wisdom of the Ancients)(1609)一书中指出:“机械艺术的用途是模糊的,它既可用于治疗,也可用于伤害。”随着人工智能在经济、社会、科学、医疗、金融和军事领域发挥越来越重要的作用,我们应该考虑一下它可能带来的伤害和补救措施——用现代的说法,就是风险和收益。这里总结的话题在第27章和第28章中有更深入的讨论。
首先从收益说起。简而言之,我们的整个文明是人类智慧的产物。如果我们有机会获得更强大的机器智能,我们的理想上限就会大大提高。人工智能和机器人技术可以将人类从繁重的重复性工作中解放出来,并大幅增加商品和服务的生产,这可能预示着一个和平富足的时代的到来。加速科学研究的能力可以治愈疾病,并解决气候变化和资源短缺问题。正如谷歌DeepMind首席执行官德米斯·哈萨比斯(Demis Hassabis)所建议的那样:“首先解决人工智能问题,然后再用人工智能解决其他所有问题。”
然而,早在我们有机会“解决人工智能”之前,我们就会因误用人工智能而招致风险,无论这是无意的还是其他原因。其中一些风险已经很明显,而另一些似乎基于当前趋势。
● 致命性自主武器:联合国将其定义为无须人工干预即可定位、选择并击杀人类目标的武器。这种武器的一个主要问题在于它们的可扩展性——不需要人类监督意味着一小群人就可以部署任意数量的武器,并且这些武器的打击目标可以是通过任何可行的识别准则来定义的人类。自主武器所需的技术类似于自动驾驶汽车所需的技术。关于致命性自主武器潜在风险的非正式专家讨论始于2014年的联合国会议,并于2017年进入正式的官方专家组的条约审议阶段。
● 监视和劝诱:安全人员监视电话线路、视频摄像头、电子邮件和其他消息渠道的代价昂贵、乏味且存在法律问题,但可以以一种可扩展的方式使用人工智能(语音识别、计算机视觉、自然语言理解)对个人进行大规模监视并检测感兴趣的活动。基于机器学习技术,通过社交媒体为个人量身定制信息流,可以在一定程度上修改和控制政治行为,这一问题在2016年开始的美国总统选举中变得显而易见。
● 有偏决策:在评估假释和贷款申请等任务中,粗心或故意滥用机器学习算法可能会导致因种族、性别或其他受保护类别而产生有偏见的决策。通常,数据本身反映了社会中普遍存在的偏见。
● 就业影响:关于机器会减少工作岗位的担忧由来已久。故事从来都不是简单的。机器能够完成一些人类可能会做的工作,但它们也让人类更有生产力,因此更适合被雇佣;让公司更具盈利能力,因此能够支付更高的工资。它们可能使一些本来不切实际的活动在经济上可行。它们的使用通常会导致财富增加,但往往会将财富从劳动力向资本转移,从而进一步加剧不平等。之前的技术进步(如机械织布机的发明),对就业造成了严重的影响,但最终人们还是找到了新的工作。另外,人工智能也有可能从事这些新的工作。这个话题正迅速成为世界各地经济学家和政府关注的焦点。
● 安全关键的应用:随着人工智能技术的进步,它们越来越多地应用于高风险、安全关键的应用,如驾驶汽车和管理城市供水。已经发生过致命事故,这凸显了对使用机器学习技术开发的系统进行正式验证和统计风险分析的困难。人工智能领域需要制定技术和道德标准,至少要与其他工程和医疗领域中普遍存在的标准相当,而这些标准关乎人们的生命。
● 网络安全:人工智能技术可用于防御网络攻击,如检测异常的行为模式,但这些技术也能用于增强恶意软件的威力、生存能力和扩散能力。例如,强化学习方法已被用于创建高效的工具,这些工具可以进行自动化、个性化的勒索和钓鱼攻击。
我们将在27.3节更深入地讨论这些主题。随着人工智能系统变得越来越强大,它们将更多承担以前由人类扮演的社会角色。正如人类过去曾利用这些角色作恶一样,可以预见,人类可能会在这些角色中滥用人工智能系统而作恶更多。上面给出的所有例子都指出了治理的重要性,以及最终监管的重要性。目前,研究团体和参与人工智能研究的主要公司已经为人工智能相关活动制定了自愿自治原则(见27.3节)。各国政府和国际组织正在设立咨询机构,为每个具体的用例制定适当的条例,准备应对经济和社会影响,并利用人工智能的能力来解决重大的社会问题。
长期来看呢?我们能否实现长期以来的目标:创造出与人类智力相当或更强大的智能?如果我们做到了,然后呢?
在人工智能的大部分历史上,这些问题都被日常工作所掩盖——让人工智能系统做任何事情,哪怕是远程智能。与任何广泛的学科一样,绝大多数人工智能研究人员专注于特定的子领域,例如博弈、知识表示、视觉或自然语言理解,通常假设这些子领域的进展将有助于实现更广泛的人工智能目标。尼尔斯·约翰·尼尔森(Nils John Nilsson)(Nilsson, 1995)作为SRI的Shakey项目的最初负责人之一,提醒了该领域那些更广泛的目标,并警告说这些子领域本身有成为目标的风险。后来,一些有影响力的人工智能创始人,包括约翰·麦卡锡(McCarthy, 2007)、马文·明斯基(Minsky, 2007)和帕特里克·温斯顿(Beal and Winston, 2009),都认同尼尔森的警告,认为人工智能应该回归其本源,而不是专注于具体应用中可衡量的性能,用赫伯特·西蒙的话来说就是“会思考、会学习、会创造的机器”。他们将这种努力方向称为人类级别的人工智能(human-level AI,HLAI)——机器应该能够学会做人类可以做到的任何事情。他们在2004年召开了第一次研讨会(Minsky et al., 2004)。另一个有着类似目标的工作是通用人工智能(artificial general Intelligence,AGI)运动(Goertzel and Pennachin, 2007),在2008年举行了第一次会议并组织出版了The Journal of Artificial General Intelligence。
大约在同一时间,人们担心创造远远超过人类能力的超级人工智能(artificial superintelligence,ASI)可能是个坏主意(Yudkowsky, 2008; Omohundro, 2008)。图灵(Turing, 1996)在1951年曼彻斯特的一场演讲中也提出了同样的观点,他借鉴了塞缪尔·巴特勒(Samuel Butler)(Butler, 1863)的早期观点:[21]
[21] 甚至在更早的1847年,《原始解释者》(Primitive Expounder)的编辑理查德·桑顿(Richard Thornton)就对机械计算器大加抨击:“思想……超越自身,并通过发明机器进行自我思考来消除自身存在的必要性……但是谁知道,当这种机器变得更加完美的时候,它会不会想出一个规划来弥补自己的所有缺陷,然后想出超出常人所能理解的思想!”
似乎很可能,机器思维方法一旦开始,用不了多久它就会超越我们微弱的力量……因此,在某个阶段,我们应该需要期待机器能够受控制,就像塞缪尔·巴特勒在Erewhon中所提到的那样。
随着深度学习方面的最新进展,尼克·波斯特洛姆(Nick Bostrom)的《超级智能》(Superintelligence)(2014)等图书的出版,以及斯蒂芬·霍金(Stephen Hawking)、比尔·盖茨(Bill Gates)、马丁·里斯(Martin Rees)和埃隆·马斯克(Elon Musk)的公开声明,这些担忧只会变得更加普遍。
对创造超级智能机器的想法产生普遍的不安感是自然的。我们可以称之为大猩猩问题(gorilla problem):大约700万年前,一种现已灭绝的灵长类进化了,一个分支进化为大猩猩,另一个分支进化为人类。今天,大猩猩对人类分支不太满意,大猩猩根本无法控制自己的未来。如果这是成功创造出超级人工智能的结果(人类放弃对未来的控制),那么我们也许应该停止人工智能的研究,并且作为一个必然的结果,放弃人工智能可能带来的好处。这就是图灵警告的本质:我们可能无法控制比我们更聪明的机器。
如果超级人工智能是一个来自外太空的黑匣子,那么谨慎地打开这个黑匣子确实是明智之举。但事实并非如此:我们设计了人工智能系统,所以如果它们最终“掌控了自己”,那将是设计失败的结果(正如图灵所说)。
为了避免这种结果,我们需要了解潜在失败的根源。诺伯特·维纳(Wiener, 1960)在看到亚瑟·塞缪尔的西洋跳棋程序学会下棋并打败其创造者后,开始考虑人工智能的长远未来,他说:
如果我们为了达到目的而使用一个我们无法有效干预其运作方式的机械智能体……那么我们最好能完全确定设定给机器的目标是我们真正想要实现的。
许多文化都有关于人类向神灵、精灵、魔术师或魔鬼索取东西的神话。在这些故事中,他们总是得到了他们真正想要的东西并最终后悔。如果还有第三个愿望的话,那就是撤销前两个。我们将其称为迈达斯国王问题(King Midas problem):迈达斯是希腊神话中的传奇国王,他要求他所接触的一切都变成黄金,但他在接触了他的食物、饮料和家人后,就后悔了。[22]1.1.5节中我们已经提到过这个问题,将固定目标设定给机器的标准模型需要进行重大修改。解决维纳困境的方法根本不是“给机器设定一个明确的目的”。相反,我们希望机器努力实现人类的目标,但知道它们并不确切地知道这些目标是什么。
[22] 如果迈达斯遵循基本的安全原则,并在他的愿望中包括“撤消”按钮和“暂停”按钮,他会过得更好。
遗憾的是,迄今为止,几乎所有的人工智能研究都是在标准模型下进行的,这意味着这版书中几乎所有的技术材料都反映了这一知识框架。然而,在新框架内已经有一些初步成果。在第16章中,我们指出,当且仅当机器对人类的目标不确定时,机器才有积极的动机允许自己关闭。在第18章中,我们设计并研究辅助博弈(assistance game),它在数学上描述了一种情况,即人类有一个目标而机器试图实现它,但最初不确定目标是什么。在第22章中,我们解释逆向强化学习(inverse reinforcement learning)的方法,它允许机器通过观察人类的选择来更多地了解人类的偏好。在第27章中,我们探讨两个主要的困难:首先,我们的选择取决于我们的偏好,这是通过一个非常复杂、难以逆向的认知结构来实现的;其次,我们人类可能在一开始就没有一致的偏好(无论是作为个人还是作为一个群体),所以人工智能系统可能并不清楚应该为我们做什么。
本章定义了人工智能并阐述了其发展的文化背景。本章要点如下。
● 不同的人对人工智能的期望不同。首先要问的两个重要问题是:你关心的是思想还是行为?你想模拟人类,还是试图达到最佳结果?
● 根据我们所说的标准模型,人工智能主要关注理性行为。理想的智能体会在某种情况下采取可能的最佳行为,在这个意义下,我们研究了智能体的构建问题。
● 这个简单的想法需要两个改进:首先,任何智能体(无论是人还是其他物体)选择理性行为的能力都受到决策计算难度的限制;其次,机器的概念需要从追求明确目标转变到追求目标以造福人类,虽然不确定这些目标是什么。
● 哲学家们(追溯到公元前400年)暗示大脑在某些方面就像一台机器,操作用某种内部语言编码的知识,并且这种思维可以用来选择要采取的行动,从而认为人工智能是有可能实现的。
● 数学家提供了运算逻辑的确定性陈述以及不确定的概率陈述的工具,也为理解计算和算法推理奠定了基础。
● 经济学家将决策问题形式化,使决策者的期望效用最大化。
● 神经科学家发现了一些关于大脑如何工作的事实,以及大脑与计算机的相似和不同之处。
● 心理学家采纳了人类和动物可以被视为信息处理机器的观点。语言学家指出,语言的使用符合这一模式。
● 计算机工程师提供了更加强大的机器,使人工智能应用成为可能,而软件工程师使它们更加易用。
● 控制理论涉及在环境反馈的基础上设计最优行为的设备。最初,控制理论的数学工具与人工智能中使用的大不相同,但这两个领域越来越接近。
● 人工智能的历史经历了成功、盲目乐观以及由此导致的热情丧失和资金削减的循环,也存在引入全新创造性的方法和系统地改进最佳方法的循环。
● 与最初的几十年相比,人工智能在理论和方法上都已经相当成熟。随着人工智能面对的问题变得越来越复杂,该领域从布尔逻辑转向概率推理,从手工编码知识转向基于数据的机器学习。这推动了真实系统功能的改进以及与其他学科更大程度的集成。
● 随着人工智能系统在真实世界中的应用,必须考虑各种风险和道德后果。
● 从长远来看,我们面临着控制超级智能的人工智能系统的难题,它们可能以不可预测的方式进化。解决这个问题似乎需要改变我们对人工智能的设想。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
我们在此讨论智能体的本质,完美的或不完美的、环境的多样性以及由此产生的智能体类型的集合。
第1章将理性智能体(rational agent)的概念确定为研究人工智能的方法的核心。本章将使这个概念更加具体。我们将看到,在任何可以想象的环境中运行的各种智能体都可以应用理性的概念。本书的计划是使用这个概念来制定一小组设计原则,并用于构建成功的智能体,可以合理地称之为智能系统。
我们从检查智能体、环境以及它们之间的耦合开始。观察到某些智能体比其他智能体表现得更好,可以自然而然地引出理性智能体的概念,即行为尽可能好。智能体的行为取决于环境的性质。我们将对环境进行粗略分类,并展示环境的属性如何影响智能体的设计。我们描述一些基本的“框架”智能体设计,本书余下的部分将充实相关内容。
任何通过传感器(sensor)感知环境(environment)并通过执行器(actuator)作用于该环境的事物都可以被视为智能体(agent)。这个简单的想法如图2-1所示。一个人类智能体以眼睛、耳朵和其他器官作为传感器,以手、腿、声道等作为执行器。机器人智能体可能以摄像头和红外测距仪作为传感器,还有各种电动机作为执行器。软件智能体接收文件内容、网络数据包和人工输入(键盘/鼠标/触摸屏/语音)作为传感输入,并通过写入文件、发送网络数据包、显示信息或生成声音对环境进行操作。环境可以是一切,甚至是整个宇宙!实际上,我们在设计智能体时关心的只是宇宙中某一部分的状态,即影响智能体感知以及受智能体动作影响的部分。
图2-1 智能体通过传感器和执行器与环境交互
我们使用术语感知(percept)来表示智能体的传感器正在感知的内容。智能体的感知序列(percept sequence)是智能体所感知的一切的完整历史。一般而言,一个智能体在任何给定时刻的动作选择可能取决于其内置知识和迄今为止观察到的整个感知序列,而不是它未感知到的任何事物。通过为每个可能的感知序列指定智能体的动作选择,我们或多或少地说明了关于智能体的所有内容。从数学上讲,我们说智能体的行为由智能体函数(agent function)描述,该函数将任意给定的感知序列映射到一个动作。
可以想象将描述任何给定智能体的智能体函数制成表格。对大多数智能体来说,这将是一个非常大的表,事实上是无限的(除非限制考虑的感知序列长度)。给定一个要进行实验的智能体,原则上,我们可以通过尝试所有可能的感知序列并记录智能体响应的动作来构建此表[1]。当然,该表只是该智能体的外部特征。在内部,人工智能体的智能体函数将由智能体程序(agent program)实现。区别这两种观点很重要,智能体函数是一种抽象的数学描述,而智能体程序是一个具体的实现,可以在某些物理系统中运行。
[1] 如果智能体在选择其动作时使用一些随机化,那就必须多次尝试每个序列来确定每个动作的概率。有人可能会认为随机地行动是相当愚蠢的,但本章后面展示出它可能非常聪明。
为了阐明这些想法,我们举一个简单的例子——真空吸尘器世界。在一个由方格组成的世界中,包含一个机器人真空吸尘器智能体,其中的方格可以是脏的,也可以是干净的。图2-2展示了只有两个方格——方格A和方格B——的情况。真空吸尘器智能体可以感知它在哪个方格中,以及方格中是否干净。智能体从方格A开始。可选的操作包括向右移动、向左移动、吸尘或什么都不做。[2]一个非常简单的智能体函数如下:如果当前方格是脏的,就吸尘;否则,移动到另一个方格。该智能体函数的部分表格如图2-3所示,实现它的智能体程序如图2-8所示。
[2] 真正的机器人不太可能会有“向右移动”和“向左移动”这样的动作,而是采用“向前旋转轮子”和“向后旋转轮子”这样的动作。我们选择的动作更易于在书本上理解,而不是为了在实际的机器人中易于实现。
图2-2 一个只有两个方格的真空吸尘器世界。每个位置可以是干净的,也可以是脏的,智能体可以向左移动或向右移动,可以清理它所占据的方格。不同版本的真空吸尘器世界允许不同的规则,例如智能体可以感知什么,它的动作是否总是成功等
从图2-3中可以看到,通过以各种方式填充右边的列可以简单地定义各种真空世界的智能体。那么,显而易见的问题是:填充表格的正确方法是什么? 换句话说,是什么使智能体表现好或坏、聪明或愚蠢?我们将在2.2节中回答这些问题。
在结束本节之前,我们应该强调,智能体这一概念旨在成为分析系统的工具,而不是将世界划分为智能体和非智能体的绝对表征。人们可以将手持计算器视为一个智能体,它在给定感知序列“2+2=”时选择显示“4”的动作,但这样的分析很难帮助我们理解计算器。在某种意义上,工程的所有领域都可以被视为设计与世界互动的人工制品,人工智能运行在(作者认为是)这个系列最有趣的一端,在这一端,人工制品具有重要的计算资源,任务环境需要非凡的决策。
图2-3 图2-2所示的真空吸尘器世界的简单智能体函数的部分表项。如果当前方格是脏的,智能体就会进行清理,否则它将移到另一个方格。注意,除非限制可能感知序列的长度,否则该表的大小是无限的
理性智能体(rational agent)是做正确事情的事物。显然,做正确的事情比做错误的事情要好,但是做正确的事情意味着什么呢?
道德哲学发展了几种不同“正确事情”的概念,但人工智能通常坚持一种称为结果主义(consequentialism)的概念:我们通过结果来评估智能体的行为。当智能体进入环境时,它会根据接受的感知产生一个动作序列。这一动作序列会导致环境经历一系列的状态。如果序列是理想的,则智能体表现良好。这种可取性的概念由性能度量(performance measure)描述,该度量评估任何给定环境状态的序列。
人类有自己的欲望和偏好,因此,人类有适用于自身的理性概念。这一概念与成功地选择产生环境状态序列的行动有关,这些环境状态序列从人类的角度来看是可取的。但是,机器没有自己的欲望和偏好,至少在最初,性能度量是在机器设计者的头脑中或者是在机器受众的头脑中。我们将看到,一些智能体设计具有性能度量的显式表示(一个版本),而在其他设计中,性能度量完全是隐式的,智能体可能会做正确的事情,但它不知道为什么。
回顾诺伯特·维纳的警告,以确保“施以机器的目的是我们真正想要的目的”(1.5节),注意,正确地制定性能度量可能非常困难。例如,考虑2.1节中的真空吸尘器智能体,我们可能会建议用单个8小时班次中清理的灰尘量来度量性能。当然,有了理性的智能体,你所要求的就是你所得到的。然而一个理性的智能体可以通过清理灰尘,然后将其全部倾倒在地板上,然后再次清理,如此反复,从而最大化这一性能度量。更合适的性能度量是奖励拥有干净地板的智能体。例如,在每个时间步中,每个干净的方格都可以获得1分(可能会对耗电和产生的噪音进行惩罚)。作为一般规则,更好的做法是根据一个人在环境中真正想要实现的目标,而不是根据一个人认为智能体应该如何表现来设计性能度量。
即使避免了明显的缺陷,一些棘手的问题仍然存在。例如,上一段中“干净地板”的概念是基于一段时间内的平均整洁度。然而,两个不同的智能体可以达到相同的平均整洁度,其中一个智能体工作始终保持一般水平,而另一个智能体短时间工作效率很高但需要长时间的休息。哪种工作方式更可取似乎是保洁科学的好课题,但实际上这是一个具有深远影响的深刻哲学问题。大起大落、不计后果的生活,和安全但单调的生活,哪个更好?一个人人都生活在中度贫困的经济体,和一个有些人生活富裕而另一些人非常贫困的经济体,哪个更好?我们把这些问题留给勤奋的读者作为习题。
对于本书的大部分内容,我们将假设性能度量可以正确地指定。然而,出于前面所述原因,我们必须接受这样一种可能性:我们可能会将错误的目的施加给机器,确切地说,就是1.5节描述的迈达斯国王问题。此外,当设计一款软件(其副本将属于不同的用户)时,我们无法预测每个用户的确切偏好。因此,我们可能需要构建相应的智能体,它能够反映真实性能度量的初始不确定性,并随着时间的推移对其了解更多,第16章、第18章和第22章介绍了此类智能体。
在任何时候,理性取决于以下4方面:
● 定义成功标准的性能度量;
● 智能体对环境的先验知识;
● 智能体可以执行的动作;
● 智能体到目前为止的感知序列。
这引出了理性智能体的定义:
对于每个可能的感知序列,给定感知序列提供的证据和智能体所拥有的任何先验知识,理性智能体应该选择一个期望最大化其性能度量的动作。
考虑一个简单的真空吸尘器智能体,如果一个方格是脏的就清理它,如果不脏就移动到另一个方格,这就是图2-3中给出的智能体函数。它是理性智能体吗?这需要看情况了!首先,我们需要说明性能度量是什么,对环境了解多少,以及智能体具有哪些传感器和执行器。我们假设:
● 在1000个时间步的“生命周期”内,性能度量在每个时间步为每个干净的方格奖励1分;
● 环境的“地理信息”是先验的(图2-2),但灰尘的分布和智能体的初始位置不是先验的,干净的方格会继续保持干净,吸尘(Suck)动作会清理当前方格,向左(Left)或向右(Right)的动作使智能体移动一个方格,如果该动作会让智能体移动到环境之外,智能体将保持在原来的位置;
● 可用的动作仅有向右(Right)、向左(Left)和吸尘(Suck);
● 智能体能够正确感知其位置以及该位置是否有灰尘。
在这种情况下,智能体确实是理性的,它的预期性能至少与任何其他智能体一样。
显而易见,同一个智能体在不同的情况下可能会变得不理性。例如,一旦清除了所有灰尘,该智能体将会毫无必要地反复来回;如果性能度量考虑对每个动作罚1分,那么智能体的表现就会很差。在确定所有方格都干净的情况下,一个更好的智能体不会做任何事情。如果干净的方格可能再次变脏,智能体应该偶尔检查,并在必要时重新清理。如果环境的地理信息是未知的,智能体则需要对其进行探索(explore)。习题2.VACR要求在这些情况下设计智能体。
我们需要仔细区分理性和全知(omniscience)。全知的智能体能预知其行动的实际结果,并能据此采取行动,但在现实中,全知是不可能的。考虑这样一个例子:有一天我正沿着香榭丽舍大街散步,我看到街对面的一位老朋友。附近没有车流,我也没有别的事要做,所以理性上,我会开始过马路。与此同时,在 10千米的高空,一架飞过的客机上有一扇货舱门脱落下来[3],在我到达马路对面之前,我就被压扁了。我过马路是不理性的吗?我的讣告上不太可能写“试图过马路的白痴”。
[3] 参见N. Henderson,“波音747大型喷气式飞机迫切需要新门锁”,华盛顿邮报,1989年8月24日。
这个例子表明,理性不等同于完美。理性使期望性能最大化,而完美使实际性能最大化。不要求完美不仅仅是对智能体公平的问题。关键是,如果我们期望一个智能体做事后证明是最好的行动,就不可能设计一个符合规范的智能体,除非我们改进占卜水晶球或时间机器的性能。
因此,我们对理性的定义并不需要全知,因为理性决策只取决于迄今为止的感知序列。我们还必须确保我们没有无意中允许智能体进行低智的行动。例如,如果一个智能体在穿过繁忙的道路之前没有向两边看,那么它的感知序列将不会告诉它有一辆大卡车正在以高速接近。我们对理性的定义是不是说现在就可以过马路了?绝非如此!
首先,考虑到这种缺乏信息的感知序列,过马路是不理性的:不观察路况就过马路发生事故的风险太大。其次,理性智能体在上街之前应该选择“观察”动作,因为观察有助于最大化期望性能。采取行动来改变未来的感知,有时被称为信息收集(information gathering),这是理性的一个重要组成部分,将在第16章中详细介绍。信息收集的另一个例子是真空吸尘器在最初未知的环境中必须进行的探索(exploration)。
我们的定义要求理性智能体不仅要收集信息,还要尽可能多地从它所感知到的东西中学习(learn)。智能体的初始配置可以反映对环境的一些先验知识,但随着智能体获得经验,这可能会被修改和增强。在一些极端情况下,环境完全是先验已知的和完全可预测的。在这种情况下,智能体不需要感知或学习,只需正确地运行。
当然,这样的智能体是脆弱的。如卑微的粪甲虫例子,在挖出巢穴产卵后,它会从附近的一堆粪中取出一团粪来堵住入口。如果粪球在途中被截下,粪甲虫根本不会注意到粪球已经不见了,仍会继续它的任务,并滑稽地用不存在的粪球堵住巢穴。进化已经在粪甲虫的行为中建立了一个假设,当它被违反时,不成功的行为就会产生。
稍微聪明一点的是掘土黄蜂。雌性掘土黄蜂会挖一个洞,出去刺一只毛毛虫并把它拖到洞口,再次进入洞里检查一切是否正常,然后把毛毛虫拖进洞里再去产卵。当蜂卵孵化时,毛毛虫会充当食物来源。到目前为止还不错,但如果昆虫学家在掘土黄蜂检查洞穴时将毛毛虫移动几厘米远,它将回到其规划中的“把毛毛虫拖到洞口”步骤,即使经过数十次移动毛毛虫的干预,它仍然继续执行该规划而不进行修改,不断地重新检查洞穴。掘土黄蜂无法知道其固有规划正在失败,因此不会改变规划。
如果在某种程度上,智能体依赖于其设计者的先验知识,而不是其自身的感知和学习过程,我们就说该智能体缺乏自主性(autonomy)。一个理性的智能体应该是自主的,它应该学习如何弥补部分或不正确的先验知识。例如,能学习预测何时何地会出现额外灰尘的真空吸尘器比不能学习预测的要好。
实际上,我们很少从一开始就要求智能体完全自主:除非设计者提供一些帮助,否则当智能体几乎没有经验或完全没有经验时,它将不得不随机行动。正如进化为动物提供了足够的内建反射,使其能够生存足够长的时间来学习一样,为人工智能体提供一些初始知识和学习能力也是合理的。在充分体验相应环境后,理性智能体的行为可以有效地独立于其先验知识。因此,结合学习能够让我们设计单个理性智能体,它能在各种各样的环境中取得成功。
既然已经有了理性的定义,考虑构建理性智能体的准备几乎已经完成。然而,还必须考虑任务环境(task environment),它本质上是“问题”,理性智能体是“解决方案”。我们首先展示如何指定任务环境,并用一些示例说明该过程。然后,展示任务环境的多种形式。任务环境的性质直接影响智能体程序的恰当设计。
在讨论简单的真空吸尘器智能体的理性时,我们必须指定性能度量、环境以及智能体的执行器和传感器。我们将所有这些都归在任务环境的范畴下,基于首字母缩写规则,我们称其为PEAS(Performance,Environment,Actuator,Sensor)描述。在设计智能体时,第一步必须始终是尽可能完整地指定任务环境。
真空吸尘器世界是一个简单的例子,让我们考虑一个更复杂的问题:自动驾驶出租车司机。图2-4总结了出租车任务环境的PEAS描述。我们将在以下段落中更详细地讨论每个元素。
图2-4 自动驾驶出租车司机任务环境的PEAS描述
首先,我们希望自动驾驶追求的性能度量(performance measure)是什么?理想的标准包括到达正确的目的地,尽量减少油耗和磨损,尽量减少行程时间或成本,尽量减少违反交通法规和对其他驾驶员的干扰,最大限度地提高安全性和乘客舒适度,最大化利润。显然,其中一些目标是相互冲突的,因此需要权衡。
接下来,出租车将面临什么样的驾驶环境(environment)?任何出租车司机都必须能够在各种道路上行驶,如乡村车道、城市小巷以及12车道的高速公路。道路上有其他交通工具、行人、流浪动物、道路工程、警车、水坑和坑洼。出租车还必须与潜在以及实际的乘客互动。另外,还有一些可选项。出租车可以选择在很少下雪的南加利福尼亚州或者经常下雪的阿拉斯加运营。它可能总是靠右行驶,或者我们可能希望它足够灵活,在英国或日本时可以靠左行驶。显然,环境越受限,设计问题就越容易解决。
自动驾驶出租车的执行器(actuator)包括可供人类驾驶员使用的器件,例如通过加速器控制发动机以及控制转向和制动。此外,它还需要输出到显示屏或语音合成器,以便与乘客进行对话,或许还需要某种方式与其他车辆进行礼貌的或其他方式的沟通。
出租车的基本传感器(sensor)将包括一个或多个摄像头以便观察,以及激光雷达和超声波传感器以便检测其他车辆和障碍物的距离。为了避免超速罚单,出租车应该有一个速度表,而为了正确控制车辆(特别是在弯道上),它应该有一个加速度表。要确定车辆的机械状态,需要发动机、燃油和电气系统的传感器常规阵列。像许多人类驾驶者一样,它可能需要获取GPS信号,这样就不会迷路。最后,乘客需要触摸屏或语音输入才能说明目的地。
图2-5中简要列举了一些其他智能体类型的基本PEAS元素。更多示例参见习题2.PEAS。这些示例包括物理环境和虚拟环境。注意,虚拟任务环境可能与“真实”世界一样复杂。例如,在拍卖和转售网站上进行交易的软件智能体(software agent),或称软件机器人或软机器人(softbot),为数百万其他用户和数十亿对象提供交易,其中许多对象具有真实的图片。
图2-5 智能体类型及其PEAS描述的示例
人工智能中可能出现的任务环境范围显然非常广泛。然而,我们可以确定相当少的维度,并根据这些维度对任务环境进行分类。这些维度在很大程度上决定了恰当的智能体设计以及智能体实现的主要技术系列的适用性。首先我们列出维度,然后分析几个任务环境,阐明思路。这里的定义是非形式化的,后面的章节提供了每种环境的更精确的陈述和示例。
完全可观测的(fully observable)与部分可观测的(partially observable):如果智能体的传感器能让它在每个时间点都能访问环境的完整状态,那么我们说任务环境是完全可观测的。如果传感器检测到与动作选择相关的所有方面,那么任务环境就是有效的完全可观测的,而所谓的相关又取决于性能度量标准。完全可观测的环境很容易处理,因为智能体不需要维护任何内部状态来追踪世界。由于传感器噪声大且不准确,或者由于传感器数据中缺少部分状态,环境可能部分可观测。例如,只有一个局部灰尘传感器的真空吸尘器无法判断其他方格是否有灰尘,自动驾驶出租车无法感知其他司机的想法。如果智能体根本没有传感器,那么环境是不可观测的(unobservable)。在这种情况下,有人可能会认为智能体的困境是无解的,但是正如我们在第4章中讨论的那样,智能体的目标可能仍然可以实现,有时甚至是确定可以实现的。
单智能体的(single-agent)与多智能体的(multiagent):单智能体和多智能体环境之间的区别似乎足够简单。例如,独自解决纵横字谜的智能体显然处于单智能体环境中,而下国际象棋的智能体则处于二智能体环境中。然而,这里也有一些微妙的问题。首先,我们已经描述了如何将一个实体视为智能体,但没有解释哪些实体必须视为智能体。智能体A(例如出租车司机)是否必须将对象B(另一辆车)视为智能体,还是可以仅将其视为根据物理定律运行的对象,类似于海滩上的波浪或随风飘动的树叶?关键的区别在于B的行为是否被最佳地描述为一个性能度量的最大化,而这一性能度量的值取决于智能体A的行为。
例如,国际象棋中的对手实体B正试图最大化其性能度量,根据国际象棋规则,这将最小化智能体A的性能度量。因此,国际象棋是一个竞争性(competitive)的多智能体环境。但是,在出租车驾驶环境中,避免碰撞使所有智能体的性能度量最大化,因此它是一个部分合作的(cooperative)多智能体环境。它还具有部分竞争性,例如,一个停车位只能停一辆车。
多智能体环境中的智能体设计问题通常与单智能体环境下有较大差异。例如,在多智能体环境中,通信通常作为一种理性行为出现;在某些竞争环境中,随机行为是理性的,因为它避免了一些可预测性的陷阱。
确定性的(deterministic)与非确定性的(nondeterministic):如果环境的下一个状态完全由当前状态和智能体执行的动作决定,那么我们说环境是确定性的,否则是非确定性的。原则上,在完全可观测的确定性环境中,智能体不需要担心不确定性。然而,如果环境是部分可观测的,那么它可能是非确定性的。
大多数真实情况非常复杂,以至于不可能追踪所有未观测到的方面;出于实际目的,必须将其视为非确定性的。从这个意义上讲,出租车驾驶显然是非确定性的,因为人们永远无法准确地预测交通行为。此外,轮胎可能会意外爆胎,发动机可能会在没有警告的情况下失灵。我们描述的真空吸尘器世界是确定性的,但变化可能包括非确定性因素,如随机出现的灰尘和不可靠的吸力机制(参考习题2.VFIN)。
最后注意一点,随机的(stochastic)一词被一些人用作“非确定性”的同义词,但我们会区分这两个术语。如果环境模型显式地处理概率(例如,“明天的降雨可能性为25%”),那么它是随机的;如果可能性没有被量化,那么它是“非确定性的”(例如,“明天有可能下雨”)。
回合式的(episodic)与序贯的(sequential):在回合式任务环境中,智能体的经验被划分为原子式的回合。在每一回合中,智能体接收一个感知,然后执行单个动作。至关重要的是,下一回合并不依赖于前几回合采取的动作。许多分类任务是回合式的。例如,在装配流水线上检测缺陷零件的智能体需要根据当前零件做出每个决策,而无须考虑以前的决策;而且,当前的决策并不影响下一个零件是否有缺陷。但是,在序贯环境中,当前决策可能会影响未来所有决策。[4]国际象棋和出租车驾驶是序贯的:在这两种情况下,短期行为可能会产生长期影响。因为在回合式环境下智能体不需要提前思考,所以要比序贯环境简单很多。
[4] “sequential”(串行)一词在计算机科学中也被用作“parallel”(并行)的反义词,与此处的含义在很大程度上是不相关的。
静态的(static)与动态的(dynamic):如果环境在智能体思考时发生了变化,我们就说该智能体的环境是动态的,否则是静态的。静态环境很容易处理,因为智能体在决定某个操作时不需要一直关注世界,也不需要担心时间的流逝。但是,动态环境会不断地询问智能体想要采取什么行动,如果它还没有决定,那就等同于什么都不做。如果环境本身不会随着时间的推移而改变,但智能体的性能分数会改变,我们就说环境是半动态的(semidynamic)。驾驶出租车显然是动态的,因为驾驶算法在计划下一步该做什么时,其他车辆和出租车本身在不断移动。在用时钟计时的情况下国际象棋是半动态的。填字游戏是静态的。
离散的(discrete)与连续的(continuous):离散/连续的区别适用于环境的状态、处理时间的方式以及智能体的感知和动作。例如,国际象棋环境具有有限数量的不同状态(不包括时钟)。国际象棋也有一组离散的感知和动作。驾驶出租车是一个连续状态和连续时间的问题,出租车和其他车辆的速度和位置是一系列连续的值,并随着时间平稳地变化。出租车的驾驶动作也是连续的(转向角等)。严格来说,来自数字照相机的输入是离散的,但通常被视为表示连续变化的强度和位置。
已知的(known)与未知的(unknown):严格来说,这种区别不是指环境本身,而是指智能体(或设计者)对环境“物理定律”的认知状态。在已知环境中,所有行动的结果(如果环境是非确定性的,则对应结果的概率)都是既定的。显然,如果环境未知,智能体将不得不了解它是如何工作的,才能做出正确的决策。
已知和未知环境之间的区别与完全可观测和部分可观测环境之间的区别不同。一个已知的环境很可能是部分可观测的,例如,在纸牌游戏中,知道规则但仍然无法看到尚未翻转的牌。相反,一个未知环境可以是完全可观测的,如一个全新的电子游戏,屏幕可能会显示整个游戏状态,但在尝试之前并不知道各个按钮的作用。
如2.2.1节所述,性能度量本身可能是未知的,这可能是因为设计者不确定如何正确地描述,也可能是因为最终用户(其偏好很重要)是未知的。例如,出租车司机通常不知道新乘客是喜欢悠闲还是快速的旅程,是喜欢谨慎还是激进的驾驶风格。虚拟个人助理一开始对新主人的个人喜好一无所知。在这种情况下,智能体可以基于与设计者或用户的进一步交互来了解更多关于性能度量的信息。继而,这表明,任务环境必须被视为一个多智能体环境。
最困难的情况是部分可观测的、多智能体的、非确定性的、序贯的、动态的、连续的且未知的。驾驶出租车除了驾驶员的环境大多是已知的,在所有其他方面都很难。在一个陌生的国家驾驶租来的汽车,那里有不熟悉的地理环境、不同的交通法规以及焦虑的乘客,这令人更加紧张。
图2-6列出了许多熟悉环境的属性。注意,这些属性并不总是一成不变的。例如,因为将患者的患病过程作为智能体建模并不适合,所以我们将医疗诊断任务列为单智能体,但是医疗诊断系统还可能必须应对顽固的病人和多疑的工作人员,因此环境还具有多智能体的方面。此外,如果我们将任务设想为根据症状列表进行诊断,那么医疗诊断是回合式的;如果任务包括提出一系列测试、评估治疗过程中的进展、处理多个患者等,那么则是序贯的。
图2-6 任务环境的例子及其特征
因为如前所述,“已知的/未知的”不是严格意义上的环境属性,所以图2-6中没有包含此列。对于某些环境,例如国际象棋和扑克,很容易为智能体提供完整的规则知识,但考虑智能体如何在没有这些知识的情况下学会玩这些游戏仍然是有趣的。
与本书相关的代码库包括多个环境实现以及用于评估智能体性能的通用环境模拟器。实验通常不是针对单个环境进行的,而是针对从环境类(environment class)中抽象的许多环境进行的。例如,要在模拟交通中评估出租车司机,我们需要运行具有不同的交通状况、照明和天气条件的多次模拟。我们关注智能体在环境类上的平均性能。
到目前为止,我们通过描述行为(即在任意给定的感知序列之后执行的动作)讨论了智能体。现在我们必须迎难而上来讨论智能体内部是如何工作的。人工智能的工作是设计一个智能体程序(agent program)实现智能体函数,即从感知到动作的映射。假设该程序将运行在某种具有物理传感器和执行器的计算设备上,我们称之为智能体架构(agent architecture):
智能体 = 架构 + 程序
显然,我们选择的程序必须是适合相应架构的程序。如果程序打算推荐步行这样的动作,那么对应的架构最好有腿。架构可能只是一台普通PC,也可能是一辆带有多台车载计算机、摄像头和其他传感器的机器人汽车。通常,架构使程序可以使用来自传感器的感知,然后运行程序,并将程序生成的动作选择反馈给执行器。尽管本书第25章和第26章涉及传感器和执行器,但其余大部分内容都是关于设计智能体程序的。
我们在本书中设计的智能体程序都有相同的框架:它们将当前感知作为传感器的输入,并将动作返回给执行器。[5]注意智能体程序(将当前感知作为输入)和智能体函数(可能依赖整个感知历史)之间的差异。因为环境中没有其他可用信息,所以智能体程序别无选择,只能将当前感知作为输入。如果智能体的动作需要依赖于整个感知序列,那么智能体必须记住历史感知。
[5] 智能体程序框架还有其他选择。例如,我们可以让智能体程序作为与环境异步运行的协程。每个这样的协程都有一个输入和输出端口,并由一个循环组成,该循环读取输入端口的感知,并将动作写到输出端口。
我们用附录B中定义的简单伪代码语言描述智能体程序。(在线代码库包含真实编程语言的实现。)图2-7显示了一个相当简单的智能体程序,它记录感知序列,然后使用它来索引动作表,以决定要执行的动作。动作表(如图2-3中给出的真空吸尘器世界示例)明确表示了智能体程序所体现的智能体函数。作为设计者,为了以这种方式构建理性智能体,我们必须构造一个表,该表包含每个可能的感知序列所对应的适当动作。
图2-7 每个新感知都会调用Table-Driven-Agent程序,并且每次返回一个动作。它在内存中保留了完整的感知序列
表驱动的智能体构建方法注定失败,深入思考这一问题会很有启发性。设为可能的感知集,T为智能体的生存期(对应它将接收的感知总数),查找表将包含
条记录。考虑自动驾驶出租车:来自单个摄像头(通常是8个摄像头)的视觉输入速度约为70 MB/s(每秒30帧,每帧1080 像素× 720像素,每个像素包含24位颜色信息),驾驶1小时后,将会生成一张超过10600 000 000 000条记录的表。即使是作为真实世界中微小的、表现良好的片段的国际象棋,其查找表也至少有10150条记录。相比之下,可观测宇宙中的原子数量少于1080个。这些表的巨大规模意味着:(a)这个宇宙中没有任何物理智能体有空间存储表;(b)设计者没有时间创建表;(c)任何智能体都无法从其经验中学习所有正确的记录。
尽管如此,假设表填充正确,Table-Driven-Agent确实做了我们想要做的事情:它实现了所需的智能体函数。
人工智能面临的关键挑战是找出编写程序的方法,尽可能从一个小程序而不是从一个大表中产生理性行为。
历史上有许多例子表明,在其他领域可以成功地做到这一点:例如, 20世纪70年代以前,工程师和学生使用的巨大平方根表格,现在已经被电子计算器上运行的仅有5行代码的牛顿方法所取代。现在问题是,人工智能能像牛顿处理平方根那样处理一般智能行为吗?我们相信答案是肯定的。
在本节剩余部分中,我们将概述4种基本的智能体程序,它们体现了几乎所有智能系统的基本原理:
● 简单反射型智能体;
● 基于模型的反射型智能体;
● 基于目标的智能体;
● 基于效用的智能体。
每种智能体程序以特定的方式组合特定的组件来产生动作。2.4.6节大致解释了如何将所有这些智能体转换为学习型智能体,以提高其组件的性能,从而产生更好的动作。2.4.7节描述在智能体中表示组件本身的各种方式。这种多样性为这一领域和这本书本身提供了一个主要的组织原则。
最简单的智能体是简单反射型智能体(simple reflex agent)。这些智能体根据当前感知选择动作,忽略感知历史的其余部分。例如,真空吸尘器的智能体函数在图2-3所示,是一种简单反射型智能体,因为它的决策仅基于当前位置以及该位置是否有灰尘。该智能体的智能体程序如图2-8所示。
图2-8 在只有两个位置的真空吸尘器环境中,简单反射型智能体的智能体程序,该程序实现图2-3中列出的智能体函数
注意,与之前对应的表相比,真空吸尘器的程序确实非常轻量。最明显的简化来自忽略感知历史,这将相关感知序列的数量从4T减少到4。进一步的简化基于以下事实:动作不依赖于位置,只依赖于当前方格是否有灰尘。虽然我们已经使用if-then-else语句来编写智能体程序,但它非常简单,可以将其实现为布尔电路。
即使在更复杂的环境中,也会出现简单的反射行为。想象自己是自动驾驶出租车司机。如果前面的汽车刹车并且刹车灯亮起,那么你应该注意到这一点并开始刹车。换句话说,你通过对视觉输入进行一些处理来建立我们称之为“前面的汽车正在刹车”的条件。然后,这会触发智能体程序中的既定联结,对应动作“启动刹车”。我们称这样的联结为条件-动作规则(condition-action rule)[6],写作:
[6] 也称为情境-动作规则、产生式系统或 if-then规则。
如果前面的车正在刹车,则启动刹车。
人类也有许多这样的联结,其中一些是习得反应(如驾驶),而另一些则是先天反射(如在有东西接近眼睛时眨眼)。在本书中,我们展示了学习和实现这种联结的几种不同方式。
图2-8所示的程序限定于一个特定的真空吸尘器环境。一种更通用、更灵活的方法是,首先为条件操作规则构建通用解释器,然后为特定任务环境创建规则集。图2-9给出了通用程序的结构示意图,展示条件-动作规则如何在智能体中建立从感知到动作的联结。如果这看起来普通,不要担心,很快就会变得更加有趣。
图2-9 简单反射型智能体的示意图。我们使用矩形表示智能体决策过程的当前内部状态,使用椭圆表示过程中使用的背景信息
图2-9中智能体对应的智能体程序如图2-10所示。Interpret-Input函数根据percept生成当前状态的抽象描述。给定状态描述,Rule-Match函数返回规则集中匹配的第一条规则。注意,关于“规则”和“匹配”的描述纯粹是概念性的。如上所述,实际实现可以像实现布尔电路的逻辑门集合一样简单。或者,也可以使用“神经”电路,其中逻辑门由人工神经网络中的非线性单元代替(见第21章)。
图2-10 简单反射型智能体。它根据一条规则进行操作,该规则的条件与感知定义的当前状态相匹配
简单反射型智能体具有值得赞扬的简单特性,但它们的智能有限。图2-10中的智能体只有在当前感知的基础上才能做出正确的决策,也就是说,只有在环境完全可观测的情况下才可行。
即使是轻微的不可观测性也会造成严重的问题。例如,前面给出的刹车规则假设前车正在刹车的条件可以通过当前的感知(视频的单帧)确定。如果前车有一个安装在中间的(因此是唯一可识别的)刹车灯,这是可行的。但是,旧款车型的尾灯、刹车灯和转向灯的配置各不相同,而且从单幅图像中分辨出汽车是在刹车还是仅仅打开了尾灯不是总能做到的。一个简单反射型智能体在这样一辆车后面行驶,要么会连续不必要地刹车,或者更糟的是根本就不刹车。
我们在真空吸尘器世界中也可以看到类似的问题。假设一个简单的真空吸尘器反射型智能体没有位置传感器,只有一个灰尘传感器。这样的智能体只有两种可能的感知:[Dirty]和[Clean]。它可以用吸尘(Suck)来响应[Dirty],它该如何响应[Clean]呢?如果碰巧从方格A开始,向左(Left)移动会(永远)失败,如果从方格B开始,向右(Right)移动会(永远)失败。对在部分可观测环境中工作的简单反射型智能体而言,无限循环通常是不可避免的。
如果智能体可以随机化(randomize)其操作,则可以跳出无限循环。例如,如果真空吸尘器智能体感知到[Clean],它可能会通过抛硬币来选择左右。我们很容易就能证明智能体将平均通过两步到达另一个方格。如果方格是脏的,智能体将清理它,任务就会完成。因此,随机化的简单反射型智能体可能优于确定性的简单反射型智能体。
我们在2.3节中提到,在某些多智能体环境中,正确的随机行为是理性的。在单智能体环境中,随机化通常是不理性的。在某些情况下,这是一个有用的技巧,可以帮助简单反射型智能体,但在大多数情况下,我们可以使用更复杂的确定性智能体以做得更好。
处理部分可观测性的最有效方法是让智能体追踪它现在观测不到的部分世界。也就是说,智能体应该维护某种依赖于感知历史的内部状态(internal state),从而至少反映当前状态的一些未观测到的方面。对于刹车问题,内部状态范围不仅限于摄像头拍摄图像的前一帧,要让智能体能够检测车辆边缘的两个红灯何时同时亮起或熄灭。对于其他驾驶任务,如变道,如果智能体无法同时看到其他车辆,则需要追踪它们的位置。为了在任何时候都能驾驶,智能体需要追踪其钥匙的位置。
随着时间的推移,更新这些内部状态信息需要在智能体程序中以某种形式编码两种知识。首先,需要一些关于世界如何随时间变化的信息,这些信息大致可以分为两部分:智能体行为的影响和世界如何独立于智能体而发展。例如,当智能体顺时针转动方向盘时,汽车就会向右转;而下雨时,汽车的摄像头就会被淋湿。这种关于“世界如何运转”的知识(无论是在简单的布尔电路中还是在完整的科学理论中实现)被称为世界的转移模型(transition model)。
其次,我们需要一些关于世界状态如何反映在智能体感知中的信息。例如,当前面的汽车开始刹车时,前向摄像头的图像中会出现一个或多个亮起的红色区域;当摄像头被淋湿时,图像中会出现水滴状物体并部分遮挡道路。这种知识称为传感器模型(sensor model)。
转移模型和传感器模型结合在一起让智能体能够在传感器受限的情况下尽可能地跟踪世界的状态。使用此类模型的智能体称为基于模型的智能体(model-based agent)。
图2-11给出了基于模型的反射型智能体的结构,它具有内部状态,展示了当前感知如何与旧的内部状态相结合,并基于世界如何运转的模型生成当前状态的更新描述。智能体程序如图2-12所示。有趣的部分是函数Update-State,它负责创建新的内部状态描述。模型和状态的表示方式的细节因环境类型和智能体设计中使用的特定技术而异。
无论使用哪种表示,智能体几乎不可能准确地确定部分可观测环境的当前状态。相反,标有“现在的世界是什么样子”(图2-11)的框表示智能体的“最佳猜测”(或者在具有多种可能性的情况下的最佳猜测)。例如,一辆自动驾驶出租车可能无法看到停在它前面的大卡车周围的情况,只能猜测是什么导致了拥堵。因此,关于当前状态的不确定性可能是不可避免的,但智能体仍然需要做出决定。
图2-11 基于模型的智能体
图2-12 基于模型的反射型智能体。它使用内部模型追踪世界的当前状态,然后以与反射型智能体相同的方式选择动作
了解环境的现状并不总是足以决定做什么。例如,在一个路口,出租车可以左转、右转或直行。正确的决定取决于出租车要去哪里。换句话说,除了当前状态的描述之外,智能体还需要某种描述理想情况的目标信息,例如设定特定的目的地。智能体程序可以将其与模型(与基于模型的反射型智能体中使用的信息相同)相结合,并选择实现目标的动作。图2-13展示了基于目标的智能体结构。
有时,基于目标的动作选择很直接,例如,单个动作能够立刻实现目标的情况。有时会更棘手,例如,智能体为了找到实现目标的方法而不得不考虑很长的复杂序列。搜索(第3~5章)和规划(第11章)是人工智能的子领域,专门用于寻找实现智能体目标的动作序列。
注意,这类决策从根本上不同于前面描述的条件-动作规则,因为它涉及对未来的考虑,包括“如果我这样做会发生什么?”和“这会让我快乐吗?”在反射型智能体设计中,这种信息并没有被明确地表示出来,因为内置规则直接从感知映射到动作。反射型智能体在看到刹车灯时刹车,但它不知道为什么。基于目标的智能体在看到刹车灯时会刹车,因为这是它预测的唯一动作,这个动作可以实现不撞到其他汽车的目标。
图2-13 基于模型、基于目标的智能体。它追踪世界状态以及它试图实现的一系列目标,并选择一项最终能够实现目标的动作
尽管基于目标的智能体看起来效率较低,但它更灵活,因为支持其决策的知识是显式表示的,并且可以修改。例如,只要将目的地指定为目标,就可以很容易地更改基于目标的智能体的行为,以到达不同的目的地。反射型智能体关于何时转弯和何时直行的规则只适用于单一目的地,这些规则必须全部更换才能去新的目的地。
在大多数环境中,仅靠目标并不足以产生高质量的行为。例如,许多动作序列都能使出租车到达目的地(从而实现目标),但有些动作序列比其他动作序列更快、更安全、更可靠或更便宜。目标只是在“快乐”和“不快乐”状态之间提供了一个粗略的二元区别。更一般的性能度量应该允许根据不同世界状态的“快乐”程度对智能体进行比较。经济学家和计算机科学家通常用效用(utility)这个词来代替“快乐”,因为“快乐”听起来不是很科学。[7]
[7] 这里的“utility”一词指的是“实用的品质”,而不是电力公司或自来水厂等公共设施。
我们已经看到,性能度量会给任何给定的环境状态序列打分,因此它可以很容易地区分到达出租车目的地所采取的更可取和更不可取的方式。智能体的效用函数(utility function)本质上是性能度量的内部化。如果内部效用函数和外部性能度量一致,那么根据外部性能度量选择动作,以使其效用最大化的智能体是理性的。
再次强调,这不是理性的唯一实现方式,我们已经看到了一个适用于真空吸尘器世界的理性智能体程序(图2-8),但并不知道它的效用函数是什么。与基于目标的智能体一样,基于效用的智能体在灵活性和学习方面有很多优势。此外,在两种情况下,仅靠目标是不充分的,但基于效用的智能体仍然可以做出理性的决策。首先,当存在相互冲突的目标时,只能实现其中的一部分(例如速度和安全),效用函数会进行适当的权衡。其次,当智能体有多个目标实现,但没有一个目标可以确定地实现时,效用提供了一种方法,可以权衡目标的重要性和成功的可能性。
部分可观测性和非确定性在真实世界中普遍存在,因此,不确定性下的决策也普遍存在。从技术上讲,基于效用的理性智能体会选择能够最大化其动作结果期望效用(expected utility)的动作,也就是在给定每个结果的概率和效用的情况下,智能体期望得到的平均效用(附录A更精确地定义了期望)。在第16章中,我们证明,任何理性智能体的行为都必须表现得好像拥有一个效用函数,并试图最大化其期望值。具有显式效用函数的智能体可以使用通用算法做出理性决策,该算法不依赖于特定效用函数的最大化。通过这种方式,理性的“全局”定义(将那些具有最高性能的智能体函数指定为理性)变成了对理性智能体设计的“局部”约束,并可以通过一个简单的程序来表示。
基于效用的智能体结构如图2-14所示。基于效用的智能体程序见第16章和第17章,其中设计了决策型智能体,必须处理非确定性或部分可观测环境中固有的不确定性。如第18章所述,多智能体环境中的决策也在效用理论的框架下进行了研究。
图2-14 基于模型、基于效用的智能体。它使用了一个世界模型以及一个效用函数来衡量它在各状态之间的偏好,然后选择产生最佳期望效用的动作,其中期望效用是通过对所有可能的结果状态和对应概率加权所得
说到这里,读者可能会想,“这么简单吗?只需要构建能够最大化期望效用的智能体,我们就完成了?”这类智能体确实是智能的,但这并不简单。基于效用的智能体必须对其环境进行建模和跟踪,这些任务涉及大量关于感知、表示、推理和学习的研究。这些研究结果填满了本书的许多章节。选择效用最大化的行动方案也是一项艰巨的任务,需要更多的章节描述精巧的算法。即使使用这些算法,由于计算复杂性,完美理性在实践中通常是无法实现的(正如我们在第1章中所指出的)。我们还应该注意到,并非所有基于效用的智能体都是基于模型的。我们将在第22章和第26章中看到,无模型的智能体(model-free agent)可以学习在特定情况下什么样的动作是最好的,而不必确切地了解该动作如何改变环境。
最后,所有这些都假设设计者能够正确地指定效用函数,第17章、第18章和第22章将更深入讨论未知效用函数的问题。
我们已经描述了一些智能体程序和选择动作的方法。到目前为止,我们还没有解释智能体程序是如何产生的。在图灵(Turing,1950)早期的著名论文中,他考虑手动编程实现智能机器的想法。他估计了这可能需要多少工作量,并得出结论,“似乎需要一些更快捷的方法”。他提出的方法是构造学习型机器,然后教它们。在人工智能的许多领域,这是目前创建最先进系统的首选方法。任何类型的智能体(基于模型、基于目标、基于效用等)都可以构建(或不构建)成学习型智能体。
正如我们之前提到的,学习还有另一个优势:它让智能体能够在最初未知的环境中运作,并变得比其最初的知识可能允许的能力更强。在本节中,我们简要介绍学习型智能体的主要思想。在整本书中,我们对特定类型智能体中的学习因素和方法的评论贯穿全书。第19~22章将更加深入地介绍学习算法本身。
学习型智能体可分为4个概念组件,如图2-15所示。最重要的区别在于负责提升的学习元素(learning element)和负责选择外部行动的性能元素(performance element)。性能元素是我们之前认为的整个智能体:它接受感知并决定动作。学习元素使用来自评估者(critic)对智能体表现的反馈,并以此确定应该如何修改性能元素以在未来做得更好。
图2-15 通用学习型智能体。“性能元素”框表示我们之前认为的整个智能体程序,现在“学习元素”框可以修改该程序以提升其性能
学习元素的设计在很大程度上取决于性能元素的设计。当设计者试图设计一个学习某种能力的智能体时,第一个问题不是“我要如何让它学习这个?”而是“一旦智能体学会了如何做,它将使用什么样的性能元素?”给定性能元素的设计,可以构造学习机制来改进智能体的每个部分。
评估者告诉学习元素:智能体在固定性能标准方面的表现如何。评估者是必要的,因为感知本身并不会指示智能体是否成功。例如,国际象棋程序可能会收到一个感知,提示它已将死对手,但它需要一个性能标准来知道这是一件好事;感知本身并没有这么说。确定性能标准很重要。从概念上讲,应该把它看作完全在智能体之外,因为智能体不能修改性能标准以适应自己的行为。
学习型智能体的最后一个组件是问题生成器(problem generator)。它负责建议动作,这些动作将获得全新和信息丰富的经验。如果性能元素完全根据自己的方式,它会继续选择已知最好的动作。但如果智能体愿意进行一些探索,并在短期内做一些可能不太理想的动作,那么从长远来看,它可能会发现更好的动作。问题生成器的工作是建议这些探索性行动。这就是科学家在进行实验时所做的。伽利略并不认为从比萨斜塔顶端扔石头本身有价值。他并不是想要打碎石头或改造不幸行人的大脑。他的目的是通过确定更好的物体运动理论来改造自己的大脑。
学习元素可以对智能体图(图2-9、图2-11、图2-13和图2-14)中显示的任何“知识”组件进行更改。最简单的情况是直接从感知序列学习。观察成对相继的环境状态可以让智能体了解“我的动作做了什么”以及“世界如何演变”以响应其动作。例如,如果自动驾驶出租车在湿滑路面上行驶时进行一定程度的刹车,那么它很快就会发现实际减速多少,以及它是否滑出路面。问题生成器可能会识别出模型中需要改进的某些部分,并建议进行实验,例如在不同条件下的不同路面上尝试刹车。
无论外部性能标准如何,改进基于模型的智能体的组件,使其更好地符合现实几乎总是一个好主意。(从计算的角度来看,在某些情况下简单但稍微不准确的模型比完美但极其复杂的模型更好。)当智能体试图学习反射组件或效用函数时,需要外部标准的信息。
例如,假设出租车司机因为乘客在旅途中感到非常不适,没有收到小费。外部性能标准必须告知智能体,小费的损失对其整体性能有负面影响;然后,该智能体可能会了解到暴力操作有损其自身的效用。从某种意义上说,性能标准将传入感知的一部分区分为奖励(reward)或惩罚(penalty),以提供对智能体行为质量的直接反馈。动物的疼痛和饥饿等固有的性能标准可以通过这种方式理解。
更一般地说,人类的选择可以提供有关人类偏好的信息。例如,假设出租车不知道人们通常不喜欢噪声,于是决定不停地按喇叭以确保行人知道它即将到来。随之而来的人类行为,如盖住耳朵、说脏话甚至可能剪断喇叭上的电线,将为智能体提供更新其效用函数的证据。这个问题将在第22章进一步讨论。
总之,智能体有各种各样的组件,这些组件可以在智能体程序中以多种方式表示,因此学习方法之间似乎存在很大差异。然而,主题仍然是统一的:智能体中的学习可以概括为对智能体的各个组件进行修改的过程,使各组件与可用的反馈信息更接近,从而提升智能体的整体性能。
我们已经将智能体程序(用非常高级的术语)描述为由各种组件组成,其功能是回答诸如“现在的世界是什么样的?”“我现在应该采取什么动作?”“我的动作将导致什么?”等问题。人工智能学生的下一个问题是,“这些组件究竟是如何工作的?”要正确回答这个问题大约需要一千页的篇幅,但在这里我们希望读者能够注意一些基本区别,即组件表示智能体所处环境的各种方式之间的区别。
粗略地说,我们可以通过一个复杂性和表达能力不断增加的横轴来描述表示,即原子表示、因子化表示和结构化表示。为了辅助说明这些观点,我们可以考虑特定的智能体组件,例如处理“我的动作会导致什么”。这个组件描述了作为采取动作的结果可能在环境中引起的变化,图2-16展示了如何表示这些转移的示意图。
在原子表示(atomic representation)中,世界的每一个状态都是不可分割的,它没有内部结构。考虑这样一个任务:通过城市序列找到一条从某个国家的一端到另一端的行车路线(我们在图3-1中会解决这个问题)。为了解决这个问题,将世界状态简化为所处城市的名称就足够了,这就是单一的知识原子,也是一个“黑盒”,它唯一可分辨的属性是与另一个黑盒相同或不同。搜索和博弈中的标准算法(第3~5章)、隐马尔可夫模型(第14章)以及马尔可夫决策过程(第17章)都基于原子表示。
因子化表示(factored representation)将每个状态拆分为一组固定的变量或属性,每个变量或属性都可以有一个值。考虑同一驾驶问题更真实的描述,即我们需要关注的不仅仅是一个城市或另一个城市的原子位置,可能还需要关注油箱中的汽油量、当前的GPS坐标、油量警示灯是否工作、通行费、收音机上的电台等。两个不同的原子状态没有任何共同点(只是不同的黑盒),但两个不同的因子化状态可以共享某些属性(如位于某个特定的GPS位置),而其他属性不同(如有大量汽油或没有汽油),这使得研究如何将一种状态转换为另一种状态变得更加容易。人工智能的许多重要领域都基于因子化表示,包括约束满足算法(第6章)、命题逻辑(第7章)、规划(第11章)、贝叶斯网络(第12~16章)以及各种机器学习算法。
图2-16 表示状态及其之间转移的3种方法:(a)原子表示一个状态(如B或C)是没有内部结构的黑盒;(b)因子化表示状态由属性值向量组成,值可以是布尔值、实值或一组固定符号中的一个;(c)结构化表示状态包括对象,每个对象可能有自己的属性以及与其他对象的关系
出于许多目的,我们需要将世界理解为存在着相互关联的事物,而不仅仅是具有值的变量。例如,我们可能会注意到前面有一辆卡车正在倒车进入一个奶牛场的车道,但一头散养的奶牛挡住了卡车的路。因子化表示不太可能为属性TruckAheadBackingIntoDairyFarmDrivewayBlockedByLooseCow预先配备true或false的值。这就需要一个结构化表示(structured representation),在这种表示中可以明确地描述诸如奶牛和卡车之类的对象及其各种不同的关系(见图2-16c)。结构化表示是关系数据库和一阶逻辑(第8~10章)、一阶概率模型(第15章)和大部分自然语言理解(第23章和第24章)的基础。事实上,人类用自然语言表达的大部分内容都与对象及其关系有关。
如前所述,原子表示、因子化表示和结构化表示所在的轴是表达性(expressiveness)增强的轴。粗略地说,可以通过简洁的描述捕捉到更具表达性的表示,表达性差的表示也可以捕捉到一切,但需要更多描述。通常,表达性更强的语言更简洁;例如,国际象棋规则可以用一两页结构化表示语言(如一阶逻辑)来描述,但需要数千页因子化表示语言(如命题逻辑)来描述,而需要1038页的原子语言(如有限状态自动机)来描述。但是,随着表示能力的增强,推理和学习变得更加复杂。为了在避免缺点的同时获得表达性表示的好处,真实世界中的智能系统可能需要轴上的所有点同时运行。
另一个表示轴涉及从概念到物理记忆中位置的映射,包括计算机的内存和大脑的记忆。如果概念和记忆位置之间存在一对一的映射,我们称之为局部表示(localist representation)。但是,如果一个概念的表示分布在多个记忆位置,并且每个记忆位置被用作多个不同概念表示的一部分,我们称之为分布式表示(distributed representation)。分布式表示对噪声和信息丢失更健壮。使用局部表示,从概念到记忆位置的映射是随机的,如果传输错误而导致几位乱码,我们可能会将卡车(Truck)与无关的概念停战(Truce)混淆。但在分布式表示中,可以把每个概念想象成多维空间中的一个点,即使有一些乱码,也会移动到该空间中附近的点,其具有相似的含义。
本章是人工智能的旋风之旅,在这个过程中我们认为人工智能是智能体设计的科学。本章要回顾的要点如下。
● 智能体是在环境中感知和行动的事物。智能体的智能体函数指定智能体在响应任意感知序列时所采取的动作。
● 性能度量评估智能体在环境中的行为。给定到目前为止所看到的感知序列,理性智能体的动作是为了最大化性能度量的期望值。
● 任务环境规范包括性能度量、外部环境、执行器和传感器。在设计智能体时,第一步必须始终是尽可能完整地指定任务环境。
● 任务环境在几个重要维度上有所不同。它们可以是完全可观测的或部分可观测的、单智能体的或多智能体的、确定性的或非确定性的、回合式的或序贯的、静态的或动态的、离散的或连续的、已知的或未知的。
● 在性能度量未知或难以正确指定的情况下,智能体优化错误目标的风险很大。在这种情况下,智能体设计应该反映真实目标的不确定性。
● 智能体程序实现智能体函数。存在各种基本的智能体编程,反映了决策过程中明确使用的信息类型。这些设计在效率、紧凑性和灵活性方面各不相同。智能体程序的适当设计取决于环境的性质。
● 简单反射型智能体直接响应感知,而基于模型的反射型智能体保持内部状态以跟踪当前感知中不明晰的世界状态。基于目标的智能体采取行动来实现目标,而基于效用的智能体试图最大化自己期望的“快乐”。
● 所有智能体都可以通过学习提升性能。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们讨论一个智能体是如何向前搜索,找到一个动作序列来实现它的最终目标。
当要采取的正确动作不是很明显时,智能体可能需要提前规划:考虑一个形成通往目标状态路径的动作序列。这样的智能体被称为问题求解智能体(problem-solving agent),它所进行的计算过程被称为搜索(search)。
如2.4.7节所述,问题求解智能体使用原子(atomic)表示,也就是说,世界状态被视为一个整体,其内部结构对问题求解算法来说是不可见的。使用状态的因子化(factored)表示或结构化(structured)表示的智能体称为规划智能体(planning agent),第7章和第11章中将会讨论。
我们将在本书中介绍若干搜索算法。在本章中,我们将只考虑最简单的环境,即回合式的、单智能体的、完全可观测的、确定性的、静态的、离散的和已知的环境,并对有信息(informed)算法和无信息(uninformed)算法进行区分。在有信息算法中,智能体可以估计自己到目标的距离,而在无信息算法中不能进行这样的估计。第4章会讨论更一般的环境中的问题,第5章则考虑了多智能体的情形。
本章使用了渐近复杂性的概念(即O(n)表示法)。不熟悉这些概念的读者可以参阅附录A。
想象一下,一个智能体正在罗马尼亚度假。它想参观景点,想学习罗马尼亚语,想享受罗马尼亚的夜生活但又不想宿醉,等等。这一决策问题是复杂的。现在,假设智能体目前位于Arad,并且买了一张第二天从Bucharest起飞且不能退款的机票。智能体观察路牌后发现,从Arad出发有3条路:一条通往Sibiu,一条通往Timisoara,还有一条通往Zerind。但这都不是它的目的地,所以除非智能体熟悉罗马尼亚的地理环境,不然它不知道该走哪条路。[1]
[1] 我们假设大多数读者都处于同样的处境,并且很容易想象自己和智能体一样毫无头绪。我们向不能利用这一教学安排的罗马尼亚读者道歉,因为他们清楚地知晓哪条路更易到达Bucharest。
如果智能体没有额外信息,也就是说,如果环境是未知的(unknown),那么智能体只能随机执行一个动作。这种情况将在第4章讨论。在本章中,我们假设智能体总是能够访问与世界相关的信息,例如图3-1中的地图。有了这些信息,智能体可以执行以下4个阶段的问题求解过程。
● 目标形式化(goal formulation):智能体的目标为到达Bucharest。目标通过限制智能体的目的和需要考虑的动作来组织其行为。
图3-1 罗马尼亚部分地区的简化道路图,道路距离单位为英里(1英里 = 1.61千米)
● 问题形式化(problem formulation):智能体刻画实现目标所必需的状态和动作——进而得到这个世界中与实现目标相关的部分所构成的抽象模型。对智能体来说,一个好的模型应该考虑从一个城市到其相邻城市的动作,这时,状态中只有“当前所在城市”会由于动作而改变。
● 搜索(search):在真实世界中采取任何动作之前,智能体会在其模型中模拟一系列动作,并进行搜索,直到找到一个能到达目标的动作序列。这样的序列称为解(solution)。智能体可能不得不模拟多个无法到达目标的序列,但最终它要么找到一个解(例如从Arad到Sibiu到Fagaras再到Bucharest),要么发现问题是无解的。
● 执行(execution):现在智能体可以执行解中的动作,一次执行一个动作。
一个重要的性质是,在一个完全可观测的、确定性的、已知的环境中,任何问题的解都是一个固定的动作序列:开车到Sibiu,然后到Fagaras,最后到达Bucharest。如果模型是正确的,那么一旦智能体找到了一个解,它就可以在执行动作时忽略它的感知(“闭上眼睛”),因为解一定会到达目标。控制理论家称之为开环(open-loop)系统,因为忽略感知打破了智能体和环境之间的环路。如果模型有可能是不正确的,或者环境是非确定性的,那么监控感知的闭环(closed-loop)方法会更安全(见4.4节)。
在部分可观测或非确定性环境中,问题的解将是一个根据感知推荐不同的未来动作的分支策略。例如,智能体可能规划从Arad开车到Sibiu,但还需要一个应变规划,以防它不小心到了Zerind或者发现了“Drum Închis”(道路封闭)的标志。
搜索问题(problem)的形式化定义如下。
● 可能的环境状态(state)的集合,我们称之为状态空间(state space)。
● 智能体启动时的初始状态(initial state),例如Arad。
● 一个或多个目标状态(goal state)的集合。有时问题只有一个目标状态(如Bucharest),有时存在若干个可供选择的目标状态,也有时目标是由一个适用于许多状态(可能是无限多个状态)的属性所定义的。例如,在一个真空吸尘器世界里,目标可能是让任何位置都没有灰尘,而无论该状态的其他情况如何。我们通过给问题指定一个Is-Goal方法来将这3种可能性都考虑在内。在本章中,为了简单起见,我们有时会直接用“目标”一词,它表示“任一可能的目标状态”。
● 智能体可以采取的行动(action)。给定一个状态s,Actions(s)将返回在s中可以执行的有限[2]动作集合。我们称集合中的任一动作在s中都是适用的(applicable)。例如:
[2] 对于具有无限多个动作的问题,我们需要本章之外的其他技巧。
● 转移模型(transition model)用于描述每个动作所起到的作用。Result(s, a)将返回在状态s中执行动作a所产生的状态。例如:
● 动作代价函数(action cost function),在编程中记作Action-Cost(s, a, s' ),在数学运算中记作c(s, a, s' )。它给出了在状态s中执行动作a从而转移到状态s'的数值代价。问题求解智能体应该使用反映其自身性能指标的代价函数;例如,对于寻径智能体,动作代价可能是以英里为单位的长度(如图3-1所示),也可能是完成动作所花费的时间。
一个动作序列形成一条路径(path),而解(solution)是一条从初始状态到某个目标状态的路径。我们假设动作代价是可累加的;也就是说,一条路径的总代价是各个动作代价的总和。最优解(optimal solution)是所有解中路径代价最小的解。在本章中,我们假设所有的动作代价都为正,以减少复杂性。[3]
[3] 在任何存在负代价环的问题中,代价最优解为在这个环中循环无限次。不存在负代价环时,Bellman-Ford算法和Floyd-Warshall算法(本章暂未涉及)可以处理负代价动作。只要连续的零代价动作的数量是有限的,处理零代价动作就很容易。例如,假设有一个机器人,其移动的代价为正,但旋转90°的代价为0;只要连续旋转90°动作的数量不超过3个,本章的算法就可以处理这个问题。存在无限多个任意小的动作代价的问题也很复杂。考虑Zeno悖论的情况,存在一个动作,它每次向目标移动剩余距离的二分之一,代价为上一次移动代价的二分之一。这个问题不存在动作数量有限的解,但为了防止搜索在没有完全到达目标的情况下采取无限数量的动作,我们可以要求所有动作的代价至少为,
为某个较小的正值。
状态空间可以用图(graph)来表示,图中的顶点表示状态,顶点之间的有向边表示动作。图3-1所示的罗马尼亚地图就是这样一个图,每条道路表示两种动作,即两个方向各表示一种。
我们将前文中去往Bucharest的问题形式化为一个模型(model)——一种抽象的数学描述,而不是真实存在的实物。与简单的原子状态描述Arad相比,实际的旅行的世界状态包括很多内容:旅行伙伴、当时的广播节目、窗外的风景、附近是否有执法人员、到下一个休息站的距离、道路状况、天气、交通等。所有这些因素都被排除在我们的模型之外,因为它们与寻找前往Bucharest的路线问题无关。
从表示中剔除细节的过程称为抽象(abstraction)。一个良好的问题形式化应该具有适度的细节层次。如果智能体的动作细化到“右脚向前移动1厘米”或“方向盘向左转动1度”的层次上,那它可能永远都找不到走出停车场的路,更不用说去Bucharest了。
我们能更精确地定义合适的抽象层级(level of abstraction)吗?我们所选择的抽象状态和动作对应于大量具体的世界状态和动作序列。现在考虑抽象问题的解,例如,从Arad到Sibiu,到Rimnicu Vilcea,到Pitesti,再到Bucharest的路径。这个抽象解对应于大量更详细的路径。例如,从Sibiu开往Rimnicu Vilcea的途中,我们可以打开收音机,而在其他的旅程中关掉收音机。
如果我们能够将任何抽象解细化为更详细的世界中的解,那么这种抽象就是合理的;一个充分条件是,对于“in Arad”的每个详细状态,都有一条到达“in Sibiu”状态的详细路径,以此类推。[4]如果执行解中的每个动作都比原始问题更容易,那么抽象是有用的;在我们的示例中,“从Arad开车到Sibiu”的动作,任何一个一般水平的司机都可以在不进一步搜索或规划的情况下完成。因此,选择一个好的抽象需要删除尽可能多的细节,同时保留合理性,并确保抽象动作易于执行。如果没有构造有用的抽象的能力,智能体将被真实世界完全淹没。
[4] 参见11.4节。
问题求解的方法已被应用于大量任务环境中。我们在这里列出一些典型问题,区分为标准化问题和真实世界问题。标准化问题(standardized problem)常用于说明或训练各种问题求解方法。它具有简洁、准确的描述,因此适合作为研究人员比较算法性能的基准。真实世界问题(real-world problem),如机器人导航,则意味着这一问题的解是人们实际使用的,且问题的形式化是独特的而非标准化的,因为例如在机器人导航问题中,每个机器人具有不同的传感器,产生不同的数据。
网格世界(grid world)问题是一个由正方形单元格组成的二维矩形阵列,在这个阵列中,智能体可以从一个单元格移动到另一个单元格。一般来说,智能体可以水平或垂直地移动到任何无障碍的相邻单元格,在某些问题中还可以沿对角线移动。单元格中可以包含智能体能拿起、推开或施加其他动作的物体,也可以存在阻止智能体进入单元格内的墙壁或其他不可逾越的障碍。2.1节中的真空吸尘器世界(vacuum world)可以表示为一个网格世界问题。
● 状态:即哪些对象在哪些单元格中。在真空吸尘器世界中,对象就是智能体和灰尘。对于只有两个单元格的简单情形,智能体可以位于这两个单元格中的任何一个,每个单元格都可能存在灰尘,所以共有2×2×2 = 8个状态(见图3-2)。一般来说,存在n个单元格的真空吸尘器环境有n×2n 个状态。
● 初始状态:任一状态都可以被指定为初始状态。
● 动作:在只有两个单元格的情形中,我们可以定义3种动作,即吸尘(Suck)、向左(Left)移动和向右(Right)移动。在二维多单元格世界中,我们则需要更多种移动动作。我们可以增加向上(Upward)和向下(Downward)的动作,从而得到4种绝对的(absolute)移动动作,或者可以将其转换为以自我为中心的动作,即从相对于智能体的角度来定义,例如,向前(Forward)、向后(Backward)、右转(TurnRight)和左转(TurnLeft)。
● 转移模型:Suck将去除单元格内的任何灰尘;Forward将智能体朝它所面对的方向向前移动一个单元格,除非它撞到墙(在这种情况下,这个行动不起作用)。Backward让智能体朝相反的方向移动一个单元格,而TurnRight和TurnLeft则将智能体的朝向旋转90°。
● 目标状态: 每个单元格都保持干净的状态。
● 动作代价: 每个动作的代价都是1。
图3-2 两个单元格的真空吸尘器世界的状态空间图。共有8个状态,每个状态有3种动作:L = Left(向左)、R = Right(向右)、S = Suck(吸尘)
另一种类型的网格世界是推箱子问题(sokoban puzzle),在这个问题中,智能体的目标是将一些散落在网格中的箱子推到指定的存储位置。每个单元格最多容纳一个箱子。当智能体向前移动到放有一个箱子的单元格,而箱子另一侧的单元格为空时,箱子和智能体都向前移动一格。智能体不能把一个箱子推到另一个箱子上或墙上。对于存在n个无障碍单元格和b个箱子的世界,共有个状态;例如,在一个存在12个箱子的8×8网格中,有超过200万亿个状态。
在滑块问题(sliding-tile puzzle)中,若干滑块(有时称为块或片)排列在一个有若干空白区域的网格中,其中滑块可以滑进空白区域。它的一个变体是汽车华容道问题(Rush Hour puzzle),在这个问题中,我们需要在6×6的网格中滑动汽车和卡车,目标是将一辆汽车从交通堵塞中解救出来。滑块问题中最著名的变体是8数码问题(8-puzzle)(见图3-3),它由一个3×3的网格、8个带编号的滑块和一个空格组成,目标是达到指定的状态,如图3-3中右侧所示。类似的还有由4×4的网格组成的15数码问题(15-puzzle)。对8数码问题做如下形式化处理。
● 状态:指定每个滑块位置的状态描述。
● 初始状态:任何状态都可以被指定为初始状态。注意,可以根据奇偶性划分状态空间——任何给定目标都可以从恰好一半的可能初始状态到达(见习题 3.PART)。
● 动作:虽然在真实世界中是滑块在移动,但描述动作的最简单方法是假设空格执行Left、Right、Up或Down动作。如果空格位于边缘或角落,则不是所有的动作都可用。
● 转移模型:将状态和动作映射为一个结果状态;例如,图3-3中,对于初始状态,我们采取Left动作,那么结果状态中滑块5和空格将交换位置。
● 目标状态:尽管任何状态都可以作为目标状态,但我们通常用有序编号指定目标状态,如图3-3所示。
● 动作代价:每个动作的代价都为1。
注意,每个问题的形式化都涉及抽象。8数码问题中的动作被抽象为它们的开始状态和结束状态,忽略滑块滑动的中间位置。我们已经通过抽象除去了一些动作,例如,当滑块被卡住时需要晃动木板,并排除了用刀取出滑块然后再放回去的可能性。最终只剩下对规则的描述,避免了实际操作的所有细节。
图3-3 8数码问题的一个典型实例
我们介绍的最后一个标准化问题是由高德纳(Knuth, 1964)设计的,它说明了无限状态空间是如何产生的。高德纳推测,通过只由平方根、向下取整和阶乘操作组成的序列可以从数字4得到任何正整数。例如,我们可以这样从4得到5:
问题定义很简单,如下所述。
● 状态:正实数。
● 初始状态:4。
● 动作:应用平方根、向下取整或阶乘操作(阶乘仅用于整数)。
● 转移模型:根据运算的数学定义给出。
● 目标状态:所求的正整数。
● 动作代价:每个动作的代价都是1。
这一问题的状态空间是无限的:对于任意大于2的整数,阶乘操作总是产生一个更大的整数。这个问题很有趣,因为它探索了非常大的数字:从4到5的最短路径生成了数字(4!)! = 620 448 401 733 239 439 360 000。无限状态空间经常出现在涉及数学表达式生成、电路、证明、程序和其他递归定义对象的任务中。
我们已经了解了如何根据指定的位置和沿着它们之间的边进行的位置转移来定义寻径问题(route-finding problem)。寻径算法有许多应用场景。其中一些是上文中罗马尼亚例子的直接扩展,例如提供导航的网站和车载系统等。(需要考虑的主要复杂因素是因与交通相关的延迟而导致的代价变化,以及因道路封闭而导致的路线变更。)另一些例如计算机网络中的视频流路由、军事行动规划和飞机航线规划系统等,则更加复杂。下面介绍旅行规划网站必须解决的航空旅行问题。
● 状态:每个状态显然包括当前位置(例如,某个机场)和当前时间。此外,由于每个动作(一个航段)的代价可能依赖于之前的航段、票价基础以及它们是国内航班还是国际航班,状态必须记录这些额外的“历史”信息。
● 初始状态:用户家所在的机场。
● 动作:在当前时间之后,从当前位置乘坐任意航班任意舱位起飞,如果需要,还要留出足够的时间在机场中转。
● 转移模型:乘坐航班产生的结果状态将航班的目的地作为新的当前位置,将航班的到达时间作为新的当前时间。
● 目标状态:目的地城市。有时目标可能更复杂一点,例如“乘坐直达航班到达目的地”。
● 动作代价:金钱成本、等待时间、飞行时间、海关和入境手续、舱位质量、当日时间、飞机类型、常旅客奖励积分等的组合。
商业旅行咨询系统使用的就是上述问题的形式化。不过,在处理航空公司错综复杂的票价结构时,还会有许多额外的复杂因素。例如,任何有经验的旅行者都知道,并不是所有的航空旅行都能按计划进行。因此,一个真正好的系统应该包括应变规划——如航班延误或者错过转机时的应对方案。
旅行问题(touring problem)描述的是一组必须访问的地点,而非单一目的地。旅行商问题(traveling salesperson problem,TSP),就是一个旅行问题,即地图上每个城市都必须被访问。其目标是找到代价小于C的旅行路线(在优化版本中,目标是找到代价最低的旅行路线)。为了提高TSP算法的性能,科研人员付出了大量的努力。该算法也可以扩展到处理车队问题。例如,规划波士顿校车路线的搜索优化算法为人们节约了500万美元,减少了交通拥堵和空气污染,同时还为司机和学生节省了时间(Bertsimas et al., 2019)。除了规划行程,搜索算法还被用于规划自动电路板钻孔机钻头的运动和装料机在车间内的移动等任务。
超大规模集成电路布图(VLSI layout)问题需要在一个芯片上定位数百万个元件和连接点,以最小化芯片面积、电路延迟和杂散电容,并最大化成品率。布图问题在逻辑设计阶段之后,通常分为两个部分:单元布图(cell layout)和通道布线(channel routing)。在单元布图中,电路的基本元件分组为若干单元,每个单元执行一些特定功能。每个单元都有固定的占用区域(大小和形状),并且需要与其他每个单元建立一定数量的连接。单元布图的目的是将单元彼此不重叠地放置在芯片上,并且单元之间有足够的空间布置连线。通道布线的目的则是通过单元之间的间隙为每条导线寻找特定的路线。这些搜索问题极其复杂,但绝对值得研究。
机器人导航(robot navigation)是寻径问题的一个推广。机器人不必沿着明确的路径(如罗马尼亚的道路)行走,而是可以四处游走,实际上是自己走自己的路。对于在平面上移动的圆形机器人,空间本质上是二维的。当机器人的手臂和腿也必须受到控制时,搜索空间就变成了多维的——每个关节角都是一个维度。为了使基本上连续的搜索空间变成有限空间,需要一些更先进的技术(见第26章)。除了问题的复杂性外,真正的机器人还必须处理传感器读取错误、电动机控制中的错误、部分可观测性以及可能改变环境的其他智能体等问题。
自20世纪70年代以来,由机器人对复杂物体(例如电动机)进行自动装配排序(automatic assembly sequencing)已成为标准的工业实践。算法首先找到一个可行的装配序列,然后对装配过程进行优化。将装配线上的人工劳动减少到最低限度可以节省大量时间和成本。装配问题的目标是找到某个对象的各个零件的组装顺序。如果顺序错误,那么只能撤消某些已完成的工序,否则无法在序列的后面添加其他部分。检查序列中动作的可行性是与机器人导航问题密切相关的几何搜索难题。因此,合法动作的生成是装配排序问题中代价较高的部分。任何实用算法都必须尽量避免探索全部的状态空间,而应只探索状态空间中的很小一部分。一类重要的装配问题是蛋白质设计(protein design),其目的是找到一种氨基酸序列,该序列能够折叠成具有正确特性的三维蛋白质结构,以治疗某些疾病。
搜索算法(search algorithm)将搜索问题作为输入并返回问题的解或报告failure(当解不存在时)。在本章中,我们考虑在状态空间图上叠加一棵搜索树(search tree)的算法,该算法从初始状态形成各条路径,并试图找到一条可以达到某个目标状态的路径。搜索树中的每个节点(node)对应于状态空间中的一个状态,搜索树中的边对应于动作。树的根对应于问题的初始状态。
理解状态空间和搜索树之间的区别非常重要。状态空间描述了世界的(可能无限的)状态集,以及允许从一个状态转移到另一个状态的动作。搜索树描述了这些状态之间通向目标的路径。搜索树可以有多条路径(因此可以有多个节点)到达任何给定状态,但树中的每个节点都只有唯一一条返回根的路径(与所有树一样)。
图3-4展示了寻找从Arad到Bucharest的路径的前几步。搜索树的根节点位于初始状态,Arad。我们可以按如下方式扩展(expand)节点:考虑该状态的可用动作Actions,使用Result函数查看这些动作指向何处,并为每个结果状态生成(generating)一个新节点,称为子节点(child node)或后继节点(successor node)。每个子节点的父节点(parent node)都是Arad。
图3-4 3棵部分搜索树,用于寻找从Arad到Bucharest的路线。已扩展节点用淡紫色和粗体字母表示;边界上已生成但未被扩展的节点用绿色表示;对应于这两种类型节点的状态集被称为已达。接下来可能生成的节点用虚线表示。注意,在最下面的树中,有一个从Arad到Sibiu再到Arad的环,这不可能是最优路径,因此搜索不应该从那里继续
现在我们必须从这3个子节点中选择一个考虑下一步扩展。这就是搜索的本质——先跟踪一个选项,之后再考虑其他选项。假定我们选择先扩展Sibiu。结果如图3-4中最下面的搜索树所示,我们得到了6个未被扩展的节点(以绿色节点显示)。我们称之为搜索树的边界(frontier)。任何已经生成过节点的状态都称为已达(reached)状态(无论该节点是否被扩展)。[5]图3-5为叠加在状态空间图上的搜索树。
[5] 一些作者将边界称为开节点表,这在地理学上不太容易引起共鸣,在计算上也不太合适,因为在这里,队列比表更有效。这些作者还使用闭节点表一词来指代之前已扩展的节点的集合,在我们的术语中,这些节点为已达节点去掉边界节点后的剩余节点。
图3-5 由图3-1中的罗马尼亚问题的图搜索生成的搜索树序列。在每一阶段,我们扩展边界上的每个节点,使用所有不指向已达状态的可用动作延伸每条路径。需要注意的是,在第三阶段,最高位置的城市(Oradea)有两个后继城市,这两个城市都已经有其他路径到达,所以没有路径可以从Oradea延伸
注意,边界分离(separate)了状态空间图的两个区域,即内部区域(其中每个状态都已被扩展)和外部区域(尚未到达的状态)。该属性如图3-6所示。
图3-6 以矩形网格问题为例说明图搜索的分离性质。边界(绿色)分离了内部(淡紫色)和外部(虚线)。边界是已达但尚未扩展的节点(及相应的状态)的集合;内部是已被扩展的节点(及相应的状态)的集合;外部是尚未到达的状态的集合。在(a)中,只有根节点被扩展。在(b)中,上面的边界节点被扩展。在(c)中,按顺时针顺序扩展根节点的其他后继节点
我们如何决定下一步从边界扩展哪个节点?最佳优先搜索(best-first search)是一种非常通用的方法,在这种方法中,我们选择使得某个评价函数(evaluation function)f(n)的值最小的节点n。算法如图3-7所示。在每次迭代中,选择边界上具有最小f(n)值的一个节点,如果它的状态是目标状态,则返回这个节点,否则调用Expand生成子节点。对于每个子节点,如果之前未到达过该子节点,则将其添加到边界;如果到达该子节点的当前路径的代价比之前任何路径都要小,则将其重新添加到边界。该算法要么返回failure,要么返回一个节点(表示一条通往目标的路径)。通过使用不同的f(n)函数,可以得到不同的具体算法,本章将介绍这些算法。
图3-7 最佳优先搜索算法以及扩展节点的函数。这里使用的数据结构将在3.3.2节中介绍。yield的说明见附录B
搜索算法需要一个数据结构来跟踪搜索树。树中的节点(node)由一个包含4个组成部分的数据结构表示。
● node.State:节点对应的状态。
● node.Parent:父节点,即树中生成该节点的节点。
● node.Action:父节点生成该节点时采取的动作。
● node.Path-Cost:从初始状态到此节点的路径总代价。在数学公式中,一般使用g(node)表示Path-Cost。
通过从一个节点返回的Parent指针,我们可以复原到达该节点的路径上的状态和动作。从一个目标节点开始复原,我们就可以得到问题的解。
我们需要一个数据结构来存储边界。一个恰当的选择是某种队列(queue),因为边界上的操作有以下几个。
● Is-Empty( frontier):返回true当且仅当边界中没有节点。
● Pop( frontier):返回边界中的第一个节点并将它从边界中删除。
● Top( frontier):返回(但不删除)边界中的第一个节点。
● Add(node, frontier):将节点插入队列中的适当位置。
搜索算法使用了3种不同类型的队列。
● 优先队列(priority queue)首先弹出根据评价函数f计算得到的代价最小的节点。它被用于最佳优先搜索。
● FIFO队列(FIFO queue),即先进先出队列(first-in-first-out queue),首先弹出最先添加到队列中的节点;它被用于广度优先搜索。
● LIFO队列(LIFO queue),即后进先出队列(last-in-first-out queue),也称为栈(stack),首先弹出最近添加的节点;它被用于深度优先搜索。
已达状态可以存储为一个查找表(例如,哈希表),其中每个键是一个状态,对应的值是该状态的节点。
图3-4(最下面一排)所示的搜索树包含了一条从Arad到Sibiu再回到Arad的路径。这时我们称Arad为搜索树中的一个重复状态(repeated state),在本例中该重复状态是由循环(cycle)[也称为环路(loopy path)]生成的。因此,即使状态空间只有20种状态,完整的搜索树也是无限的,因为遍历循环的频率没有限制。
循环是冗余路径(redundant path)的一种特殊情况。例如,我们可以通过路径Arad—Sibiu(总长140英里)或路径Arad—Zerind—Oradea—Sibiu(总长297英里)到达Sibiu。第二条路径是冗余的——是到达相同状态的一种比较差的方式——在我们寻找最优路径时不需要考虑它。
考虑一个10×10网格世界中的智能体,它能够移动到8个相邻方格中的任何一个。如果没有障碍,智能体可以在9步或更少的移动内到达100个方格中的任何一个。但是长度为9的路径的数量几乎是89(由于网格边缘的存在,路径数稍微少了一点),超过了1亿条。也就是说,平均意义下,有超过100万条长度为9的冗余路径到达同一个单元格,如果我们消除了冗余路径,搜索完成的速度可以快大约100万倍。俗话说,不记得历史的算法注定要重复历史。有3种方法可以解决这一问题。
第一,我们可以记住之前到达的所有状态(就像最佳优先搜索一样),这样能够检测到所有冗余路径,并只保留每个状态的最优路径。这适用于存在大量冗余路径的状态空间,当内存可以容纳下已达状态表时,它是首选方法。
第二,我们不必担心对过去的重复。在一些问题形式化中,很少或不可能出现两条路径到达相同状态。以装配问题为例,每个动作都会将一个零件添加到一个不断发展的装配中,零件是有序的,因此可以先添加A,然后再添加B,但不能先添加B,然后再添加A。对于这些问题, 如果我们不记录已达状态也不检查冗余路径,则可以节省内存空间。如果搜索算法会检查冗余路径,我们称之为图搜索(graph search);否则,称之为树状搜索(tree-like search)[6]。图3-7中的Best-First-Search算法是一种图搜索算法;如果删除所有对reached的引用,即为树状搜索,它使用更少的内存,但会出现到达相同状态的冗余路径,因此运行速度会更慢。
[6] 我们称之为“树状搜索”,是因为无论如何搜索,状态空间仍然是相同的图;我们只是把它当作一棵树,从每个节点返回根只有一条路径。
第三,我们可以选择折中方法,检查循环,但通常不检查冗余路径。由于每个节点都有一个父指针链,因此可以通过跟踪父指针链来查看路径末端的状态之前是否在路径中出现过,从而不需要额外内存即可检查是否存在循环。某些算法实现一直沿着这个链向上移动,从而消除了所有循环。另一些算法实现仅跟踪少数几个链接(例如,到父节点、祖父节点和曾祖父节点),因此仅需花费固定的时间就可以消除所有短循环(并依靠其他机制来处理长循环)。
在开始设计各种搜索算法之前,需要考虑在这些算法中进行选择时所使用的标准。我们可以从以下4个方面评价算法的性能。
● 完备性(completeness):当存在解时,算法是否能保证找到解,当不存在解时,是否能保证报告失败?
● 代价最优性(cost optimality):它是否找到了所有解中路径代价最小的解?[7]
[7] 一些作者使用“可容许性”这一术语表示寻找最小代价解的性质,还有一些作者仅使用“最优性”,但这可能与其他类型的最优性相混淆。
● 时间复杂性(time complexity):找到解需要多长时间?可以用秒数来衡量,或者更抽象地用状态和动作的数量来衡量。
● 空间复杂性(space complexity):执行搜索需要多少内存?
为了理解完备性,考虑一个具有单一目标的搜索问题。这个目标可能是状态空间的任何地方;因此,一个完备的算法必须能够系统地探索从初始状态可以到达的每一个状态。在有限状态空间中,这是很容易实现的:只要我们跟踪路径并切断循环(例如,Arad到Sibiu再到Arad),最终我们将到达每一个可到达的状态。
在无限状态空间中,则需要更加小心。例如,在高德纳的“4”问题中反复应用“阶乘”操作的算法将沿着从4到4!到(4!)!……的无限路径行进。同样地,在一个没有障碍的无限网格上,沿着直线不停前进也会形成由新状态组成的无限路径。在这两种情况下,算法永远不会返回它之前到达的状态,但它是不完备的,因为状态空间中的大部分状态永远都不会到达。
完备的搜索算法探索无限状态空间的方式必须是系统的(systematic),以确保它最终能够到达与初始状态相关的任何状态。例如,在无限网格上,一种系统搜索方法是螺旋路径,它覆盖了距离原点s步远的所有单元格,然后移动到s + 1步远的单元格。遗憾的是,在一个不存在解的无限状态空间中,一个合理的算法会一直搜索,它不会终止,因为它不知道下一个状态是否是目标状态。
时间复杂性和空间复杂性与问题的困难程度相关。在理论计算机科学中,一种典型的度量方式是状态空间图的大小,,其中
是图中顶点(状态节点)的数量,
是边(不同的状态/动作对)的数量。当状态空间图是显式的数据结构(如罗马尼亚地图)时,这种度量是合适的。但在许多人工智能问题中,状态空间图只是由初始状态、动作和转移模型隐式地表示。对于隐式的状态空间,复杂性可以用3个量来衡量:d,最优解的深度(depth)或动作数;m,任意路径的最大动作数;b,需要考虑的节点的分支因子(branching factor)或后继节点数。
无信息搜索算法不提供有关某个状态与目标状态的接近程度的任何线索。例如,考虑一个位于Arad且目标为Bucharest的智能体。一个对罗马尼亚地理一无所知的无信息智能体无法判断第一步应该前往Zerind还是Sibiu。相比之下,了解每个城市位置的有信息智能体(3.5节)则知道Sibiu距离Bucharest更近,因此Sibiu更有可能在最短路线上。
当所有动作的代价相同时,正确的策略是采用广度优先搜索(breadth-first search),即先扩展根节点,然后扩展根节点的所有后继节点,再扩展后继节点的后继,以此类推。这是一种系统的搜索策略,因此即使在无限状态空间上也是完备的。我们可以通过调用Best-First-Search实现广度优先搜索,其中评价函数f(n)是节点的深度,即到达该节点所需的动作数。
然而,我们可以通过一些技巧来提高算法效率。先进先出队列比优先队列速度更快,并且能提供正确的节点顺序:新节点(总是比其父节点更深)进入队列的队尾,而旧节点,即比新节点浅的节点,首先被扩展。此外,reached可以是一组状态,而不是状态到节点的映射,因为一旦到达某个状态,我们就再也找不到到达该状态的更好路径了。这也意味着我们可以进行早期目标测试(early goal test),即在生成节点后立即检查该节点是否为一个解,而不是像最佳优先搜索使用的后期目标测试(late goal test)那样,等节点弹出队列后再检查该节点是否为一个解。图3-8展示了在二叉树上进行广度优先搜索的过程,图3-9展示了使用早期目标测试来提高效率的算法。
图3-8 简单二叉树上的广度优先搜索。每个阶段接下来要扩展的节点用三角形标记表示
图3-9 广度优先搜索和一致代价搜索算法
广度优先搜索总是能找到一个动作最少的解,因为当它生成深度为d的节点时,说明它已经生成了深度为d - 1的所有节点,如果其中一个节点是解,它应该已经被找到了。这意味着,对于所有动作都具有相同代价的问题,它是代价最优的,但对于不具有该特性的问题,则不一定是最优的。这两种情况都是完备的。在时间和空间方面,想象我们在搜索一棵均衡树,其中每个状态都有b个后继。搜索树的根生成b个节点,每个节点又生成b个节点,第二层总共是b2个节点。每个节点又生成b个节点,从而在第三层产生b3个节点,以此类推。现在假设解的深度为d,那么生成的节点总数为
所有节点都存储在内存中,所以时间复杂性和空间复杂性都是O(bd)。这样的指数级上界是可怕的。举一个典型的真实世界中的例子,考虑一个分支因子b = 10、处理速度为每秒100万节点、内存需求为1 KB/节点的问题。深度d = 10的搜索将花费不到3小时的时间,但需要10 TB的内存。对广度优先搜索来说,内存需求是一个比执行时间更严重的问题。但时间仍然是一个重要因素。深度d = 14时,即使有无限内存,搜索也需要3.5年。一般来说,除了最小的问题实例,指数级复杂性的搜索问题无法通过无信息搜索求解。
当动作具有不同的代价时,一个显而易见的选择是使用最佳优先搜索,评价函数为从根到当前节点的路径的代价。理论计算机科学界称之为Dijkstra算法,人工智能界则称之为一致代价搜索(uniform-cost search)。不同于广度优先搜索在深度一致的波(首先是深度1,然后是深度2,以此类推)中展开,一致代价搜索算法的思想是在路径代价一致的波中展开。该算法可以通过调用Best-First-Search实现,评价函数为Path-Cost,如图3-9所示。
考虑图3-10,问题是从Sibiu到达Bucharest。Sibiu的后继是Rimnicu Vilcea和Fagaras,代价分别为80和99。然后扩展代价最小的节点Rimnicu Vilcea,加入节点Pitesti,其代价为80 + 97 = 177。此时代价最小的节点是Fagaras,所以接着扩展Fagaras,加入节点Bucharest,代价为99 + 211 = 310。目标节点是Bucharest,但算法只在扩展节点时测试其是否为目标节点,而不是在生成节点时测试,因此它还没有检测到这是一条通往目标的路径。
图3-10 罗马尼亚问题状态空间的一部分,选择这部分来说明一致代价搜索
算法继续进行,接下来选择Pitesti进行扩展,添加到Bucharest的第二条路径,代价为80 + 97 + 101 = 278。它的代价更低,因此用它取代reached中之前的路径,并添加到frontier中。结果证明,这个节点目前具有最小代价,因此它被认为是下一个要扩展的节点,此时我们发现它是一个目标节点,从而返回该节点。注意,如果我们在生成节点时检查目标,而不是在扩展代价最小的节点时检查,那么我们将返回一个代价更高的路径(即经过Fagaras的路径)。
一致代价搜索的复杂性用C*和表示,C*是最优解的代价[8],
是每个动作代价的下界,
。那么算法在最坏情况下的时间复杂性和空间复杂性是
,比bd大得多。这是因为一致代价搜索在探索包含一个可能有用的高代价动作的路径之前,可能会先探索具有低代价动作的大型树。当所有动作代价相同时,
等于bd+1,这时一致代价搜索类似于广度优先搜索。
[8] 在这里,以及整本书中,C*中的“*”表示C的最优值。
一致代价搜索是完备的,也是代价最优的,因为它找到的第一个解的代价至少与边界上的任何其他节点的代价一样小。一致代价搜索会按照代价递增的顺序系统地考虑所有路径,而不会陷入一直沿单一无限路径探索的困境(假设所有动作的代价 )。
深度优先搜索(depth-first search)总是优先扩展边界中最深的节点。它可以通过调用Best-First-Search来实现,其中评价函数f为深度的负数。然而,它通常不是以图搜索的形式实现而是以树状搜索(不维护已达状态表)的形式实现。搜索的过程如图3-11所示,搜索先直接到达搜索树的最深层,这里的节点不存在后继节点。然后,搜索将“回退”到下一个仍存在未扩展后继节点的最深的节点。深度优先搜索不是代价最优的,它会返回它找到的第一个解,即使这个解不是路径代价最小的。
图3-11 二叉树的深度优先搜索过程中,从开始状态A到目标M,共12步(从左到右,从上到下)。边界节点为绿色,用三角形表示下一步要扩展的节点。已扩展的节点为淡紫色,潜在的未来节点用模糊的虚线表示。边界中没有后继的已扩展节点(用非常模糊的线表示)可以丢弃
对于树型的有限状态空间,算法是有效且完备的。对于无环状态空间,算法可能会通过不同路径多次扩展同一状态,但是(最终)将系统地探索整个空间。
在有环状态空间中,深度优先搜索算法可能陷入无限循环;因此,一些深度优先搜索算法的实现会检查每个新节点是否存在循环。在无限状态空间中,深度优先搜索不是系统性的:即使没有循环,它也可能陷入无限路径。因此,深度优先搜索是不完备的。
那么,为什么还会有人选择使用深度优先搜索而不是广度优先搜索或最佳优先搜索呢?答案是,对于使用树状搜索可以处理的问题,深度优先搜索对内存的需求要小得多。深度优先搜索根本不保留reached表,并且边界集很小:如果将广度优先搜索中的边界集视为不断扩展的球体的表面,那么深度优先搜索中的边界集只是球体的半径。
对于图3-11所示的有限树状状态空间,深度优先的树状搜索所花费的时间与状态数成正比,其空间复杂性仅为O(bm),其中b是分支因子,m是树的最大深度。有些问题在广度优先搜索时需要EB量级的内存,而在深度优先搜索时仅需要KB量级。由于其对内存的节约使用,深度优先树状搜索已经成为许多人工智能领域的基本工具,例如,约束满足(第6章)、命题可满足性(第7章)和逻辑编程(第9章)。
回溯搜索(backtracking search)是深度优先搜索的一种变体,它使用的内存更少。(详见第6章。)在回溯搜索中,一次只生成一个后继,而不是所有后继节点;每个部分扩展的节点会记住下一个要生成的后继节点。此外,回溯通过直接修改当前状态描述而不是为一个全新的状态分配内存来生成后继状态。这将内存需求减少到只有一个状态描述和一条具有O(m)个动作的路径;与深度优先搜索的O(bm)个状态相比,节省了大量资源。通过回溯,我们还可以为当前路径上的状态维护一个有效的集合数据结构,从而使检查循环的时间从O(m)减少到O(1)。为了使回溯起作用,我们必须能够在回溯时撤销每个动作。回溯对许多具有大型状态描述的问题(例如机器人组装)的成功求解至关重要。
为了避免深度优先搜索陷入无限路径,我们可以使用深度受限搜索(depth-limited search)。这是一个深度优先搜索的改进版本,在深度受限搜索中,我们设置深度界限,将深度
上的所有节点视为其不存在后继节点(见图3-12)。深度受限搜索算法的时间复杂性为O(b
),空间复杂性为O(b
)。遗憾的是,如果我们对
的选择不当,算法将无法得到解,成为不完备的算法。
由于深度优先搜索是一种树状搜索,通常无法避免在冗余路径上浪费时间,但我们可以以一定的计算时间为代价来消除循环。沿着父节点向上查看几个节点,就能检测出大多数循环;更长的循环则由深度界限处理。
有时可以根据对问题的了解选择一个较好的深度界限。例如,罗马尼亚地图上有20个城市。因此, = 19是一个有效的界限。但是如果仔细研究地图,我们会发现,从任何一个城市到达另一个城市最多需要9步。这个数值称为状态空间图的直径(diameter),它为我们提供了更好的深度界限,从而可以更有效地进行深度受限搜索。然而,对于大多数问题,在求解问题之前,我们无法知道什么深度界限是好的。
迭代加深搜索(iterative deepening search)解决了如何选择一个合适的的问题,方法是尝试所有值:首先是0,然后是1,然后是2,依次类推——直到找到一个解,或者深度受限搜索返回failure值(而不是cutoff值)。算法如图3-12所示。迭代加深搜索结合了深度优先和广度优先搜索的许多优点。和深度优先搜索一样,它对内存的需求也不大:当问题存在解时,是O(bd),在不存在解的有限状态空间上,是O(bm)。与广度优先搜索一样,迭代加深搜索对于所有动作都具有相同代价的问题是最优的,并且在有限无环状态空间上是完备的,或者说在任何有限状态空间上,当我们检查路径节点上所有的循环时,它都是完备的。
图3-12 迭代加深和深度受限树状搜索。迭代加深搜索反复调用界限递增的深度受限搜索。它返回以下3种类型的值中的一种:一个解节点;当它搜索了所有节点,证明在任何深度都不存在解时,返回failure;当在比更深的层上可能存在解时,返回cutoff。这是一种树状搜索算法,它不记录reached状态,因此比最佳优先搜索使用的内存要少得多,但存在通过不同路径多次访问相同状态的风险。另外,如果Is-Cycle检验函数不检查所有环,那么算法可能会陷入一个无限循环
存在解时,时间复杂性为O(bd),不存在解时,时间复杂性为O(bm)。与广度优先搜索相同,迭代加深搜索的每次迭代也会生成一个新层级,但是广度优先搜索将所有节点都存储在内存中,而迭代加深搜索则会重复之前的层级,从而以花费更多的时间为代价节省了内存。图3-13展示了二叉搜索树上的迭代加深搜索的4次迭代,在第4次迭代时找到了解。
迭代加深搜索可能看起来很浪费,因为搜索树顶端附近的状态被多次重复生成。但是对于许多状态空间,大多数节点位于底层,所以上层是否重复并不重要。在迭代加深搜索中,底层(深度d)的节点被生成一次,倒数第二层的节点被生成两次,以此类推,直到根节点的子节点(生成d次)。所以在最坏情况下生成的节点总数是
时间复杂性为O(bd)——与广度优先搜索相近。例如,当b = 10、d = 5时,生成的节点数分别为
如果你确实很在意重复的问题,可以使用一种混合方法,即先运行广度优先搜索,直到几乎消耗掉所有可用内存,然后对边界集中的所有节点应用迭代加深搜索。通常,当搜索状态空间大于内存容量而且解的深度未知时,迭代加深搜索是首选的无信息搜索方法。
图3-13 二叉搜索树上的迭代加深搜索的4次迭代(目标为M),深度界限从0到3。注意,内部节点形成了一条路径。三角形标记下一步要扩展的节点,边界为加粗轮廓的绿色节点,非常模糊的节点可被证明不可能是这种深度界限下的解的一部分
到目前为止,我们介绍的算法都是从一个初始状态开始,最终到达多个可能目标状态中的任意一个。另一种称为双向搜索(bidirectional search)的方法则同时从初始状态正向搜索和从目标状态反向搜索,直到这两个搜索相遇。算法的动机是,要比bd小得多(例如,当b = d = 10时,复杂性不到之前算法的五万分之一)。
为此,我们需要维护两个边界集和两个已达状态表,并且要能反向推理:如果状态s'是s的正向后继,那么我们需要知道s是s'的反向后继。当两个边界触碰到一起时,我们就找到了一个解。[9]
[9] 在我们的实现中,reached数据结构支持查询给定状态是否为其成员,而边界数据结构(一个优先队列)不支持,因此我们使用reached检查是否互相触碰;但从概念上讲,我们查询的是这两个边界是否已经相遇。通过将每个目标状态的节点加载到反向边界和反向已达表中,可以将实现扩展为处理多个目标状态。
双向搜索有很多不同版本,就像有很多不同的单向搜索算法一样。在这一节中,我们将介绍双向最佳优先搜索。尽管存在两个独立的边界,但接下来要扩展的节点始终是两个边界中的评价函数值最小的节点。当函数为路径代价时,我们得到双向一致代价搜索,如果最优路径的代价是C*,则不扩展代价大于的节点。这将使得速度大大提高。
一般的最佳优先双向搜索算法如图3-14所示。我们传入问题和评价函数的两个版本,一个是正向的(下标F),另一个是反向的(下标B)。当评价函数是路径代价时,找到的第一个解将是最优解,但是对于不同的评价函数,这一结论不一定是正确的。因此,我们会记录迄今为止找到的最优解,并且可能不得不多次更新最优解,直到Terminated测试证明不可能再有更好的解。
图3-14 双向最佳优先搜索维护两个边界集和两个已达状态表。当一个边界中的路径到达另一半搜索已达状态时,这两条路径(通过Join-Nodes函数)被连起来构成一个解。我们得到的第一个解不一定是最优的;函数Terminated决定了什么时候停止寻找新的解
图3-15根据3.3.4节中列出的4个评价标准对无信息搜索算法进行了比较。这种比较适用于不检查重复状态的树状搜索版本。对于检查重复状态的图搜索,主要区别在于,对于有限状态空间,深度优先搜索是完备的,并且空间复杂性和时间复杂性受到状态空间大小(顶点和边的数量,)的限制。
图3-15 搜索算法比较。b是分支因子;m是搜索树的最大深度;d是最浅层解的深度,当不存在解时为m;是深度界限
本节将展示有信息搜索(informed search)策略——使用关于目标位置的特定领域线索——如何比无信息搜索策略更有效地找到解。线索以启发式函数(heuristic function)的形式出现,记为h(n):[10]
[10] 这看起来可能很奇怪,启发式函数真正需要的只是节点的状态,但作用对象却是节点。一般使用h(n)而不是h(s),是为了与评价函数f (n)和路径代价g(n)保持一致。
h(n) = 从节点n的状态到目标状态的最小代价路径的代价估计值
例如,在寻径问题中,我们可以通过计算地图上两点之间的直线距离来估计从当前状态到目标的距离。我们将在3.6节中详细研究启发式函数及其来源。
贪心最佳优先搜索(greedy best-first search)是最佳优先搜索的一种形式,它首先扩展h(n)值最小的节点——看起来最接近目标的节点——因为这样可能可以更快找到解。因此,评价函数f(n) = h(n)。
让我们看看这种算法如何求解罗马尼亚寻径问题;我们使用直线距离(straight-line distance)作为启发式函数,记为hSLD。如果目标是Bucharest,我们需要知道到Bucharest的直线距离,如图3-16所示。例如,hSLD(Arad) = 366。注意,无法从问题描述本身(即Actions和Result函数)来计算hSLD的值。此外,根据经验可知,hSLD与实际道路距离相关,因此是一个有用的启发式函数。
图3-17展示了使用hSLD搜索从Arad到Bucharest的路径的贪心最佳优先搜索的过程。从Arad扩展的第一个节点是Sibiu,因为启发式函数认为它比Zerind或Timisoara更接近Bucharest。下一个要扩展的节点是Fagaras,因为根据启发式函数,它现在最接近Bucharest。Fagaras接着生成了Bucharest,即目标节点。对于这一特定问题,使用hSLD的贪心最佳优先搜索无须扩展不在解路径上的节点就找到了解。但是,它找到的解并不是代价最优的:经由Sibiu和Fagaras到达Bucharest的路径比经过Rimnicu Vilcea和Pitesti的路径长32英里。这就是为什么这种算法会被称为“贪心的”——在每次迭代中,它都会做出在当前看来最优的(即可以最接近目标的)选择,但这也会导致贪心法在全局意义上可能产生比谨慎的算法更糟糕的结果。
图3-16 hSLD(到Bucharest的直线距离)的值
图3-17 基于直线距离启发式函数hSLD的贪心最佳优先树状搜索的各个阶段(目标为Bucharest)。节点上标有h值
贪心最佳优先图搜索在有限状态空间中是完备的,但在无限状态空间中是不完备的。最坏情况下的时间复杂性和空间复杂性是。然而,使用一个好的启发式函数,复杂性可以大大降低,对于某些问题可以达到O(bm)。
最常见的有信息搜索算法是A*搜索(A* search)(读为“A星搜索”),这是一种最佳优先搜索,评价函数为
其中g(n)是从初始状态到节点n的路径代价,h(n)是从节点n到一个目标状态的最短路径的代价估计值,因此我们有
f(n) = 经过n到一个目标状态的最优路径的代价估计值
在图3-18中,我们展示了目标为Bucharest的A*搜索过程。g的值由图3-1中的动作代价计算得到,hSLD的值在图3-16中给出。注意,Bucharest首先出现在图3-18的步骤e的边界中,但算法并没有选择它来进行扩展(因此它没有被检测为一个解),因为此时它不是边界中代价最小的节点(f = 450)——代价最小的节点是Pitesti(f = 417)。换句话说,可能存在一个经过Pitesti的解,代价低至417,所以算法不会满足于一个代价为450的解。在图3-18的步骤f中,另一条到Bucharest的路径此时代价最小(f = 418),因此它被选中并被检测为最优解。
A*搜索是完备的。[11]它是否是代价最优则取决于启发式函数的某些性质。一个关键性质是可容许性(admissibility):一个可容许的启发式(admissible heuristic)函数永远不会高估到达某个目标的代价。(因此,一个可容许的启发式函数是乐观的。)
[11] 再强调一次,假设所有动作的代价都 ,状态空间要么有解,要么有限。
对于可容许的启发式函数,A*是代价最优的,我们可以通过反证法来证明这一点。假设最优路径的代价为C*,但是该算法返回的路径代价为C C*,那么最优路径上一定存在某个未扩展的节点n(因为如果最优路径上的所有节点都已被扩展,那么算法返回的将是这个最优解)。因此,使用符号g*(n)表示从起点到n的最优路径的代价,h*(n)表示从n到最近目标的最优路径的代价,我们将得到
第一行和最后一行矛盾,所以“算法可能返回次优路径”的假设一定是错误的——A*一定只返回代价最优路径。
另一个稍强的性质为一致性(consistency)。如果对于每个节点n以及由动作a生成的n的每个后继节点n' 有以下条件,则启发式函数h(n)是一致的:
这是三角不等式(triangle inequality)的一种形式,它规定三角形的一条边不能大于其他两条边之和(见图3-19)。一致的启发式函数的一个实例是上文中的直线距离hSLD。
图3-18 A*搜索的各个阶段(目标为Bucharest)。节点上标有f = g + h,h值为图3-16中得到的到Bucharest的直线距离
图3-19 三角不等式:如果启发式函数h是一致的,那么单个数值h(n)小于从n到n'的动作代价值c(n, a, n')加上启发式函数的估计值h(n')的和
一致的启发式函数都是可容许的(反过来不成立),因此,使用一致的启发式函数的A*搜索都是代价最优的。此外,如果使用一致的启发式函数,算法第一次到达某个状态时,它就在一条最优路径上,因此我们永远不需要将某个状态重复添加到边界中,也不必更改reached中的条目。但是,如果使用不一致的启发式函数,最终可能导致多个路径到达相同状态,而且如果每条新路径的路径代价都小于前一条路径,最终在边界中该状态会有多个节点,这会耗费时间和空间。因此,有些A*搜索算法的实现会注意让一个状态只进入边界一次,如果找到了到达该状态的更优路径,那么该状态的所有后继都会更新(这要求节点除了父指针外还要有子指针)。这些复杂性使得许多研究人员在实现A*搜索时避免使用不一致的启发式函数,但费尔纳等人(Felner et al., 2011)认为,最坏的结果在实践中很少发生,因此不应该害怕不一致的启发式函数。
如果采用不可容许的启发式函数,那么A*搜索可能是代价最优的,也可能不是。存在两种情况使得A*搜索是代价最优的:第一,如果存在一条代价最优路径,对于该路径上的所有节点n,h(n)都是可容许的,那么无论启发式函数在路径外状态上的值如何,算法都能找到这条路径。第二,假设最优解的代价为C*,次优解的代价为C2,如果h(n)高估了部分代价但又没有高估太多,都不超过C2 − C*,那么也可以保证A*返回的解是代价最优的。
一种对搜索进行可视化的方法是在状态空间中绘制等值线(contour),就像在地形图中绘制等高线一样。如图3-20所示,在标记为400的等值线内,所有节点都有,以此类推。因为A*扩展的是f代价最小的边界节点,所以它是从初始节点扇形地向外扩展,以f 值递增的同心带状方式添加节点。
一致代价搜索中也存在等值线,但是等值线表示g代价,而不是g + h。一致代价搜索中,等值线将以初始状态为圆心呈“圆形”向各个方向均匀扩展,而不是偏向于目标状态。对于具有好的启发式函数的A*搜索,g + h带将朝一个目标状态延伸(如图3-20所示),并且在最优路径周围收敛变窄。
需要清楚的是,扩展路径时,g代价是单调的(monotonic):路径代价始终随着路径的延伸而不断增加,因为动作代价始终为正。[12]因此,所得到的同心等值线彼此不会交叉,如果希望画出的等值线足够精细,则可以在任何路径上的任意两个节点之间画一条线。
[12] 从技术上讲,始终保持增加的代价称为“严格单调的”;永远不会减少但可能保持不变的代价称为“单调的”。
但代价是否单调递增则并不显然。当你将一条路径从n扩展到n'时,代价从
变为
。消去g(n)项,我们可以看到,当且仅当
时,路径代价单调递增。换句话说,当且仅当启发式函数是一致的时,路径代价单调递增。[13]但需要注意的是,一条路径可能会在一行中贡献若干个具有相同g(n) + h(n)得分的节点;当h的减少量恰好等于刚刚采取的动作代价时,就会发生这种情况(例如,在一个网格问题中,当n与目标在同一行然后向目标迈进一步时,g增加1,h减少1)。如果C*是最优解路径的代价,那么以下说法成立。
[13] 事实上,“单调启发式函数”这一术语是“一致的启发式函数”的同义词。这两种观点是独立发展的,但是之后被证明是等价的(Pearl, 1984)。
● A*搜索将扩展从初始状态可以到达并且路径上的每个节点都满足的所有节点。我们称这些节点为必然扩展节点(surely expanded node)。
● A*搜索可能会在选出目标节点之前扩展某些恰好在“目标等值线”(即f (n) = C*)上的节点。
● A*搜索不扩展的节点。
图3-20 罗马尼亚地图,其中等值线为f = 380、f = 400和f = 420,初始状态为Arad。给定等值线内的节点的代价f = g + h小于或等于等值线值
我们认为具有一致启发式函数的A*搜索是效率最优(optimally efficient)的,因为任何从初始状态扩展搜索路径并使用相同启发式信息的算法都必须扩展A*的所有必然扩展节点(因为任何一个必然扩展节点都可能是某个最优解的一部分)。对于f(n)=C*的节点,某个算法可能运气好,首先选择了最优节点,而另一个算法就没这么幸运。我们在定义最优效率时不考虑这种差异。
A*之所以高效,是因为它会对那些对于寻找最优解没有帮助的搜索树节点进行剪枝(pruning)。在图3-18b中,我们看到,对于Timisoara,f = 447;对于Zerind,f = 449。即使它们是根的子节点并且是采用一致代价搜索或广度优先搜索时首先扩展的节点,它们也永远不会被A*搜索扩展,因为A*会首先找到f = 418的解。对许多人工智能领域来说,剪枝(不必进行检查就可以排除不正确的答案)非常重要。
在所有这些算法中,A*搜索都是完备的、代价最优的和效率最优的,这是相当令人满意的结果。遗憾的是,这并不意味着A*适用于所有搜索需求。问题在于,对于许多问题,所扩展的节点数可能是解路径长度的指数级。例如,考虑一个具有超强吸力的真空吸尘器世界,它可以以单位代价清理任一方格却不需要访问该方格。在这种情况下,可以按任何顺序清理方格。如果开始时有N个脏的方格,则有2N种状态,其中某个子集已被清理;所有这些状态都在最优解路径上,因此满足,所以所有这些状态都会被A*搜索访问。
A*搜索有很多好的性质,但它扩展了大量节点。如果我们愿意接受次优但“足够好”的解——我们称之为满意(satisficing)解,则可以探索更少的节点(花费更少的时间和空间)。如果我们允许A*搜索使用不可容许的启发式函数(inadmissible heuristic)(它可能会高估到达某个目标的代价),那么我们就有可能错过最优解,但是该启发式函数可能更准确,从而减少了需要扩展的节点数。例如,道路工程师知道弯道指数(detour index)的概念,它是应用于直线距离的乘数,用来说明道路的典型曲率。弯道指数1.3意味着如果两个城市的直线距离相距10千米,那么它们之间的最优路径的一个恰当的估计值是13千米。对于大多数地区,弯道指数的范围是1.2到1.6。
不仅仅是与道路相关的问题,我们还可以将这一思想应用于任何问题,我们采用一种称为加权A*搜索(weighted A* search)的方法,对启发式函数的值进行更重的加权,评价函数为,其中
。
图3-21为一个网格世界中的搜索问题。在图3-21a中,A*搜索必须探索大部分状态空间才能找到最优解。在图3-21b中,加权A*搜索找到一个代价稍高的解,但搜索时间要快得多。我们看到,加权搜索使得已达状态的等值线专注于趋向某个目标。这意味着需要探索的状态变少,但如果最优路径偏离加权搜索的等值线(就像在这种情况下一样),则无法找到最优路径。一般来说,如果最优解的代价是C*,那么加权A*搜索将找到一个代价介于C*和W×C*之间的解;但在实践中,通常结果更接近于C*而不是W×C*。
图3-21 同一网格上的两种搜索:(a)A*搜索,(b)加权A*搜索,权重W = 2。灰色线条表示障碍,紫色线是一条从绿色起始点到红色目标点的路径,较小的点是每次搜索到达的状态。在这个特定问题上,加权A*搜索探索的状态数不到A*搜索探索的状态数的七分之一,找到的路径的代价只比最优代价大了5%
我们已经考虑过以各种方式组合g和h来评价状态的搜索方法;加权A*搜索可以看作是其他方法的一般化。
A*搜索:
一致代价搜索:
贪心最佳优先搜索:
加权A*搜索:
你可以称加权A*搜索为“有点贪心的搜索”:就像贪心最佳优先搜索一样,它使得搜索专注于趋向一个目标;但是,它不会完全忽略路径代价,并且会暂停代价高昂但进展甚微的路径。
次优的搜索算法有很多,其区别在于“足够好”的标准。在有界次优搜索(bounded suboptimal search)中,我们寻找一个能保证代价在最优代价的常数因子W倍内的解。加权A*搜索提供了这一保证。在有界代价搜索(bounded-cost search)中,我们寻找一个代价小于某个常数C的解。在无界代价搜索(unbounded-cost search)中,我们接受任何代价的解,只要能快速找到它。
无界代价搜索算法的一个例子是快速搜索(speedy search),它是一种贪心最佳优先搜索,使用到达目标所需动作个数的估计值作为启发式函数,不考虑这些动作的代价。因此,对于所有动作都具有相同代价的问题,它等于贪心最佳优先搜索,但当动作具有不同代价时,它往往会导致搜索快速找到一个代价可能很高的解。
A*搜索的主要问题是它对内存的使用较多。在本节中,我们将介绍一些可以节省空间的实现技巧和一些能够更好地利用可用空间的全新算法。
内存被分为frontier状态和reached状态。在我们所实现的最佳优先搜索中,边界上的状态存储在两个位置:边界中的一个节点(因此我们可以决定下一步扩展哪个节点)和已达状态表中的一个表项(因此我们知道之前是否访问过该状态)。对于许多问题(例如探索网格),这种重复不是关注点,因为frontier要比reached小得多,所以复制边界中的状态所需内存相对较少。但是有些算法实现只保留这两个位置中的其中一个,从而节省了一点空间,其代价是算法变得更复杂(可能会减慢速度)。
另一种可能性是,当我们能够证明不再需要某些状态时,就将它们从reached中删除。对于某些问题,我们可以利用分离性质(图3-6),同时禁止掉头行动,以确保所有行动要么是从边界向外移动,要么是移动到另一个边界状态。在这种情况下,我们只需检查边界就能判断是否有冗余路径,并且可以删除reached状态表。
对于其他问题,我们可以维护引用计数(reference count)——到达某一状态的次数,并且在再也没有路径可以到达该状态时将其从reached表中删除。例如,在网格世界中,每个状态只能从它的4个邻居状态到达,一旦我们已经到达了一个状态4次,就可以将它从表中删除。
现在,我们考虑旨在节省内存使用的新算法。
束搜索(beam search)对边界的大小进行了限制。最简单的方法是只保留具有最优f值的k个节点,放弃其他已扩展节点。这当然会导致搜索变成不完备的和次优的算法,但我们可以选取合适的k以充分利用可用内存,算法执行速度也会更快,因为它只扩展了较少的节点。对于许多问题,它可以找到很好的近似最优解。你可以将一致代价搜索或A*搜索看作在同心等值线的各个方向扩展,而将束搜索看作只探索这些等值线的主要部分,即包含k个最佳候选的部分。
另一种形式的束搜索并不严格限制边界的大小,而是保留f值在最优f值的范围内的所有节点。这样的话,当存在几个强得分节点时,只会保留几个节点,但如果不存在强节点,则会保留更多节点,直到出现一个强节点。
迭代加深A*搜索(iterative-deepening A* search,IDA*)之于A*搜索,就像迭代加深搜索之于深度优先搜索一样:IDA*既拥有A*的优点,又不要求在内存中保留所有已达状态,这样做的代价是需要多次访问某些状态。它是一种非常重要且常用的用于解决内存不足问题的算法。
在标准的迭代加深搜索中,截断值为深度,每次迭代深度增加1。而在IDA*中,截断值是f代价(g + h);在每次迭代中,新的截断值为超过上一次迭代截断值的节点中最小的f代价。换句话说,每次迭代都会彻底地搜索一个f等值线,找到一个刚好超出该等值线的节点,并使用该节点的f代价作为下一个等值线。像8数码这样的问题,每条路径的f代价都是整数,这非常有效地使得每次迭代都朝着目标稳步前进。如果最优解的代价是C*,那么迭代的次数不可能超过C*(例如,最难的8数码问题的迭代次数不超过31)。但对于每个节点的f代价都不相同的问题,每一个新的等值线可能只包含一个新节点,并且迭代次数可能等于状态数。
递归最佳优先搜索(recursive best-first search,RBFS)(见图3-22)试图模拟标准的最佳优先搜索的操作,但仅仅使用线性空间。RBFS类似于递归深度优先搜索,但它不是沿着当前路径无限地向下搜索,而是使用f_limit变量跟踪从当前节点的任意祖先节点可得到的最优备选路径的f值。如果当前节点超过了这个限制,那么递归将回到备选路径上。随着递归的展开,RBFS将路径上每个节点的f值替换为一个倒推值(backed-up value)——其子节点的最优f值。通过这种方式,RBFS可以记住被它遗忘的子树中最优叶节点的f值,因此,在之后的某个时刻,RBFS可以决定是否要重新扩展该子树。图3-23展示了RBFS是如何到达Bucharest的。
图3-22 递归最佳优先搜索算法
在一定程度上,RBFS比IDA*更高效,但仍然存在重复生成大量节点的问题。在图3-23的示例中,RBFS沿着经过Rimnicu Vilcea的路径,然后“改变主意”去尝试经过Fagaras,然后又“回心转意”。之所以会发生这些改变,是因为每次扩展当前的最优路径时,它的f值很可能增加——对于靠近目标的节点,h值通常不那么乐观。当这种情况发生时,次优路径可能会成为最优路径,因此搜索必须回溯。每一次改变对应于IDA*的一次迭代,并且可能需要多次重新扩展已经遗忘的节点,以重建最优路径,并对该路径再扩展一个节点。
图3-23 使用RBFS搜索到Bucharest的最短路线的各个阶段。每次递归调用的f_limit值标注在每个当前节点的上方,每个节点上都标有它的f代价。(a)沿着经过Rimnicu Vilcea的路径前进,直到当前最优叶节点(Pitesti)的值比最优备选路径(Fagaras)差。(b)递归回溯,被遗忘子树的最优叶节点值(417)被备份到Rimnicu Vilcea;接着扩展Fagaras,得到最优叶节点值450。(c)递归回溯,被遗忘子树的最优叶节点值(450)被备份到Fagaras;然后扩展Rimnicu Vilcea。这一次,因为最优备选路径(经由Timisoara)的代价至少为447,所以继续扩展Bucharest
如果启发式函数h(n)是可容许的,那么RBFS是最优的。它的空间复杂性在最深的最优解的深度上是线性的,但时间复杂性很难刻画:既取决于启发式函数的准确性,也取决于最优路径随节点扩展变化的频率。它按照f得分递增的顺序来扩展节点,即使f是非单调的。
IDA*和RBFS使用内存太少,它们的时间复杂性会受到影响。在两次迭代之间,IDA*只保留一个数值:当前的f代价限制。RBFS在内存中保留了更多的信息,但它只使用线性空间:即使有更多的内存可用,RBFS也无法利用。因为它们会遗忘它们所做的大部分事情,这两种算法都可能会多次重复探索相同状态。
因此,确定我们有多少可用内存并允许算法使用所有内存似乎是明智的。执行这样操作的两种算法是MA*(memory-bounded A*,内存受限的A*)和SMA*(simplified MA*,简化的MA*)。SMA*更简单一些,所以我们介绍SMA*。SMA*很像A*算法,不断扩展最优叶节点,直到内存被填满。此时,它不能再为搜索树添加新节点,除非删除旧节点。SMA*总是丢弃最差的叶节点,即f值最大的叶节点。和RBFS一样,SMA*将被遗忘节点的值备份到其父节点。这样,被遗忘子树的祖先知道该子树中最优路径的质量。有了这一信息,只有在所有其他路径看起来都比它已经遗忘的路径更差时,SMA*才会重新生成该子树。这意味着如果节点n的所有后代都被遗忘了,那么尽管我们不知道从n开始应该走哪条路径,但我们仍知道是否应该从n开始走。
本书附带的在线代码库中描述了完整的SMA*算法。有一点值得注意,我们之前提到SMA*将扩展最优叶节点,删除最差叶节点。如果所有叶节点的f值都相同呢?为了避免算法选择同一个节点进行删除和扩展操作,SMA*扩展最新的最优叶节点并删除最老的最差叶节点。当只有一个叶节点时,这两者是同一个节点,但在这种情况下,当前的搜索树一定是一条从根节点到叶节点的占满所有内存的单一路径。如果叶节点不是目标节点,那么即使它在最优解路径上,也无法在可用内存范围内得到这个解。因此,完全可以丢弃该节点,就好像它没有后继节点一样。
如果存在任意可达解,也就是说,如果最浅的目标节点的深度d小于内存大小(用节点数表示),那么SMA*就是完备的。如果存在可达的最优解,那么SMA*就是最优的;否则,就返回当前最优的可达解。在实践中,SMA*是寻找最优解的一个相当稳健的选择,特别是当状态空间是一个图、行动代价不一致,并且生成节点的总开销相比维护边界集和已达集的总开销更大时。
然而,在非常困难的问题上,常常会出现SMA*被迫在许多候选解路径之间来回不断切换的情况,只有一小部分路径可以存入内存。[这类似于磁盘分页系统中的抖动(thrashing)问题。]那么,重复生成相同节点就需要额外的时间,这意味着,在给定无限内存的情况下可以用A*实际求解的问题,对于SMA*将变得难以处理。也就是说,从计算时间的角度,内存限制会使问题变得难以处理。虽然还没有现有理论解释如何在时间和内存之间权衡,但这似乎是一个不可避免的问题。唯一的出路是放弃最优性要求。
我们发现,在单向最佳优先搜索中,使用f(n) = g(n) + h(n)作为评价函数可以得到A*搜索,保证找到代价最优的解(假设h是可容许的),同时在所扩展的节点数上效率最优。
在双向最佳优先搜索中,我们也可以尝试使用f(n) = g(n) + h(n),但遗憾的是,即使使用可容许的启发式函数,算法也不能保证可以找到代价最优的解,更不能保证效率最优。可以证明的是,在双向搜索中一定会被扩展的并不是单个的节点,而是节点对(分别来自两个边界),因此任何效率证明都必须考虑节点对(Eckerle et al., 2017)。
我们先介绍一些新的符号。对于正向搜索(以初始状态作为根节点)中的节点,我们用fF(n) = gF(n) + hF(n)作为评价函数;对于反向搜索(以某个目标状态作为根节点)中的节点,我们用fB(n) = gB(n) + hB(n)作为评价函数。尽管正向搜索和反向搜索求解的是同一个问题,但它们具有不同的评价函数,这是因为,启发式函数依据其努力方向是目标状态还是初始状态而有所不同。我们假设启发式函数是可容许的。
考虑从初始状态到节点m的正向路径和从目标到节点n的反向路径。我们可以如下定义一个解代价的下界(这个解先沿着前向路径从初始状态到达m,然后以某种方式到达n,最后再沿着后向路径从n到达目标)。
换句话说,这样一条路径的代价一定不小于两部分路径代价之和(因为它们之间的剩余连接一定具有非负代价),而且也一定不小于任一部分的f代价估计值(因为启发式的估计是乐观的)。因此,有如下的定理:对于任意一对节点m和n,若lb(m, n)小于最优代价C*,那么算法必须扩展m或n,因为经过这两个节点的路径是一个潜在的最优解。然而,一个难题是我们无法确定扩展这两者中的哪个节点才是最优的,因此,没有一个双向搜索算法可以保证效率最优——如果算法总是首先选择一对节点中错误的那个进行扩展,那么任何算法都可能需要扩展到最小节点数两倍的节点。一些双向启发式搜索算法显式地管理一个(m, n)节点对队列,但我们将坚持双向最佳优先搜索(图3-14),它有两个边界优先队列,并使用模拟lb准则的评价函数:
接下来要扩展的节点将是f2值最小的节点;它可以来自任何一个边界。这个f2函数保证算法永远不会扩展(来自任一边界的)的节点。当两个边界相交时,任一边界内的节点都不存在超过C*/2的路径代价,在这种意义上,我们可以说搜索的两部分“在中间相遇”。图3-24为一个双向搜索的示例。
图3-24 双向搜索维护两个边界:左半部分,节点A和B是开始状态的后继;右半部分,节点F是目标状态的逆向后继。每个节点都标有f = g + h值和f2 = max(2g, g + h)值。(g值是每个箭头上所显示的动作代价的总和;h值是任意的,而且不能从图中的任何内容推出。)最优解“开始-A-F-目标”的代价C* = 4 + 2 + 4 = 10,这意味着一个在中间相遇的双向算法不应该扩展任何的节点;实际上,下一个要扩展的节点是A或F(g = 4),这将引导我们找到一个最优解。如果我们首先扩展f代价最低的节点,那么下一个扩展的将是B和C,D和E将与A并列,但它们的
,因此当f2是评价函数时它们永远不会被扩展
我们已经介绍了一种方法,即用hF估计到目标的距离(或者说,当问题有多个目标状态时,估计到最近目标的距离),用hB估计到开始状态的距离。这就是所谓的front-to-end搜索。另一种方法是front-to-front搜索,它试图估计到另一个边界的距离。显然,如果边界内有数百万个节点,那么对每个节点应用启发式函数然后取最小值是非常低效的。但它可以从边界中抽样几个节点。在某些特定问题域中,可以对边界进行总结,例如,在网格搜索问题中,我们可以递增地计算边界的界限框,并使用到界限框的距离作为启发式函数。
双向搜索有时比单向搜索更有效,有时则不然。一般来说,如果我们有一个很好的启发式函数,那么A*搜索会生成专注于目标的搜索等值线,使用双向搜索则增益不大。使用一般的启发式函数时,在中间相遇的双向搜索往往会扩展较少的节点,因此双向搜索是首选方法。在启发式函数较差的最坏情况下,搜索算法将不再专注于目标,并且双向搜索具有与A*相同的渐近复杂性。使用f2评价函数和可容许的启发式函数h的双向搜索算法是完备且最优的。
在本节中,我们将研究启发式函数的准确性是如何影响搜索性能的,并考虑如何构造启发式函数。我们将8数码问题作为主要示例。如3.2节所述,它的目标是将滑块水平或竖直地滑动到空格中,直到棋盘布局与目标布局一致(图3-25)。
图3-25 8数码问题的典型实例。最短的解需要26步动作
在一个8数码问题中,存在9!/2 = 181 400个可达状态,所以搜索算法可以轻松地将它们全部保存在内存中。但是对于15数码问题,存在16!/2个状态(超过10万亿个),因此,为了搜索这个空间,我们需要借助一个较好的可容许的启发式函数。对于15数码问题,这样的启发式函数有着悠久的历史。下面介绍两个常用的选择。
● h1 = 错位滑块的数量(不包括空格)。图3-25中,所有的8个滑块都不在原位,所以开始状态的h1 = 8。h1是一个可容许的启发式函数,因为任何错位滑块都至少需要一次移动才能回到正确的位置。
● h2 = 滑块到其目标位置距离的总和。因为滑块不能沿对角线移动,所以距离是水平距离和垂直距离之和——有时称为城市街区距离或曼哈顿距离(Manhattan distance)。h2也是可容许的,因为任何移动操作所能做的就是将一个滑块向目标移近一步。图3-25中开始状态的滑块1到滑块8得到的曼哈顿距离为
正如我们希望的那样,这两种方法都没有高估实际的解代价26。
一种描述启发式函数质量的方法是有效分支因子(effective branching factor)b*。如果针对一个特定问题,A*搜索所生成的总节点数是n,而解的深度是d,那么b*就是深度为d的均衡树要包含n + 1个节点所必需的分支因子。因此有
例如,如果A*用52个节点在第5层上找到了一个解,那么有效分支因子是1.92。在不同的问题实例中,有效分支因子可能会发生变化,但通常对于特定领域(如8数码问题),在所有复杂的问题实例中它都是相当恒定的。因此,对一小部分问题的b*进行实验测量可以为启发式函数的总体有用性提供良好的指导。设计良好的启发式函数的b*接近1,使得我们能以合理的计算代价求解相当大的问题。
科尔夫和里德(Korf and Reid, 1998)认为,对于一个使用给定启发式函数h的A*剪枝,刻画其效果的一个更好方式是:有效深度(effective depth)相比于真实深度的减少量kh(一个常数)。这意味着相较于无信息搜索的代价O(bd),上述方法的总搜索代价为。他们在魔方和n数码问题上的实验结果表明,这一公式可以准确地预测各种解长度范围内(至少对于大于kh的解长度)的抽样问题实例的总搜索代价。
在图3-26中,我们生成了随机8数码问题,并使用无信息广度优先搜索和使用h1或h2的A*搜索求解该问题,报告了每种搜索策略和每种解长度所生成的平均节点数及相应的有效分支因子。结果表明,h2优于h1,两者都优于无启发式算法。
图3-26 使用广度优先搜索、使用h1(错位滑块)的A*搜索或使用h2(曼哈顿距离)的A*搜索求解8数码问题的搜索代价和有效分支因子的比较。每个解长度d(6~28)的数据为100多个实例的平均结果
有人可能会问,h2是否总是优于h1。答案是“基本上,是的”。从这两种启发式函数的定义可以看出,对于任意节点n,都有。因此我们说h2占优于(dominate)h1。优势可以直接转化为效率:使用h2的A*永远不会比使用h1的A*扩展更多的节点(除了
的节点)。证明很简单。回想一下3.5.3节观察到的,每个
的节点都一定会被扩展。也就是说,当h一致时,每个
的节点都一定会被扩展。但是,因为对于所有节点,h2至少和h1一样大,每个在h2下一定会被扩展的节点在h1下也一定会被扩展,而h1还可能导致其他的节点也被扩展。因此,通常情况下,只要启发式函数是一致的并且其计算时间不太长,使用具有较高值的启发式函数效果都会更好。
我们已经看到,对于8数码问题,h1(错位滑块)和h2(曼哈顿距离)都是相当好的启发式函数,其中h2更好。人们是怎么想出h2这样的启发式函数的?计算机是否有可能自动地设计出这种启发式函数?
h1和h2是对8数码问题剩余路径长度的估计,但对简化版本的问题来说,它们也是非常精确的路径长度。如果改变游戏规则,即滑块可以移动到任何地方,而不是只能移动到相邻的空格,那么h1将给出最短解的准确长度。类似地,如果一个滑块可以向任意方向移动一个方格,甚至移动到一个被占用的方格上,那么h2将给出最短解的准确长度。减少了对动作的限制条件的问题称为松弛问题(relaxed problem)。松弛问题的状态空间图是原始状态空间的一个超图,因为删除限制条件会导致原图中边的增加。
因为松弛问题向状态空间图中添加了一些边,根据定义,原问题的任一最优解也是松弛问题的一个解;但是,如果增加的边提供了捷径,松弛问题可能有更好的解。因此,松弛问题中最优解的代价可以作为原问题的一个可容许的启发式函数。此外,因为得到的启发式函数是松弛问题的准确代价,所以它一定满足三角不等式,因此它是一致的(见3.5.2节)。
如果用形式语言定义一个问题,则可以自动构造它的松弛问题。[14]例如,如果将8数码问题的行动描述为
[14] 在第8章和第11章中,我们将介绍适用于此任务的形式语言:有了可操纵的形式化描述,就可以自动化地构建松弛问题。现在,我们先使用自然语言。
如果方格X与方格Y相邻,且Y是空格,那么滑块可以从方格X移动到方格Y。
我们可以通过删除一个或两个条件来生成3种松弛问题。
(a)如果方格X与方格Y相邻,那么滑块可以从方格X移动到方格Y。
(b)如果方格Y是空格,那么滑块可以从方格X移动到方格Y。
(c)滑块可以从方格X移动到方格Y。
由(a)可以推导出h2(曼哈顿距离)。原因是,如果我们将每个滑块依次移动到其目标位置,那么h2就是准确的步数。由(b)推导出的启发式函数将在习题3.GASC中讨论。由(c)我们可以推导出h1(错位滑块),因为如果可以仅用一步就将滑块移动到其预期目标位置,那么h1就是准确的步数。需要注意的是,通过这种方法生成的松弛问题本质上不需要搜索就能求解,因为松弛规则将问题分解为8个独立的子问题。如果松弛问题本身很难求解,那么获取相应的启发式函数值的代价将非常高。
Absolver程序可以通过“松弛问题”方法及各种其他技术从问题定义中自动生成启发式函数(Prieditis, 1993)。Absolver为8数码问题生成了一种新的启发式函数,它优于任何已有的启发式函数。此外,Absolver为著名的魔方问题找到了第一种有效的启发式函数。
如果一个可容许的启发式函数集合h1, …, hm可以求解同一个问题,但没有一个函数明显优于其他函数,那么我们应该选择哪个函数?事实证明,我们可以通过如下定义,得到最优的启发式函数:
这种复合启发式函数将选择对于所讨论节点最准确的函数。因为hi都是可容许的,所以h也是可容许的(如果hi都是一致的,则h也是一致的)。此外,h优于所有组成它的启发式函数。唯一的缺点是h(n)的计算时间更长。如果考虑这一问题,另一种选择是在每次评价时随机选择一个启发式函数,或者使用机器学习算法来预测哪个启发式函数是最优的。这样做可能会导致启发式函数失去一致性(即使每个hi都是一致的),但在实践中,它通常能更快地求解问题。
可容许的启发式函数也可以由给定问题的子问题(subproblem)的解代价推导得到。例如,图3-27为图3-25中8数码问题实例的一个子问题。子问题涉及将滑块1、2、3、4和空格分别放置到正确位置。显然,这个子问题最优解的代价是完整问题代价的一个下界。在某些情况下,它比曼哈顿距离更准确。
图3-27 图3-25中所给出的8数码实例的子问题。任务是将滑块1、2、3、4和空格放置到正确位置,而不考虑其他滑块的情况
模式数据库(pattern database)的思想是为每个可能的子问题(在我们的示例中,为4个滑块和空格的所有可能排列)存储准确的解代价。(数据库中将有9×8×7×6×5 = 15 120种模式。其他4个滑块与子问题的求解无关,但移动这些滑块将计入子问题的解代价。)然后,通过在数据库中查找相应的子问题,为搜索过程中遇到的每个状态计算一个可容许的启发式函数hDB。数据库本身是从目标状态反向搜索并记录所遇到的每个新模式的代价来构建的[15];这一搜索的开销将分摊到后续的问题实例中,因此如果我们需要求解很多问题,那么这种方法是有意义的。
[15] 通过从目标反向回溯,可以立即获得所遇到的每个实例的准确的解代价。这是动态规划的一个示例,我们将在第17章进一步讨论。
与空格搭配的滑块1-2-3-4的选择是相当随意的;我们还可以为5-6-7-8、2-4-6-8等建立数据库。每个数据库产生一种可容许的启发式函数,正如前文所述,可以通过取最大值对这些启发式函数进行组合。这种组合的启发式函数要比曼哈顿距离精确得多;求解随机15数码问题时所生成的节点数可以减少到千分之一。然而,每增加一个数据库,收益会随之减少,内存和计算成本也会增加。
你们可能想知道从1-2-3-4数据库和5-6-7-8数据库中得到的启发式函数是否可以相加,因为这两个子问题似乎没有重叠。这会是一个可容许的启发式函数吗?答案是否定的,因为对于一个给定的状态,1-2-3-4子问题和5-6-7-8子问题的解一定会有一些重复操作——1-2-3-4不可能在不接触5-6-7-8的情况下移动到位,反之亦然。但是,如果我们不计入这些操作,换句话说,如果我们让其他滑块直接消失呢?也就是说,我们不记录求解1-2-3-4子问题的总代价,而只记录与1-2-3-4有关的操作数。那么这两个代价的和仍然是求解完整问题代价的一个下界。这就是不相交模式数据库(disjoint pattern database)的思想。有了这样的数据库,可以在几毫秒内求解随机的15数码问题——与使用曼哈顿距离相比,生成的节点数不到原来的万分之一。对于24数码问题,则可以获得大约一百万倍的加速。不相交模式数据库适用于滑块数码问题,因为每次移动只涉及一个滑块,因而原问题可以被划分成若干个子问题使得每次移动只影响一个子问题。
一些在线服务可以托管含有数千万个顶点的地图,并在毫秒内找到代价最优的驾驶路线。即使是我们之前提到的最优的搜索算法,做到这一点也要比这些在线服务多耗费100万倍的时间。那在线服务是怎么做到这一点的呢?这里有很多技巧,但最重要的是对一些最优路径代价的预计算(precomputation)。虽然预计算可能相当耗时,但只需完成一次预计算,就可以摊销数十亿用户的搜索请求。
我们可以通过预计算并存储每对顶点之间的最优路径代价来生成完美的启发式函数。这需要空间和
时间——对于含有1万个顶点的图很实用,但对于1000万个顶点,这样的复杂性不可接受。
更好的方法是从顶点中选择一些(也许10个或20个)地标点(landmark point)[16]。然后,对于图中每个地标L和每个其他顶点v,我们计算并存储C*(v, L),即从v到L的最优路径的准确代价。(我们同样需要C*(L, v);在无向图上,C*(L, v)与C*(v, L)相同;在有向图上,如单行道,我们则需要单独计算C*(L, v)。)给定存储的C*表,我们可以很容易地创建出一个高效的(尽管是不可容许的)启发式函数:在所有地标中,从当前节点到地标然后到目标节点代价的最小值为
[16] 地标点有时被称为“枢轴”或“锚点”。
如果最优路径刚好经过一个地标,这个启发式函数将是准确的;否则,这个启发式函数就是不可容许的——它高估了到目标的代价。在A*搜索中,如果启发式函数是准确的,那么一旦到达一个位于最优路径上的节点,此后所扩展的每个节点都将位于最优路径上。把等值线想象为沿着这条最优路径前进。搜索将沿着最优路径进行,在每次迭代中加入一个代价为c的动作,然后到达一个h值减少c的结果状态,这意味着在整条路径上总的f = g + h得分将保持在常量C*。
一些寻径算法通过在图中添加捷径(shortcut)——人工定义的对应于一条最优多行动路径的边——来节省更多的时间。例如,如果我们在美国最大的100个城市之间预先定义了捷径,并且尝试从位于加利福尼亚州的加利福尼亚大学伯克利分校校区导航到纽约的纽约大学,那么我们可以走萨克拉门托(Sacramento)到曼哈顿(Manhattan)之间的捷径,一次动作就能覆盖90%的路径。
hL(n)是高效的,但不是可容许的。只要稍加注意,我们就可以提出一种既高效又可容许的启发式函数:
这被称为差分启发式(differential heuristic)函数(因为包含减法)。可以把它理解为在比目标还要远的某个位置设置一个地标点。如果目标恰好在从n到该地标点的最优路径上,那么“考虑从n到L的完整路径,然后减去这条路径的最后一部分,即从goal到L,即可得到从n到goal的这段路径的准确代价”。如果目标稍微偏离到地标的最优路径,启发式函数将是不准确的,但仍然是可容许的。比目标近的地标是没有用的;例如,一个恰好位于n和goal正中间的地标将导致hDH = 0,这是没有用的。
下面我们介绍几种选择地标点的方法。随机选择速度较快,但如果我们多花些功夫将地标分散开来,使得它们彼此之间不太接近,我们将得到更好的结果。贪心方法是随机选择第一个地标,然后找到离它最远的点,将其添加到地标集合中,接着在每次迭代中添加离最近地标最远的点。如果你有用户过去的搜索请求日志,那么你可以选择搜索中经常请求的地点作为地标。对于差分启发式函数,地标分布在图的周界上更好。因此,一个比较好的技术是找到图的质心,围绕质心划分出k个楔形(就像饼状图一样),并在每个楔形中选择离中心最远的顶点。
地标在寻径问题上尤其有效,这是由世界上道路的布局方式导致的:许多交通运输实际上都是在地标之间穿行,所以土木工程师在这些路线上修建最宽、最快的道路;地标式搜索可以更轻松地复原这些路线。
我们介绍了几种固定的搜索策略(广度优先、A*等),这些都是计算机科学家精心设计和编程实现的。那么智能体能自己学习如何更好地搜索吗?答案是肯定的,这种方法基于一个重要的概念,元级状态空间(metalevel state space)。元级状态空间中的每个状态将捕捉在普通状态空间(例如罗马尼亚地图)进行搜索的程序的内部(计算)状态。[为了区分这两个概念,我们将罗马尼亚地图称为对象级状态空间(object-level state space)。]例如,A*算法的内部状态由当前搜索树组成。元级状态空间中的每个动作都是一个改变内部状态的计算步;例如,A*中的每一个计算步扩展一个叶节点,并将其后续节点添加到树中。因此,图3-18展示了一个逐渐增大的搜索树序列,它描述了元级状态空间中的一条路径,路径上的每个状态都是一棵对象级搜索树。
现在,图3-18中的路径共有5步,包括一个扩展Fagaras的步骤,这一步不是非常有用。对于更困难的问题,将存在很多这样的错误步骤,元级学习(metalevel learning)算法可以从这些经验中学习,以避免探索毫无希望的子树。这种学习算法将在第22章中介绍。学习的目标是对计算开销和路径代价进行权衡,以最小化求解问题的总代价。
我们已经看到,生成启发式函数的一种方法是设计一个容易找到最优解的松弛问题,另一种选择是从经验中学习。这里的“经验”意味着,例如,求解大量8数码问题。一个8数码问题的每个最优解都提供了一个“(目标,路径)”对作为示例。可以利用学习算法通过这些示例构造一个函数h,(幸运的话)它可以近似搜索过程中出现的其他状态的真实路径代价。这些方法中的大多数学习到的都是启发式函数的一个不完美的近似,因此存在启发式函数不可容许的风险。这必然导致算法需要在学习时间、搜索运行时间和解的代价之间进行权衡。机器学习技术将在第19章中介绍。第22章中介绍的强化学习方法也适用于搜索问题。
如果除了原始状态描述外,还提供与预测启发式函数值相关的状态特征(feature),那么一些机器学习技术将表现得更好。例如,“错位滑块数”这一特征可能有助于预测8数码问题中状态与目标的实际距离。我们将这一特征记作x1(n)。我们可以使用100个随机生成的8数码配置,并收集其真实解代价的统计数据。我们可能会发现,当x1(n) = 5时,平均的解代价大约是14,等等。当然,可以使用多种特征。例如,第二个特征x2(n)可能是“在当前状态相邻而在目标状态中不相邻的滑块对的数量”。如何对x1(n)和x2(n)进行组合来预测h(n)?一种常见的方法是线性组合:
可以调整常数c1和c2以适应随机生成的配置中实际数据的值。我们希望c1和c2都是正值,因为错位滑块和不正确的相邻对都会使得问题更难求解。注意,这个启发式函数满足目标状态h(n) = 0的条件,但它不一定是可容许的或一致的。
本章对搜索算法进行了介绍,智能体可以用这些算法在各种环境中选择动作序列——只要环境是回合式的、单智能体的、完全可观测的、确定性的、静态的、离散的和已知的。算法需要在搜索所需时间、可用内存和解的质量之间进行权衡。如果我们对于启发式函数的形式拥有额外的领域相关知识来估计给定状态离目标有多远,或者我们预计算涉及模式或地标的部分解,算法会更高效。
● 在智能体开始搜索之前,必须形式化一个良定义的问题。
● 问题由5部分组成:初始状态、动作集合、描述这些动作结果的转移模型、目标状态集合和动作代价函数。
● 问题的环境用状态空间图表示。通过状态空间(一系列动作)从初始状态到达一个目标状态的路径是一个解。
● 搜索算法通常将状态和动作看作原子的,即没有任何内部结构(尽管我们在学习时引入了状态特征)。
● 根据完备性、代价最优性、时间复杂性和空间复杂性来评估搜索算法。
● 无信息搜索方法只能访问问题定义。算法构建一棵搜索树,试图找到一个解。算法会根据其首先扩展的节点而有所不同。
❏ 最佳优先搜索根据评价函数选择节点进行扩展。
❏ 广度优先搜索首先扩展深度最浅的节点;它是完备的,对于单位动作代价是最优的,但具有指数级空间复杂性。
❏ 一致代价搜索扩展路径代价g(n)最小的节点,对于一般的动作代价是最优的。
❏ 深度优先搜索首先扩展最深的未扩展节点。它既不是完备的也不是最优的,但具有线性级空间复杂性。深度受限搜索增加了一个深度限制。
❏ 迭代加深搜索在不断增加的深度限制上调用深度优先搜索,直到找到一个目标。当完成全部循环检查时,它是完备的,同时对于单位动作代价是最优的,且具有与广度优先搜索相当的时间复杂性和线性级空间复杂性。
❏ 双向搜索扩展两个边界,一个围绕初始状态,另一个围绕目标,当两个边界相遇时搜索停止。
● 有信息搜索方法可以访问启发式函数h(n)来估计从n到目标的解代价。它们可以访问一些附加信息,例如,存有解代价的模式数据库。
❏ 贪心最佳优先搜索扩展h(n)值最小的节点。它不是最优的,但通常效率很高。
❏ A*搜索扩展f(n) = g(n) + h(n)值最小的节点。在h(n)可容许的条件下,A*是完备的、最优的。对于许多问题,A*的空间复杂性仍然很高。
❏ 双向A*搜索有时比A*搜索本身更高效。
❏ IDA*(迭代加深A*搜索)是A*搜索的迭代加深版本,它解决了空间复杂性问题。
❏ RBFS(递归最佳优先搜索)和SMA*(简化的内存受限A*)搜索是健壮的最优搜索算法,它们仅使用有限的内存;如果时间充足,它们可以解决对A*来说内存不足的问题。
❏ 束搜索限制了边界的大小;因此它是非完备的、次优的,但束搜索通常能找到相当好的解,运行速度也比完备搜索更快。
❏ 加权A*搜索将搜索专注于一个目标,以扩展更少的节点,但它牺牲了最优性。
● 启发式搜索算法的性能取决于启发式函数的质量。我们有时可以通过松弛问题定义、在模式数据库中存储预计算的子问题的解代价、定义地标点,或者从问题类的经验中学习来构建良好的启发式函数。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们放宽了第3章的简化假设,以更接近真实世界。
第3章讨论了完全可观测的、确定性的、静态的、已知的环境中的问题,问题的解是一个动作序列。在本章中,我们将放宽这些限制。首先,我们考虑这样一个问题,即寻找一个好的状态而不考虑到达该状态的路径,状态包括离散状态(4.1节)和连续状态(4.2节)。然后,我们放宽了确定性假设(4.3节)和可观测性假设(4.4节)。在一个非确定性的世界中,智能体将需要一个条件规划,并根据它所观测到的情况执行不同的动作——例如,红灯停,绿灯行。对于部分可观测性环境,智能体还需要记录它的可能状态。最后,4.5节将指导智能体使用在线搜索(online search)通过一个未知空间,在未知空间中一边前进一边学习。
在第3章的搜索问题中,我们希望找到一条通过搜索空间的路径,如一条从Arad到Bucharest的路径。但有时我们只关心最终状态,而不是到达状态的路径。例如,在8皇后问题中(图4-3),我们只关心如何找到8个皇后的有效最终配置(因为如果知道配置,重构它的创建步骤就非常简单)。这也适用于许多重要应用,例如集成电路设计、工厂车间布局、作业车间调度、自动编程、电信网络优化、农作物种植规划和投资组合管理。
局部搜索(local search)算法的操作是从一个起始状态搜索到其相邻状态,它不记录路径,也不记录已达状态集。这意味着它们不是系统性的——可能永远不会探索问题的解实际所在的那部分搜索空间。但是,它们有两个主要优点:(1)使用很少的内存;(2)通常可以在系统性算法不适用的大型或无限状态空间中找到合理的解。
局部搜索算法也可以求解最优化问题(optimization problem),其目标是根据目标函数(objective function)找到最优状态。
为了理解局部搜索,我们考虑在状态空间地形图(state-space landscape)中布局的问题状态,如图4-1所示。地形图中的每个点(状态)都有一个“标高”,由目标函数值定义。如果标高对应于目标函数,那么目的就是找到最高峰——全局极大值(global maximum)——我们称这个过程为爬山(hill climbing);如果标高对应于代价,那么目的就是找到最低谷——全局极小值(global minimum)——我们称之为梯度下降(gradient descent)。
图4-1 一维状态空间地形图,其标高对应于目标函数。目的是找到全局极大值
爬山搜索算法如图4-2所示。它记录当前状态并在每次迭代中移动到值最大的相邻状态,也就是说,它朝最陡上升(steepest ascent)的方向前进。当它到达一个没有邻居具有更高值的“峰值”时,算法终止。爬山法不会考虑超出当前状态的直接邻居之外的状态。这就像是一个健忘的人在大雾中试图找到珠穆朗玛峰的顶峰。注意,使用爬山搜索的一种方法是使用启发式代价函数的负值作为目标函数;算法将局部地爬升至到目标的启发式距离最小的状态。
图4-2 爬山搜索算法是最基本的局部搜索技术。在每一步中,当前节点被其最优邻居节点替换
我们将使用8皇后问题(图4-3)进一步说明爬山法。我们将使用一个完整状态形式化(complete-state formulation),即每个状态都包含解的所有组成部分,但它们可能并不都在正确的位置。在这种情况下,每个状态都包括在棋盘上放置8个皇后,每列一个。初始状态是随机选择的,状态后继是通过将一个皇后移动到同一列中的另一格所生成的所有可能状态(所以每个状态有8×7 = 56个后继)。启发式代价函数h是可相互攻击的皇后对的数量;只有当该状态是一个解时,h值才是0。(如果两个皇后在同一条线上,即使它们之间存在一个中间棋子,这两个皇后也会被视为形成相互攻击。)图4-3b展示了一个h = 17的状态以及它所有后继的h值。
爬山法有时被称为贪心局部搜索(greedy local search),因为它只是选择最优的邻居状态,而不事先考虑下一步该如何走。虽然贪婪被视为七宗罪之一,但事实证明,贪心算法往往相当有效。爬山法可以在求解问题时取得快速进展,因为它通常可以很容易地改善一个差的状态。例如,只需5步就可以从图4-3b的状态到达图4-3a的状态,该状态的h = 1,与解非常接近。遗憾的是,爬山法可能会由于以下原因而陷入困境。
● 局部极大值(local maxima):局部极大值是一个比它每个相邻状态都高但比全局极大值低的峰顶。爬山法到达局部极大值附近就会被向上拉向峰顶,但随后将困在局部极大值处无路可走。图4-1示意性地说明了这一问题。更具体地说,图4-3a中的状态是一个局部极大值(即代价h的局部极小值);不管移动哪个皇后都会让情况变得更差。
图4-3 (a)8皇后问题:在棋盘上放置8个皇后,使得它们不能互相攻击。(皇后会攻击同一行、同一列或对角线上的任何棋子。)当前状态非常接近于一个解,除了第4列和第7列的两个皇后会沿对角线互相攻击。(b)一个8皇后状态,其启发式代价估计值h = 17。棋盘显示了通过在同一列移动皇后而获得的每一个可能后继的h值。有8个移动并列最优,其h = 12。爬山法将选择它们中的一个
● 岭(ridge):如图4-4 所示。岭的存在将导致一系列局部极大值,对于贪心算法,这是很难处理的。
图4-4 岭为爬山法带来困难的示意图。状态网格(蓝色圆点)叠加在从左到右上升的岭上,形成了一个彼此不直接相连的局部极大值序列。从每个局部极大值出发,所有可选动作都指向下坡。这样的拓扑在低维状态空间中很常见,例如二维平面中的点。但是在具有成百上千个维度的状态空间中,这种直观图并不成立,而且通常至少存在几个维度使得算法有可能漏掉岭和平台区
● 平台区(plateau):平台区是指状态空间地形图中的平坦区域。它可能是一块平坦的局部极大值,不存在上坡的出口;也可能是一个山肩(shoulder),从山肩出发还有可能继续前进(参见图4-1)。爬山搜索可能会迷失在平台区上。
在每种情况下,算法都会到达一个无法再取得进展的点。从一个随机生成的8皇后状态开始,在86%的情况下,最陡上升爬山法会被卡住,它只能解决14%的问题实例。但是,它求解速度很快,成功找到解时平均步数为4,被卡住时平均步数为3,这对一个具有万个状态的状态空间来说不算糟糕。
我们怎么才能求解更多问题?一个答案是当我们到达一个平台区时继续前进——允许横向移动(sideways move),希望这个平台区真的是一个山肩,如图4-1所示。但如果我们实际上位于一块平坦的局部极大值上,那么算法就会陷入死循环。因此,我们可以限制连续横向移动的次数,如在100次连续横向移动之后停止。这种方法将爬山法成功求解问题实例的百分比从14%提高到了94%。成功是有代价的:平均下来,对每个成功实例算法需要运行约21步,失败实例约64步。
爬山法存在很多变体。随机爬山法(stochastic hill climbing)在上坡行动中随机选择一个;被选中的概率随着上坡陡度的变化而变化。这种方法通常比最陡上升法收敛得更慢,但在某些状态地形图中,它能找到更好的解。首选爬山法(first-choice hill climbing)通过不断随机地生成后继直到生成一个比当前状态更好的后继为止来实现随机爬山。当一个状态存在众多(如数千个)后继时,这是一个很好的策略。
另一种变体是随机重启爬山法(random-restart hill climbing),它来自于一句格言:“如果一开始没有成功,那么尝试,再尝试。”它从随机生成的初始状态开始,执行一系列爬山搜索,直到找到目标。算法完备的概率为1,因为它最终会生成一个目标状态作为初始状态。如果每一次爬山搜索成功的概率为p,那么需要重启的期望次数为1 / p。对于不允许横向移动的8皇后实例,,所以大概需要7次迭代才能找到一个目标(6次失败,1次成功)。所需步数的期望为一次成功迭代的代价加上(1−p)/p倍的失败代价,总共约为22步。当允许横向移动时,平均需要
次迭代,
步。因此,对于8皇后问题,随机重启爬山法是非常有效的。即使有300万个皇后,这种方法也能在很短的时间内找到解。[1]
[1] 卢比等人(Luby et al., 1993)建议在搜索固定次数之后重启,并表明这比让每次搜索都无限期地继续下去要有效得多。
爬山法是否能成功在很大程度上取决于状态空间地形图的形状:如果几乎不存在局部极大值和平台区,那么随机重启爬山法可以很快找到一个好的解。但是,许多实际问题的地形图看起来更像是平地上散布着一群秃顶豪猪,每个豪猪的刺上还住着微型豪猪。NP困难问题(参见附录 A)通常存在指数级数量的局部极大值。尽管如此,在几次重启后,通常也可以找到相当好的局部极大值。
从不“下坡”,即从不向值较低(或代价较高)的状态移动的爬山算法总是很容易陷入局部极大值。相比之下,纯粹的随机游走算法不考虑状态值,而是随机移动到一个后继状态,它最终能够找到全局极大值,但它的效率非常低。因此,尝试将爬山法和随机游走结合起来以同时获得高效性和完备性,似乎是合理的。
模拟退火(simulated annealing)就是这样一种算法。在冶金学中,退火(annealing)是一种通过将金属或玻璃加热到高温然后逐渐冷却的方法使材料达到低能量结晶态以进行回火或硬化的过程。为了更好地解释模拟退火,我们将关注点从爬山转换为梯度下降(gradient descent)(即,最小化代价),想象这样一项任务,把一个乒乓球放入一个崎岖表面的最深的裂缝中。如果只是让球滚动,它会停在一个局部极小值。如果晃动平面,乒乓球会从局部极小值中弹出来——也许会弹到更深的局部极小值中,在那里它将耗费更多的时间。诀窍是晃动幅度要足够大,以使球从局部极小值中弹出,但又不能太大,以至于从全局极小值中弹出。模拟退火就是开始时用力晃动(即高温),然后逐渐降低晃动强度(即降低温度)。
模拟退火算法的总体结构(图4-5)与爬山法类似。然而,它不是选择最佳移动,而是选择随机移动。如果该移动使得情况改善,那么它总是会被接受。否则,算法以小于1的概率接受该移动。概率随着该移动的“坏的程度”——评估值变差的量——呈指数级下降。概率也会随“温度”T的降低而减小:开始时T较高,“坏”的移动更有可能被接受,当T降低时,可能性也逐渐降低。如果schedule所设置的T降到0的速度足够慢,那么玻尔兹曼分布
的一个性质是所有概率都集中在全局极大值上,即算法将以接近1的概率找到全局极大值。
图4-5 模拟退火算法,一种允许某些下坡移动的随机爬山法。输入的schedule是关于时间的函数,它决定了“温度”T的值
从20世纪80年代开始,模拟退火就被用于求解VLSI布图问题。它已广泛应用于工厂调度和其他大规模优化任务。
对于内存限制问题,在内存中只保存一个节点似乎有些极端。局部束搜索(local beam search)算法记录k个状态而不是只记录一个。它从k个随机生成的状态开始。在每一步中,生成全部k个状态的所有后继状态。如果其中任意一个是目标状态,那么算法停止。否则,它将从完整列表中选择k个最佳后继并重复上述操作。
从第一印象来看,具有k个状态的局部束搜索似乎只不过是并行(而非串行)地运行k次随机重启。事实上,这两种算法是完全不同的。在随机重启搜索中,每个搜索进程独立运行。而在局部束搜索中,有用信息将在并行的搜索线程之间传递。实际上,生成最佳后继的那些状态会对其他状态说:“过来,这里的草更绿!”算法将很快放弃那些没有效果的搜索并把资源转移到取得最大进展的路径上。
如果k个状态之间缺乏多样性,局部束搜索可能会受到影响——k个状态可能聚集在状态空间的一块小区域内,导致搜索只不过是k倍慢版本的爬山法。一种被称作随机束搜索(stochastic beam search)的变体可以帮助缓解这个问题,它类似于随机爬山法。随机束搜索不是选择最佳的k个后继状态,而是选择概率与它对应的目标函数值成正比的后继状态,从而增加了多样性。
进化算法(evolutionary algorithm)可以看作随机束搜索的变体,算法的动机明显来自生物学中自然选择的隐喻:一个由个体(状态)组成的种群,其中最适应环境(值最高)的个体可以生成后代(后继状态)来繁衍下一代,这个过程被称为重组(recombination)。进化算法存在无数种形式,它们按照以下方式变化。
● 种群规模。
● 每个个体的表示。在遗传算法(genetic algorithm)中,每个个体都是有限字母表上的一个字符串(通常是一个布尔字符串),就像DNA是字母表ACGT上的一个字符串一样。在进化策略(evolution strategy)中,个体是实数序列,而在遗传编程(genetic programming)中,个体是计算机程序。
● 混合数,,是一起形成后代的亲本的数量。最常见的情况是
:双亲结合它们的“基因”(它们表示的一部分)来形成后代。当
时,为随机束搜索(可以看作无性繁殖)。
也是可能的,这在自然界中很少发生,但很容易在计算机上进行模拟。
● 选择(selection)过程。选择将成为下一代亲本的个体:一种可能是从所有个体中选择,被选中的概率与其适应度得分成正比。另一种可能是随机选择n个个体(),然后选择最适合的
个个体作为亲本。
● 重组过程。一种常见的方法(假设)是随机选择一个杂交点(crossover point)来分割每个父字符串,并将这些部分重新组合以形成两个子串,一个是亲本1的第一部分和亲本2的第二部分的组合;另一个是亲本1的第二部分和亲本2的第一部分的组合。
● 突变率(mutation rate),它决定了后代在其表示上发生随机突变的频率。一旦产生了一个后代,其组成中的每位都将以与突变率相等的概率被翻转。
● 下一代的构成。可能只包括新形成的后代,也可能还包括一些上一代中得分最高的个体[这种做法被称为精英主义(elitism),它确保总体适应度永远不会随着时间的推移而下降]。而淘汰(culling),即丢弃所有分数低于给定阈值的个体,会使得进化加速(Baum et al., 1995)。
图4-6a为由4个8位数字符串组成的种群,每个字符串代表8皇后问题的一个状态:第c位数字表示第c列中皇后的行号。在图4-6b中,每个状态根据适应度函数进行评级。适应度越高越好,所以对于8皇后问题,我们使用非攻击皇后对的数量作为适应度,解的适应度为8×7/2 = 28。图4-6b中4个状态的值分别为24、23、20和11。然后将适应度得分归一化为概率,结果显示在图4-6b中的适应度旁边。
图4-6 遗传算法,图示为表示8皇后状态的数字字符串。(a)中的初始种群根据(b)中的适应度函数进行排序从而得到(c)中的配对,(d)是产生的后代,(e)是可能发生的突变
在图4-6c中,根据图4-6b中的概率选出两对父字符串。注意,有一个个体被选择了两次,还有一个没有被选择。对于每一对被选择的亲本,随机选择一个杂交点(虚线)。在图4-6d中,我们在杂交点处交叉两个父串,以生成新的后代。例如,第一对亲本中的第一个子串从第一个父串获得前三个数字(327),从第二个父串获得剩余数字(48552)。这一重组步骤中所包含的8皇后状态如图4-7所示。
图4-7 对应于图4-6c中前两个亲本和图4-6d中第一个后代的8皇后状态。在杂交步中,丢弃绿色列,保留红色列。(图4-6中数字的解释:第1行是最下面一行,第8行是最上面一行)
最后,在图4-6e中,每个字符串中的每个位置都以某个很小的独立概率发生随机突变。第一个、第三个和第四个后代的某个位发生了突变。在8皇后问题中,这相当于随机选择一个皇后,并将其随机移动到它所在列的某个位置。通常情况下,早期的种群是多样化的,所以在搜索过程的早期阶段,杂交常常在状态空间中采取较大的步调(类似于模拟退火)。在经过许多代选择提高了适应度后,种群的多样性减少,步调也随之变小。图4-8介绍了实现所有这些步骤的算法。
图4-8 遗传算法。在这个函数中,population是种群中个体的有序列表,weights是每个个体所对应的适应度值的列表,而fitness是计算这些值的函数
遗传算法类似于随机束搜索,但增加了杂交操作。如果存在可以执行有用功能的区域,杂交操作是有利的。例如,将前3列皇后分别放在第2行、第4行和第6行(在这些位置上它们不会互相攻击),就组成了一个有用的区域,它可以与其他个体中出现的其他有用区域相结合,从而形成一个解。数学上可以证明,如果这些区域没有任何用途——例如,如果遗传密码的位置是随机排列的——那么杂交就没有任何优势。
遗传算法理论用模式(schema)思想来解释它是如何运作的,模式是指其中某些位未确定的子串。例如,模式246*****表示前3个皇后分别位于位置2、4和6的所有8皇后状态。与该模式相匹配的字符串(例如24613578)称作该模式的实例(instance)。可以证明,如果某模式实例的平均适应度高于平均值,那么该模式的实例数量将随着时间推移而不断增加。
进化和搜索
进化论是由查尔斯·达尔文(Charles Darwin)(Darwin, 1859)和艾尔弗雷德·拉塞尔·华莱士(Alfred Russel Wallace)(Wallace, 1858)各自独立提出的。它的中心思想很简单:变异发生在繁殖过程中,并将在后代中以一定比例保存下来,大概与它们对生殖适应度的影响成比例。
达尔文在《物种起源》(On the Origin of Species by Means of Natural Selection)中的理论没有解释生物体的特征是如何遗传和改变的。控制这些过程的概率定律由修道士格雷戈尔·孟德尔(Gregor Mendel)(Mendel, 1866)首先发现,他使用豌豆进行了实验。很久之后,沃森和克里克(Watson and Crick, 1953)确定了DNA分子的结构及其AGTC(腺嘌呤、鸟嘌呤、胸腺嘧啶、胞嘧啶)序列。在标准模型中,基因序列上某点发生突变和“杂交”(后代的DNA通过合成父母双方的DNA长片段产生)都会导致变异。
进化和局部搜索算法的相似性前文已经介绍过了;随机束搜索和进化的主要区别在于是否为有性生殖,有性生殖中后代是由多个而非单个个体产生的。然而,进化的实际机制比大多数遗传算法要丰富得多。例如,突变包括DNA的逆转、复制和大段移动;有些病毒会从一个生物体中借用DNA再将其自身插入另一个生物体;还有一些转座基因只是在基因组中把自己复制成千上万次。
甚至还有一些基因会破坏不携带该基因的可能配对对象的细胞,从而增加它们自身的复制机会。最重要的是,基因自身对基因组复制和翻译成生物体的机制进行编码。在遗传算法中,这些机制是单独的程序,不体现在被操作的字符串中。
达尔文进化论可能看起来效率很低,它盲目地产生了大约1043个生物体,却丝毫没有改进它的搜索启发式函数。但是学习在进化中确实起着作用。尽管另一位伟大的法国博物学家让·拉马克(Jean Lamarck)(Lamarck, 1809)曾错误地提出,生物体一生中通过适应而获得的特性会遗传给后代,但詹姆斯·鲍德温(James Baldwin)(Baldwin, 1896)提出的表面上相似的理论则是正确的:学习可以有效地放宽适应度要求,从而加快进化速度。如果一个生物体具有一种不太适应环境的特性,但它也具有足够的可塑性,可以学习以一种有益的方式适应环境,那么生物体会将这种特性传递下去。计算机仿真(Hinton and Nowlan, 1987)证实了鲍德温效应(Baldwin effect)是真实存在的,其结果是,难以学习的事情最终会存在于基因组中,而容易学习的事情不必进入基因组(Morgan and Griffiths, 2015)。
显然,如果相邻位之间完全不相关,效果就没那么显著,因为几乎不存在功能一致的连续区域。当模式对应于解中有意义的组件时,遗传算法效果最优。例如,如果字符串表示天线,那么模式则表示天线的各组成部分,如反射器和导向器。一个好的组件可能在各种不同的设计中都是好的。这表明,遗传算法的成功依赖于精细的表示工程。
实际上,遗传算法在广泛的最优化方法中占有一席之地(Marler and Arora, 2004),尤其是复杂结构问题,如电路布图或作业车间调度,以及最近的深度神经网络架构演变(Miikkulainen et al., 2019)。目前还不清楚遗传算法的吸引力是来自于它在特定任务上的性能优势,还是来自于进化本身。
在第2章中,我们解释了离散环境和连续环境之间的区别,并指出大多数的真实世界环境都是连续的。连续动作空间的分支因子是无限的,因此我们目前介绍的大多数算法(除了首选爬山法和模拟退火)都无法处理连续空间。
本节将非常简要地介绍一些连续空间的局部搜索技术。关于这个主题的文献有很多。许多基本技术起源于牛顿和莱布尼茨发明微积分之后的17世纪。[2]本书的一些章节会介绍这些技术的应用,包括学习、视觉和机器人技术相关的章节。
[2] 向量、矩阵和导数的知识对于学习本节内容很有帮助(见附录A)。
考虑一个实例。假设我们希望在罗马尼亚新建3个机场,使得地图上每个城市到其最近机场的直线距离平方和最小。(罗马尼亚地图见图3-1。)状态空间定义为3个机场的坐标:(x1, y1)、(x2, y2)和(x3, y3)。这是一个六维空间;我们也可以说状态由6个变量(variable)定义。一般地,状态定义为n 维向量,x。在这个空间中移动对应于移动地图上的一个或多个机场。对于任一特定状态,一旦计算出最近城市,目标函数f(x) = f (x1, y1, x2, y2, x3, y3)的计算就会变得相对容易。设Ci是最近机场(在状态x下)为机场 i 的城市集合。那么,我们有
(4-1)
这一方程不仅对于状态x是正确的,而且对于x局部邻域中的状态也是正确的。然而,对全局来说,它是不正确的;如果我们偏离x太远(通过大幅改变一个或多个机场的位置),那么该机场的最近城市集合会发生变化,我们需要重新计算Ci。
处理连续状态空间的一种方法是离散化(discretize)。例如,我们可以将(xi, yi)的位置限制在矩形网格上间距为的固定点,而不是允许它的位置可以为连续二维空间中的任意点。那么,空间中的每个状态将存在12个后继(对应于将6个变量分别增加
),而不是之前的无限多个。然后我们就可以对离散空间应用任意局部搜索算法。或者,我们可以通过随机采样后继状态,即在随机方向上移动一个小量
,使分支因子变为有限值。通过两个相邻点之间目标函数值的变化来衡量进度的方法称为经验梯度(empirical gradient)法。经验梯度搜索与离散化状态空间中的最陡上升爬山法相同。随着时间逐渐减小
的值可以得到更准确的解,但不一定在极限范围内收敛到全局最优值。
通常我们有一个以数学形式表达的目标函数,这样我们就可以用微积分来解析地而非经验地求解问题。许多方法都试图利用地形图的梯度(gradient)来找到最大值。目标函数的梯度是一个向量∇f,它给出了最陡斜面的长度和方向。对于我们的问题,有
在某些情况下,我们可以通过解∇f = 0方程找到一个极大值。(这是可以做到的,例如,如果我们只新建一个机场;问题的解是所有城市坐标的算术平均值。)然而,在许多情况下,这个方程不存在闭式解。例如,对于3个机场的情况,梯度的表达式依赖于当前状态中哪些城市离各个机场最近。这意味着我们只能局部地(而非全局地)计算梯度,例如,
(4-2)
给定一个局部正确的梯度表达式,我们可以根据下式来更新当前状态从而实现最陡上升爬山法:
其中是一个很小的常数,通常称为步长(step size)。存在很多调整
的方法。基本问题是,如果
太小,需要的迭代步太多;如果
太大,搜索可能会越过最大值。线搜索(line search)技术试图通过不断延伸当前梯度方向——通常通过对
反复加倍——直到f再次开始减小来克服上述困境。出现上述现象的点成为新的当前状态。在这点上如何选择新的方向,有几种不同的方法。
对于许多问题,最有效的算法是古老的牛顿-拉弗森法(Newton-Raphson method)。这是一种求函数根(即求解g(x) = 0形式的方程)的通用方法。它的工作原理是根据牛顿公式计算根x的一个新的估计值:
要找到f的最大值或最小值,需要找到使得梯度为零向量(即)的x。因此,牛顿公式中的g(x)为
,更新方程可以写成矩阵-向量形式:
其中Hf(x)为二阶导数的黑塞矩阵(Hessian matrix),其元素Hij由给出。对于上述机场问题实例,从式(4-2)可以看出,Hf(x)相当简单:非对角元素为零,机场i的对角线元素的值恰好为Ci中城市数目的两倍。每一时刻的计算表明,每一步更新将机场i直接移动到Ci的质心处,即式(4-1)中f的局部表达式的最小值。[3]然而,对于高维问题,计算黑塞矩阵的n2个元素以及对它求逆的开销可能非常昂贵,因此产生了许多牛顿-拉弗森法的近似版本。
[3] 一般来说,牛顿-拉弗森更新可以看作在x处用一个二次曲面拟合f,下一步则直接移动到该曲面的最小值——如果f是二次的,则也是f的最小值。
局部搜索方法在连续状态空间和离散状态空间中一样,同样受到局部极大值、岭和平台区的影响。随机重启和模拟退火通常很有用。然而,高维连续空间非常大,算法很容易陷入困境。
最后一个话题是约束优化(constrained optimization)。如果一个优化问题的解必须满足对变量值的一些硬性约束,那么这个问题就是受约束的。例如,在机场选址问题中,我们可能会将选址限制在罗马尼亚境内的陆地上(而不是某个湖中心)。约束优化问题的难度取决于约束和目标函数的性质。最著名的一类问题是线性规划(linear programming)问题,其约束必须是能构成凸集的线性不等式[4],目标函数也必须是线性的。线性规划的时间复杂性是关于变量数目的多项式。
[4] 如果点集S中任意两点的连线也包含在S中,则称S是凸的。凸函数(convex function)是指其上方空间构成凸集的函数;根据定义,凸函数没有局部(相对于全局)极小值。
线性规划可能是最广泛研究和最有用的优化方法。它是更一般的凸优化(convex optimization)问题的一种特例,允许约束区域为任意凸区域,目标函数为约束区域内的任意凸函数。在一定条件下,凸优化问题也是多项式时间内可解的,即使有上千个变量,也可能是实际可行的。机器学习和控制理论中的几个重要问题可以形式化为凸优化问题(见第20章)。
在第3章中,我们假设环境为完全可观测的、确定性的、已知的。因此,智能体可以观测到初始状态,计算出可以到达目标的动作序列,然后“闭着眼睛”执行这些动作,而不需要使用自己的感知。
然而,当环境部分可观测时,智能体并不确定它处于什么状态;当环境是非确定性的时,智能体不知道在执行某个动作后将转移到什么状态。这意味着智能体所思考的不再是“我现在位于s1状态,如果我执行a动作,我将会进入s2状态”,而是“我现在位于s1或s3状态,如果我执行a动作,我将会进入s2、s4或s5状态”。我们把智能体认为其可能位于的物理状态集合称为信念状态(belief state)。
在部分可观测的和非确定性的环境中,问题的解不再是一个序列,而是一个条件规划(conditional plan)(有时也称为应变规划或策略),条件规划根据智能体在执行规划时接收到的感知来指定动作。本节先讨论非确定性,部分可观测性留待4.4节讨论。
如图4-9所示,第2章中的真空吸尘器世界具有8种状态。有3种动作——向左Left、向右Right和吸尘Suck,目标是清理所有的灰尘(状态7和8)。如果环境是完全可观测的、确定性的和完全已知的,那么使用第3章的任意算法都很容易求解这个问题,它的解是一个动作序列。例如,如果初始状态是1,那么动作序列[Suck, Right, Suck]可以到达目标状态8。
图4-9 真空吸尘器世界的8种可能状态;状态7和8是目标状态
现在假设我们以一个功能强大但不稳定的真空吸尘器的形式引入非确定性。在不稳定的真空吸尘器世界中,Suck的工作原理如下。
● 在一个脏的方格中,Suck会清理这一方格,有时也会清理它的相邻方格。
● 在一个干净方格中,Suck有时反而会把灰尘弄到地面上。[5]
[5] 我们假设大多数读者都会遇到类似的问题,并且会共情我们的智能体。我们向那些拥有现代化高效清洁设备从而无法利用这一教学设计的读者道歉。
为了更准确地形式化这一问题,我们需要推广第3章的转移模型概念。我们不使用返回单个结果状态的Result函数来定义转移模型,而是使用返回一组可能的结果状态的新的Result函数。例如,在不稳定的真空吸尘器世界中,状态1中的Suck动作要么只清理当前位置,要么同时清理两个位置:
如果我们是从状态1开始,那么没有任何一个单独的动作序列能够求解问题,因此我们需要如下的条件规划:
(4-3)
我们看到,条件规划可以包含if–then–else步骤;这意味着解是树而不是序列。这里的if语句中的条件用来测试当前状态;这是智能体在运行时能够观测到的,但规划时还不知道。或者,我们也可以用公式来测试感知而不是状态。真实物理世界中的许多问题都是应变问题,因为不可能对未来进行准确预测。因此,许多人在走路时都会睁着眼睛。
我们如何得到这些非确定性问题的条件解?和第3章一样,我们首先从构造搜索树开始,但是这里的树有一个不同的特性。在确定性环境中,分支是由智能体在每个状态下自己的选择引入的:我可以执行这个动作或那个动作。我们称这些节点为或节点(OR node)。例如,在真空吸尘器世界中,智能体在或节点上选择Left、Right或Suck。而在非确定性环境中,环境对每个动作的结果的选择也会引入分支。我们称这些节点为与节点(AND node)。例如,状态1中的Suck动作会产生信念状态{5,7},因此智能体需要为状态5与状态7分别找到一个规划。这两种节点交替出现,形成如图4-10所示的与或树(AND–OR tree)。
图4-10 不稳定的真空吸尘器世界搜索树的前两层。状态节点是必须选择某个动作的或节点。与节点(用圆圈表示)上的每个结果都必须处理,结果分支间用弧线连接。找到的解用粗线标识
与或搜索问题的解是完整搜索树的一棵子树:(1)每个叶子都是一个目标节点,(2)在每个或节点上选择一个动作,(3)每个与节点包括所有结果分支。解在图中用粗线标识;对应于式(4-3)中的规划。
图4-11给出了与或图搜索的深度优先递归算法。该算法的一个关键是它处理环的方法,环经常出现在非确定性问题中(例如,动作有时不起作用,或者一个意外的影响被纠正)。如果当前状态与从根到它的路径上的某个状态相同,就返回失败。这并不意味着从当前状态出发没有解;这仅仅意味着,如果存在一个非循环解,那么它肯定可以从当前状态的早期镜像到达,因此可以丢弃新的镜像。有了这一检查,可以确保算法在任何有限状态空间中都能终止,因为每条路径都必定到达一个目标、一个死胡同或一个重复状态。注意,该算法并不检查当前状态是否是从根出发的其他路径上的某个状态的重复状态,这一点对效率来说很重要。
图4-11 非确定性环境生成的与或图的搜索算法。解是一个条件规划,它考虑每一个非确定性的结果,并为每个结果制定规划
与或图也可以使用广度优先或最佳优先的方式进行探索。我们必须修改启发式函数的概念,即估计一个条件解而不是一个序列的代价,但可容许性的概念可以继续保留,而且存在类似的用于寻找最优解的A*算法(参见本章末尾的参考文献与历史注释)。
考虑一个光滑的真空吸尘器世界,它与普通的(稳定的)真空吸尘器世界基本相同,但移动操作有时会失效,使得智能体停在原地。例如,在状态1中执行Right将产生信念状态{1,2}。图4-12为部分搜索图;显然,从状态1出发不存在非循环解,And-Or-Search将返回失败。然而,存在一个循环解(cyclic solution),即反复尝试Right动作,直到它生效。我们可以用一个新的while结构来表示上述过程:
或者用标签(label)表示规划的某一部分,之后可以引用这个标签:
什么时候可以考虑将循环规划作为解?最小条件是每个叶节点都是一个目标状态,并且叶节点可以从规划中的任意点到达。除此之外,我们还要考虑造成非确定性的原因。如果情况确实是,真空吸尘器机器人的驱动机制在某些时间工作,但在其他时间真空吸尘器会发生随机、独立地滑动,那么智能体可以保证,如果动作重复足够多次,最终总会生效,规划也会成功。但是,如果这种非确定性来自机器人或环境的一些尚未观测到的原因(例如,传动带断了,那么机器人将永远不会移动),重复这个动作也没有用。
为了便于理解,我们可以认为,它是将初始问题形式(完全可观测的,非确定性的)转化为另一种形式(部分可观测的,确定性的),其中循环规划的失败正是由于传动带的某个不可观测的特性。在第12章中,我们将讨论如何判断几种不确定可能性中哪个可能性更大。
图4-12 光滑的真空吸尘器世界的部分搜索图,(一些)循环已经明确地标出。这个问题的所有解都是循环规划,因为真空吸尘器无法稳定地移动
现在我们考虑部分可观测性问题,即智能体的感知不足以确定准确的状态。这意味着,智能体的一些动作将致力于减少当前状态的不确定性。
当智能体的感知根本不提供任何信息时,问题就变成了无传感器(sensorless)问题,或称一致性(conformant)问题。起初,你可能会认为,如果无传感器智能体不知道起始状态,那它就无法求解问题,但出人意料的是,无传感器解非常普遍且有用,主要是因为它们不依赖于传感器是否正常工作。例如,在制造系统中,已经开发出许多巧妙的方法,通过使用一系列行动而无须任何感知,从未知初始位置正确定位零件。有时,即使存在可感知的条件规划,无传感器规划也会更好。例如,医生通常会开一种广谱抗生素,而不是使用条件规划:先验血,接着等待结果,然后再开一种更具体的抗生素。这种无传感器规划节省了时间和金钱,并且避免了在检测结果出来之前感染恶化的风险。
考虑一个(确定性)真空吸尘器世界的无传感器版本。假设智能体知道它所在世界的地理环境,但不知道它自己的位置和灰尘的分布。在这种情况下,它的初始信念状态为{1, 2, 3, 4, 5, 6, 7, 8}(见图4-9)。现在,如果智能体执行Right动作,它将位于{2, 4, 6, 8}中的某个状态——智能体在没有感知的情况下获得了信息!执行[Right, Suck]之后,智能体将总是位于{4, 8}中的某个状态。最终,无论初始状态是什么,执行[Right, Suck, Left, Suck]之后,智能体必定会到达目标状态7。我们称,智能体可以强迫(coerce)世界到达状态7。
无传感器问题的解是一个动作序列,而不是条件规划(因为它没有感知)。但是,我们是在信念状态空间而非物理状态空间中进行搜索。[6]在信念状态空间中,问题是完全可观测的,因为智能体始终知道自己的信念状态。此外,无传感器问题的解(如果有的话)始终是一个动作序列。这是因为,正如第3章的原始问题一样,每个动作后接收到的感知是完全可预测的——它们总是空的!所以不存在需要规划的偶发事件。即使环境是非确定性的,这也是正确的。
[6] 在完全可观测的环境中,每个信念状态只包含一个物理状态。因此,我们可以将第3章的算法看作在信念状态为单元素的信念状态空间中搜索。
我们可以为无传感器搜索问题介绍新的算法。但是,如果我们将底层物理问题转化为信念状态问题,我们就可以使用第3章中现有的算法,即,对信念状态而非物理状态进行搜索。原问题P,由ActionsP、ResultP等组成,信念状态问题则包括以下部分。
● 状态:信念状态空间包含物理状态的每一个可能子集。如果原问题P有N个状态,那么信念状态问题有2N个信念状态,尽管有很多状态都无法从初始状态到达。
● 初始状态:通常,初始信念状态包含P中的所有状态,尽管在某些情况下,智能体具有更多的先验知识。
● 动作:这部分有点棘手。假设智能体位于信念状态,但是
;那么智能体就无法确定哪些动作是合法的。如果我们假定非法动作不会对环境产生影响,那么执行当前信念状态b下的任意物理状态的所有动作的并集都是安全的。
但是,如果非法动作可能导致严重后果,那么只允许执行动作的交集(对所有状态都合法的动作的集合)更安全。对于真空吸尘器世界,每个状态都具有相同的合法动作,所以两种方法将给出相同的结果。
● 转移模型:对于确定性动作,对于每个当前可能状态,新的信念状态中都存在一个如下结果状态(尽管一些结果状态可能是相同的)。
(4-4)
对于非确定性动作,新的信念状态则包含了将该动作应用于当前信念状态中的任一状态的所有可能结果。
对于确定性动作,b'不会大于b,而对于非确定性动作,b'可能会大于b(见图4-13)。
图4-13 (a)预测在无传感器真空吸尘器世界执行确定性动作Right后的下一个信念状态;(b)在光滑的无传感器真空吸尘器世界中的同一状态下执行同一动作的预测
● 目标测试:如果信念状态中的任一状态s满足底层问题的目标测试,Is-GoalP(s),则智能体有可能到达了目标。如果所有状态都满足Is-GoalP(s),则智能体必定到达了目标。我们的目标是使得智能体必定到达了目标。
● 路径代价:这部分也很棘手。如果同一动作在不同状态下代价不同,那么在给定信念状态下执行动作的代价是几种不同值中的一种。(这导致了一类新的问题,我们将在习题4.MVAL中讨论。)现在我们假定同一动作在所有状态下具有相同代价,因此动作代价可以直接从底层物理问题中转换。
图4-14为确定性无传感器真空吸尘器世界的可达信念状态空间。在28 = 256种可能信念状态中只有12种可以到达。
图4-14 确定性无传感器真空吸尘器世界的信念状态空间的可达部分。每个矩形框对应一个信念状态。在任何给定点,智能体都有一个信念状态,但它不知道自己位于哪个物理状态。初始信念状态(完全未知)位于最上面的中间方框
上述定义确保信念状态问题的形式化能够从底层物理问题的定义自动构建。一旦完成,就可以用第3章的任何普通搜索算法求解无传感器问题。
在一般的图搜索中,需要检测新到达的状态之前是否已经到达过。这也适用于信念状态;例如,在图4-14中,动作序列[Suck, Left, Suck]从初始状态出发,到达与序列[Right, Left, Suck]相同的信念状态,即,{5, 7}。现在,考虑[Left]到达的信念状态,{1, 3, 5, 7}。显然,这与{5, 7}不同,但它是{5, 7}的超集。我们可以抛弃(剪枝)任何一个这样的信念状态超集。为什么?因为从{1, 3, 5, 7}出发的解一定也是任何单一状态1、3、5和7的解,因此,它也是这些单一状态任意组合的解,例如{5, 7};因此我们没有必要试着求解{1, 3, 5, 7},可以专注于求解更严格简单的信念状态{5, 7}。
反过来,如果已经生成{1, 3, 5, 7},并且发现它是可解的,那么它的任何子集,如{5, 7},可以确保也是可解的。(如果我有一个解,它在我对自己处于何种状态“非常困惑”时都是有效的,那么在我“不那么困惑”时它仍然是有效的。)这种额外剪枝可能会显著提高无传感器问题的求解效率。
然而,即使有这样的改进,我们所介绍的无传感器问题求解方法在实践中也几乎是不可行的。一个问题是信念状态空间非常庞大——我们在第3章中看到过,一个大小为N的搜索空间已经过于庞大,而现在我们搜索空间的大小为2N。此外,搜索空间中的每个元素都是一个不超过N个元素的集合。对于较大的N,内存空间甚至不足以表示单个的信念状态。
一种解决方案是用更紧凑的描述来表示信念状态。例如,在英语中,我们可以用“Nothing”表示初始状态;我们可以用“Not in the rightmost column”表示执行Left动作后的信念状态,等等。第7章介绍了如何在形式化表示模式中实现上述表示。
另一种方法是避免使用标准搜索算法,它们将信念状态看作和任何其他问题状态一样的黑盒。然而,我们可以选择查看信念状态内部,并设计增量信念状态搜索(incremental belief-state search)算法,即,每次只为一个物理状态建立解。例如,在无传感器真空吸尘器世界中,初始信念状态为{1, 2, 3, 4, 5, 6, 7, 8},我们必须找到一个在所有8种状态下都有效的动作序列。我们可以先找到状态1的解;然后检查它对于状态2是否有效;如果无效,则回溯寻找状态1的另一个解,以此类推。
正如与或搜索必须为与节点上的每个分支找到解一样,这一算法也必须为信念状态下的每个物理状态找到解;区别在于与或搜索可以为每个分支找到不同的解,而增量信念状态搜索必须找到一个对所有状态都有效的解。
增量方法的主要优点是,它通常能够快速检测出失败——当一个信念状态无解时,通常情况下,它的子集(包含最先检测的几个状态)也是无解的。在某些情况下,这将导致与信念状态规模成正比的加速,信念状态本身可能就和物理状态空间一样大。
对许多问题来说,没有感知就无法求解。例如,求解无传感器8数码问题是不可能的。但是,一点点感知可能就有很大帮助:如果我们能够看到左上角的方格,就能求解8数码问题。解包括依次将每个滑片移动到可观测的方格中,并从那时起记录该滑片的位置。
对于部分可观测问题,问题形式化将定义一个Percept(s)函数,它返回智能体在给定状态下接收到的感知。如果感知是非确定性的,那么我们可以使用Percepts函数返回可能感知的集合。对于完全可观测问题,每个状态s下,Percept(s) = s,对于无传感器问题,Percept(s)= null。
考虑一个局部感知真空吸尘器世界,智能体拥有一个位置传感器(在左侧方格中生成感知L,右侧方格中生成感知R)和一个灰尘传感器(当前方格内有灰尘时生成感知Dirty,否则生成Clean)。因此,状态1的Percept为[L, Dirty]。对于部分可观测的情况,通常会存在几个状态产生相同感知的情况;状态3也会产生[L, Dirty]。因此,给定这一初始感知,初始信念状态将为{1,3}。我们可以将部分可观测问题信念状态之间的转移模型分为3个阶段,如图4-15所示。
● 预测(prediction)阶段与无传感器问题相同,计算由动作所导致的信念状态,Result(b, a)。为了强调这是一个预测,我们将其记为bˆ = Result(b, a),其中b上方的“hat”表示“估计值”,我们还可以使用Predict(b, a)代替Result(b, a)。
● 可能感知(possible percept)阶段计算在预测的信念状态下可以观测到的感知集合(用字母o表示观测到的感知):
● 更新(update)阶段为每个可能感知计算其可能得到的信念状态。更新后的信念状态bo是bˆ中可能产生这一感知的状态集合:
● 智能体需要在规划阶段处理可能的感知,因为在执行规划之前它不知道实际的感知。注意,在预测阶段,物理环境中的非确定性会扩大信念状态,但每个更新后的信念状态bo不会大于预测的信念状态bˆ;观测到的感知只能帮助减少不确定性。此外,对于确定性感知,不同感知的信念状态是不相交的,从而形成原始预测信念状态的一个划分。
图4-15 局部感知真空吸尘器世界中的两个转移实例。(a)确定性世界中,在初始信念状态下执行Right动作,所得到的新的预测信念状态有两个可能的物理状态;对于这些状态,可能的感知是[R, Dirty]和[R, Clean],从而得到两种信念状态,每种都只包含一个物理状态。(b)光滑世界中,在初始信念状态下执行Right动作,所得到的新的信念状态具有4个物理状态;对于这些状态,可能的感知是[L, Dirty]、[R, Dirty]和[R, Clean],从而得到图中所示的3种信念状态
综合这3个阶段,我们可以得到由给定动作及后续的可能感知所产生的可能信念状态:
(4-5)
4.4.2节介绍了在给定Percept函数的情况下,如何从底层物理问题推导出非确定性信念状态问题的Results函数。使用这一形式化,可以直接应用图4-11的与或搜索算法得到问题的解。图4-16为局部感知真空吸尘器世界的部分搜索树,假定初始感知为[L, Dirty]。它的解是一个条件规划:
注意,因为我们是在信念状态问题中应用与或搜索算法,所以它返回的条件规划所测试的是信念状态,而非实际状态。这是应该的:在部分可观测环境中,智能体并不知道实际状态。
图4-16 局部感知真空吸尘器世界问题的第一层与或搜索树,Suck是解序列中的第一个动作
与标准搜索算法应用于无传感器问题的情况一样,与或搜索算法将信念状态看作和任何其他问题状态一样的黑盒。可以通过检查先前生成的信念状态——它们是当前状态的子集或超集——来改进这一点,就像求解无传感器问题一样。同样可以推导出与无传感器问题中描述的那些算法类似的增量搜索算法。与黑盒方法相比,它们提供了显著的加速。
部分可观测环境中的智能体先对问题形式化,接着调用搜索算法(例如And-Or-Search)求解,然后执行解步骤。这种智能体和完全可观测确定性环境中的智能体之间有两个主要区别。首先,问题的解将是一个条件规划而不是一个序列;为了执行if-then-else表达式,智能体需要测试if语句中的条件并执行正确的条件分支。其次,智能体需要在执行动作和接收感知时维护其信念状态。这一过程类似于式(4-5)中的预测-观测-更新过程,但更加简单,因为感知是由环境给出的,而不是由智能体自己计算的。给定初始信念状态b、动作a、感知o,则新的信念状态为
(4-6)
考虑一个类幼儿园真空吸尘器世界,智能体只能感知当前方格的状态,任一方格在任一时刻都有可能变脏,除非智能体恰好在那一时刻主动清理该方格。[7]图4-17为此环境中所维护的信念状态。
[7] 向那些不熟悉幼儿对环境影响的人表示歉意。
在部分可观测环境中——涵盖绝大多数真实世界环境——维护自身的信念状态是任何智能系统的核心功能。这一功能有很多不同的名称,包括监视(monitoring)、过滤(filtering)和状态评估(state estimation)。式(4-6)称为递归状态评估器,因为它根据前一状态计算新的信念状态,而不是检查整个感知序列。如果智能体不想“落后”,计算速度必须和感知进入的速度一样快。随着环境越来越复杂,智能体将只有时间计算近似信念状态,它可能重点关注感知对当前感兴趣的环境方面的影响。关于这一问题的大部分工作都是用概率论的工具处理随机的连续状态的环境,详见第14章。
图4-17 在局部感知的类幼儿园真空吸尘器世界中,信念状态维护的两个预测-更新周期
在本节中,我们将展示一个离散环境中的实例,其传感器是确定性的,动作是非确定性的。这个实例中涉及的机器人具有特定的状态评估任务,该任务称为定位(localization):即在给定世界地图和一系列感知及行动的情况下,找到自己的位置。机器人放置在图4-18所示的迷宫环境中。它配备了4个声呐传感器,可以判断在4个罗盘方向上是否存在障碍物——外墙或者图中的深色阴影方格。感知以位向量的形式出现,每一位依次代表北、东、南、西方向,所以1011表示北、南、西方向有障碍物。
图4-18 机器人的可能位置,⊙,(a)一次观测E1 = 1011后。(b)移动一个方格并进行第二次观测E2 = 1010后。如果传感器没有噪声且转移模型是准确的,那么只有一个可能位置与这两个观测序列一致
我们假设传感器所提供的数据完全正确,而且机器人拥有正确的环境地图。但遗憾的是,机器人的导航系统发生故障,所以当它执行Right动作时,会随机移动到一个相邻方格。机器人的任务是确定它的当前位置。
假设机器人刚刚启动,并不知道自己的位置——那么它的初始信念状态b为包含所有位置的集合。接着机器人接收到感知1011,并使用公式bo = Update(1011)进行更新,得到如图4-18a所示的4个位置。查看整个迷宫你会发现这是仅有的4个可以产生感知1011的位置。
接下来,机器人执行Right动作,但结果是非确定性的。新的信念状态,ba = Predict(bo, Right),包含了与bo中的位置相邻的所有位置。当接收到第二个感知1010时,机器人执行Update(ba, 1010),此时信念状态已经只剩图4-18b所示的一个位置。这是下式得到的唯一位置:
对于非确定性动作,Predict阶段信念状态增加,但是Update阶段信念状态又减少回去——只要感知提供了有用的识别信息。有时感知对定位帮助不大:如果存在一个或多个很长的东西向走廊,那么机器人可能会接收到一个很长的1010感知序列,但它永远不会知道它在走廊的哪一位置。但对于地理上存在合理差异的环境,定位往往会迅速收敛到单个点,即使动作是非确定性的。
如果传感器发生故障怎么办?如果我们只能用布尔逻辑进行推理,那么我们就无法判断每个传感器位的正误,相当于没有任何感知信息。但我们将看到,概率推理(第12章)允许我们从故障传感器中提取有用信息,只要它出错的时间不超过一半。
到目前为止,我们主要关注使用离线搜索(offline search)算法的智能体。它们在执行第一个动作之前就已经计算出一个完整的解。相比之下,在线搜索(online search)[8]智能体则交替进行计算和动作:它首先执行一个动作,然后观测环境并计算下一个动作。在线搜索适用于动态或半动态环境,因为在这些环境中停止不动或计算时间太长都要付出代价。在线搜索在非确定性领域也很有用,因为它允许智能体将计算精力集中在实际发生的偶然事件上,而不是那些也许会发生但很可能不会发生的事件。
[8] 这里的“在线”指的是必须在接收到输入时立即进行处理的算法,而不是等待整个输入数据集都可用时再进行处理。“在线”的这种用法与“因特网连接”的概念无关。
当然,这里需要权衡:智能体提前规划得越多,发现自己陷入困境的频率越低。在未知环境中,智能体不清楚存在什么状态或者动作会产生什么结果,必须使用自身的动作作为实验来了解环境。
在线搜索的一个典型实例是地图构建问题(mapping problem):机器人放置在一个未知建筑中,它必须进行探索以绘制一个从A到B的地图。逃离迷宫的方法——有抱负的古代英雄所需的知识——也是在线搜索算法的实例。然而,空间探索并不是在线探索的唯一形式。以一个新生儿为例:它可能可以做许多举动,却不知道这些动作的后果,而且它只体验过少数几个它能达到的可能状态。
求解在线搜索问题需要交替进行计算、感知和动作。我们首先假设环境是确定性的和完全可观测的(第17章放宽了这些假设),并规定智能体只知道以下内容。
● Actions(s),状态s下的合法动作。
● c(s, a, s'),在状态s下执行动作a到达状态s'的代价。注意,前提是智能体知道s'是结果。
● Is-Goal(s),目标测试。
特别要注意的是,智能体不能确定Result(s, a)的值,除非它确实在s中执行了a。例如,在图4-19所示的迷宫问题中,智能体并不知道从(1, 1)执行Up动作会到达(1, 2);也不知道再执行Down动作会回到(1, 1)。在某些应用中可以减少这种无知——例如,机器人探测器可能知道它是如何移动的,只是不知道障碍物的位置。
最后,智能体可能可以访问一个可容许的启发式函数h(s),该函数对从当前状态到目标状态的距离进行估计。例如,在图4-19中,智能体可能知道目标的位置,从而可以使用曼哈顿距离启发式函数(3.6节)。
图4-19 一个简单的迷宫问题。智能体必须从S出发到达G,但它对环境一无所知
通常,智能体的目标是以最小代价到达目标状态。(另一个可能目标是简单地探索整个环境。)代价是智能体在移动过程中产生的总的路径代价。通常将它与智能体事先知道搜索空间时所产生的路径代价(即已知环境中的最优路径)进行比较。在在线算法的术语中,这种比较被称为竞争比(competitive ratio),我们希望它尽可能地小。
在线探索器很容易陷入死胡同(dead-end):无法到达任何目标状态的状态。如果智能体不知道每个动作的后果,它可能会“跳进陷阱”,因此永远无法到达目标。一般来说,没有一种算法能在所有状态空间中都避免进入死胡同。以图4-20a中的两个死胡同状态空间为例。对已经访问过状态S和A的在线搜索算法来说,它无法分辨自己是处于顶部的状态还是底部的状态;根据智能体观测到的感知信息,这两个状态看起来是相同的。因此,它不可能知道如何在两个状态空间中选择正确的动作。这是一个对手论证(adversary argument)的实例——想象对手在智能体探索状态空间时构建状态空间,并将目标和死胡同放在它所选择的任何地方,如图4-20b所示。
图4-20 (a)两个可能将在线搜索智能体引入死胡同的状态空间。任何给定智能体都会在至少一个空间中失败。(b)二维环境实例,将导致在线搜索智能体沿着一条任意低效的路线到达目标。无论智能体做出何种选择,对手都会用另一堵很长很薄的墙来阻挡这条路线,这样智能体所走的路径就会比最优可能路径长得多
死胡同是机器人探索中的一个真正的难点——楼梯、斜坡、悬崖、单行道甚至自然地形中都存在从它出发某些动作不可逆(irreversible)的状态——没有办法回到之前的状态。我们提出的探索算法只保证在可安全探索(safely explorable)的状态空间中是有效的,也就是说,从每个可达状态出发都存在可以到达的目标状态。所有动作都可逆的状态空间,如迷宫和8数码,显然是可安全探索的(如果它们有解的话)。我们将在22.3.2节中更深入地讨论安全探索的话题。
即使在可安全探索的环境中,如果存在代价无界的路径,也不能保证竞争比有界。在动作不可逆的环境中,很容易发现上述结论,但事实上,可逆情况下也是如此,如图4-20b所示。因此,通常会根据整个状态空间的大小来描述在线搜索算法的性能,而不是仅仅根据最浅层目标的深度。
可观测环境中的在线智能体在每个动作之后都会接收到一个感知,告诉它目前到达了哪一状态,通过这些信息,智能体可以更新它的环境地图。更新后的地图将用于规划下一步。规划和动作交替进行意味着在线搜索算法与之前介绍的离线搜索算法有很大不同:离线算法探索其状态空间模型,而在线算法探索真实世界。例如,A*可以在空间的某部分扩展一个节点,然后马上在空间的另一相距很远的部分扩展另一个节点,因为节点扩展设计的是模拟动作而非真实动作。
另外,在线算法只能找到其实际占据的状态的后继。为了避免长途跋涉到一个相距较远的状态来扩展下一个节点,按照局部顺序扩展节点似乎更好。深度优先搜索恰好具有这一性质,因为(如果算法不用回溯)下一个扩展节点是前一个扩展节点的子节点。
图4-21为在线深度优先探索智能体(动作是确定性但未知的)。智能体将它的地图存储在一个result[s, a]表中,记录了在状态s下执行动作a所产生的状态。(对于非确定性动作,智能体可以在results[s, a]中记录状态集合。)只要当前状态存在未探索过的动作,智能体就会尝试其中一个动作。当智能体尝试完某个状态下的所有动作时,问题就来了。在离线深度优先搜索中,我们只是将状态从队列中删除;而在线搜索中,智能体必须在物理世界中回溯。在深度优先搜索中,这意味着回溯到智能体进入当前状态前的最近状态。为了实现这一点,算法需要维护另一个表,表中列出了每个状态尚未回溯到的前驱状态。如果智能体已经没有可回溯的状态,那么搜索就完成了。
图4-21 使用深度优先探索的在线搜索智能体。智能体只有在每个动作都可以被其他动作“撤消”的状态空间中才能安全地探索
我们建议读者在求解图4-19中的迷宫问题时跟踪Online-DFS-Agent的进度。很容易看到,最坏情况下,智能体最终恰好要遍历状态空间中的每个连接两次。对探索来说,这是最优的;但是,对寻找目标来说,如果在初始状态旁边恰好有一个目标状态,智能体的竞争比将变得无限差。在线迭代加深算法可以解决这一问题;对于均衡树环境,这样一个智能体的竞争比是一个很小的常数。
由于其回溯方法,Online-DFS-Agent只在动作可逆的状态空间中有效。在一般的状态空间中,有一些更复杂的算法,但是这类算法的竞争比都不是有界的。
与深度优先搜索一样,爬山搜索在节点扩展上也有局部性。事实上,因为爬山搜索在内存中只保存一个当前状态,它已经是在线搜索算法!遗憾的是,基础算法并不适用于探索,因为智能体会陷入局部极大值而无路可走。此外,不能使用随机重启,因为智能体无法将自己瞬移到一个新的初始状态。
相比于随机重启,我们可以考虑使用随机游走(random walk)来探索环境。随机游走只是从当前状态中随机选择一个可用动作,可以优先考虑尚未尝试的动作。容易证明,当空间有限且可安全探索时,随机游走最终会找到一个目标或完成探索。[9]但是,这一过程可能非常慢。图4-22为一个环境实例,在这个环境中,随机游走将耗费指数级的步骤来寻找目标,因为对于第一行除S之外的每个状态,后退的可能性是前进的两倍。当然,这个例子是人为设计的,但是真实世界中许多状态空间的拓扑结构都会导致这类随机游走“陷阱”。
[9] 随机游走在无限的一维和二维网格上是完备的。在三维网格上,游走返回起点的概率只有大约0.3405(Hughes, 1995)。
图4-22 环境实例,随机游走需要耗费指数级的步骤来寻找目标
事实证明,增加爬山法的内存而非随机性是一种更有效的方法。基本思想是,存储从已访问的每个状态出发到达目标所需代价的“当前最佳估计”H(s)。H(s)开始时只是启发式估计,然后根据智能体在状态空间中获得的经验不断更新。
图4-23为一维状态空间中的一个简单示例。在图4-23a中,智能体似乎陷入了位于红色状态的局部极小值。智能体不应该停留在原地,而应该根据其邻居节点的当前代价估计值选择到达目标的最优路径。经由邻居节点s'到达目标的估计代价等于到达s'的代价加上从s'到达目标的估计代价,即c(s, a, s') + H(s')。在这个示例中,有2个动作,估计代价分别为向左1 + 9,向右1 + 2,因此最好向右移动。
在图4-23b中,显然,将图4-23a中红色状态的代价估计为2是过于乐观的。因为最佳移动的代价为1,而且其结果状态离目标状态至少还有2步,所以红色状态离目标一定至少还有3步,所以应该相应地更新红色状态的H,如图4-23b所示。继续上述过程,智能体将再来回移动两次,每次都会更新H并“拉平”局部极小值,直到它逃逸到右侧。
能够实现上述方案的智能体称为实时学习A*(learning real-time A*,LRTA*)智能体,如图4-24所示。同Online-DFS-Agent一样,它用result表构建环境地图。它首先更新刚刚离开的状态的代价估计值,然后根据当前的代价估计值选择“显然最佳”移动。一个重要的细节是,在状态s下尚未尝试的动作总是被假定为以最少的可能代价,即h(s)直接到达目标。这种不确定性下的乐观主义(optimism under uncertainty)鼓励智能体去探索新的、可能更有希望的路径。
图4-23 一维状态空间上LRTA*的5次迭代。每个状态都标有H(s),即到达目标的当前代价估计值,每个连接的动作代价为1。红色状态表示智能体的位置,每次迭代所更新的代价估计值以双圈标记
图4-24 LRTA*-Agent根据相邻状态的值选择动作,智能体在状态空间中移动时更新状态值
LRTA* 智能体保证在任何有限的、可安全探索的环境中都能找到目标。然而,不同于A*,LRTA*在无限状态空间中是不完备的——在某些情况下,它可能被无限地引入歧途。在最坏情况下,探索状态数为n的环境可能需要O(n2)步,但通常情况下会比这种情况好得多。LRTA* 智能体只是一个庞大的在线智能体家族中的一员,可以通过以不同方式指定动作选择规则和更新规则来定义。我们将在第22章中详细讨论这一发源于随机环境的在线智能体家族。
在线搜索智能体初始时对环境的无知为我们提供了一些学习的机会。首先,智能体通过记录它们的每一次经验来学习环境“地图”——更准确地说,学习每种状态下每个动作的结果。其次,当智能体以正确的方式探索状态空间时,局部搜索智能体可以利用局部更新规则获得每个状态代价更准确的估计值。一旦知道代价的准确值,只需移动到代价最低的后继状态就能实现最优决策,也就是说,纯粹的爬山法就是一个最优策略。
如果按照我们的建议在图4-19的环境中跟踪Online-DFS-Agent的行为,你会注意到智能体不是非常聪明。例如,在它已经知道Up动作能够从(1, 1)到达(1, 2)后,它仍然不知道Down动作能回到(1, 1),或者Up动作还能从(2, 1)到(2, 2),从(2, 2)到(2, 3),等等。一般来说,我们希望智能体能够学到,Up在不遇到墙的情况下使得y坐标值增加,Down则使得y坐标值降低,等等。
要实现这一点,我们需要做两件事。首先,需要对这类一般规则有一个形式的、可显式操纵的表示;到目前为止,信息都被隐藏在名为Result函数的黑盒中。第8~11章将专门讨论这个问题。其次,需要能够根据智能体所得到的具体观测信息构造合适的一般规则的算法。这些内容将在第19章中讨论。
如果我们预计将来会被要求求解多个类似问题,那么投入时间(和内存)使得这些未来搜索更容易是有意义的。有几种方法可以做到这一点,它们都属于增量搜索(incremental search)的范畴。我们可以将搜索树保留在内存中,并复用在新问题中未发生改变的部分。我们可以保留启发式代价函数h的值,并在获得新信息时更新它们——要么是因为世界发生改变,要么是因为我们计算出了更好的估计值。或者我们可以保留最优路径的g值,用它们拼凑出一个新的解,并在世界发生改变时对它们进行更新。
本章讨论了部分可观测的、非确定性的、未知的和连续的环境中问题的搜索算法。
● 局部搜索算法,如爬山法,在内存中只保留少量状态。这些方法已被应用于优化问题,其思想是找到一个高分值的状态,而不考虑进入该状态的路径。研究人员已经开发了一些随机局部搜索算法,包括模拟退火,当给定适当的冷却方案时它能返回最优解。
● 许多局部搜索方法同样适用于连续空间中的问题。线性规划和凸优化问题服从状态空间形状和目标函数性质上的某些限制,并且允许多项式时间算法,这些算法在实践中往往非常高效。对于一些数学上合式的问题,我们可以使用微积分找到梯度为零的最大值;对于其他问题,我们必须使用经验梯度,即测量两个邻近点间的适应度差值。
● 进化算法是一种维护状态种群的随机爬山搜索。通过突变和杂交(结合状态对)产生新状态。
● 在非确定性环境中,智能体可以应用与或搜索算法生成应变规划,无论执行过程中出现何种结果,它都能实现目标。
● 如果环境是部分可观测的,信念状态表示智能体可能位于的可能状态的集合。
● 标准搜索算法可以直接应用于信念状态空间求解无传感器问题,而信念状态与或搜索算法可以求解一般的部分可观测问题。在一个信念状态中逐状态构造解的增量算法通常效率更高。
● 探索问题发生在智能体对环境的状态和动作一无所知时。对于可安全探索的环境,在线搜索智能体能够构建地图并找到目标(如果存在的话)。根据经验来更新启发式估计值提供了一种避免局部极小值的有效方法。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们将探索有其他智能体计划与我们对抗时的环境。
在本章中,我们将讨论竞争环境(competitive environment),在这种环境中,两个或两个以上的智能体具有互相冲突的目标,这引出了对抗搜索(adversarial search)问题。我们将专注于讨论博弈[1],如国际象棋、围棋和扑克,而不是处理真实世界中的混乱冲突。对人工智能研究人员来说,这些博弈的简化特性是一个优势:博弈状态很容易表示,智能体通常仅能执行少数几个动作,而且动作的效果由明确的规则定义。对于体育比赛(如槌球和冰球),描述更加复杂,可能动作的范围更大,而且定义动作合法性的规则也不够明确。除足球机器人外,体育比赛并没有引起人工智能社区的很大兴趣。
[1] 对应英文game在博弈论中译为“博弈”,但在本书中不同语境下会根据具体情况使用博弈、游戏、比赛等。——译者注
对于多智能体环境,我们至少可以有3种观点。第一种观点适用于智能体数量非常大的情况,即把它们看作一个经济(economy)整体来考虑,这让我们可以做出例如“需求增长会导致价格上涨”这样的预测,而不需要预测任何个体智能体的动作。
第二种观点是,我们可以认为对抗智能体只是环境的一部分——这一部分让环境变成非确定性的。但如果我们以对雨建模一样的方式(例如,雨有时下,有时不下)对对手进行建模,我们就会忽略对手正在积极地尝试击败我们这一事实,而雨没有这样的意图。
第三种观点是用对抗博弈树搜索技术显式地对对抗智能体建模。这就是本章所涵盖的内容。我们从一类受限的博弈开始,定义最优移动并寻找最优移动的算法——极小化极大搜索(minimax search),它是与或搜索的一种推广(见图4-11)。我们指出,剪枝(pruning)通过忽略搜索树中对最优移动没有影响的部分来提高搜索效率。对于非平凡博弈,我们通常没有足够的时间以确保找到最优移动(即使使用剪枝),我们不得不在某个时刻停止搜索。
对于每一个我们选择在那里停止搜索的状态,我们都需要知道谁是获胜者。要回答这个问题,有一个选择:可以基于状态特征应用启发式评价函数来估计谁是获胜者(5.3节),或者可以从该状态开始快速模拟至博弈结束,再取多次模拟结果的平均值(5.4节)。
5.5节讨论了包含机会因素(通过掷骰子或洗牌)的博弈,5.6节讨论了不完美信息(imperfect information)博弈(如扑克和桥牌,即并非所有牌对所有玩家都可见)。
人工智能领域中最常研究的博弈(例如国际象棋和围棋)是博弈论学者所称的确定性、双人、轮流、完美信息(perfect information)的零和博弈(zero-sum game)。“完美信息”是“完全可观测”的同义词[2],“零和”意味着对一方有利的东西将对另一方同等程度有害:不存在“双赢”结果。在博弈论中,我们通常用移动(move)作为“动作”(action)的同义词,用局面(position)作为“状态”(state)的同义词。
[2] 对应英文player在博弈论中为“参与者”,但在本书中不同语境下会根据具体情况使用参与者、玩家、选手等。——译者注
我们将两个参与者[3]分别称为max和min,这么命名的原因稍后解释。max先移动,然后两个参与者轮流移动,直到博弈结束。博弈结束时,获胜者得分,而失败者受到惩罚。可以使用以下元素对博弈进行形式化定义。
[3] 一些作者对此进行了区分,用“不完美信息博弈”指扑克之类的游戏,其中玩家将获得其他玩家没有的关于自己手牌的私人信息,而用“部分可观测博弈”指《星际争霸II》之类的游戏,其中每个玩家可以看到其附近的环境,但看不到远处的环境。
● S0:初始状态,指定博弈开始时如何设置。
● To-Move(s):在状态s下,轮到其移动的参与者。
● Actions(s):在状态s下,全体合法移动的集合
● Result(s, a):转移模型,定义状态s下执行动作a所产生的结果状态。
● Is-Terminal(s):终止测试(terminal test),博弈结束时返回真,否则返回假。博弈结束时的状态称为终止状态(terminal state)。
● Utility(s, p):效用函数(也称为目标函数或收益函数),定义博弈结束时终止状态s下参与者p得到的最终的数值收益。在国际象棋中,结果为赢、输或平局,收益分别为1、0或1/2。[4]一些博弈存在更大范围的可能结果,例如,西洋双陆棋的收益范围为0~192。
[4] 国际象棋被认为是一种“零和”游戏,尽管两个选手每局游戏的结果之和为+1,而不是0。“常量和”是一个更准确的术语,但“零和”更传统,你可以将其看作每个选手被收取了1/2的入场费。
同第3章一样,初始状态、Actions函数和Result函数定义了状态空间图(state space graph)——在图中,顶点表示状态,边表示移动,一个状态可以通过多条路径到达。如第3章所述,我们可以在图的一部分上叠加搜索树(search tree)以确定下一步移动。我们将完整的博弈树(game tree)定义为搜索树,它会记录每个一直到终止状态的移动序列。如果状态空间本身是无界的,或者博弈规则允许局面可以无限次重复,那么博弈树可能是无限的。
图5-1为井字棋(圈叉游戏tic-tac-toe)的部分博弈树。从初始状态开始,max有9种可能的移动。游戏交替进行,max放x,min放o,直到到达对应于终止状态的叶节点,即一个玩家占据某一行,或者所有方格都被填满。每个叶节点上的数字是对max来说该终止状态的效用值,值越高对max越有利,对min越不利(这也是玩家名字的由来)。
对井字棋来说,博弈树相对较小——不超过9!= 362 880个终止节点(只有5478个不同状态)。但是对国际象棋来说,节点数超过1040,所以博弈树被认为是一个在物理世界中无法实现的理论结构。
图5-1 井字棋的(部分)博弈树。最上面的节点是初始状态,max先移动,在某个空位上放一个x。我们展示了树的一部分,给出min(o)和max(x)的交替移动,直到最终到达终止状态,根据博弈规则为终止状态分配效用值
max想要找到通往胜利的动作序列,但min不希望max获胜。这意味着max的策略必须是一个条件规划——一个随机应变策略,指定对min的每个可能移动的响应。在具有二元结果(赢或输)的博弈中,我们可以使用与或搜索(4.3.2节)生成条件规划。事实上,对于这类博弈,博弈的获胜策略的定义与非确定性规划问题的解的定义相同:在这两种情况下,无论“另一方”做什么,都必须保证己方能获得理想结果。对于具有多个结果分数的博弈,我们需要一种更一般的算法,即极小化极大搜索。
考虑图5-2中的简单博弈。根节点上max的可能移动被标记为a1、a2和a3。min对a1的可能响应为b1、b2、b3等。这个特殊游戏在max和min各移动一次后结束。(注意,在某些游戏中,“move”一词意味着双方都执行了一次移动,因此,ply一词被用来明确表示一个玩家的一次移动,即我们在博弈树中又深入了一层。)博弈中终止状态的效用值范围为2~14。
图5-2 二层博弈树。△节点为“max节点”,即轮到max移动,节点为“min节点”。终止节点显示max的效用值,其他节点标记有它们的极小化极大值。max在根节点的最佳移动是a1,因为它指向极小化极大值最高的状态,而min的最佳响应是b1,因为它指向极小化极大值最低的状态
给定博弈树,可以通过计算树中每个状态的极小化极大值(minimax value)确定最优策略,记为Minimax(s)。某一状态的极小化极大值是指,假设从该状态到博弈结束两个参与者都以最优策略行动,到达的终止状态对于max的效用值。终止状态的极小化极大值就是它的效用值。在非终止状态下,轮到max移动时,max倾向于移动到极小化极大值最大的状态,而min倾向于移动到极小化极大值最小的状态(对max来说值最小,因此对min来说值最大)。所以有:
让我们将上述定义应用于图5-2中的博弈树。底层的终止节点从Utility函数中获取它们的效用值。第一个min节点,标记为B,存在3个后继状态,值分别为3、12和8,因此它的极小化极大值为3。类似地,另外两个min节点的极小化极大值都为2。根节点为max节点,它的后继状态的极小化极大值分别为3、2和2,因此,它的极小化极大值为3。我们还可以在根节点处确定极小化极大决策(minimax decision):动作a1是max的最优选择,因为它指向极小化极大值最大的状态。
max的最优策略假设min也是按照最优策略动作。如果min不按照最优策略动作呢?那么max至少会表现得与它面对最优对手时一样好,甚至可能更好。然而,这并不意味着,面对次优对手时选择极小化极大最优移动总是最好的。考虑这样一种情况,双方均按照最优策略行动,结果为平局,但max有一种冒险的走法,在这种走法导致的状态下,min有10种可能的响应,这些响应似乎都是合理的,但其中9种都会使min输掉游戏,只有1种会使max输掉游戏。如果max认为min没有足够的计算能力找到最优移动,那么max可能会尝试这种冒险的走法,因为9/10的获胜机会要比一个确定的平局好。
现在我们来计算Minimax(s),我们可以将其转化为一个搜索算法,即尝试所有动作然后选择其结果状态的Minimax值最大的动作作为max的最佳移动。算法如图5-3所示。这是一种递归算法,它一直向下进行到叶节点,然后随着递归的展开通过搜索树倒推极小化极大值。例如,图5-2中的算法,首先递归到左下角的3个节点,并对它们调用Utility函数,发现它们的值分别为3、12和8。然后选择其中的最小值,3,并将其返回,作为节点B的倒推值。同理可得,C和D的倒推值都为2。最后,我们选择3、2和2中的最大值3作为根节点的倒推值。
极小化极大算法对博弈树进行完整的深度优先探索。如果树的最大深度为m,并且在每个点都有b种合法移动,那么极小化极大算法的时间复杂度为O(bm)。对于一次生成所有动作的算法,空间复杂度为O(bm),对于一次只生成一个动作的算法,空间复杂度为O(m)(见3.4.3节)。指数级的复杂度使得Minimax无法应用于复杂博弈。例如,国际象棋的分支因子约为35,平均深度约为80层,搜索个状态显然是不可行的。然而,Minimax确实是对博弈进行数学分析的基础。通过以各种方式近似极小化极大分析,我们可以推导出更实用的算法。
图5-3 使用极小化极大计算最优移动的算法。最优移动是指,在假定对手移动是为了使效用值最小的前提下,使终止状态效用值最大的移动。函数Max-Value和Min-Value遍历整个博弈树直到叶节点,以确定每个状态的倒推值以及如何移动以到达该状态
许多流行游戏都允许多个玩家参与。让我们来看看如何将极小化极大思想推广到多人博弈中。从技术角度来看,这很自然,但是也产生了一些有趣的新的概念上的问题。
首先,我们需要将每个节点的单一值替换为值向量。例如,在玩家A、B和C参与的3人博弈中,每个节点都与一个向量相关联。对于终止状态,这一向量表示每个玩家各自在该状态得到的效用值。(在双人零和博弈中,二元向量可以简化为一个值,因为两个值总是互为相反数。)最简单的实现方法是让Utility函数返回效用值向量。
现在我们要考虑非终止状态。考虑图5-4的博弈树中标为X的节点。此时,轮到玩家C选择如何移动。两种选择产生了效用值向量分别为和
的两种终止状态,因为6大于3,所以C应该选择第一种移动。这意味着,如果到达状态X,后续的博弈将产生效用值为
的终止状态。因此,这个向量就是X的倒推值。一般地,节点n的倒推值是对在该点进行选择的玩家来说效用值最大的后继状态的效用值向量。
任何参与多人博弈(如Diplomacy或Settlers of Catan游戏)的参与者都会很快意识到,比起双人博弈,多人博弈要复杂得多。多人博弈通常涉及参与者之间的正式或非正式联盟(alliance)。联盟会随着博弈的发展建立和瓦解。我们如何理解这种行为?联盟是多人博弈中每个参与者都按照最优策略行动的自然结果吗?事实证明的确如此。
例如,假设现在A和B处于弱势,而C处于强势。那么,对A和B来说,最理想的做法往往是一起攻击C,而不是彼此攻击,以免C对它们逐个消灭。这样的话,合作其实产生于纯粹的自私行为。当然,一旦C在联合攻击下被削弱,联盟就失去了价值,A或B都有可能违反协议。
图5-4 三人博弈的博弈树的前三层,3个玩家为A、B、C。每个节点都标有3个玩家各自的效用值。最佳移动标示在根节点上
在某些情况下,显式联盟只是将无论如何都会发生的事情具体化。而在其他情况下,破坏联盟会被记录为社会污点,所以参与者必须权衡破坏联盟所带来的即时优势和失去信任所造成的长期劣势。有关这些复杂问题的更多讨论,详见18.2节。
如果博弈不是零和博弈,那么在只有两个参与者时,合作也可能发生。例如,假设存在一个效用值为的终止状态,并且每个参与者最高的可能效用值也是1000。那么最优策略是双方都尽一切可能到达该状态,也就是说,参与者会自动合作以实现共同的期望目标。
博弈的状态数关于树的深度是指数量级的。没有一种算法可以完全消除指数项,但有时可以将它减半,即通过剪枝(见3.5.3节)消除对结果没有影响的树的大部分,从而不需要检查所有状态就能计算出正确的极小化极大决策。这种技术称为剪枝(alpha-beta pruning)。
再次考虑图5-2中的双层博弈树。让我们再进行一次最优决策的计算,这一次要仔细观察在这个过程中的每个点上都获得了什么信息。步骤如图5-5所示。结果是,我们可以在无须评估其中两个叶节点的情况下就能确定极小化极大决策。
另一种考虑这一问题的方式是将Minimax公式简化。假设图5-5中节点C的两个未评估的后继节点的值分别为x和y,则根节点的值为
也就是说,根节点的值以及极小化极大决策与叶节点x和y的值无关,因此可以将它们剪枝。
剪枝可以应用于任何深度的树,而且通常可以将整个子树而不只是叶节点剪枝。一般原则是:考虑树中某个位置的节点n(见图5-6),玩家可以选择移动到n。如果玩家在树中同一层(如图5-6中的m')或更上层的任何位置(如图5-6中的m)有更好的选择,那么玩家永远都不愿移动到n。所以,一旦我们对n有了足够的了解(通过检查它的某些后继)来得出上述结论,就可以将它剪枝。
图5-5 图5-2中博弈树的最优决策计算过程。每一步都标有每个节点可能的值的范围。(a)B下面的第一个叶节点值为3。因此,作为min节点,B的值最多为3。(b)B下面的第二个叶节点值为12,min将避免移动到该节点,所以B的值仍然最多为3。(c)B下面的第三个叶节点值为8,此时我们已经检查完了B的所有后继状态,所以B的值就是3。现在我们可以推断根节点的值至少是3,因为max在根节点处有值为3的选择。(d)C下面的第一个叶节点值为2。因此,作为min节点,C的值最多为2。但是我们知道B的值为3,所以max永远不会选择C。因此,没有必要再去检查C的其他后继状态。这是剪枝的一个实例。(e)D下面的第一个叶节点值为14,所以D的值最多为14。这仍然高于max的最佳选择(即3),所以我们需要继续探索D的后继状态。注意,此时根节点的所有后继都有界,所以根节点的值也最多为14。(f)D的第二个后继值为5,所以我们又需要继续探索。第三个后继值为2,所以D的值就是2。最终,max在根节点处的决策是移动到值为3的节点B
图5-6 剪枝的一般情况。如果对玩家来说m或m'要好于n,那么我们永远都不会在博弈中到达n
记住,极小化极大搜索是深度优先的,所以在任何时候我们只需考虑树中单个路径上的节点。剪枝得名于Max-Value(state,
,
)(见图5-7)中的两个额外参数,它们分别是路径上任何位置的倒推值的下界和上界。
= 到目前为止,路径上发现的max的任一选择点中最佳(即最大值)选择的值。也就是 说,
= “至少”。
= 到目前为止,路径上发现的min的任一选择点中最佳(即最小值)选择的值。也就是 说,
= “至多”。
搜索不断更新
和
的值,并且一旦当前节点的值比此时的
(对于max)或
(对于min)值更差,就剪掉该节点的剩余分支(即终止递归调用)。完整算法如图5-7所示。图5-5跟踪了博弈树上的算法进程。
图5-7 搜索算法。注意,这些函数与图5-3中的Minimax-Search函数相同,除了需要维护变量
和
,以及在值超出边界时截断搜索
剪枝的有效性很大程度上依赖于状态的检查顺序。例如,在图5-5e和图5-5f中,根本不能剪掉D的任何后继,因为最差的后继(从min的角度来看)是最先生成的。如果最先生成D的第三个后继,它的值为2,那么我们就可以剪掉另外两个后继。这表明,应该先检查有可能是最佳选择的后继节点。
如果能够完美地实现这一点,搜索算法只需要检查
个节点就能选出最佳移动,而极小化极大算法需要O(bm)。这意味着有效分支因子从b变为了
,对国际象棋来说,大约从35变为了6。换句话说,在相同时间内,拥有完美移动顺序的
剪枝可以求解的树的深度大约是极小化极大算法的两倍。如果移动顺序随机,对于适当大小的b,需要检查的节点总数约为
。显然我们现在无法实现完美移动顺序,否则,在这种情况下,可以用排序函数玩一个完美的游戏!但通常我们可以非常接近完美。对国际象棋来说,一个非常简单的排序函数(例如,先尝试吃子,然后是威胁,再后是前进和后退)就能让检查的节点数减少到不超过最好情况
的大约2倍。
增加动态的移动排序方案,例如先尝试之前发现的最佳移动,能让我们非常接近理论极限。“之前”可能指上一次移动(通常面临同样的威胁),也可能来自之前通过迭代加深(见3.4.4节)过程对当前移动的探索。首先,搜索一层并根据它们的评估结果记录这些移动的排名。然后再深入搜索一层,利用之前的排名指导移动顺序,以此类推。由于迭代加深过程而增加的搜索时间可以通过更好的移动顺序来弥补。这些最佳移动称为绝招(killer move),首先尝试绝招称为绝招启发式评价函数。
在3.3.3节中,我们指出通往重复状态的冗余路径会导致搜索代价呈指数级增长,而维护一个先前到达状态的表可以解决这个问题。在博弈树搜索中,重复状态的产生是由于换位(transposition)——移动序列的不同排列最终导致相同的局面,这个问题可以通过换位表(transposition table)解决,它将缓存状态的启发式值。
例如,假设白方进行了移动w1,而黑方用b1应对,在棋盘的另一边有一个不相关的移动w2,黑方可以用b2应对,我们搜索移动序列[w1, b1, w2, b2],将其结果状态记为s。在探索了s下面一棵较大的子树之后,我们找到了它的倒推值,并将其存储在换位表中。当我们之后搜索移动序列[w2, b2, w1, b1]时,我们再次到达s,这时我们可以在表中查找它的值而无须重复搜索。在国际象棋中,换位表非常有效,在相同时间内能到达的搜索深度将扩大一倍。
即使采用剪枝和精巧的移动顺序,极小化极大算法也不适用于国际象棋和围棋这样的游戏,因为在可用时间内仍然有太多状态需要探索。在关于计算机博弈的第一篇论文“Programming a Computer for Playing Chess”(Shannon, 1950)中,克劳德·香农意识到这一问题,并提出了两种策略。A型策略(Type A strategy)考虑搜索树中某一深度的所有可能的移动,然后使用启发式评价函数估计该深度下状态的效用值。它探索了树的宽但浅的部分。B型策略(Type B strategy)舍弃了那些看起来就很差的移动,“尽可能”走那些更有可能的路线。它探索了树的深但窄的部分。
历史上,大多数国际象棋程序都是A型策略(我们将在5.3节讨论),而围棋程序通常是B型策略(将在5.4节讨论),因为围棋的分支因子要高得多。最近,B型程序在各种游戏中都达到了世界冠军级水平,包括国际象棋(Silver et al., 2018)。
为了充分利用有限的计算时间,我们可以提前截断搜索,并对状态应用启发式评价函数,从而有效地将非终止节点转变为终止节点。换句话说,我们用Eval函数代替Utility函数,Eval对状态效用值进行估计。用截断测试(cutoff test)代替终止测试,对于终止状态,截断测试必定返回真,但是它可以根据搜索深度和当前状态的任意属性自由决定何时终止搜索。这样我们得到了搜索深度d处状态s的启发式极小化极大值的计算公式H-Minimax(s, d):
就像第3章的启发式函数返回到目标距离的估计值一样,启发式评价函数Eval(s, p)向参与者p返回状态s的期望效用的估计值。对于终止状态,一定是Eval(s, p) = Utility(s, p),而对于非终止状态,估计值必须介于输和赢之间:。
除了满足这些需求之外,一个好的评价函数是由什么组成的?首先,计算时间不能太长!(重点是加快搜索速度。)其次,评价函数应与实际的获胜机会密切相关。你可能会对“获胜机会”一词感到疑惑。毕竟,国际象棋并不是一种碰运气的游戏:我们确定地知道当前的状态,博弈没有任何随机性;如果双方都没有犯错,结果是预先确定的。但是,如果搜索必须在非终止状态截断,那么算法对这些状态的最终结果必然是不确定的(即使这种不确定性可以通过提供无限的计算资源来解决)。
让我们把这一思想进一步具体化。大多数评价函数需要计算状态的各种特征(feature),例如,在国际象棋中,我们将拥有白兵数目、黑兵数目、白后数目、黑后数目等特征。这些特征合在一起,定义了状态的各种类别或等价类:同一类别中的状态,对所有特征都具有相同值。例如,某一类别包含所有的“两兵对一兵”残局。任何给定类别都可能包含一些通往(以完美玩法)胜利的状态,一些通往平局的状态和一些通往失败的状态。
评价函数不知道到底是处于哪种状态,但它可以返回一个值来估计每个结果的状态比例。例如,假设我们的经验表明,在“两兵对一兵”类中,82%的状态通向胜利(效用值+1),2%导致失败(效用值0),16%为平局(效用值1/2)。那么,该类别中状态的合理评估为期望值(expected value):(0.82×+1) + (0.02×0) + (0.16×1/2) = 0.90。原则上,可以为每一个状态类确定一个期望值,这样我们就得到了适用于任何状态的评价函数。
在实践中,这种方法需要分析太多类别,因此需要非常多的经验去估计所有的可能性。与上述方法不同,大多数评价函数会分别计算每个特征的数值贡献,将它们结合起来得到总数值。几个世纪以来,国际象棋棋手们已经提出了一些使用这一思想评估局面价值的方法。例如,国际象棋入门书籍给出了各个棋子的子力价值(material value)估计:兵值1分,马或象值3分,车值5分,后值9分。其他特征,如“好的兵阵”和“王的安全”可能值半个兵。这些特征值简单地相加即可得到局面的评估值。
数学上,这种评价函数称为加权线性函数(weighted linear function),因为它可以表示为如下形式:
其中fi是局面的某一特征(例如“白象数目”),wi是其权重(表明该特征的重要性)。权重需要归一化,使总和始终保持在输(0)到赢(+1)的范围内。如图5-8a所示,一个兵的确定优势提供了很大的获胜可能性,而3个兵的确定优势则几乎必胜。之前提到,评价函数应与实际的获胜机会密切相关,但并不需要线性相关:如果状态s获胜的可能性是状态s'的两倍,并不意味着Eval(s)必须是Eval(s')的两倍,只需要Eval(s) Eval(s')。
将特征的值相加似乎是合理的,但实际上它涉及一个很强的假设:每个特征的贡献独立于其他特征的值。因此,目前的国际象棋和其他游戏程序也会使用特征的非线性组合。例如,一对象的价值可能比单个象价值的两倍还要大,并且在残局时,象比之前价值更大,即当移动数这一特征很大或剩余棋子数这一特征很小时。
如何得到特征和权重?它们不属于国际象棋规则,而是来自人类下棋的经验。在没有这种经验的游戏中,评价函数的权重可以通过第22章的机器学习技术来估计。将这些技术应用到国际象棋中,结果表明一个象确实相当于大约3个兵,而且似乎几个世纪的人类经验都可以在短短几小时的机器学习中被复制。
图5-8 两个国际象棋局面,只有右下角车的位置不同。在(a)中,黑方有一个马两个兵的优势,这足以取胜。在(b)中,白方将吃掉对方的皇后,这几乎是必胜的优势
下一步是修改Alpha-Beta-Search,让它在合适的时候调用启发式Eval函数截断搜索。我们把图5-7中提到Is-Terminal的两行代码替换为下面这行代码:
我们还必须记录一些信息,这样在每一次递归调用时可以逐渐增加当前的depth。控制搜索量最直接的方法是设置一个固定的深度限制,这样的话,对所有大于固定深度d的depth(以及所有终止状态),Is-Cutoff(state, depth)都返回true。深度d的选择取决于分配时间内所选择的移动。更稳健的方法是使用迭代加深(见第3章)。当时间耗尽时,程序将返回最深的已完成搜索所选择的移动。如果在每一轮迭代加深中,我们都维护换位表中的条目,那么作为奖励,后续轮次的速度将加快,我们可以使用评估值改进移动顺序。
由于评价函数只是一种近似,这些简单方法可能导致误差。重新考虑象棋中基于子力优势的简单评价函数。假设程序搜索到达了深度限制,例如到达图5-8b中的局面,即黑方多了一个马、两个兵。程序会将其报告为该状态的启发式值,从而认为该状态很可能导致黑方获胜。但其实白方下一步就可以不留退路地吃掉黑方的皇后。因此,这个局面实际上对白方有利,但这只有通过向前看才能知道。
评价函数只能应用于静态(quiescent)局面,也就是说,在这些局面中不存在会使评估值大幅度摇摆变化的待定移动(例如吃掉皇后)。对于非静态局面,Is-Cutoff将返回false,并继续搜索直到到达静态局面。这种额外的静态搜索(quiescence search)有时会被进一步限制为只考虑特定类型的移动(例如吃子),它能快速消除当前局面的不确定性。
视野效应(horizon effect)则更难消除。它是指程序面临一个将给我方造成严重损失而且基本无法避免的对方移动,但可以使用拖延战术暂时避开。考虑图5-9中的国际象棋局面。很明显,黑象已经无路可逃。例如,白车可以通过依次移动到h1、a1、a2吃掉黑象,在第6步完成吃子。
但黑方确实可以采取一系列移动,将象被吃掉这一结果推向“视野”以外。假设黑方搜索深度为8层。黑方的大多数出招都会导致象最终被吃掉,因此被标记为“坏招”。但黑棋也会考虑这样的移动序列,即先用兵来阻挡王,引诱王去吃兵。然后黑方可以同样地处理第二个兵。上述过程占用了太多步,在剩余的搜索步数内,象不会被吃掉。黑方自认为这一策略用两个兵保住了象,但实际上它所做的只是白白浪费了兵,象被吃掉是不可避免的,只是被推到了黑方能搜索到的视野之外。
缓解视野效应的一种策略是允许单步延伸(singular extension),该策略是说,即使搜索本应在此状态截断,但是,如果在给定局面中有比其他所有移动都“明显更好”的一种移动,我们就允许算法继续沿着这个移动延伸搜索。在我们的例子中,搜索将发现白车的3次移动——h2到h1,h1到a1,从a1吃掉a2处的象——依次都是明显更好的移动,因此,即使兵的某个移动序列将搜索推到视野之外,这些明显更好的移动将有机会被延伸搜索。这会使树变得更深,但由于单步延伸通常很少,这一策略并不会增加很多节点,在实践中,它已被证明是有效的。
图5-9 视野效应。黑方移动后,黑象注定难逃厄运。但是黑方可以用兵来阻挡白方的王,引诱王去吃掉兵。这会将不可避免的象的损失推到视野之外,因此,搜索算法将牺牲兵的这一步看作“好招”
剪枝将剪掉对最终评估没有影响的树的分支,但前向剪枝(forward pruning)将剪掉那些看上去很糟糕但也可能实际很好的移动。因此,这一策略以出错风险增大的代价节省了计算时间。用香农的话说,这是B型策略。显然,大多数人类棋手都会这么做,仅考虑每个局面的几步移动(至少是潜意识地)。
前向剪枝的一种方法是束搜索(见4.1.3节):在每一层,只考虑一“束”n个最佳移动(根据评价函数),而不是所有可能的移动。遗憾的是,这种方法相当危险,因为无法保证最佳移动不被剪枝。
ProbCut(概率截断,probabilistic cut)算法(Buro, 1995)是搜索的前向剪枝版本,它使用从先前经验中获得的统计数据来减少最佳移动被剪除的概率。
搜索将剪除所有可证明位于当前
窗口之外的节点。ProbCut算法则剪除有可能位于窗口之外的节点。它通过执行浅层搜索计算某个节点的倒推值v,然后利用过去的经验估计树中深度为d的节点的值v位于
范围之外的可能性。布罗(Buro)将这种技术应用到了他的黑白棋程序Logistello,发现即使常规版本的黑白棋程序拥有两倍的可用时间,ProbCut版本依然以64%的获胜率击败了常规版本。
另一种技术,即后期移动缩减(late move reduction)技术,假设移动顺序已经调整好,因此在可能的移动的列表中后期才出现的移动不太可能是好的移动。这一技术没有将后期的移动完全删除,只是减少了搜索这些移动的深度,从而节省了时间。如果缩减后的搜索返回的值高于当前值,我们可以重新运行全深度搜索。
结合本章介绍的所有技术,可以得到一个国际象棋(或其他游戏)程序。我们假设,已经实现了一个国际象棋评价函数——一个使用静态搜索的合理截断测试。我们还假设,经过几个月的努力,可以在最新的个人计算机上每秒生成并评估大约100万个节点。国际象棋的分支因子平均约为35,而355约等于5000万,因此,如果我们使用极小化极大搜索,在大约1分钟的计算时间内只能向前搜索5层。按照比赛规则,我们没有足够的时间去搜索第6层。平均水平的人类棋手就可以击败这样的程序,因为他们偶尔会向前规划6~8步。
通过搜索和大型换位表,我们可以向前搜索大约14层,已经到达了专家级水平。我们可以将个人计算机换成一台拥有8个GPU的工作站,每秒可以计算超过10亿个节点,但如果要达到大师级水平,还需要一个经过精心调整的评价函数和一个存储残局招式的大型数据库。像Stockfish这样的顶级国际象棋程序拥有所有这些功能,它在搜索树中通常能达到超过30的深度,远远超过任何一个人类棋手的能力。
对一个国际象棋程序来说,开局就考虑一个包含10亿个博弈状态的树似乎有些过犹不及:漫长的搜索得出的结论仅仅是将兵放到e4(最常见的第一步)。一个世纪以来,许多国际象棋书籍都介绍了如何下好开局和残局(Tattersall, 1911)。因此,许多游戏程序使用查表而非搜索来处理开局和残局也就不足为奇了
对于开局,计算机主要依靠人类的专业知识。可以从书中复制人类专家关于如何打好每个开局的最佳建议并将其输入表中供计算机使用。此外,计算机还可以从以前玩过的游戏的数据库中收集统计数据,以判断哪种开局最容易取胜。最开始的几步可能的局面很少,大多数局面都能存储在表中。通常,移动10~15步后,我们会到达一个很少见到的局面,程序必须从查表切换到搜索。
在游戏接近结束时,可能的局面又变少,因此更容易查表。这是计算机的专长:计算机对残局的分析能力远远超过了人类。新手玩家按照一些简单的规则就能在王、车对王(KRK)残局中获胜。而其他残局,例如王、象、马对王(KBNK),则很难掌握,也不存在简明的策略。
另外,计算机可以通过生成一种策略完全解决残局问题,这一策略是从每种可能状态到该状态下最佳移动的映射。这样计算机就可以在这个表中查到正确移动从而完美完成棋局。这个表由逆向(retrograde)极小化极大搜索构建:首先考虑在棋盘上放置KBNK的所有方法。有些局面是白方获胜,将它们标为“赢”。然后反转国际象棋规则,做逆向移动。无论黑方的应对是什么,白方的任何一步最终位于“赢”局面的移动,都标为“赢”。继续上述搜索,直到所有可能局面都被解析为赢、输或平局,这样就得到了一个包含所有KBNK残局的准确无误的查询表。这种做法不仅适用于KBNK残局,也适用于所有棋子数不超过7的残局,这样的表格包含400万亿个状态。棋子数为8的表则包含40 000万亿个状态。
对围棋来说,启发式树搜索有两个主要缺点:首先,围棋的分支因子开始时为361,这意味着
搜索被限制在4~5层。其次,很难为围棋定义一个好的评价函数,因为子力价值并不是一个强有力的指标,而且大多数状态直到最后阶段都在不断变化。为了应对这两个挑战,现代围棋程序已经放弃了
搜索,而是使用一种称为蒙特卡罗树搜索(Monte Carlo tree search,MCTS)的策略。[5]
[5] “蒙特卡罗”算法是以摩纳哥蒙特卡罗赌场命名的随机算法。
基本的MCTS策略不使用启发式评价函数。相反,状态值是根据从该状态开始的多次完整博奕模拟(simulation)的平均效用值估算的。一次模拟(也被称为一个playout或rollout)先为一个参与者选择移动,接着为另一个参与者选择,重复上述操作直到到达某个终止局面。这时,博弈规则(而非不可靠的启发式)决定输赢以及比分。对于那些只有输赢两种结果的博弈,“平均效用值”为“获胜百分比”。
在模拟中我们如何选择要采取的移动?如果只是随机选择,那么多次模拟之后,我们仅能得到“如果两个参与者都随机选择,那么最佳移动是什么?”这一问题的答案。对于一些简单游戏,这恰好与“如果两名参与者都玩得很好,那么最佳移动是什么?”的答案相同,但对大多数游戏却并非如此。为了从模拟中获得有用信息,我们需要一个模拟策略(playout policy),使其偏向于好的行动。对围棋和其他游戏来说,人们已经使用神经网络成功地从自我对弈中学习到了模拟策略。有时还会根据游戏的不同,使用不同的启发式方法,如国际象棋中的“考虑吃子”,或黑白棋中的“占据角落”。
给定了模拟策略,我们接下来需要决定两件事:从什么局面开始模拟,以及分配给每个局面多少次模拟?最简单的答案是纯蒙特卡罗搜索(pure Monte Carlo search),即从博弈当前状态开始做N次模拟,并记录从当前局面开始哪一种可能移动胜率最高。
对于一些随机游戏,随着N的增加,这一策略会收敛到最优策略,但对大多数博弈来说,这还不够——我们需要一个选择策略(selection policy),有选择地将计算资源集中在博弈树的重要部分上。选择策略需要平衡两个因素以做出更准确的估计:对那些模拟次数很少的状态的探索(exploration),以及对那些在过去的模拟中表现良好的状态的利用(exploitation)。(有关探索/利用权衡的更多信息,请参阅17.3节。)蒙特卡罗树搜索维护一个搜索树,它在每次迭代(包含以下4个步骤)中不断增长,如图5-10所示。
图5-10 使用蒙特卡罗树搜索(MCTS)选择移动的算法的一次迭代,该算法使用“应用于树搜索的置信上界”法(UCT)作为选择度量,此时已完成了100次迭代。(a)选择移动,沿着树一直向下,到标记为27/35(35次模拟中黑方赢了27次)的叶节点结束。(b)扩展所选节点并进行模拟,最终黑方获胜。(c)将模拟结果沿树反向传播
● 选择:从搜索树的根节点开始,选择一个移动(在选择策略的指导下),到达一个后继节点,然后重复该过程,沿着树向下移动到叶节点。图5-10a为一棵搜索树,根表示白方刚刚移动的状态,到目前为止,白方已经在100次模拟中赢了37次。粗箭头表示黑方选择的移动,在它指向的节点上黑方赢了60/79次。这是3种移动中最高的胜率,所以选择它是一次利用。但为了探索,选择2/11节点也是合理的——只有11次模拟,该节点的估值仍有很高的不确定性,如果我们获得更多相关信息,它最终可能是最好的。继续选择直到到达标有27/35的叶节点。
● 扩展:我们通过为所选节点生成一个新的子节点的方式增长搜索树,图5-10b中展示了标记为0/0的新节点。(一些版本在这一步中会生成多个子节点。)
● 模拟:我们从新生成的子节点开始执行一次模拟,根据模拟策略为两个参与者选择移动。这些移动不会记录在搜索树中。在图中,模拟结果为黑方获胜。
● 反向传播:我们现在使用模拟结果自底向上地更新所有搜索树节点。因为这次模拟的结果是黑方获胜,所以黑方节点的获胜次数和模拟次数都会增加,27/35变为28/36,60/79变为61/80。因为白方失败,其节点只增加模拟次数,所以16/53变为16/54,根节点的37/100变为37/101。
我们在固定次数的迭代中重复这4个步骤,或者迭代到所分配的时间耗尽,然后返回模拟次数最多的移动。
一种非常有效的选择策略称为“应用于树搜索的置信上界”,即UCT。它根据称为UCB1的置信上界公式对每个可能的移动排序。(详见17.3.3节。)对节点n来说,公式为
其中U(n)为经过节点n的所有模拟的总效用值,N(n)是经过节点n的模拟次数,Parent(n)是树中n的父节点。因此为利用项,即节点n的平均效用值。带有平方根的项是探索项:分母为N(n),这意味着对只探索过几次的节点来说,这一项的值比较高;分子记录了我们对n的父节点的探索次数,这意味着,如果我们选择n的概率不是0,那么随着计数的增加,探索项会趋于零,最终模拟次数将被分配给平均效用值最高的节点。
C是一个平衡利用和探索的常数。有一种理论认为C应该是,但在实践中,程序员会尝试多个C值,从中选择一个表现最好的。(有些程序则使用一些稍微不同的公式。例如,AlphaZero增加了一个行动概率项,由根据之前的自我对弈训练得到的神经网络计算。)当C = 1.4时,图5-10中60/79节点的UCB1值最高,而当C = 1.5时,2/11节点分值最高。
图5-11给出了完整的UCT MCTS算法。当迭代终止时,算法返回模拟次数最多的移动。你可能认为应该返回平均效用值最高的节点,但算法的思想是获胜65/100次的节点优于获胜2/3次的节点,因为后者有很多不确定性。在任何情况下,UCB1公式确保模拟次数最多的节点几乎总是拥有最高的获胜概率,因为随着模拟次数的增加,选择过程将越来越偏向获胜概率。
图5-11 蒙特卡罗树搜索算法。首先,初始化博弈树tree,然后重复Select/Expand/Simulate/Back-Propagate的循环,直到时间耗尽,最后返回指向模拟次数最多的节点的移动
计算一次模拟结果的时间对博弈树的深度来说是线性的,而不是指数级的,因为在每个选择点上只采用一个移动。这样我们就有足够的时间进行多次模拟。例如,假设有一个分支因子为32的博弈,博弈平均持续100步。如果我们有足够的计算能力可以在执行移动前考虑10亿个博弈状态,那么极小化极大算法可以搜索6层深度,具有完美行动顺序的算法可以搜索12层深度,蒙特卡罗搜索算法可以搜索1000万次模拟。哪种方法更好呢?这取决于所用的启发式函数与选择策略、模拟策略的准确性的高下。
传统观点认为,对于围棋这种分支因子非常高(因此搜索不够深)或者很难定义一个好的评价函数的游戏,蒙特卡罗搜索要优于
搜索。考虑到对手的目标是最小化得分,
搜索将选择指向可实现评价函数得分最高的节点的路径。因此,如果评价函数不准确,
搜索也会不准确。对单个节点的错误计算可能导致
搜索错误地选择(或避开)指向该节点的路径。而蒙特卡罗搜索依赖于多次模拟的聚合,因此不容易受到单次错误的影响。我们也可以将MCTS和评价函数结合起来:对一定数量的移动进行模拟,然后截断模拟,并在截断的节点上应用评价函数。
也可以将搜索和蒙特卡罗搜索结合。例如,在可以持续很多步的博弈中,我们可能希望提前终止模拟(early playout termination),即终止持续太多步的模拟,并使用启发式评价函数对其进行评估,或者干脆宣布平局。
蒙特卡罗搜索可以应用于没有任何经验可以用来定义评价函数的全新博弈。只要我们知道博弈规则,蒙特卡罗搜索不需要任何附加信息。选择和模拟策略可以充分利用人工制定的专家知识,也可以通过仅仅使用自我对弈训练得到的神经网络来学习好的策略。
当单步移动可以改变游戏进程时,蒙特卡罗搜索存在缺陷,因为蒙特卡罗搜索的随机性意味着它可能不会考虑这一移动。换句话说,蒙特卡罗搜索中的B型剪枝意味着它可能根本没有探索关键路线。当博弈状态“明显”是一方或另一方获胜时(根据人类的知识和评价函数),蒙特卡罗搜索也存在缺陷,它仍然需要模拟很多步来验证获胜者。长期以来,人们一直认为,在国际象棋等具有较低分支因子和较好评价函数的游戏中,搜索更好。但最近,蒙特卡罗方法在国际象棋及其他游戏中也取得了成功。
模拟未来的行动,观测结果,并根据结果来确定哪些行动是好的,这样的一般思想其实就是一种强化学习思想,我们将在第22章中介绍。
包含随机因素(例如掷骰子)的随机博弈(stochastic game)使我们更接近现实生活的不可预测性。西洋双陆棋是一种典型的运气和技巧相结合的随机游戏。在图5-12的西洋双陆棋局面中,黑方掷出“6-5”,有4种可能走法[每种走法将一个棋子向前(顺时针)移动5步,另一个棋子向前移动6步]。
图5-12 一个典型的西洋双陆棋局面。游戏的目标是把自己的所有棋子移出棋盘。黑方向25顺时针移动,白方向0逆时针移动。一个棋子可以移动到任何位置,除非那里有多个对方棋子;如果只有一个对方棋子,对方棋子就会被吃掉,然后必须从起点重新开始。图中所示的局面,黑棋已经掷出了6-5,必须从(5−11, 5−10)、(5−11, 19−24)、(5−10, 10−16)和(5−11, 11−16)这4种合法移动中选择,其中符号(5−11, 11−16)表示将一个棋子从位置5移动到位置11,另一个棋子从位置11移动到位置16
此时,黑方知道可以走什么棋,但不知道白方会掷出什么,因此也不知道白方的合法移动会是什么。这意味着黑方无法构建我们在国际象棋和井字棋中看到的那种标准博弈树。西洋双陆棋的博弈树除了max和min节点外,还必须包括机会节点(chance node)。机会节点如图5-13中的圆圈所示。从每个机会节点引出的分支表示可能掷出的骰子点数,每个分支都标有掷出的点数及其概率。两个骰子有36种组合,每一种都是等可能的,但是,因为6-5和5-6是一样的,所以只有21种不同的点数组合。6个点数相同的组合(1-1到6-6)的概率都是1/36,即P(1−1) = 1/36。其他15种不同组合的概率都是1/18。
图5-13 西洋双陆棋局面的博弈树图解
下一步是了解如何做出正确决策。显然,我们仍然想选择能够到达最佳局面的那一步棋。然而,局面没有明确的极小化极大值。我们只能计算局面的期望值(expected value):机会节点所有可能结果的平均值。
可以将确定性博弈的极小化极大值推广为包含机会节点的博弈的期望极小化极大值(expectiminimax value)。终止节点、max节点和min节点的工作方式与之前完全相同(注意,max和min的合法移动取决于前一个机会节点的掷骰子结果)。对于机会节点,我们则计算期望值,即用每个机会动作的概率加权的所有结果的值之和:
其中,r表示可能的掷骰子结果(或其他概率事件),而Result(s, r)仍表示状态s,附加了掷骰子结果r。
和极小化极大算法一样,可以通过在某点截断搜索并对每个叶节点应用评价函数来近似估计期望极小化极大值。有人可能会认为,西洋双陆棋等游戏的评价函数应该与国际象棋的评价函数类似——更好的局面得分更高。但事实上,机会节点的存在意味着我们必须更加仔细地定义这些值。
图5-14表明:如果评价函数给叶节点分配的值为[1, 2, 3, 4],那么移动a1是最佳的;如果值为[1, 20, 30, 400],移动a2是最佳的。因此,如果我们更改一些评估值,即使优先顺序保持不变,程序的选择也会完全不同。
图5-14 在保持叶节点值排序不变的情况下,不同的叶节点赋值改变了最佳移动
为了避免这一问题,评价函数应该返回获胜概率(对于结果非输或赢的博弈返回的是期望效用值)的正线性变换值。这是在不确定性下非常重要和普遍的性质,将在第16章进一步讨论。
如果程序事先知道游戏接下来的所有掷骰子结果,那么求解有骰子的游戏和求解没有骰子的游戏是一样的,即极小化极大算法的时间复杂度为O(bm),其中b为分支因子,m为博弈树的最大深度。因为期望极小化极大值还要考虑所有可能的掷骰子序列,它的时间复杂度为O(bmnm),其中n是掷骰子的不同结果的数目。
即使将搜索深度限制在某个很小的值d内,与极小化极大算法相比,额外代价的存在也使得在大多数机会博弈中向前看很远是不现实的。在西洋双陆棋中,n是21,b通常是20左右,但在某些情况下,骰子数翻倍,b可能高达4000。我们大概只能搜索3层。
换一种方式考虑这一问题:搜索的优势在于,在采取最佳玩法的情况下它忽略了那些未来不可能发生的情况。因此,它将精力集中于可能发生的情况。但在一个每次移动前都要掷两个骰子的游戏中,没有可能的移动序列,即使是最有可能的移动也只在2/36的情况下出现,因为执行移动的前提是,骰子点数是正确的组合从而使该移动合法。这是不确定性下的一个普遍问题:可能性急剧增多,制定详细的动作规划变得毫无意义,因为世界可能不会朝你规划的方向发展。
你可能会想到像剪枝这样的方法也可以应用于包含机会节点的博弈树。事实证明的确可以。对min和max节点的分析不变,但可以用一点聪明才智对机会节点剪枝。考虑图5-13中的机会节点C,以及在计算其子节点时它的值发生了什么变化。在我们检查完C的所有子节点之前是否有可能找到C的上界?(回想一下,这是
剪枝剪除某个节点及其子树时需要的。)
乍一看,这似乎是不可能的,因为C的值是它子节点值的平均,为了计算一组数字的平均值,我们必须查看所有的数字。但如果限制效用函数的可能值的范围,那么就可以得到平均值的范围而不需要查看每一个数字。例如,假设所有效用值都在−2和+2之间,那么叶节点的值是有界的,反过来,我们就可以在不检查所有子节点的情况下为机会节点的值设置上界。
在机会节点分支因子较高的博弈中——考虑Yahtzee这样的游戏,即每回合掷5个骰子——你可能要考虑前向剪枝,即采样少数几个可能的机会分支。或者,你可能想要完全避免使用评价函数,而选择蒙特卡罗树搜索,其中每次模拟都包含随机掷骰子。
博比·费希尔(Bobby Fischer)认为“国际象棋就是战争”,但国际象棋缺少真实战争的一个主要特征——部分可观测性。在《战争之雾》(Fog of War)游戏中,敌人的行踪往往是未知的,除非与他直接接触。因此,战争中常常使用侦察兵和间谍来收集信息,用隐匿处和虚张声势来迷惑敌人。
部分可观测游戏也具有这些特征,因此与前文提到的游戏有本质不同。像《星际争霸》这样的电子游戏尤其具有挑战性,因为它是部分可观测、多智能体、非确定性、动态且未知的。
在确定性部分可观测博弈中,关于棋盘状态的不确定性完全来自无法获知对手做出的选择。这类博弈包括Battleship(每个玩家战舰的放置位置都对敌人隐藏)和Stratego(棋子的位置已知,但种类隐藏)这样的儿童游戏。我们考虑四国军棋(Kriegspiel)游戏,它是国际象棋的部分可观测变体,即完全看不到对方的棋子。其他游戏也有部分可观测版本:幻影围棋、幻影井字棋和Screen Shogi。
四国军棋的规则如下:白方和黑方各自只能看到自己一方的棋子。裁判可以看到所有棋子,他对比赛进行判定并定期向双方宣布。首先,白方向裁判提出合法移动(只要位置上没有黑方)。如果该位置有黑方占位,裁判会宣布移动“非法”,白方不断向裁判提出下一步的走法,直到找到一个合法移动——在这个过程中也了解到了黑方的位置。
一旦提出了一个合法移动,裁判会宣布以下一项或多项内容:如果在X处有吃子则宣布“在X上吃子”,如果黑王被将军,则宣布“被D将军”,其中D是将军的方向,可以是“马”“行”“列”“长对角线”或“短对角线”。如果黑方被将死或陷入僵局,裁判也会宣布;否则,轮到黑方行棋。
四国军棋看起来非常难处理,但人类可以很好地掌握它,计算机程序也开始迎头赶上。回顾4.4节和图4-14中介绍的信念状态的概念——在给定目前为止所有历史感知的情况下,所有逻辑可能的棋盘状态的集合。初始时,白方的信念状态只有一个元素,因为黑方还没有移动。白方下了一步且黑方做出应对后,白方的信念状态就包含了20种局面,因为黑方对白方的任意一种开局都存在20种回应。
在游戏过程中跟踪信念状态正是状态评估问题,4.4.4节中的式(4-6)给出了更新步骤。如果我们把对手看作不确定性的来源,那么可以把四国军棋的状态评估直接映射到4.4节的部分可观测的、非确定性的框架中;也就是说,白方所选移动的Results由白方自身移动带来的(可预测)结果和黑方回应给出的不可预测结果组成。[6]
[6] 有时,信念状态会变得非常大以至于无法仅用棋盘状态列表表示,但我们将暂时忽略这个问题,第7章和第8章将介绍大型信念状态的紧凑表示方法。
给定当前的信念状态,白方可能会问:“我能赢吗?”对于部分可观测游戏,策略的概念会发生改变,我们不需要规定如何回应对手的每个可能移动,而是需要规定如何回应玩家可能接收到的每种可能感知序列。
对四国军棋来说,必胜策略或确保将死(guaranteed checkmate)是指,对于每种可能感知序列和当前信念状态中的每种可能棋盘状态,不管对手如何移动,该策略都会取胜。在这种定义下,对手的信念状态无关紧要——即使对手能看到所有棋子,这一策略也必须奏效。这大大简化了计算。图5-15为KRK(王车对王)残局必胜策略的一部分。在这种情况下,黑方只有一个棋子(王),所以可以通过在单个棋盘上标记黑王的所有可能位置来表示白方的信念状态。
如4.4节中所述,可以将一般的与或搜索算法应用于信念状态空间来寻找必胜策略。4.4.2节提到的增量信念状态算法通常能在中盘找到深度高达9的必胜策略——这远远超过了大多数人类棋手的能力。
除确保将死之外,四国军棋还存在一个在完全可观测游戏中毫无意义的全新概念:概率将死(probabilistic checkmate)。在信念状态中的每一种棋盘状态下,这种将死都要奏效,而概率一词则来源于获胜玩家移动的随机性。要了解它的基本思想,可以考虑只用白王来捉住黑王的问题。通过简单地随机移动,白王最终一定会吃掉黑王,这是因为,即使黑王总是设法逃跑,它也不可能永远都猜对正确的逃跑方向。在概率论的术语中,这一事件以概率1发生。
在这种意义上,KBNK残局——王、象、马对王——一定会赢,白方为黑方提供一个无限的随机选择序列,黑方总是会猜错其中一个,因此暴露自己的位置,然后被将死。另外,KBBK残局的获胜概率是。白方要想获胜,只能移动象(此时这个象不受保护)。如果黑方碰巧在正确的位置上并吃掉了象(如果象是受保护的,那么这步棋就是非法的),游戏就会变成平局。白方可以在一段很长的序列中随机选择一点来走这步险棋,这样会使
减小到一个任意小的常数,但无法将
减小到零。
有时将死策略只对当前信念状态中的某些棋盘状态有效,而对其他状态无效。尝试这种策略可能会成功,导致意外将死(accidental checkmate)。这里的意外是指,如果黑方刚好在特定的位置,白方不会知道自己将会将死对方。(在人类博弈中,大多数将死都是偶然的。)这个想法自然引出了一个问题,给定策略有多大可能获胜,这又引出了一个问题,当前信念状态中的每种棋盘状态有多大可能是真正的棋盘状态。
图5-15 KRK残局必胜策略的一部分,图中为缩减后的棋盘。在初始信念状态中,黑王位于3种可能位置之一。通过一系列探索移动,该策略将黑王的范围缩小到其中一种。将死策略的剩余部分留作习题
人们的第一倾向可能认为当前信念状态中的所有棋盘状态都是等可能的——但这是错误的。例如,考虑黑方走第一步棋后白方的信念状态。根据定义(假设黑方遵循最优策略),黑方一定采取了最优移动,所以由次优移动产生的所有棋盘状态的概率应该为零。
这一论点也不完全正确,因为每个玩家的目标不仅仅是将棋子移动到正确的方格中,还需要最小化对手能掌握的关于自己位置的信息。遵循任何可预测的“最优”策略都能为对手提供信息。因此,在部分可观测博弈中,最佳玩法需要一定随机性。(这也是餐厅卫生检查员进行随机检查的原因。)这意味着他们偶尔要选择一些“本质上”较差的移动——但他们能从不可预测性上获益,因为对手不大可能为防御这些移动做好准备。
从这些考虑来看,似乎只有在给定最优随机策略的情况下,才能计算出当前信念状态中各种棋盘状态的概率;反过来,计算这一策略似乎需要知道棋盘可能处于的各种状态的概率。这个难题可以利用博弈论中均衡解的概念解决,我们将在第17章中进一步探讨。均衡为每个玩家指定了一个最优随机策略。对四国军棋来说,计算均衡的代价太昂贵了。目前,一般四国军棋游戏的有效算法设计是一个开放的研究课题。大多数系统在自己的信念状态空间中执行有限深度的前瞻搜索,而不考虑对手的信念状态。评价函数与完全可观测博弈的评价函数类似,但包含一个新的组成部分,信念状态大小——越小越好!我们将在18.2节的博弈论主题下重新讨论部分可观测博弈。
桥牌、惠斯特牌、红心大战和扑克等纸牌游戏都具有随机的部分可观测性,即无法观测的信息是由随机发牌产生的。
乍一看,这些纸牌游戏似乎很像掷骰子:纸牌是随机分配的,并且决定了每个玩家的可能移动,但所有的“掷骰子”都发生在游戏的开始!尽管将纸牌游戏类比为掷骰子是错误的,但它提出了一种算法:将游戏的开始视为一个机会节点,每一种可能的发牌视为一个结果,然后使用Expectiminimax公式选择最佳移动。注意,在这种方法中,唯一的机会节点是根节点;在那之后,游戏则是完全可观测的。这种方法有时被称为观测力平均,因为它假设,一旦发牌实际发生,游戏对双方都是完全可观测的。尽管这种策略在直观上具有吸引力,但有可能让人误入歧途。考虑下面这个故事。
第一天:道路A通向一桶金子,道路B通向一个岔路口。你可以看到,岔路口左转是两桶金子,右转则会撞上一辆公共汽车。
第二天:道路A通向一桶金子,道路B通向一个岔路口。你可以看到,岔路口右转是两桶金子,左转则会撞上一辆公共汽车。
第三天:道路A通向一桶金子,道路B通向一个岔路口。你知道岔路口的一个分支通向两桶金子,另一个分支会撞上一辆公共汽车。遗憾地是,你不知道哪个分支通向金子。
观测力平均会得出以下推论:第一天,B是正确选择;第二天,B也是正确选择;第三天,情况和第一天或第二天一样,所以B仍然是正确选择。
现在我们可以看出观测力平均为什么会失败:它没有考虑智能体执行行动后所处的信念状态。完全忽略信念状态是不可取的,特别是当其中一种可能性是必死时。因为它假设每种未来状态都自动成为一个完美知识,观测力方法从不选择那些收集信息的行动(例如图5-15中的第一个移动),也不会选择那些向对手隐藏信息或向同伴提供信息的行动,因为它假定对方已经知道这些信息。在扑克游戏中,它永远不会虚张声势(bluff)[7],因为它假设对手知道自己的牌。在第17章中,我们将介绍如何构造算法解决真正的部分可观测决策问题,得到最优均衡策略(见18.2节)。
[7] 虚张声势——即使自己的手牌很差,也要装作很好——是扑克策略的核心部分。
尽管存在上述缺陷,观测力平均仍是一个有效策略,通过一些技巧可以使其更好地发挥作用。在大多数纸牌游戏中,可能的发牌结果数量都相当大。例如,在桥牌中,每个玩家只能看到四手牌中的两手,剩余两手各包含13张牌,所以可能的发牌结果有= 10 400 600种。即使求解一种发牌结果也是相当困难的,所以求解1000万种更是不可能的。处理这样巨大数目的一种方法是抽象(abstraction):将相似的手牌视为相同手牌。例如,手牌中的A和K非常重要,但是4或5就不那么重要了,可以将其抽象。
另一种处理方法是前向剪枝:只考虑一个小随机样本(样本数为N),再次计算Expectiminimax得分。即使是相当小的N (例如100~1000),这种方法也能提供很好的近似值。它也可以应用于确定性博弈,例如四国军棋(在四国军棋中,我们对游戏的可能的状态进行采样,而不是可能的发牌),只要我们有方法估计每个状态的可能性。除了搜索整个博弈树,使用深度截断进行启发式搜索也很有帮助。
到目前为止,我们假设每种发牌结果的可能性相等。对于惠斯特牌和红心大战,这样的假设是有意义的。但是对于桥牌,比赛之前为叫牌阶段,在这个阶段中,每支队伍都会表明它要赢多少。由于玩家是根据自己持有的牌出价,因此其他玩家可以了解到每种发牌结果的概率P(s)。在决定如何玩这手牌时考虑这一点是很难的,原因就像我们在四国军棋的描述中所提到的:玩家在出价时,可能会尽量最小化传达给对手的信息。
计算机在扑克牌上的表现已经超出了人类水平。在为期20天的无限注德州扑克比赛中,扑克程序Libratus与4位世界顶尖的扑克玩家展开较量,并果断地将他们全部击败。因为在扑克中存在很多可能状态,Libratus使用抽象法减少状态空间:它可能会认为手牌AAA72和AAA64是等价的(它们都是“3个A和一些小牌”),并且可能认为赌200美元与赌201美元是一样的。但是Libratus也会监视其他玩家,如果它发现他们正在使用抽象法,它会立即做一些额外的计算填补这个漏洞。总的来说,它在超级计算机上耗费了2500万CPU小时才取得胜利。
Libratus的计算开销(以及AlphaZero和其他系统的开销)表明,预算有限的研究人员可能无法达到世界冠军水平。从某种程度上来说,这是正确的:就像你不能指望在你的车库里用零部件组装出一辆F1冠军赛车一样,拥有超级计算机或专业硬件(如TPU)是有优势的。训练一个系统时尤其如此,但训练也可以通过众包完成。例如,开源LeelaZero系统是AlphaZero的复现,它通过志愿参与者计算机上的自我对弈进行训练。一旦训练完成,实际比赛中的计算需求是适中的。AlphaStar在使用单个GPU的商用台式计算机上赢得了《星际争霸II》比赛,而AlphaZero也可以在这种模式下运行。
计算复杂博弈中的最优决策是非常困难的,因此所有算法都必须做出一些假设和近似。搜索使用启发式评价函数作为近似,而蒙特卡罗搜索计算随机选择的模拟的近似平均值。选择哪种算法在一定程度上取决于每种博弈的特征:当分支因子较高或评价函数难以定义时,首选蒙特卡罗搜索。但这两种算法都存在其基本的局限性。
搜索的一个局限性是它容易受到启发式函数的近似误差的影响。图5-16为一个二层博弈树,极小化极大搜索会选择右边的分支,因为100
99。如果所有的评估值都是精确的,那么这就是正确的选择。但假设每个节点的评估值都有一个独立于其他节点的随机分布的误差,其标准差为s。当s = 5时,实际上71%的情况下是左侧分支更好,当s = 2时,58%的情况下左侧分支更好(因为在这些情况下,右侧分支的4个叶节点之一可能小于99)。如果评价函数中的误差不是独立的,那么发生错误的可能性更大。这是很难避免的,因为我们没有一个很好的兄弟节点值之间依赖关系的模型。
图5-16 启发式极小化极大算法可能出错的二层博弈树
搜索和蒙特卡罗搜索的第二个局限性是,它们都是设计用于计算合法移动的(边界)值的。但有时其中一种移动显然是最佳的(例如,合法移动只有一种),在这种情况下,浪费时间计算它的值是没有意义的——最好是直接选择该移动。更好的搜索算法应该使用节点扩展的效用值的思想,选择效用值高的节点扩展,所谓高效用值的节点是指,有可能导致算法发现一个明显更好的移动。如果没有一个节点扩展的效用值高于它的代价(从时间上考虑),那么算法应该停止搜索并执行一个移动。这不仅适用于存在明显更好移动的情况,也适用于对称情况,在这种情况下,再多的搜索也无法证明一种移动比另一种更好。
这种关于计算该做什么的推理叫作元推理(metareasoning)(关于推理的推理)。它不仅适用于博弈,也适用于任意一种推理。所有计算都是为了做出更好的决策,所有计算都有代价,并且都有可能导致决策质量的一定程度上的改进。蒙特卡罗搜索的确尝试进行元推理,将资源分配给树中最重要的部分,但不是以最优方式。
第三个局限性是搜索和蒙特卡罗搜索都是在单步移动的层级上进行所有推理的。显然,这与人类玩游戏的方式不同:人类可以在更抽象的层级上进行推理,会考虑更高层级的目标(例如,诱捕对方的后),并使用该目标有选择地生成看似合理的规划。在第11章中,我们将学习这种类型的规划,在11.4节中,我们将介绍如何用从抽象表示到具体表示的层次结构进行规划。
第四个问题是能否将机器学习融入博弈搜索过程。早期的游戏程序依靠人类的专业知识人为制定评价函数、开局库、搜索策略和高效技巧。我们才刚刚开始看到像AlphaZero这样的程序(Silver et al., 2018),它依赖于自我对弈的机器学习,而非人类在特定游戏上的专业知识。我们将从第19章开始深入探讨机器学习。
我们探讨了各种各样的博弈,以理解什么是最佳玩法以及如何在实际中玩好游戏,还了解了智能体在任意类型的对抗性环境中应该如何行动。最重要的思想如下。
● 博弈可以由初始状态(棋盘如何设置)、每个状态下的合法动作、每个动作的结果、终止测试(说明什么时候博弈结束)以及应用于终止状态表明输赢和最终比分的效用函数定义。
● 在具有完美信息的离散、确定性、轮流的双人零和博弈中,极小化极大算法可以通过对博弈树的深度优先枚举选出最优移动。
● 搜索算法可以计算出与极小化极大算法相同的最优移动,通过消除可证明与结果无关的子树来提高效率。
● 通常,考虑整个博弈树是不可行的(即使是搜索),所以我们需要在某个点截断搜索,然后应用启发式评价函数估计状态的效用值。
● 蒙特卡罗树搜索(MCTS)则是另一种方法,它不是通过应用启发式函数来评估状态,而是通过将游戏模拟到结束使用游戏规则来判断输赢。因为在模拟过程中选择的移动可能不是最优移动,所以这个过程需要重复多次,对结果求平均值作为评估值。
● 许多游戏程序会预先计算开局和残局的最佳移动表,这样它们就可以直接查表而不用搜索。
● 机会博弈可以通过期望极小化极大算法(极小化极大算法的扩展)来处理,该算法通过计算所有子节点的平均效用值并按每个子节点的概率加权来估计机会节点的平均效用值。
● 在不完美信息博弈中,例如四国军棋和扑克,最佳玩法需要对每个玩家当前和将来的信念状态进行推理。可以通过对缺失信息的每种可能配置上的动作值取平均得到一个简单的近似。
● 在国际象棋、跳棋、黑白棋、围棋、扑克及许多其他游戏中,程序已经彻底击败了人类冠军选手。在一些不完美信息博弈中人类仍然保持优势,如桥牌和四国军棋。在像《星际争霸》和《刀塔2》这样的电子游戏中,程序可以与人类专家媲美,但它们的成功可能一部分要归功于它们可以快速执行许多动作的能力。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们不把状态仅仅当作小黑盒,从而导出新的搜索方法和对问题结构的更深入理解。
第3章和第4章讨论了通过搜索状态空间进行问题求解的思想:状态空间是一个由节点表示状态,边表示动作的图。我们看到,领域特定的启发式算法可以估计从给定状态到达目标的代价,但从搜索算法的角度来看,每个状态都是原子的,即不可分割的——一个没有内部结构的黑盒。对于每个问题,我们需要领域特定的代码来描述状态之间的转移。
在本章中,我们通过对每个状态使用因子化表示(factored representation)来打破黑盒:因子化表示为一组变量,每个变量都有自己的值。当每个变量的值都满足对该变量的所有约束时,问题就解决了。以上述方式描述的问题称为约束满足问题(constraint satisfaction problem,CSP)。
CSP搜索算法利用了状态结构的优势,并且使用通用的而不是领域特定的启发式算法来求解复杂问题。其主要思想是,通过识别违反约束的变量/值组合来一次性消除大部分搜索空间。CSP的另一个优势是可以从问题描述中推导出行动和转移模型。
约束满足问题由3个部分组成,即X、D和C。
● X是变量集合,。
● D是域集合,,每个变量有一个域。
● C是约束集合,用来规定允许的值的组合。
域Di,由变量Xi的一组允许的值组成。例如,布尔变量的域为
。不同变量可以有不同大小的域。每个约束Cj由
对组成,其中scope是该约束中的变量元组,而rel定义了这些值应该满足的关系(relation)。关系可以表示为满足约束的所有元组值的显式集合,或者表示为判断一个元组是否为关系成员的函数。例如,如果X1和X2的域都是{1, 2, 3},那么约束“X1必须大于X2”可以表示为
或
。
CSP要处理变量赋值(assignment)问题,即。不违反任何约束的赋值称为一致(consistent)或合法赋值。完整赋值(complete assignment)是指每个变量都已被赋值;CSP的解(solution)是一致完整赋值。部分赋值(partial assignment)是指某些变量还未赋值,而部分解(partial solution)是一致部分赋值。一般来说,CSP求解是NP完全问题,尽管CSP的一些重要子类已经可以非常高效地求解。
也许你已经逛够了罗马尼亚,现在来看看澳大利亚地图(如图6-1a所示)[1],地图显示了澳大利亚的州和地区,分别是:西澳大利亚州(Western Australia)、北部地区(North Territory)、昆士兰州(Queensland)、新南威尔士州(New South Wales)、维多利亚州(Victoria)、南澳大利亚州(South Australia)、塔斯马尼亚州(Tasmania)、澳大利亚首都直辖区(Australia Capital Territory)。我们的任务是给每个区域涂上红色、绿色或蓝色,要求相邻的两个区域颜色不能相同。[2]为了将其形式化为CSP,我们将图中的区域定义为变量,变量名为各区域的英文名缩写:
[1] 本图系原书原图。
[2] 本书未将澳大利亚首都直辖区作为一个待着色区域,这使该地图着色问题更简洁明晰。——编者注
每个变量的域为集合。约束要求相邻区域颜色不同。由于相邻区域的边界线有9段,所以有9个约束:
这里我们使用缩写。是
的缩写,其中
可以依次完整枚举为:
这个问题有很多可能的解,例如:
将CSP可视化为约束图(constraint graph)非常有用,如图6-1b所示。图的节点对应于问题的变量,图的边连接同一约束中的任意两个变量。
为什么要将问题形式化为CSP呢?第一个原因是CSP可以自然地表示各种问题,将一个问题形式化为CSP通常很容易;第二个原因是多年的研究工作使得CSP求解器快速而高效;第三个原因是相比于原子的状态空间搜索器,CSP求解器可以快速消除大面积搜索空间。例如,一旦我们在澳大利亚问题中选择了,就可以得出结论,它的5个相邻变量都不能取值为blue。不使用约束的搜索过程必须考虑这5个相邻变量的35 = 243种赋值;有了约束,我们只需考虑25 = 32种赋值,计算量减少了87%。
图6-1 (a)澳大利亚的州和地区。对该地图着色可以看作约束满足问题(CSP)。目标是为每个区域分配颜色,使得相邻区域颜色不同。(b)用约束图表示地图着色问题
在原子的状态空间搜索中,我们只能问:这个特定状态是目标状态吗?不是?那么这一个呢?使用CSP,一旦发现某个部分赋值违反了约束,我们可以马上放弃对该部分赋值的进一步改进。此外,我们可以看出为什么某个赋值不是解——可以看出哪些变量违反了约束——从而把注意力集中在关键变量上。因此,许多原子状态空间搜索难以求解的问题形式化为CSP后都可以快速求解。
工厂有很多日常工作调度问题,要满足各种约束。在实践中,使用CSP技术可以求解很多这样的问题。考虑汽车装配调度问题。整个作业由不同任务组成,我们可以将每个任务建模成一个变量,其中每个变量的值为任务开始时间,由整数分钟数表示。约束为“一个任务必须在另一个任务之前完成”(例如,安装车轮必须在安装轮毂盖之前完成)和“一次只能同时执行一定数量的任务”等断言。约束还可以指定任务完成所需的时间。
我们考虑汽车装配的一小部分环节,包括15个任务:安装轮轴(axle)(前、后),固定4个车轮(wheel)(左和右、前和后),拧紧每个车轮的螺母(nuts),固定轮毂盖(cap),并检查(inspect)最终装配。我们可以将任务表示为15个变量:
接着,我们需要表示各个任务间的优先约束(precedence constraint)。当任务T1必须在T2之前完成且任务T1所需时间为d1时,我们将添加一个如下形式的算术约束:
在这个示例中,轮轴必须在车轮安装前到位,安装一个轮轴需要10分钟,所以有
接下来,我们必须固定每个车轮(需要1分钟),拧紧螺母(2分钟),最后安装轮毂盖(1分钟,但暂未表示):
假设有4个工人来安装车轮,但他们必须共用一个工具来辅助安装轮轴。此时我们需要一个析取约束(disjunctive constraint)表示AxleF和AxleB在时间上不能重叠:要么先做AxleF,要么先做AxleB:
这一约束看起来更加复杂,结合了算术约束和逻辑约束。但它仍可以简化为AxleF和AxleB可以取的一组值。
我们还需要说明,检查是最后一项任务,需要3分钟。对于除Inspect外的每个变量,我们都需要添加一个形式的约束。最后,假设我们需要在30分钟内完成整个装配任务。因此,所有变量的域被限制为
这一特定问题的求解非常琐碎,但CSP已经成功地应用于此类具有几千个变量的车间作业调度问题。
最简单的CSP所涉及的变量具有离散有限域(discrete, finite domain)。地图着色问题和带有时间限制的调度问题都属于这类问题。8皇后问题(图4-3)也可以看作是一个有限域CSP,其中变量对应第1~8列中的皇后,每个变量的域为该列皇后可能的行号,
。约束为不允许两个皇后在同一行或同一对角线上。
离散域也可以是无限的(infinite),例如整数集或字符串集。(如果我们不对作业调度问题设置截止时间,那么每个变量的开始时间构成的域将是无限的。)对于无限域,我们必须使用类似这样的隐式约束,而不是显式的值元组。对于整数变量的线性约束(linear constraint)(像刚刚给出的约束一样,每个变量都只以线性形式出现)存在特殊的求解算法(在这里不讨论)。可以证明,不存在求解整数变量上一般非线性约束(nonlinear constraint)的算法——这个问题是不可判定的。
连续域(continuous domain)约束满足问题是真实世界中的常见问题,在运筹学领域得到了广泛研究。例如,哈勃太空望远镜的实验调度需要非常精确的观测时间,每次观测和机动的开始时间、结束时间都是连续值变量,必须服从各种天文的、优先级的和电力的约束。最著名的一类连续域CSP是线性规划问题,其约束必须为线性等式或不等式。线性规划(linear programming)问题可以在关于变量个数的多项式时间内求解。此外人们还研究了具有不同类型约束和目标函数的问题——二次规划、二阶锥规划等。这些问题构成了应用数学的一个重要领域。
除了检查CSP中变量的类型以外,检查约束的类型也是很有用。最简单的类型是一元约束(unary constraint),它限制单个变量的值。例如,在地图着色问题中,南澳大利亚州人可能不喜欢绿色,我们可以用一元约束表示。(变量的域的初始说明也可以看作一元约束。)
二元约束(binary constraint)关系到两个变量。例如,是一个二元约束。二元CSP(binary CSP)只存在一元约束和二元约束,可以用如图6-1b所示的约束图表示。
我们也可以定义高阶约束。例如,三元约束Between(X, Y, Z)可以定义为。
包含任意个数变量的约束称为全局约束(global constraint)。(这个名称很传统,但容易混淆,因为它不需要包含问题中的所有变量)。最常见的全局约束之一是Alldiff,它表示约束中涉及的所有变量必须具有不同的值。在数独问题中(见6.2.6节),一行、一列或3×3框中的所有变量必须满足Alldiff约束。
另一个例子是密码算术(cryptarithmetic)谜题(图6-2a)。密码算术谜题中的每个字母代表一个不同数字。图6-2a中的情况,将表示为全局约束Alldiff(F, T, U, W, R, O)。4列上的加法约束可以写成如下n元约束:
其中C1、C2和C3为辅助变量,表示十位、百位或千位上的进位数。这些约束可以用约束超图(constraint hypergraph)表示,如图6-2b所示。超图由普通节点(图中的圆圈)和表示n元约束的超节点(正方形)组成,n元约束为包含n个变量的约束。
图6-2 (a)密码算术问题。不同字母表示不同数字,目的是找到使加法算式成立的代替字母的数字,附加约束为不允许前导零。(b)密码算术问题的约束超图,用来表示Alldiff约束(最上面的方框)以及每列的加法约束(中间的4个方框)。变量C1、C2和C3表示从右到左3列的进位数
或者,正如习题6.NARY需要你证明的,如果引入足够多的辅助变量,每个有限域约束都可以简化为一组二元约束。这意味着我们可以将任意一个CSP转换为只有二元约束的CSP,这将使算法设计变得更加简单。将n元CSP转换为二元CSP的另一种方式是对偶图(dual graph)变换:创建一个新图,原图中的每个约束用新图中的一个变量表示,原图中的每对共享变量的约束用新图中的一个二元约束表示。
例如,考虑变量为的CSP,每个变量的域为
,带有两个约束
和
。对偶图的变量则为
,对偶图中C1变量的域为原问题C1约束中的
元组的集合,同样地,C2的域是
元组的集合。对偶图具有二元约束
,其中R1是定义C1和C2之间约束的新关系。在这种情况下,
。
然而,我们可能更喜欢Alldiff这样的全局约束,而不是一组二元约束,这有两个原因。首先,使用Alldiff描述问题更简单而且更不容易出错。其次,可以为全局约束设计相比于基元约束更有效的专用推理算法。我们将在6.2.5节介绍这些推理算法。
到目前为止,我们所描述的约束都是绝对约束,违反这些约束的可能解将被排除。许多真实世界的CSP包含偏好约束(preference constraint),偏好约束规定哪些解是首选的。例如,在大学排课问题中,存在绝对约束,如一个教授不可以同时上两门课。但也可能存在偏好约束:R教授可能更喜欢在上午上课,而N教授更喜欢在下午上课。让R教授在下午2点上课仍是一个可行解(除非R教授碰巧是系主任),但不是最优解。
偏好约束通常可以编码为个别变量赋值的代价。例如,为R教授分配一个下午时段相对于总体目标函数的代价为2分,而分配上午时段的代价为1分。通过这样的形式化,带偏好约束的CSP可以用基于路径的或局部的优化搜索方法求解。我们称这样的问题为约束优化问题(constrained optimization problem,COP)。线性规划是一类COP。
原子的状态空间搜索算法只有一种方式:通过扩展节点来访问后继节点。CSP算法有不同选择。它可以通过选择一个新的变量赋值来生成后继,或者执行一种称为约束传播(constraint propagation)的特定类型推断:使用约束减少一个变量的合法值的数量,这反过来又可以减少另一个变量的合法值,以此类推。其思想是,通过这一过程,当我们选择下一个变量赋值时,需要考虑的选项会减少。约束传播可以与搜索交替进行,也可以作为搜索开始前的预处理步骤。有时这种预处理就可以求解整个问题,所以根本不需要搜索。
约束传播的核心思想是局部一致性(local consistency)。如果我们将每个变量看作图中的一个节点(见图6-1b),将每个二元约束看作一条边,则增强图中每一部分局部一致性的过程会导致整个图中不一致的值被删除。局部一致性有几种不同类型,我们现在依次介绍。
如果单个变量的域中的所有值都满足该变量的一元约束,则该变量(对应于CSP图中的某个节点)是节点一致的。例如,在澳大利亚地图着色问题(图6-1)的变体中,南澳大利亚州人不喜欢绿色,变量SA的初始域为,可以通过删除green使其保持节点一致,SA的域缩减为
。如果图中的每个变量都是节点一致的,那么整个图是节点一致的。
在求解过程开始时,通过缩减具有一元约束的变量的域,可以很容易地消除CSP中的所有一元约束。如前文所述,还可以将所有n元约束转换为二元约束。因此,一些CSP求解器只处理二元约束,要求用户提前消除其他约束。除非特别说明,本章的剩余部分都基于这一假设。
如果CSP中某一变量的域内的所有值都满足该变量的二元约束,那么该变量就是弧一致的(arc consistent)[3]。更正式地说,对于变量Xi、Xj,如果对于当前域Di中的每个值,Dj中都存在一些值满足弧(Xi, Xj)上的二元约束,则称Xi相对于Xj是弧一致的。如果每个变量相对所有其他变量都是弧一致的,那么这个图就是弧一致的。例如,考虑约束Y = X2,其中X和Y的域都是十进制数字。我们可以将这一约束显式地写为。为了使X相对于Y弧一致,我们将X的域缩减为{0, 1, 2, 3}。如果要使Y相对于X弧一致,那么Y的域为{0, 1, 4, 9},此时整个CSP是弧一致的。但是,弧一致性对澳大利亚地图着色问题没有任何帮助。考虑(SA, WA)的如下不同色约束:
[3] 我们一直使用的术语是“边”而不是“弧”,所以将其称为“边一致”会更合适,但历史上使用的术语是“弧一致”。
无论为SA(或WA)选择哪个值,另一变量都存在一个有效值。所以应用弧一致性对两个变量的域都没有影响。
最流行的增强弧一致性的算法为AC-3(见图6-3)。为了使每个变量保持弧一致,AC-3算法将维护一个弧队列。初始时,队列包含CSP中的所有弧。(每个二元约束都有两条弧,每个方向各一条。)然后AC-3从队列中弹出任意一条弧(Xi, Xj)并使Xi相对于Xj弧一致。如果Di保持不变,算法就会处理下一条弧。但是如果Di得以修正(域变小),那么我们将所有的弧(Xk, Xi)添加到队列中,其中Xk是Xi的邻居。这样做的原因是,即使之前已经处理过Xk,Di的变化也可能会进一步缩减Dk。如果Di变为空集,那么表示整个CSP不存在一致解,AC-3可以马上返回失败。否则,我们继续检查,不断尝试缩减变量的域,直到队列中没有弧。此时,我们得到了一个与原始CSP等价的CSP(它们的解相同),但弧一致CSP搜索起来会更快,因为它的变量的域更小。在某些情况下,它可以完全求解问题(通过将每个域的大小缩减为1),而在其他情况下,它可以证明解不存在(通过将某些域的大小缩减为0)。
图6-3 弧一致性算法AC-3。应用AC-3算法后,要么每条弧都是弧一致的,要么某些变量的域为空集,说明该CSP无解。“AC-3”这个名字来源于算法的发明者(Mackworth, 1977),因为他论文中用到的算法是开发的第三个版本
AC-3的算法复杂性可以如下分析。假设CSP有n个变量,每个变量的域大小不超过d,带有c个二元约束(弧)。每个弧(Xk, Xi)最多只能插入队列d次,因为Xi最多有d个值要删除。对弧一致性的检查可以在O(d2)时间内完成,因此最坏情况下的时间复杂性为O(cd3)。
假设我们要给澳大利亚地图涂上两种颜色,红色和蓝色。此时弧一致性不起作用,因为将弧的一端涂成红色,另一端涂成蓝色可以分别满足每个约束。但显然这个问题是无解的:因为西澳大利亚州、北领地和南澳大利亚州彼此相邻,仅仅是它们就需要至少3种颜色。
弧一致性利用弧(二元约束)将域(一元约束)收紧。为了求解地图着色等问题,我们需要更强的一致性概念。路径一致性(path consistency)使用隐式约束(通过观测变量的三元组推断)将二元约束收紧。
考虑两个变量的集合和第三个变量Xm,如果对于每个满足
上约束(如果有的话)的赋值
,都存在Xm的一个赋值满足
和
上的约束,则称
相对于Xm是路径一致的。这一名称是指从Xi途经Xm到Xj的路径的整体一致性。
让我们考虑用两种颜色为澳大利亚地图着色时的路径一致性。我们要使集合相对于NT路径一致。首先枚举集合的一致赋值。在这种情况下,只有两个一致赋值:
和
。可以看到,对于这两种赋值,NT不能是红色或蓝色(因为它会与WA或SA发生冲突)。因为NT不存在有效选择,所以我们消除了这两种赋值,最终
不存在有效赋值。因此,我们知道了这个问题是无解的。
可以用k一致性(k-consistency)的概念定义更强的传播形式。如果对于CSP的任意(k −1)个变量的集合以及这些变量的任意一致赋值,任意第k个变量都存在一个一致赋值,则称该CSP是k一致的。1一致性表示,给定空集,我们可以使任何单变量集合满足一致性,这就是我们所说的节点一致性。2一致性等价于弧一致性。对于二元约束图,3一致性等价于路径一致性。
如果一个CSP是k一致的,也是(k −1)一致的,(k −2)一致的……一直到1一致的,则称它是强k一致的(strongly k-consistent)。现在假设我们有一个包含n个节点的CSP,并且是强n一致的(即当k = n时,强k一致),那么可以这样求解该问题:首先,为X1选择一个一致值。然后因为图是2一致的,所以保证能为X2选出一个一致值,因为它是3一致的,所以能为X3选出一个值,以此类推。对于每个变量Xi,我们只需在它的域的d个值中搜索,就可以找到一个与X1, …, Xi−1一致的值。总运行时间只有O(n2d)。
当然,世界上没有免费的午餐:约束满足问题通常是NP完全的,任何建立n一致性的算法在最坏情况下的时间复杂性都是n的指数级。更糟的是,n一致性所需的空间复杂性也是n的指数级。在实践中,确定适当的一致性检查层级基本上是一门经验科学。比较常见的是计算2一致性,其次是计算3一致性。
前文提到,全局约束涉及任意个数的变量(但不一定是所有变量)。实际问题中经常出现全局约束,可以通过专用算法处理这些约束,这些算法比目前介绍的一般方法更加高效。例如,Alldiff约束规定所有相关变量必须取不同的值(如上文的密码算术问题和下文的数独问题)。对Alldiff约束进行不一致性检测的一种简单形式如下所示:如果约束中涉及m个变量,而且它们一共具有n个可能的不同值,且,那么约束不可能满足。
这将导出以下简单算法。首先,删除约束中任意一个单值变量(域中只有一个值的变量),并且从其余变量的域中删除该变量的值。只要还存在单值变量,就重复上述过程。如果在任一点上产生了空集,或者存在比剩余取值数更多的变量,则检测到了不一致性。
上述方法可以检测图6-1中赋值的不一致性。注意,变量SA、NT和Q是通过Alldiff约束有效连接的,因为每对都必须取两种不同颜色。将AC-3应用于这个部分赋值后,SA、NT和Q的域都缩减为
。也就是说,我们有3个变量,但只有两种颜色,这违反了Alldiff约束。因此,对高阶约束进行简单一致性处理有时比对等价的二元约束集应用弧一致性更高效。
另一种重要的高阶约束是资源约束(resource constraint),有时也称为Atmost约束。例如,在一个调度问题中,设P1, …, P4分别表示分配给4个任务的人数。分配总人数不超过10的约束写为。通过检验当前域的最小值之和可以检测不一致性。例如,如果每个变量的域都是{3, 4, 5, 6},则不可能满足Atmost约束。另一个例子是,如果当前某个变量的域中的最大值加上所有其他变量的域的最小值超过约束,则可以通过删除该最大值来保持一致性。因此,如果示例中的每个变量的域都是{2, 3, 4, 5, 6},那么可以从每个域中删除5和6。
对于大规模的、具有整数值的资源有限问题(例如用几百辆车运送几千人的物流问题)将每个变量的域表示为一个大的整数集然后通过一致性检查方法逐渐缩减这个集合通常是不可能的。相反,域由上界和下界表示,通过边界传播(bound propagation)处理。例如,在航班调度问题中,假设存在两趟航班,F1和F2,其中飞机的容量分别为165和385。F1和F2航班上乘客数量的初始域为
和
现在假设我们有附加约束,两趟航班所搭载的总乘客数必须是420:。通过传播边界约束,我们将域缩减为
和
如果对于任意变量X和它的上下界值,任意变量Y,都存在满足X和Y之间约束的Y的值,则称CSP是边界一致的(bounds-consistent)。这种边界传播在实际的约束问题中得到了广泛应用。
数独(Sudoku)游戏非常流行,它将数百万人引入了约束满足问题,尽管他们可能没有意识到这一点。数独棋盘由81个方格组成,有些方格预先填有1到9的数字。谜题是将所有剩余方格填满,并且任意一行、一列或3×3方框中不存在相同数字(见图6-4)。一行、一列或一个方框称为一个单元(unit)。
图6-4 (a)一个数独问题。(b)它的解
报纸和益智书籍上的数独游戏都有一个特点,即有且只有一个解。尽管有些问题手动求解很难,需要花费几十分钟,但CSP求解器每秒可以处理几千个问题。
可以将数独游戏看作含有81个变量的CSP,每个变量对应一个方格。用变量名A1到A9表示第一行(从左到右),I1到I9表示最后一行。空方格的域为{1, 2, 3, 4, 5, 6, 7, 8, 9},预先填好的方格的域只有一个值。此外,还有27个不同的Alldiff约束,每个单元(行、列和含有9个方格的方框)各有一个Alldiff约束:
Alldiff (A1, A2, A3, A4, A5, A6, A7, A8, A9)
Alldiff (B1, B2, B3, B4, B5, B6, B7, B8, B9)
⋯
Alldiff (A1, B1, C1, D1, E1, F1, G1, H1, I1)
Alldiff (A2, B2, C2, D2, E2, F2, G2, H2, I2)
⋯
Alldiff (A1, A2, A3, B1, B2, B3, C1, C2, C3)
Alldiff (A4, A5, A6, B4, B5, B6, C4, C5, C6)
⋯
让我们看看弧一致性能带我们走多远。假设Alldiff约束已被扩展为二元约束(例如A1 A2),这样我们就可以直接应用AC-3算法。考虑图6-4a中的变量E6——正中间方框中2、8之间的空格。按照方框的约束,我们可以从E6的域中删除1、2、7和8。按照它所在列的约束,我们可以删除5、6、2、8、9和3(尽管2和8已经被删除)。此时E6的域是{4};换句话说,我们知道了E6的解。现在考虑变量I6——最后一行中间方框中被1、3、3包围的空格。在它所在列应用弧一致性,可以删除5、6、2、4(因为我们现在知道E6一定是4)、8、9和3。我们利用它和I5的弧一致性删除1,此时I6的域中只剩下7。现在第6列中有8个已知值,所以根据弧一致性可以推出A6一定是1。沿着这样的思路继续推断,最终AC-3可以求解整个问题——所有变量的域都缩减为单个值,如图6-4b所示。
当然,如果每个数独问题都可以通过机械地应用AC-3求解,那么它很快就会失去吸引力,实际上AC-3只适用于最简单的数独问题。稍微困难一点的问题可以用PC-2求解,但需要花费更大的计算代价:在一个数独问题中,需要考虑255 960个不同的路径约束。为了求解最困难的数独问题并取得高效进展,我们必须更聪明一些。
事实上,数独对人类解谜者的吸引力在于,他们需要足智多谋地应用更复杂的推理策略。数独爱好者给这些策略取了各种有趣的名字,如“三链数删减法”。它的工作原理如下:在任一单元(行、列或方框)中,找到3个方格,它们的域包含相同的3个数字或这3个数字的子集。例如,这3个域可能是、
和
。我们并不知道哪个方格是1、3或8,但我们知道这3个数字一定分布在这3个方格中。因此,我们可以将1、3和8从该单元中所有其他方格的域中删除。
有趣的是,这些方法并不只是专用于数独。对于数独,我们确实必须说它有81个变量,域是数字1~9,有27个Alldiff约束。但除此之外,所有策略(弧一致性、路径一致性等)普遍适用于所有CSP,而不仅仅是数独问题。即使是三链数删减法,也是一种加强Alldiff约束一致性的策略,而不是特定于数独本身。这就是CSP形式体系的作用:对于每个新问题域,我们只需按照约束定义问题,然后就可以使用一般的约束求解机制。
有时我们完成约束传播过程后仍存在具有多个可能值的变量。在这种情况下,我们必须通过搜索来求解问题。本节中我们将介绍用于部分赋值的回溯搜索算法,6.4节中我们将介绍用于完整赋值的局部搜索算法。
考虑标准的深度受限搜索(第3章)是如何求解CSP的。状态可能是一个部分赋值,而动作将对该赋值进行扩展,例如,在澳大利亚地图着色问题中,添加赋值NSW = red或SA = blue。对于具有n个变量,域大小为d的CSP,我们最终将得到一个搜索树,所有的完整赋值(因此所有的解)都是深度为n的叶节点。但要注意,第一层的分支因子为nd,因为n个变量中的任意变量都可以取d个值中的任意值。下一层的分支因子是(n −1)d,以此类推n层。所以树总共有n! · dn个叶节点,即使可能的完整赋值只有dn种!
如果意识到CSP具有的一个关键性质:可交换性(commutativity),我们就可以消去因子n!。如果任意给定的动作集合的应用顺序对结果没有影响,则称该问题是可交换的。在CSP中,不管我们先赋值NSW = red,再赋值SA = blue,还是交换顺序,都没有区别。因此,我们只需考虑搜索树中每个节点上的单个变量。在根节点上,我们可能需要在SA = red、SA = green和SA = blue之间做出选择,但我们永远不需要在NSW = red和SA = blue之间做出选择。在这一限制下,叶节点的数量减少到dn,这正是我们所希望的。在树的每一层中,我们都必须选择要处理哪个变量,但我们永远不需要回溯这一选择。
图6-5为CSP的回溯搜索过程。它不断选择未赋值变量,然后依次尝试该变量的域中的所有值,试图通过递归调用将每个值扩展为一个解。如果调用成功,则返回解,如果调用失败,则将赋值恢复到前一状态,然后尝试下一个值。如果所有值都不成功,则返回失败。澳大利亚地图着色问题的部分搜索树如图6-6所示,其中我们按照WA、 NT、Q……的顺序为变量赋值。
图6-5 约束满足问题的简单回溯算法。该算法以第3章的递归深度优先搜索为模型。函数Select-Unassigned- Variable和Order-Domain-Values实现了6.3.1节中讨论的通用启发式算法。函数Inference可以根据需要选择性地使用弧一致性、路径一致性或k一致性检测。如果一个赋值导致了失败(无论是在Inference还是在Backtrack中),那么该赋值(包括从Inference得到的值)将被撤销,然后重新尝试一个新的赋值
图6-6 图6-1中地图着色问题的部分搜索树
注意,Backtracking-Search只维护状态(赋值)的单个表示,然后对它进行修改,而不是创建一个新的表示(见3.4.3节)。
第3章的无信息搜索算法只能通过提供领域特定的启发式算法来改进,然而,事实证明,回溯搜索可以使用领域无关的启发式算法进行改进,这些算法利用了CSP的因子化表示。在接下来的4节中,我们将介绍如何做到这一点。
● (6.3.1节)下一步应该给哪个变量赋值(Select-Unassigned-Variable),以及应该以什么顺序尝试它的值(Order-Domain-Values)?
● (6.3.2节)在每步搜索中应该执行怎样的推断(Inference)?
● (6.3.3节)我们能在适当的时候回溯(Backtrack)不止一步吗?
● (6.3.4节)我们可以保存和复用搜索的部分结果吗?
回溯算法中包含这样一行:
Select-Unassigned-Variable的最简单的策略是使用静态排序:按列表顺序选择变量。第二简单的策略是随机选择。这两种策略都不是最优的。例如,图6-6中,进行WA = red和NT = green赋值后,SA只有一个可能的值,因此接下来应该对SA赋值SA = blue而不是对Q赋值:事实上,对SA赋值后,Q、NSW和V的取值都是确定的。
这种直观的想法——选择“合法”值最少的变量——称为最少剩余值(minimum-remaining-value,MRV)启发式算法,也被称为“最受约束变量”或“失败优先”启发式算法,后一个名字是因为它选择了最有可能马上导致失败的变量,从而可以对搜索树剪枝。如果某一变量X没有剩余合法值,那么MRV启发式算法将优先选择X然后马上检测到失败——避免遍历其他变量进行无意义地搜索。MRV启发式算法通常比随机或静态排序表现得更好,有时会带来数量级上的效率差异,尽管结果可能因问题而异。
在选择澳大利亚地图的第一个着色区域时,MRV启发式算法完全不起作用,因为初始时每个区域都有3种合法颜色。在这种情况下,度启发式(degree heuristic)算法就派上用场了。它通过选择与其他未赋值变量的约束最多的变量来降低未来选择的分支因子。在图6-1中,SA的度最大,为5;除了变量T的度为0,其他变量的度为2或3。如果先赋值SA,我们就可以按顺时针或逆时针顺序访问5个陆地区域,并为每个区域赋予不同于SA和前一个区域的颜色。最少剩余值启发式算法通常效果更好,但度启发式算法可以打破僵局。
一旦选择了一个变量,算法必须决定按什么顺序检验它的值。最少约束值(least-constraining-value)启发式算法对此非常有效。它优先选择那些为约束图中相邻变量留下最多选择的值。例如,假设在图6-1中,我们已经生成了部分赋值WA = red和NT = green,并且下一步是为Q选择赋值。此时蓝色是一个糟糕的选择,因为它消除了Q的邻居SA的最后一个可选的合法值。因此,最少约束值启发式算法会优先选择红色而不是蓝色。一般来说,启发式算法试图为后续变量赋值留下最大的灵活性。
为什么变量选择是失败优先,而值选择是失败延后呢?每个变量最终都必须被赋值,因此通过选择那些有可能最先失败的变量,在统计意义上,需要通过回溯才能找到的成功赋值就会更少。对于值排序,关键在于我们只需要找到一个解;因此,先寻找最有可能的值是有意义的。如果我们的目标是枚举所有的解而不只是找到一个解,那么值排序就无关紧要了。
我们已经讨论了AC-3算法如何在搜索前缩减变量的域。但在搜索过程中,推断的作用可能更大:每次我们为某个变量选择某个值时,都有一个全新的机会推断其相邻变量的新的域缩减。
推断的最简单形式之一是前向检验(forward checking)。当变量X被赋值时,前向检验过程为其建立弧一致性:对于每个通过约束与X连接的未赋值变量Y,从它的域中删除与X的取值不一致的值。
图6-7为在澳大利亚地图CSP上使用前向检验进行回溯搜索的过程。关于这一示例,有两点需要注意。首先,需要注意,在赋值WA = red和Q = green后,NT和SA的域缩减为单个值;通过从WA和Q传播信息,我们可以完全消除这些变量上的分支。其次,需要注意,赋值V= blue后,SA的域为空集。因此,前向检验检测到部分赋值与问题的约束不一致,算法立即回溯。
图6-7 带前向检验的地图着色搜索过程。首先赋值WA = red;然后前向检验从其相邻变量NT和SA的域中删除red。赋值Q = green后,从NT、SA和NSW的域中删除green。赋值V = blue后,从NSW和SA的域中删除blue,此时SA没有合法值
对许多问题来说,将MRV启发式算法与前向检验相结合,可以使搜索更有效。考虑图6-7中的赋值。直观上,这一赋值似乎对它的相邻变量NT和SA有所约束,所以接下来应该先处理这些变量,然后是所有其他变量。MRV正是这么做的:NT和SA各有两个值,所以先选择其中一个,接着是另一个,然后依次是Q、NSW和V。最后T仍然有3个可能的值,任意一个都是有效的。我们可以将前向检验看作一种以增量方式计算MRV启发式算法完成其工作所需信息的有效途径。
尽管前向检验能够检测出许多不一致,但它无法检测到所有的不一致。问题在于,它向前看得不够远。例如,考虑图6-7中的Q = green一行。我们已经使WA和Q弧一致,但此时NT和SA的唯一可能的值都是蓝色,这违反了一致性,因为它们是相邻变量,相邻变量不能取相同的值。
维护弧一致性(maintaining arc consistency,MAC)算法能检测出这类不一致性。当变量Xi被赋值后,Inference程序调用AC-3,但我们开始时只考虑所有与Xi相邻的未赋值变量Xj的弧(Xj, Xi),而不是CSP中的所有弧。从这出发,AC-3以通常的方式进行约束传播,如果任何变量的域缩减为空集,则AC-3调用失败,并立即回溯。我们可以看到,MAC严格来说比前向检验更强大,因为前向检验所做的事情与MAC对其队列的初始弧所做的相同;但与MAC不同的是,当变量的域发生变化时,前向检验不会递归地传播约束。
当搜索的一个分支失败时,图6-5中的Backtracking-Search算法将采取一种非常简单的策略:退回到上一个变量,并为其尝试一个不同的值。这称为时序回溯(chronological backtracking),因为时间上最近的决策点会被重新访问。在本节中,我们考虑更好的可能策略。
考虑一下,当我们按照固定的变量顺序Q、NSW、V、 T、SA、WA、NT应用图6-1中的简单回溯时会发生什么。假设我们已经生成了部分赋值。当我们尝试下一个变量SA时,发现所有值都违反了约束。我们退回到T,为塔斯马尼亚州尝试一种新颜色!显然,这种做法是愚蠢的——重新给塔斯马尼亚州着色并不能解决南澳大利亚州的问题。
一种更智能的方法是回溯到有可能求解这一问题的变量——导致SA的某个可能值变成不可能值的变量。为此,我们将记录与SA的某些值冲突的赋值集合。该集合(在本例中为)称为SA的冲突集(conflict set)。回跳(backjumping)方法将回溯到冲突集中最近的赋值,在本例中,回跳将越过塔斯马尼亚州,为V尝试一个新的值。通过修改Backtrack算法,可以很容易地实现上述方法,即在检验合法值时,同时维护冲突集。如果找不到合法值,算法应该返回失败指示和冲突集中最近的元素。
眼尖的读者可能已经注意到,前向检验不需要额外工作就能提供冲突集:当前向检验根据赋值X = x从Y的域中删除一个值时,它应该将X = x添加到Y的冲突集中。如果Y的域中的最后一个值也被删除,那么Y的冲突集中的赋值也要被添加到X的冲突集中。也就是说,我们现在知道X = x导致了(Y中的)矛盾,因此应该为X尝试不同赋值。
有眼力的读者可能已经注意到一些奇怪的事情:当域中的每个值都与当前赋值冲突时就会发生回跳,但前向检验能检测出这个事件并阻止搜索到达这样的节点!事实上,可以证明,每个被回跳剪除的分支也会被前向检验剪枝。因此,在前向检验搜索中,或者在使用更强一致性检验的搜索(如MAC)中,简单的回跳是多余的——你只需执行其中一项。
尽管存在上一段中的观测结果,回跳背后的思想仍然值得借鉴:基于失败原因进行回溯。当变量的域变为空集时,回跳发现失败,但在许多情况下,在很早之前分支就注定要失败。再次考虑部分赋值(从我们前面的讨论来看,它是不一致的)。假设我们下一步尝试T = red,然后对NT、Q、V和SA赋值。我们知道,最后这4个变量不存在有效赋值,所以最终在NT处终止。现在,问题是,回溯到哪儿?回跳是不可行的,因为NT确实存在与前面赋值过的变量一致的值——NT没有导致失败的前面变量的完整冲突集。然而,我们知道,NT、Q、V和SA这4个变量放在一起会失败,是因为前面的一组变量一定与这4个变量有直接冲突。
这引出了(对于NT这样的变量的)一种不同的、更深层次的冲突集概念:正是前面一组变量共同导致了NT连同任何后续变量都不存在一致解。在本例中,该集合是WA和NSW,所以算法应该跳过塔斯马尼亚州回溯到NSW。使用以这种方式定义的冲突集的回跳算法称为冲突导向回跳(conflict-directed backjumping)。
现在我们必须解释如何计算这些新的冲突集。方法其实很简单。搜索分支的“终端”失败总是因为某个变量的域变为空集,该变量对应一个标准冲突集。在我们的例子中,SA失败,它的冲突集是(例如)。我们回溯到Q,Q将SA的冲突集(当然要减去Q本身)吸收到它自己的直接冲突集
,新的冲突集是
。也就是说,给定前面对
的赋值,从Q向前是没有解的。因此,我们回溯到最近的变量NT。NT将
吸收到它自己的直接冲突集
中,得到
(如上一段所述)。现在算法回跳到NSW,这正是我们所希望的。总结一下:设Xj表示当前变量,conf(Xj)表示它的冲突集。如果Xj的每个可能值都失败了,则回跳到conf(Xj)中最近的变量Xi,并使用下列公式重新计算Xi的冲突集:
当我们遇到矛盾时,回跳可以告诉我们要退回多远,这样我们就不会浪费时间去改变那些无法求解问题的变量。但我们也希望不要再遇到同样的问题。当搜索得出一个矛盾时,我们知道这是冲突集的某个子集引起的。约束学习(constraint learning)的思想是从冲突集中找出引起问题的最小变量集。这组变量及其相应值称为无用赋值(no-good)。如果想要记录无用赋值,要么通过向CSP中添加一个新的约束禁止这种赋值组合,要么通过维护一个单独的缓存。
例如,考虑图6-6最下面一行中的状态。前向检验告诉我们这个状态是一个无用赋值,因为SA不存在有效赋值。在这种特定情况下,记录该无用赋值是没有意义的,因为一旦从搜索树中剪掉了这一分支,我们再也不会遇到这种组合。但假设图6-6中的搜索树实际上是更大的搜索树的一部分,该搜索树是从V和T的赋值开始的。那么将
记录为无用赋值是有意义的,因为对于V和T的每一组可能赋值,我们都会再次遇到同样的问题。
前向检验或回跳可以有效地利用无用赋值。约束学习是现代CSP求解器用以提高复杂问题求解效率的最重要技术之一。
局部搜索算法(见4.1节)对于许多CSP的求解都非常有效。它们使用完整状态形式(见4.1.1节),即每一状态为所有变量赋值,搜索一次改变一个变量的值。例如,考虑6.1.3节中定义为CSP的8皇后问题。在图6-8中,我们从左边开始,对8个变量进行了完整赋值,通常该赋值会违反一些约束。然后我们随机选择一个发生冲突的变量,在此是最右边一列的Q8。我们希望改变它的值,从而更接近问题的解。最明显的方法是选择与其他变量冲突数最少的值——最少冲突(min-conflict)启发式算法。
图6-8 使用最少冲突法求解8皇后问题的示例。每步选择一个皇后,在其所在列重新分配位置。每个方格标有冲突数(在本例中是互相攻击的皇后个数)。算法随机选择发生冲突的皇后,将皇后移动到冲突最少的方格
在图6-8中,我们看到有两行都只违反了一个约束,我们选择让Q8 = 3(也就是说,我们将皇后移动到第8列、第3行)。下一次迭代,在图6-8的中间棋盘上,我们选择Q6作为要改变的变量,然后发现将该皇后移动到第8行不会发生冲突。此时不再有发生冲突的变量,所以我们找到了一个解。最少冲突算法如图6-9所示。[4]
[4] 局部搜索可以很容易地扩展到约束优化问题(COP)。在这种情况下,爬山法和模拟退火的所有技术都可以用于优化目标函数。
图6-9 CSP的Min-Conflicts局部搜索算法。初始状态可以随机选择,也可以通过基于贪心法的赋值过程依次为每个变量选择最少冲突值。在给定当前赋值的其余部分后,Conflicts函数统计特定值违反约束的数量
对许多CSP来说,最少冲突法都相当有效。神奇的是,在n皇后问题上,如果不计入皇后的初始布局,最少冲突法的运行时间基本上与问题规模无关。它甚至可以在(初始赋值后)平均50步内求解百万皇后问题。这一不同寻常的现象是20世纪90年代大量研究局部搜索和难易问题间区别的动力,我们将在7.6.3节中讨论这些问题。粗略地说,用局部搜索求解n皇后问题非常简单,因为解密集地分布在整个状态空间上。最少冲突法也适用于困难问题。例如,它已经被用于哈勃太空望远镜的观测调度,安排一周的观测调度所花费的时间可以从3周减少到大约10分钟。
4.1节中的所有局部搜索技术都可以应用于CSP,有些技术已被证实相当有效。最少冲突启发式算法下的CSP地形图通常存在一系列平台区。可能有数百万个变量赋值都只存在一个冲突。平台区搜索——允许横向移动到另一个得分相同的状态——可以帮助局部搜索走出平台区。这种在平台区的漫游可以由一种叫作禁忌搜索的技术导引:维护一个最近访问过的状态的列表,并禁止算法返回那些状态。模拟退火也可以用于逃离平台区。
另一种技术称为约束加权(constraint weighting),旨在集中搜索重要约束。每个约束都有一个数值权重,初始时都为1。在每步搜索中,算法找出使其所违反的约束的总权重最低的变量,并修改其值。然后,增加当前赋值所违反的每个约束的权重。这种做法有两个好处:它为平台区增加了地形因素,确保从当前状态进行改进是有可能的;它还引入了学习策略,随着时间推移,难以求解的约束会被分配更高的权重。
局部搜索的另一个优点是,当问题发生变化时,它可以用于在线设定的问题(见4.5节)。考虑一个航空公司每周航班调度问题。它可能涉及上千趟航班和上万名人员的分配,但机场的恶劣天气可能会打乱这一调度。我们希望以最少的改动修正日程表。这可以通过从当前调度开始的局部搜索算法轻松完成。使用新约束集的回溯搜索通常要花费更多时间,而且找到的解可能要对当前调度进行很多改动。
在这一节中,我们将研究如何利用由约束图表示的问题的结构来快速找到解。这里的大多数方法也适用于CSP之外的其他问题,例如概率推理。
处理复杂的真实世界问题的唯一可能方法是将其分解为若干子问题。回顾澳大利亚问题的约束图(图6-1b和图6-12a),可以发现一个问题:塔斯马尼亚州和大陆不相连。[5]直观上看,对塔斯马尼亚州着色和对大陆着色显然是两个独立子问题(independent subproblem)——任何对大陆着色的解和任何对塔斯马尼亚州着色的解相结合都能得到整个地图的解。
[5] 细心的制图师或热爱塔斯马尼亚州的塔斯马尼亚人可能会反对将塔斯马尼亚州和离它最近的大陆邻域涂上相同的颜色,以免给人留下它可能是那个州的一部分的印象。
可以简单地通过寻找约束图的连通分量(connected component)来确定独立性。每个连通分量对应一个子问题CSPi。如果赋值Si是CSPi的解,那么就是
的解。为什么这很重要?假设每个CSPi具有所有n个变量中的c个变量,其中c是一个常数。那么共有n/c个子问题,求解每个子问题最多需要d c工作量,其中d是域的大小。因此,总的工作量为O(dcn/c),关于n是线性的;如果不进行问题分解,总的工作量为O(d n),关于n是指数级的。让我们更具体地说:将一个具有100个变量的布尔CSP分解为4个子问题,那么最坏情况下的求解时间将从宇宙生命周期减少到不到1秒。
完全独立的子问题很好,但很少见。幸运的是,其他一些图结构也很容易求解。例如,当任意两个变量都只由一条路径连接时,约束图是一棵树。我们将证明任何树状结构的CSP都可以在变量个数的线性时间内求解。[6]这里的关键是一种新的一致性概念——定向弧一致性(directional arc consistency)或DAC。变量顺序为X1, X2, …, Xn的CSP称为定向弧一致的,当且仅当,时,每个Xi相对于每个Xj都是弧一致的。
[6] 遗憾的是,除了苏拉威西岛(Sulawesi)的地图比较接近树状外,世界上几乎没有一个地区是树状结构的地图。
为了求解树状结构的CSP,首先选择任一变量作为树的根节点,然后选择变量顺序,每个变量必须在其父节点之后。这种排序称为拓扑排序(topological sort)。图6-10a为一棵树,图6-10b为一种可能的排序。任何有n个节点的树都有n−1条边,所以可以在O(n)步内使得该图具有定向弧一致性,每一步都必须比较两个变量的最多d个可能的值,总时间为O(nd2)。一旦我们有了一个定向弧一致的图,就可以沿着变量列表选择任意剩余值。因为从父节点到其子节点的每条边都是弧一致的,所以,对于父节点选择的任何值,子节点都存在一个可选的有效值。这意味着我们不必回溯,可以沿着变量线性移动。完整算法如图6-11所示。
图6-10 (a)树状结构CSP的约束图。(b)与以A为根节点的树一致的变量的线性排序。这称为变量的拓扑排序
既然我们有了关于树的高效算法,可以考虑更一般的约束图是否可以以某种方式简化为树结构。有两种方法可以做到这一点:删除节点(6.5.1节)或合并节点(6.5.2节)。
图6-11 用于求解树状结构CSP的Tree-CSP-Solver算法。如果CSP有解,我们可以在线性时间内找到它;如果无解,将检测到矛盾
将约束图简化为树的第一种方法是为部分变量赋值使得剩余变量能够形成一棵树。考虑澳大利亚问题的约束图,如图6-12a所示。如果没有南澳大利亚州,这个图就会变成如图6-12b所示的一棵树。幸运的是,我们可以通过将SA固定为某个值并从其他变量的域中删除任何与SA取值不一致的值来从图中删除南澳大利亚州。
图6-12 (a)图6-1中的原始约束图。(b)除去SA后,约束图变成由两棵树组成的森林
现在,删除SA及其约束后,CSP的任意一个解都与SA的值一致。(这适用于二元CSP,在高阶约束下,情况会更加复杂。)因此,我们可以用上面给出的算法求解剩余的树,从而求解整个问题。当然,在一般情况下(与地图着色不同),为SA选择的值可能是错误的,因此我们需要尝试每个可能的值。一般算法如下。
(1)选择CSP变量的一个子集S,使得约束图在删除S后成为一棵树。S称为环割集(cycle cutset)。
(2)对于满足S上所有约束的S中变量的每种可能赋值,
a. 从剩余变量的域中删除任何与S赋值不一致的值,并且
b. 如果剩余的CSP存在一个解,那么将其连同S的赋值一起返回。
如果环割集的大小为c,那么总运行时间为:我们需要尝试S中变量的值的所有d c种组合,对于每种组合,我们需要求解一个大小为(n −c)的树问题。如果约束图“几乎是一棵树”,那么c将会非常小,相比于直接使用回溯法,将省掉巨大的开销——对100个布尔变量的示例来说,如果我们能找到一个大小为c = 20的割集,时间开销可以从宇宙生命周期缩短到几分钟。然而,在最坏情况下,c可能高达(n −2)。寻找最小环割集问题是NP困难的,但有一些高效的近似算法。算法的总体过程称为割集调整(cutset conditioning),我们将在第13章详细讨论,在那里它将用于概率推理。
将约束图简化为树的第二种方法基于构建约束图的树分解(tree decomposition):将原始图转换为树,树中的每个节点由一组变量组成,如图6-13所示。树分解必须满足以下3个要求。
● 原始问题中的每个变量必须至少出现在一个树节点中。
● 如果两个变量在原始问题中由一个约束连接,那么它们必须同时出现(连同约束)在至少一个树节点中。
● 如果一个变量出现在两个树节点中,那么它必须出现在连接这两个节点的路径上的所有节点中。
前两个条件保证了所有变量和约束在树分解中都有表示。第三个条件似乎更具技术性,但保证了原始问题的任何变量无论在哪出现都具有相同的值:树中的约束表明一个树节点中的变量必须与其相邻节点中的相应变量具有相同的值。例如,图6-13中SA出现在相连的所有4个节点中,因此树分解中的每条边都包含一个约束,一个节点中SA的值必须与下个节点中SA的值相同。你可以从图6-12中验证这种分解是有意义的。
图6-13 图6-12a中约束图的一个树分解
一旦我们有了一个树状结构图,我们可以应用Tree-CSP-Solver在O(nd 2)时间内得到解,其中n是树节点的个数,d是最大域的大小。但是要注意,在树中,域是一组值元组,而不只是单个值。
例如,图6-13中的左上节点表示在原始问题层级上,变量为,域为
,约束为
、
和
的子问题。而在树的层级上,节点表示单个变量,我们可以将其称为SANTWA,它的值必须是一个由颜色组成的三元组,如(red, green, blue),但不能是(red, red, blue),因为违反了原始问题中的
约束。然后我们可以从这个节点移动到相邻节点,其变量为SANTQ,此时只有一个元组(red, green, blue)与SANTWA的选择一致。对后两个节点重复完全相同的过程,但可以独立地为T作出任何选择。
使用Tree-CSP-Solver算法可以在O(nd2)时间内求解任何树分解问题,只要d保持较小值,它都是高效的。回到100个布尔变量的示例,如果每个节点有10个变量,那么d = 210,我们可以在几秒内找到解。但如果有一个节点包含30个变量,则需要几个世纪的时间。
一个给定的图允许多种树分解,在选择分解时,目标是使子问题尽可能小。(将所有变量放在同一个节点中在技术上也是一棵树,但对求解问题没有帮助。)图的树分解的树宽(tree width)为最大节点的大小减1,图本身的树宽定义为其所有树分解的最小宽度。如果一个图的树宽为w,那么给定相应的树分解,该问题可以在O(ndw+1)时间内求解。因此,如果CSP的约束图树宽有界,则该CSP在多项式时间内是可解的。
遗憾的是,找出树宽最小的分解是 一个NP困难问题,但有一些启发式方法在实践中效果很好。时间为的割集分解和时间为O(ndw+1)的树分解哪个更好?每当有一个大小为c的环割集时,也会有一个大小为
的树宽,并且在某些情况下它可能要小得多。所以从时间上考虑,应该选择树分解,但环割集方法的优点是,它可以在线性内存中执行,而树分解需要关于w的指数级内存。
到目前为止,我们已经讨论了约束图的结构。在变量的值中,或在约束关系本身的结构中,也可能存在重要的结构。考虑有d种颜色的地图着色问题。对于每个一致解,实际上都有一组通过排列颜色名形成的d!个解。例如,在澳大利亚地图中,我们知道WA、NT和SA肯定具有不同颜色,但实际上,将3种颜色分配给3个区域有3! = 6种方法。这称为值对称(value symmetry)。我们希望通过打破这种赋值对称性将搜索空间缩小d!倍。可以通过引入对称性破缺约束(symmetry-breaking constraint)做到这一点。对于我们的例子,可以施加一个任意的排序约束,,即要求3个值按字母顺序排列。这个约束保证了d!个解中只有一个是可能解:
。
对于地图着色问题,很容易找到一个消除对称性的约束。一般来说,要消除所有的对称性是NP困难的,但打破值对称已被证明在许多问题上都是重要和有效的。
● 约束满足问题(CSP)的状态为一组变量/值对,解的条件为一组变量约束。许多重要的真实问题都可以用CSP描述。
● 许多推断技术利用约束排除某些变量赋值。这些约束包括节点一致性、弧一致性、路径一致性和k一致性。
● 回溯搜索是深度优先搜索的一种形式,通常用于求解CSP。推断可以与搜索交替进行。
● 最少剩余值启发式算法和度启发式算法是领域无关的方法,用于决定在回溯搜索中下一步选择哪个变量。最少约束值启发式算法有助于决定对于给定变量首先尝试哪个值。回溯发生在某个变量找不到合法赋值时。冲突导向回跳直接回溯到问题的根源。约束学习记录在搜索过程中遇到的冲突,以免在以后的搜索中出现相同的冲突。
● 使用最少冲突启发式算法的局部搜索也已成功地应用于约束满足问题。
● CSP求解的复杂性与其约束图的结构密切相关。树状结构问题可以在线性时间内求解。割集调整可以将一般的CSP简化为树状结构的CSP,如果能找到一个较小的割集,算法会非常高效(只需线性内存)。树分解技术将CSP转化为由子问题构成的树,当约束图的树宽较小时,算法是高效的;然而,它们需要约束图树宽的指数级的内存。将割集调整和树分解相结合可以更好地权衡所需内存和时间。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们设计能够表示复杂世界的智能体,它使用推断过程来获取关于这个世界的新表示,并使用这种表示来推导下一步该怎么做。
人类似乎具有知识,人类的知识能够帮助他们做事。在人工智能中,基于知识的智能体(knowledge-based agent)对知识的内部表示(representation)进行推理(reasoning)来确定要采取的动作。
第3章和第4章的问题求解智能体具有知识,但这种知识是非常有限且死板的。它们知道可以采取哪些动作,也知道在某个状态采取某个动作将得到哪种结果,但它们不知道一般事实。例如,寻路智能体不知道一条路的长度不可能是负数公里,而8数码智能体也不知道两块瓷砖无法放置在同一个空格当中。问题求解智能体具有的知识对寻找从起点到终点的路径这种问题非常有用,但也仅限于此。
问题求解智能体所使用的原子表示也有很大的局限性。例如,在部分可观测的环境中,问题求解智能体表示它对当前状态的了解的唯一选项是列出所有可能的具体状态。我可以让一个人驱车前往一个人口不超过1万的美国小镇,但如果要让问题求解智能体来做这件事,我只能明确地将目标描述为大约1.6万个符合条件的小镇的集合。
第6章引入了我们的第一个因子化表示,其中状态被表示为对变量的赋值。这是朝正确方向前进的一步,它能使智能体的某些部分以与领域无关的方式运作,并支持更高效的算法。在本章中,我们将这一步延伸到它的逻辑结论,可以说,我们将逻辑扩展为一类通用的表示,以支持基于知识的智能体。这些智能体可以组合或重组信息以适应各种用途。它可以与我们当下的需要毫不相关,就像数学家证明定理或天文学家计算地球的预期寿命一样。基于知识的智能体能够接受明确描述的目标作为任务,能够通过主动学习或被告知关于环境的新知识快速地获得完成任务的能力,也能够通过更新相关知识适应环境的变化。
我们在7.1节开始介绍智能体的总体设计。7.2节新引入了一个名为wumpus世界的简单环境,以便在不涉及任何技术细节的前提下,阐明基于知识的智能体的运作方式。随后我们在7.3节解释逻辑的一般原理,在7.4节介绍命题逻辑的具体细节。命题逻辑是一种因子化表示,尽管它的表达能力不如一阶逻辑(第8章)这种标准的结构化表示,但却能够阐明逻辑的所有基本概念。命题逻辑还具有丰富的推断方法,我们将在7.5节和7.6节中描述这些内容。最后,7.7节将基于知识的智能体的概念与命题逻辑的技术结合起来,为wumpus世界构建了一个简单的智能体。
基于知识的智能体的核心部件是它的知识库(knowledge base,KB)。知识库是一个语句集。(此处“语句”是一个术语。它与英语或其他自然语言的语句类似,但不完全相同。)这些语句用知识表示语言(knowledge representation language)表达,代表了关于世界的某种断言。如果一条语句是直接给出的,而不是从其他语句推导而来的,我们就称它为公理(axiom)。
向知识库添加新语句以及从知识库查询已知语句的方法是必不可少的。这些操作的标准名称分别是Tell(告知)和Ask(询问)。这两个操作都可能涉及推断(inference),也就是从原有语句中推导出新语句。推断必须符合以下要求:当向知识库询问(Ask)时,答案应当遵循先前已经告知(Tell)知识库的内容而生成。我们将在本章后续部分仔细讲解何为“遵循”。现在,我们暂且将其理解为在推断过程中不能进行捏造。
图7-1展示了基于知识的智能体程序。与所有的智能体一样,基于知识的智能体以一个感知作为输入,返回一个动作。该智能体维护一个知识库KB,这个知识库最初可能包括一些背景知识(background knowledge)。
图7-1 通用的基于知识的智能体。给定一个感知,智能体将这一感知添加进知识库,向知识库询问最优动作,并告知知识库它已经采取了这一动作
每次调用智能体程序时,程序会做3件事。首先,它告知知识库它所感知到的东西。然后,它询问知识库它应当采取什么动作。在回答这一查询时,可能会对关于世界的当前状态、可能的动作序列的执行结果等进行大量推理。最后,智能体程序告知知识库它选择的动作,并返回这一动作以便执行。
表示语言的细节隐藏在3个函数中,这3个函数一方面实现了传感器与执行器之间的接口,另一方面又实现了核心表示与推理系统的接口。Make-Percept-Sentence构建了一个语句,断言智能体在给定时间接收到给定的感知。Make-Action-Query构建了一个语句,询问当前时刻应当采取何种动作。最后,Make-Action-Sentence构建了一个语句,断言选定的动作已经执行。推断机制的细节隐藏在Tell与Ask中。后续章节将阐明这些细节。
图7-1所示的基于知识的智能体看起来与第2章所述的具有内部状态的智能体非常相似。而由于Tell和Ask的定义,基于知识的智能体并不仅是普通的用来计算动作的程序。它受到位于知识层面(knowledge level)的描述的操控,我们只需要在知识层面明确智能体所具有的知识和它的目标,就可以决定它的行为。
例如,一辆自动驾驶出租车的任务是将一名乘客从旧金山送往马林县,它或许知道金门大桥是两地间的唯一通路。因此,我们可以猜测出租车将驶过金门大桥,因为它知道这样能达成目标。注意,这一分析与出租车在实现层面(implementation level)的工作原理毫无关系。不论它是用链表或点阵图来实现地理知识,还是通过操纵寄存器中的符号串或在神经元网络中传递有噪声的信号来进行推理,都与我们的分析无关。
我们可以仅通过告知智能体必需的知识来构建基于知识的智能体。智能体设计者可以从空知识库开始,逐条告知智能体语句,直到它明白如何在它的环境中运作。我们称之为陈述性(declarative)系统构建方法。相对地,过程性(procedural)方法将所需的行为直接编码为程序代码。在20世纪70年代和80年代,两种方法的提倡者进行了激烈的辩论。我们现在明白,成功的智能体在设计中常常需要将陈述性和过程性这两种方法的元素结合起来,而陈述性的知识也往往能够被编译成更有效的过程性代码。
我们还可以给基于知识的智能体赋予自主学习的机制,我们将在第19章讲解的这些机制。智能体能够利用这些机制从一系列感知中创建关于环境的一般知识。进行学习的智能体可以是完全自主的。
本节我们将描述一个能够体现基于知识的智能体的价值的环境。wumpus世界(wumpus world)是一个洞穴,其中有许多房间,房间之间有走廊连接。在洞穴的某处潜伏着可怕的wumpus,这是一只会吃掉任何进入其房间的人的怪兽。智能体可以射杀wumpus,但智能体只有一支箭。一些房间有无底洞,能困住任何漫游到这些房间中的人(wumpus除外,它体型大得无法落入无底洞)。这个阴森环境的唯一回报是可能找到的金块。尽管以现代电子游戏的眼光来看,wumpus世界相当乏味,但它却能展示出智能的一些重要属性。
图7-2展示了一个简单的wumpus世界示例。任务环境的精确定义用2.3节所述的PEAS描述法给出。
图7-2 一个典型的wumpus世界。智能体位于左下角,面朝东(向右)
● 性能度量:带着金块从洞穴爬出+1000,跌入无底洞或被wumpus吞食−1000,每采取一个动作−1,用尽箭支−10。如果智能体死亡或爬出洞穴,游戏结束。
● 环境:一个4×4的房间网格,网格四周环绕着围墙。智能体始终从标为[1, 1]的方格开始,面向东方。金块和wumpus的位置是根据均匀分布从除了起始方格的所有方格中随机选定的。另外,除起始方格外的每个方格都可能是无底洞,出现的概率为0.2。
● 执行器:智能体可以向前(Forward)、左转(TurnLeft)90°和右转(TurnRight)90°。如果智能体进入有活着的wumpus或者有无底洞的方格,它将悲惨地死去。(但进入有死掉的wumpus的方格是安全的,尽管气味会很臭。)如果智能体试图前进并撞到墙,则智能体会原地不动。如果智能体与金块在同一个方格,抓取(Grab)动作可以用于捡起金块。射击(Shoot)动作可以用于向智能体面对的方向笔直地发射一支箭,这支箭会一直飞行,直到它命中wumpus(此时wumpus将被杀死)或击中墙壁。智能体只有一支箭,因此只有第一次射击动作有效。最后,攀爬(Climb)动作可以用于爬出洞穴,但智能体仅能从方格[1, 1]爬出。
● 传感器:该智能体有5个传感器,每个传感器给出一个单一信息。
❏ 在与wumpus直接(非对角)相邻的方格中,智能体会感知到臭味(Stench)。[1]
[1] wumpus所在的方格恐怕也有臭味,但任何进入该方格的智能体在能够进行感知前就会被吞食。
❏ 在与无底洞直接相邻的方格中,智能体会感知到微风(Breeze)。
❏ 在金块所在的方格中,智能体会感知到闪光(Glitter)。
❏ 智能体走向墙壁会感知到碰撞(Bump)。
❏ 如果wumpus被杀死,它将发出惨叫(Scream),智能体可以在洞穴的任意位置感知到。
感知将以由5个符号组成的列表的形式传给智能体程序。例如,如果有臭味和微风,但没有闪光、碰撞和惨叫,智能体程序将收到[Stench, Breeze, None, None, None]。
我们可以在第2章所述的多个维度上描述wumpus环境。显然,它是确定性的、离散的、静态的且单智能体的。(好在wumpus不移动。)它是序贯的,因为只有采取很多动作后才可能得到奖励。它是部分可观测的,因为状态的一些方面是无法直接感知到的,如智能体的位置、wumpus的健康状况以及是否还有箭支可用。对于无底洞和wumpus的位置,我们可以将其看作状态中没有观测到的部分,在这种情况下,环境的转移模型是完全已知的,找出无底洞和wumpus的位置就能补全智能体对状态的知识;抑或,我们也可以说转移模型本身是未知的,因为智能体不知道哪些向前动作是致命的,在这种情况下,找出无底洞和wumpus的位置能够补全智能体对于转移模型的知识。
对于环境中的智能体,主要的挑战是它起初并不知道环境的配置。克服这种无知似乎需要逻辑推理。在wumpus世界的大多数情况中,智能体是有可能安全地拾取金块的。但智能体偶尔也需要在空手而归和冒死寻宝之间做出选择。大约21%的环境是极不公平的,因为这时金块位于无底洞中,或被无底洞包围。
我们来看一个基于知识的智能体是如何探索图7-2所示的wumpus世界的环境的。此处使用一种非形式化的知识表示语言,在网格中写下符号来表示(如图7-3和图7-4所示)。
图7-3 智能体在wumpus世界迈出的第一步。(a)在感知到[None, None, None, None, None]后的初始状态。(b)在移动到[2, 1]后感知到[None, Breeze, None, None, None]
智能体的初始知识库包括前述的环境规则。具体来说,智能体知道自己位于[1, 1]且[1, 1]是安全的方格。我们在方格[1, 1]中用“A”和“OK”分别进行表示。
第一个感知是[None, None, None, None, None],据此智能体可以认定它的相邻方格[1, 2]和[2, 1]是安全的——它们是“OK”的。图7-3a展示了此时智能体的知识状态。
图7-4 智能体运作时的两个后续状态。(a)回到[1, 1]再移动到[1, 2]后,感知到[Stench, None, None, None, None]。(b)来到[2, 2]再移动到[2, 3],感知到[Stench, Breeze, Glitter, None, None]
一个谨慎的智能体只会移动到它所知的OK方格。我们假设智能体决定前进到[2, 1]。这个智能体在[2, 1]感受到微风(用“B”表示),因此在相邻方格中必然存在无底洞。根据游戏规则,无底洞不可能在[1, 1],因此[2, 2]和[3, 1]其中之一必然有无底洞或二者都有。图7-3b中的记号“P?”表示这些方格中可能存在无底洞。此时,仅有一个已知的且未访问过的“OK”方格。因此这个心思缜密的智能体将扭头,回到[1, 1],然后移步[1, 2]。
智能体在[1, 2]感知到臭味,导致知识状态变为图7-4a所示的状况。[1, 2]有臭味表明附近肯定有wumpus。但根据游戏规则wumpus不可能在[1, 1],也不在[2, 2](否则智能体先前在[2, 1]时会探测到臭味)。因此,智能体可以推断出wumpus在[1, 3]。记号“W!”表示这一推断。而[1, 2]没有微风表明[2, 2]没有无底洞。考虑到智能体先前已经推断出[2, 2]或[3, 1]中必然有无底洞,因此无底洞必然位于[3, 1]。这是一次相当复杂的推断,因为它结合了在不同时间、不同地点获取的信息,并在缺乏感知的情况下迈出了关键的一步。
现在智能体已经证明了[2, 2]中既没有无底洞也没有wumpus,因此可以移动到那里。我们没有展示智能体在[2, 2]的知识状态,姑且假设智能体转向并移动到[2,3],形成了图7-4b所示的情况。在[2, 3]中,智能体探测到闪光,因此它应该抓取金块然后回家。
注意,在智能体从可用信息中得出结论的每个情形下,如果可用信息是正确的,则可以保证结论都是正确的。这是逻辑推理的一个重要性质。本章剩余部分将描述如何构建能够表示信息并得出类似前述的结论的逻辑智能体。
本节综述逻辑表示和推理的基本概念。这些漂亮的想法独立于逻辑的具体形式。因此,我们将形式的技术细节推后到7.4节介绍,本节代之以熟悉的普通算术问题作为示例。
在7.1节,我们说过知识库由语句组成。这些语句是根据表示语言的语法(syntax)表达的,语法规定了所有的合规语句。用简单的算术就能清晰地说明语法这个概念:“x + y = 4”是合规的语句,而“x4y+=”不是。
一种逻辑还必须定义语句的语义,或者说语句的含义。语义定义每条语句在每个可能世界中的真值。例如,算术的语义指明“x + y = 4”在一个x为2且y为2的世界为真,但在一个x为1且y为1的世界中为假。在标准的逻辑学中,每个可能世界中的每条语句要么为真,要么为假——没有中间地带。[2]
[2] 第13章讨论的模糊逻辑(fuzzy logic)允许存在不同程度的真值。
当需要精确描述时,我们用模型来代替“可能世界”。可能世界可以被认为是(潜在的)真实环境,智能体可能在也可能不在其中,而模型是数学抽象,对于每个相关的语句,每个模型都有固定的真值(真或假)。非正式地举个例子:我们可以认为一个可能世界是让x个男士和y个女士坐在一张桌子边上玩桥牌,如果总共有4个人,则语句x+y=4为真。正式地说,可能的模型是对变量x和y进行非负整数赋值的所有可能。每个这样的赋值都确定了任何一个变量为x和y的算术语句的真值。如果语句在模型m中为真,我们说m满足
,有时也可以说m是
的一个模型。我们使用记号
来代表
的所有模型的集合。
有了真值的概念,我们就可以讨论逻辑推理了。这涉及语句之间的逻辑蕴含(entailment),即一个语句逻辑上引发另一语句。数学上,我们用
来表示语句蕴含语句
。蕴含的形式化定义是:
当且仅当在
为真的每个模型中
也为真。用刚才介绍的记法,我们可以将其写作
当且仅当
(注意此处⊆的方向:若,则
是比
更强的断言,它排除了更多的可能世界。)蕴含关系用算术来说明会更为亲切一些:我们很容易理解语句x=0蕴含语句xy=0。显然,在任一x为0的模型中,xy也必然为0(而无论y的值是多少)。
我们可以将同样的分析应用于7.2节所述的wumpus世界推理的例子。考虑图7-3b所示的情形:智能体在[1, 1]中什么都没有探测到,在[2, 1]中探测到微风。这些感知与智能体所具有的wumpus世界规则的知识一同构成了知识库。智能体所感兴趣的是相邻的方格[1, 2]、[2, 2]和[3, 1]是否有无底洞。这3个方格中的每一个都可能有或没有无底洞,因此(暂且忽略这个世界的其他方面),总共有23=8个可能的模型。图7-5展示了这8个模型。[3]
[3] 尽管该图用部分wumpus世界来表示模型,但模型实际上只是对类似“[1, 2]中有无底洞”这样的语句进行真或假的赋值。从数学的角度来看,模型中并不需要有可怕的长毛wumpus。
图7-5 方格[1, 2]、[2, 2]和[3, 1]中无底洞存在性的可能的模型。在[1, 1]中没有观测到任何东西且在[2, 1]中观测到微风的知识库用实线表示。(a)虚线表示的模型([1, 2]中没有无底洞)。(b)虚线表示
的模型([2, 2]中没有无底洞)
KB可以理解为一个语句的集合,或断言了所有单个语句的单个语句。在与智能体已知相矛盾的模型中,KB为假。例如,在所有[1, 2]含有无底洞的模型中,KB都为假,因为[1, 1]中没有微风。实际上,使KB为真的模型只有3个,这些模型在图7-5中用实线包围。我们现在考虑两个可能的结论:
=“[1, 2]中没有无底洞”
=“[2, 2]中没有无底洞”
在图7-5a和图7-5b中分别用虚线包围了和
的模型。仔细观察后,我们可以得出
在所有KB为真的模型中,也为真
因此,,即[1,2]中没有无底洞。我们还可以得出
在一些KB为真的模型中,为假
因此,KB不蕴含,即智能体无法断定[2,2]中没有无底洞。(也无法断定[2,2]中有无底洞。)[4]
[4] 智能体可以计算[2,2]中有无底洞的概率,第12章将介绍如何计算。
前述的例子不仅阐明了什么是蕴含,还展示了如何用蕴含的定义来推导出结论,即进行逻辑推断。图7-5所示的推断算法被称为模型检验,因为这个示例枚举了所有可能的模型来检验在所有KB为真的模型中都为真,即
。
将KB的所有推论的集合比作干草堆而将比做一根针或许有助于理解蕴含和推断。蕴含正如草堆中的针一样,而推断就像找到这根针的过程。一些形式化记法体现了这种区别:如果一个推断算法i可以从KB中推导出
,则记为
读作“是由i从KB中推得的”或“i从KB推得
”。
一个仅推导蕴含语句的推断算法被称为是可靠的或保真的。可靠性是极为重要的属性。一个不可靠的推断过程在运作时本质上会编造事实——它会声称发现了并不存在的针。我们很容易看出,模型检验在适用时[5]是一个可靠的程序。
[5] 如果模型空间是有限的,则模型检验是有效的,例如,在固定大小的wumpus世界中。而对算术来说,模型空间是无限的:即使我们局限于整数范围,语句x+y=4中x和y的值也是有无限多对的。
完备性也是很重要的属性:如果一个推断算法能够推导出所有蕴含的语句,则它是完备的。真正的草堆大小是有限的,对其进行全面仔细的检查就一定能确定针在不在草堆里,这似乎是很显然的道理。然而,对许多知识库来说,推论的草堆是无限的,因而完备性就成了一个重大问题。[6]幸运的是,逻辑学中有完备的推断过程,其表达能力足以处理许多知识库。
[6] 比如说,在第3章的无限搜索空间的情形中,深度优先搜索就是不完备的。
我们已经描述了一个推理过程,在前提为真的任何世界中都保证结论为真。具体来说,如果KB在真实世界中为真,则用可靠的推断过程从KB中推出的所有语句在真实世界中也为真。因此,当推断过程在“语法”(例如,寄存器中的位或大脑中的电信号模式这样的内部物理结构)上进行操作时,这个过程对应于一个真实世界的关系,即真实世界的某个部分为真是因为真实世界的其他一些部分为真。[7]这种世界与表示的对应如图7-6所示。
[7] 正如路德维希•维特根斯坦(Ludwig Wittgenstein)在其著名的《逻辑哲学论》(Tractatus)(Wittgenstein, 1922)中所述:“世界就是所有为真的一切。”
最后要考虑的问题是落地,也就是逻辑推理过程与智能体所存在的真实环境的联系。尤其是,我们如何知道KB在真实世界中为真?(毕竟KB只是存在于智能体头脑中的“语法”。)这是一个哲学问题,众多的书籍都对此进行了讨论(见第27章)。一个简单的回答是,智能体的传感器创建了这个联系。例如,我们的wumpus世界智能体有嗅觉传感器。一旦有气味,智能体程序就会创建一条合适的语句。因此,一旦这条语句被包含在知识库中,就意味着它在真实世界中也为真。这样,感知语句的含义和真值就是由产生这些语句的感知过程和语句构建过程定义的。那么智能体知识的其他部分呢?例如,它对于“wumpus相邻的方格有臭味”这件事的信念呢?这不是单个感知的直接表示,而是一项一般规则,它可能是从感知的经验推导出的,却与经验陈述并不完全相同。这种一般规则是通过被称为学习的语句构建过程产生的,这是第五部分的主题。学习是难免会出错的。一种可能的情况是,wumpus有臭味但闰年2月29日这一天除外,因为这一天它要洗澡。因此,KB在真实世界中可能并不为真,但因为有很好的学习过程,我们对此就有理由乐观。
图7-6 语句是智能体的物理结构,而推理是从旧结构构建新结构的过程。逻辑推理应当确保新结构所表示的部分世界确实能够从旧结构所表示的部分世界推得
本节讲解命题逻辑(propositional logic)。我们将阐述其语法(即语句的结构)和语义(确定语句真值的方法)。由此,我们将推导出一个简单的、语法的逻辑推断算法,它能够实现蕴含的语义概念。当然,这一切都仍将发生在wumpus世界中。
命题逻辑的语法定义合法的语句。原子语句(atomic sentence)由单个命题符号(proposition symbol)构成。每个这样的符号代表一个为真或假的命题。我们使用以大写字母开头的、可能包含其他字母或下标的符号来表示,例如P、Q、R、W1,3以及FacingEast等。我们可以任意地进行命名,但通常选择一些有助记功能的名字,例如,使用W1,3代表“wumpus位于[1, 3]”。请记住,像W1,3这样的符号是原子的,也就是说分开的W、1、3并非符号的有意义的部分。)有两个命题符号有固定的含义:True是永真命题,False是永假命题。使用括号和被称作逻辑联结词(logical connective)的运算符可以将简单语句构造成复合语句(complex sentence)。常用的联结词有5个。
● (非)。类似
这样的语句称为W1,3的否定。一个文字要么是原子语句,即正文字,要么是原子语句的否定,即负文字。
● ∧(与)。主要联结词是∧的语句称为合取式,例如,其各部分称为合取子句。(∧看起来像是“And”中的“A”。)
● ∨(或)。主要联结词是∨的语句称为析取式,例如,其各部分为析取子句,本例中分别为
和W2,2。
● (蕴涵)。如
这样的语句称为蕴涵式(implication)或条件式,其前提(premise)或前件(antecedent)是
,其结论(conclusion)或后件(consequent)是
。蕴涵式也被称为规则(rule)或if-then声明。有时,蕴涵符号在一些书籍中写作
或
。
● (当且仅当)。语句
是双向蕴涵式(biconditional)。
图7-7给出了命题逻辑的形式文法。[附录B将会介绍巴克斯-诺尔范式(Backus-Naur form,BNF)的概念。]我们在BNF文法上附加了运算符优先级,以避免在使用多个运算符时出现歧义。“非”运算符的优先级最高,这意味着在语句中,
的结合力更强,因此它等价于
而不是
。(这与普通算术一样:−2+4等于2而不是−6。)我们也会适时地使用圆括号和方括号来明确语句结构,以改善可读性。
图7-7 命题逻辑中语句的BNF文法以及从高到低排列的运算符优先级
了解了命题逻辑的语法后,我们来说明其语义。语义定义了用于判定特定模型中语句真值的规则。命题逻辑中,模型就是对每个命题符号设定真值,即真(true)或假(false)。例如,如果知识库中的语句使用了命题符号P1,2、P2,2和P3,1,则一个可能模型为
由于含有3个命题符号,因此有23=8种可能的模型,与图7-5所示的完全相同。但要注意,这些模型是纯粹的数学对象,不必与wumpus世界有关。P1,2只是符号,它可能代表“[1, 2]中有无底洞”,也可能代表“我今天和明天都在巴黎”。
命题逻辑的语义必须指定在给定模型下如何计算任一语句的真值。这是以递归的方式实现的。所有语句都是由原子语句和5个联结词构建的。因此,我们需要指定如何计算原子语句的真值和用5个联结词构建的语句的真值。对原子语句来说这很简单。
● true在每个模型里都为真,false在每个模型里都为假。
● 其余命题符号的真值必须在模型中直接指定。例如,在先前给出的模型m1中,P1,2为假。
对于复合语句,有5条规则,它们对任一模型m中的任一子句P和Q(原子语句或复合语句)都成立。
● 为真,当且仅当在m中P为假。
● 为真,当且仅当在m中P和Q都为真。
● 为真,当且仅当在m中P或Q中至少一个为真。
● 为真,除非在m中P为真而Q为假。
● 为真,当且仅当在m中P和Q都为真或都为假。
这些规则也可以用真值表表示。真值表指明在对复合语句的组成部分进行每种可能的真值赋值后,该复合语句的真值。图7-8给出了5个联结词的真值表。任一语句s关于任一模型m的真值都可以用简单的递归求值来计算。例如,在模型m1中求语句的值,得到
。习题7.TRUV要求写出算法PL-True?(s, m),用于计算命题逻辑语句s在模型m中的真值。
图7-8 5个逻辑联结词的真值表。若要使用真值表计算在P为真、Q为假时的值,首先在左边找到P为true而Q为false的行(第3行),然后找到该行位于
列处的值,得到结果true
“与”“或”“非”的真值表与我们对这些词的直观认识非常接近。可能会混淆的关键点是当P为真或Q为真,或者二者同时为真时,为真。而另一个联结词“排他或”(简称“异或”)则会在两个子句都为真时为假。[8]排他或没有公认的符号,有些人选择使用
、
或者⊕。
[8] 在拉丁语中,“或”用两个词表示:“vel”是相容或,“aut”是排他或。
⇒的真值表可能不太符合人们对“P蕴涵Q”或“若P则Q”的直观理解。一种解释是,命题逻辑并不要求P和Q之间有任何因果关系或相关性。(在一般的理解下)语句“5是奇数蕴涵东京是日本的首都”是命题逻辑中的真语句,尽管这句话相当奇怪。另一个容易混淆之处在于前件为假的所有蕴涵式都为真。例如,“5是偶数蕴涵Sam很聪明”为真,而不论Sam是否聪明。这似乎很怪异,但如果你将“”当作“如果P为真,则我可以断言Q为真,否则我无法断言”的话,就可以理解了。这条语句为假的唯一情形是当P为真而Q为假时。
当与
均为真时,双向蕴涵式
为真,英语中常写作“P if and only if Q”(P当且仅当Q)。wumpus世界的大部分规则都可以用
很好地表示。例如,当一个方格的相邻方格中有无底洞,该方格有微风,而且,仅当一个方格的某个相邻方格中有无底洞,该方格有微风。因此,我们需要使用双向蕴涵式
其中B1, 1代表[1, 1]有微风。
我们已经定义了命题逻辑的语义,现在可以为wumpus世界构建一个知识库了。首先关注wumpus世界的不变部分,后面章节再处理其可变部分。对于每个位置[x, y],需要用到下列符号:
当[x, y]有无底洞,Px, y为真。
当wumpus在[x, y],不论其死活Wx, y都为真。
当[x, y]有微风,Bx, y为真。
当[x, y]处有臭味,Sx, y为真。
当智能体位于位置[x, y],Lx, y为真。
我们写下的语句将足以推得([1, 2]中没有无底洞),正如7.3节用非形式化的方法所做的那样。我们用Ri代表每个语句,以便推导。
● [1, 1]中没有无底洞:
● 一个方格有微风,当且仅当其相邻方格中有无底洞。必须对每个方格都进行这样的表示,在此我们只写出相关方格的表示:
● 上述语句在所有wumpus世界中都为真。我们现在为智能体在这个特定世界中已访问过的前两个方格引入微风感知,以形成图7-3b所示的情形:
我们现在的目标是确定对于一些语句,
是否成立。例如,我们的KB是否蕴含
?我们的第一个推理算法是模型检验方法,它直接实现了蕴含的定义:枚举所有模型,检验
在KB为真的每个模型中是否为真。模型是对每个命题符号进行真或假的赋值。回到例子中的wumpus世界,它涉及的命题符号是B1, 1、B2, 1、P1, 1、P1, 2、P2, 1、P2, 2和P3, 1。在有7个符号的情况下,总共有27=128个可能的模型,KB在其中3个模型中为真(如图7-9所示)。在这3个模型中,
为真,因此[1, 2]中没有无底洞。但是,在3个模型中,P2, 2在其中两个模型中为真,在另一个模型中为假,因此我们还无法确定[2, 2]中是否有无底洞。
图7-9以更准确的形式再现了图7-5所示的推理。图7-10描述了一个确定命题逻辑中蕴含关系的通用算法。与6.3节所示的Backtracking-Search算法类似,TT-Entails?在符号赋值的有限空间中进行递归枚举。这个算法是可靠的,因为它直接实现了蕴含的定义;这个算法也是完备的,因为它对所有KB和都适用,并且算法最后都会终止——因为需要检验的模型数量是有限的。
图7-9 根据文中所述的知识库构建的真值表。如果从R1到R5都为true,则KB为true。这种情况在全部128行中只出现了3次(在最右侧的列中用下划线标出)。在这3行中,P1, 2均为false,因此[1, 2]中没有无底洞。但是,[2, 2]中可能有(也可能没有)无底洞
图7-10 用于确定命题蕴含的真值表枚举算法(TT代表真值表)。当语句在一个模型中成立,PL-True?返回true。变量model代表部分模型——对于部分符号的赋值。此处的关键字and不是命题逻辑中的运算符,而是伪代码编程语言中的中缀;如果其两个参数中的任意一个为true,则返回true
当然,“有限数量”并不总是等同于“少量”。如果KB和总共含有n个符号,那么就会有2n个模型。这样,算法的时间复杂性就会达到O(2n)。(空间复杂性仅为O(n),因为枚举是深度优先的。)在本章稍后部分,我们将展示一个在大多数情况下更高效的算法。遗憾的是,命题蕴含是余NP完全的(即很可能不比NP完全简单,见附录A),因此命题逻辑所有已知推断算法的最坏情况复杂性都是输入规模的指数量级。
至此,我们已经展示了如何用模型检验判定蕴含关系:枚举模型,并验证语句在所有模型中必须成立。本节将展示如何通过定理证明找出蕴含关系。定理证明对知识库中的语句直接应用推断规则,它能够在不检验模型的情况下,构建对所需语句的证明。如果模型的数量很多,但其证明很短,则定理证明会比模型检验更为高效。
在深入定理证明算法的细节之前,我们还需要了解一些与蕴含相关的概念。第一个概念是逻辑等价(logical equivalence):如果两个语句和
在相同的模型集合中都为真,则这两个语句逻辑等价,可以写作
。(注意,
用于对语句进行声明,而
则用作语句的一部分。)例如,我们可以很容易地(用真值表)证明
与
是逻辑等价的。其他逻辑等价见图7-11。这些等价关系在逻辑中扮演的角色与算术恒等式在普通数学中的角色非常相似。等价的另一种定义为“任意两条语句
和
是等价的,当且仅当它们互相蕴含”:
当且仅当
且
第二个概念是有效性(validity)。如果一条语句在所有模型中都为真,则这条语句是有效的。例如,语句是有效的。有效的语句也被称为重言式(tautology)——它们必然为真。由于语句True在所有模型中都为真,所有有效的语句都逻辑等价于True。有效语句有什么用?从蕴含的定义可以推导出古希腊人早已懂得的演绎定理(deduction theorem):
对于任意语句和
,
当且仅当语句
是有效的。
(习题7.DEDU要求对其进行证明。)因此,可以像图7-10所示的推断算法那样,通过检验是否在每个模型中为真来确定
是否成立,或者通过证明
等价于True来确定
是否成立。反过来,演绎定理表明每条有效的蕴涵语句都描述一个合法的推断。
图7-11 标准的逻辑等价。符号、
、
代表任意命题逻辑语句
最后一个概念是可满足性(satisfiability)。如果一条语句在某些模型中为真或能够被满足,则这条语句是可满足的。例如,前述的知识库中,是可满足的,因为如图7-9所示,它在3个模型中为真。可以通过枚举可能的模型,直到找出满足语句的模型来验证可满足性。在命题逻辑中确定语句的可满足性的问题——SAT问题——是第一个被证明为NP完全的问题。计算机科学中的许多问题实际上都是可满足性问题。例如,第6章的所有约束满足问题询问约束是否可以通过某种赋值来满足。
有效性和可满足性当然是有联系的:是有效的,当且仅当
是不可满足的;换言之,
是可满足的,当且仅当
不是有效的。我们还能得出下述非常有用的结论:
当且仅当语句
是不可满足的
通过检验的不可满足性,可以从
证明
,这正是数学证明方法中标准的归谬法(reductio ad absurdum,意为“归结为荒谬之物”)。它也被称为反证法或矛盾法。假设
为假,并证明这会导致与已知公理
矛盾,这个矛盾的含义与声明语句
是不可满足的完全相同。
本节介绍可以用于推导证明的推断规则。证明是一系列可以引向所需目标的结论。最著名的规则是肯定前件(Modus Ponens,mode that affirms的拉丁语),写作
它的意思是,当给出和具有
形式的语句时,可以推导出语句
。例如,如果给出
,并且已知
,可以推导出Shoot。
另一个有用的推断规则是合取消去(and-elimination),即可以从一个合取式推导出任一合取子句:
例如,由,可推导出WumpusAlive。
通过考虑和
的可能真值,可以证明肯定前件和合取消去是可靠的。这些规则可用于任意适用的实例,不必枚举所有模型就可以生成可靠的推断。
图7-11所示的所有逻辑等价都可以用作推断规则。例如,等价消去可以产生两条推断规则:
并非所有推断规则都能像上面这样双向适用。例如,不能反向运用肯定前件规则,从得出
和
。
让我们来看看这些推断规则和等价关系是如何应用于wumpus世界的。我们从含有R1到R5的知识库开始,演示如何证明,即证明[1, 2]中没有无底洞。
(1)对R2使用等价消去,得到
(2)对R6使用合取消去,得到
(3)假言易位逻辑等价关系得到
(4)对R8和感知R4(即)使用肯定前件,得到
(5)使用德摩根律,得到结论
也就是,[1, 2]和[2, 1]都没有无底洞。
应用第3章的任意搜索算法都可以找到构成这种证明的一系列步骤。只需要定义如下的证明问题。
● 初始状态(Initial State):最初的知识库。
● 动作(Actions):动作的集合,它包含所有推断规则应用于所有符合上半部分推断规则的语句。
● 结果(Result):一个动作的结果是将推断规则下半部分的语句实例加入知识库。
● 目标(Goal):目标是含有我们试图证明的语句的状态。
这样,搜索证明就可以替代枚举模型。在许多实际案例中,找出某种证明的效率更高,因为证明可以忽略许多无关的命题,不论这种命题有多少。例如,刚才给出的,得出的证明并没有提及命题B2,1、P1,1、P2,2或P3,1。由于目标命题P2,1只出现于语句R2,因此可以忽略它们;而R2中的其他命题只出现在R4和R2中,因此R1、R3和R5与证明无关。即使在知识库中再添加一百万条语句,这一结果依然成立。而简单的真值表算法将无法承受这种模型的指数级爆炸式增长。
逻辑系统的最后一个属性是单调性,它表明蕴含的语句集只能随着信息被加入知识库而增长。[9]对于任意语句和
,
[9] 违反单调性的非单调逻辑刻画了人类推理的常见性质:改变想法。我们将在10.6节对其进行讨论。
如果,则
例如,假设知识库含有额外的断言,它表明世界中恰好有8个无底洞。这条知识可能有助于智能体得出额外的结论,但它不能使任何已经得出的结论
失效,例如[1,2]中没有无底洞这样的结论。单调性意味着只要在知识库中找到合适的前提,就可以使用推断规则——规则的结论必然是合理的,不论知识库中还有什么东西。
我们已经论证了目前所说的推断规则是可靠的,但还没讨论过使用这些规则的推断算法的完备性问题。像迭代加深搜索(3.4.4节)这样的搜索算法能够找到任意的可达目标,从这种意义上说它是完备的;但如果可用的推断规则不充分,则目标是不可达的——仅使用这些推断规则的证明是不存在的。例如,如果去掉等价消去规则,7.5.1节所述的证明就行不通了。本节我们只介绍一个推断规则——归结(resolution),当它与任意完备的搜索算法结合后,可以产生一个完备的推断算法。
我们从在wumpus世界使用简单的归结规则入手。考虑导致图7-4a所示状态的步骤开始:智能体从[2, 1]返回到[1, 1],然后走到[1, 2],它在此处感知到臭味,但没有微风。我们将如下事实添加到知识库中:
用先前推得R10时使用的相同步骤,可以推出[2, 2]和[1, 3]中没有无底洞(别忘了已知[1, 1]中没有无底洞):
还可以对R3使用等价消去,然后对R5使用肯定前件,以得到[1, 1]、[2, 2]或[3, 1]中有无底洞的事实:
现在我们首次运用归结规则:R13中的文字与R15中的文字P2,2归结,得到归结句(resolvent)
用自然语言描述:如果[1, 1]、[2, 2]或[3, 1]中必有无底洞,而[2, 2]中没有无底洞,则无底洞在[1, 1]或[3, 1]中。类似地,R1中的文字与R16中的文字P1,1归结,得到
用自然语言描述:如果[1, 1]或[3, 1]中有无底洞,无底洞又不在[1, 1]中,则它在[3, 1]中。最后两步推断采用了单元归结(unit resolution)规则
其中每个都是文字,而
和m是互补文字(即各自是对方的否定)。这样,单元归结推断规则使用一个子句(文字的析取式)以及一个文字,生成一个新的子句。注意,单个文字可看作是一个文字的析取式,也被称为单元子句。
单元归结规则可以推广为全归结规则
其中,li和mj是互补文字。这表明归结使用两个子句并产生一个新的子句,该新子句包含除一对互补文字以外的原始子句的所有文字,例如,我们有
可以一次只归结一对互补文字。例如,可以归结P和推得
但不能同时归结P和Q来推得R。归结规则还有一个技术细节:结果子句只能含有每个文字的一个副本。[10]去除文字的多个副本被称为因子提取。例如,如果我们用归结
,得到
,通过因子提取简化为A。
[10] 如果一个子句被视作文字的集合,则这条限制自然地适用。对子句使用集合的概念可以使归结规则更简洁,但代价是引入了额外的记号。
通过对文字和另一个子句中的互补文字mj的讨论,我们可以很容易理解归结规则的可靠性。如果
为真,则mj为假,因此
必然为真,因为已知
。如果
为假,则
必为真,因为已知
。现无论
为真还是为假,结论必然成立,这与归结法则所述的完全相同。
归结法则更为惊人的部分在于,它形成了一类完备推断过程的基础。基于归结的定理证明器可以对命题逻辑中的任意语句和
确定
是否成立。接下来的“合取范式”和“归结算法”两小节将解释归结是如何完成这项任务的。
归结规则仅适用于子句(也就是文字的析取式),因此它似乎只能用于含有子句的知识库和查询。那么对于所有命题逻辑,它如何实现完备的推断过程?答案是,命题逻辑的所有语句逻辑上都等价于子句合取式。
形式为子句合取式的语句被称为合取范式(conjunctive normal form)或CNF(见图7-12)。下面介绍把语句转换为CNF的过程。我们通过将语句 转换为CNF来阐明这一过程。转换的步骤如下。
(1)消去,将
替换为
:
(2)消去,将
替换为
(3)CNF要求只能在文字前出现,因此我们反复应用图7-11的如下等价关系“将
内移”:
(双重否定律)
(德摩根律)
(德摩根律)
本例中,我们只需运用最后一条规则一次:
(4)现在我们得到了一个∧和∨嵌套、运算符直接作用于文字的语句。运用图7-11的分配律,尽可能地对∧分配∨:
原始语句现在已经成为CNF,是3个子句的合取式。它读起来难了很多,但它可以作为归结过程的输入。
图7-12 合取范式、霍恩子句、确定子句、目标子句的文法。形式如这样的CNF子句可以写成确定子句
基于归结的推断过程使用7.5.1节介绍的反证法来进行证明。也就是说,为了证明,我们要证明
是不可满足的。我们通过证明矛盾来做到这一点。
图7-13展示了一个归结算法。首先,被转换为CNF。然后,归结规则被应用在得到的子句上。每一对互补文字都被归结生成新的子句,如果新子句没有出现过,就将其加入子句集合。这一过程不断持续,直到发生下述的两件事情之一。
● 没有可供添加的新子句,此时KB不蕴含;
● 两个子句归结为空子句,此时KB蕴含。
图7-13 简单的命题逻辑归结算法。PL-Resolve返回对其两个输入进行归结得到的所有可能子句集合
空子句是一个没有析取子句的析取式,它等价于False,因为仅当至少一个析取子句为真时析取式为真。另外,空子句仅在归结两个矛盾的单元子句(如P和)时出现。
我们可以将归结过程用在wumpus世界中一个很简单的推断中。当智能体位于[1,1]时,该处没有微风,因此相邻的方格没有无底洞。相关的知识库是
我们要证明,即
。如果将
转换为CNF,我们就能得到在图7-14顶部所示的子句。该图的第二行列出了归结第一行后的子句。随后,当P1,2与
归结后,我们得到了空子句,用小方块表示。观察图7-14,可以发现许多归结是毫无意义的。例如,子句
等价于
,进而等价于True。推出True为真并没有什么用处。因此,我们可以忽略所有含有两个互补文字的子句。
图7-14 对wumpus世界的一个简单推断部分运用PL-Resolution来证明查询。顶行最左侧的4个子句的每一个与其他3个都互相成对,运用归结规则产生底行的子句。顶行的第3个和第4个子句结合生成
,它继而与P1,2归结,生成空子句,表明查询被证明
作为对归结的讨论的总结,现在来了解为何PL-Resolution是完备的。为此,我们引入子句集合S的归结闭包(resolution closure)RC(S),即对S中子句及其生成子句反复使用归结规则可推得的所有子句的集合。归结闭包就是RL-Resolution计算所得的变量clauses的最终值。易知RC(S)必然是有限的:得益于因子提取,由S中出现的符号P1, …, Pk得出的子句数量是有限的。因此,PL-Resolution总是能够终止。
命题逻辑中归结的完备性定理被称为基本归结定理(ground resolution theorem):
如果一个子句集是不可满足的,则这些子句的归结闭包含有空子句。
定理的证明是通过其假言易位进行的:如果闭包RC(S)不含有空子句,则S可满足。实际上,可以为S构建一个在P1, …, Pk上有适当真值的模型。构建过程如下:
对于i从1到k,
● 如果RC(S)中的子句含有文字且所有其他文字在对P1, …, Pi−1选定的赋值下为假,则对Pi赋值为false;
● 否则,对Pi赋值为true。
对P1, …, Pk的赋值是S的一个模型。要搞清楚这一点,我们假设其反面——在序列中的某处i,对符号Pi赋值使得某个子句C为假。此时,情况必然是C中所有其他文字都已经被对P1, …, Pi−1的赋值定为假。因此,C的形式必然类似或
。如果只有其中一个在RC(S)中,则算法将对Pi赋适当的值以使C为真,因此仅在这两个子句都在RC(S)中时,C才会为假。
现在,由于RC(S)在归结时是闭的,它会含有这两个子句的归结句,且这个归结句的所有文字已经被对P1, …, Pi−1的赋值定为假。这与我们的假设,即第一个为假的子句出现在i处矛盾。因此,我们证明了这种构建永远无法使RC(S)中的子句为假,也就是说它创建了一个RC(S)的模型。最后,由于S包含在RC(S)中,因此任意RC(S)的模型也是S本身的模型。
归结的完备性使其成为一种非常重要的推断方法。而许多实际情形并不需要用到归结的全部能力。一些真实世界的知识库中的语句满足某些限制,这使得它们可以使用更为受限而更高效的推断算法。
其中一种受限形式是确定子句(definite clause),它是文字的析取式,其中只有一个为正文字。例如,子句是确定子句而
不是,因为它含有两个正文字。
更一般性的是霍恩子句(Horn clause),它是文字的析取式,其中最多只有一个为正文字。因此所有的确定子句都是霍恩子句,没有正文字的子句也是霍恩子句——也被称为目标子句(goal clause)。霍恩子句在归结时是闭的:如果归结两个霍恩子句,仍然会得到霍恩子句。还有一种类型是k-CNF语句,它是每个子句最多含有k个文字的CNF语句。
仅含有确定子句的知识库很有意义,原因有3个。
(1)每个确定子句都可以写成一个蕴涵式,前提是正文字的合取式,结论是一个正文字。(见习题7.DISJ。)例如,确定子句可以写成蕴涵式
。蕴涵形式的语句更容易理解:它说明如果智能体位于[1, 1],且感知到微风,则[1, 1]有微风。在霍恩形式中,前提被称为体(body)而结论被称为头(head)。由单个正文字构成的语句,例如L1,1,被称为事实(fact)。它也可以写成
形式的蕴涵式,但只写成L1,1更为简洁。
(2)用霍恩子句进行推断可以通过前向链接(forward-chaining)算法和反向链接(backward-chaining)算法完成,我们稍后会介绍。这些算法都很自然,因为它们的推断步骤很直观,便于人类理解。这类推断是逻辑编程(logic programming)的基础,我们将在第9章进行讨论。
(3)用霍恩子句确定蕴含关系所需的时间与知识库大小呈线性关系,这格外令人满意。
前向链接算法PL-FC-Entails?(KB,q)确定单个命题符号q(即查询)是否被确定子句的知识库所蕴含。它从知识库中的已知事实(正文字)开始。如果一个蕴涵式的所有前提都已知,则将其结论添加到已知事实的集合中。例如,如果L1,1和Breeze已知,且在知识库中,则在知识库中添加B1,1。这一过程持续进行,直到查询q被添加,或直到无法进一步进行推断。这一算法在图7-15中展示,我们要记住的要点是它的运行时间是线性的。
用图和示例来理解算法是最好的办法。图7-16a展示了一个简单的霍恩子句知识库,其中有A和B两个已知事实。图7-16b展示了绘制为与或图(见第4章)的同一个知识库。在与或图中,用曲线连接的多个边表示一个合取式,每个边都要证明;而没有曲线连接的多个边表示一个析取式,证明任一边即可。图上很容易看懂前向链接是如何运作的。已知的叶节点(此处为A和B)具有真值之后,推断就会沿着图尽可能远地向上传递。当出现合取式时,传递过程开始等待,直到所有合取子句都已知。我们鼓励读者细致地研究这个示例。
图7-15 命题逻辑的前向链接算法。queue记录了已知为真但还没“处理过”的符号。表count记录每个蕴涵式尚未证明的前提数量。一旦queue中的新符号p被处理,count就会为每个前提中出现p的蕴涵式减1(使用合适的索引方法,很容易在常数时间内完成)。如果count为0,则蕴涵式的所有前提都已知,因此其结论可以添加到queue。最后,我们还需要记录哪个符号已经被处理过,如此在已推断符号集inferred中的符号就无需被再次加入queue。这避免了重复的工作,也避免了由类似P⇒Q和Q⇒P这样的蕴涵式引起的循环
图7-16 (a)一个霍恩子句集。(b)相应的与或图
显然,前向链接是可靠的:每个推断实际上都是对肯定前件的运用。前向链接也是完备的:所有蕴含的原子语句都将被推得。要理解这一点,最简单的方法是考虑(在算法到达不动点,无法产生新推断的时候)inferred表格的最终状态。该表中每个推得的符号都为真,所有其他符号都为假。我们可以将这个表看作一个逻辑模型,且原始KB的每条确定子句在这个模型中都为真。
为理解这一点,可以假设其反面,即存在子句在模型中为假。则
在模型中必然为真,且b在模型中必然为假。这与我们假设的算法已经到达不动点相矛盾,因为我们此时可以将b加入知识库。因此我们可以断定,不动点处推得的原子语句集定义了一个原始知识库的模型。更进一步地,知识库蕴含的任意原子语句q必然在其所有模型中都为真,在这个特定模型中也一样。因此,所有蕴含的原子语句q必然会被算法推得。
前向链接是数据驱动(data-driven)推理这一更广泛概念的例子,也就是其注意力开始集中在已知数据的推理。它可以用于智能体,以便从收到的感知推导出结论,且常常是在没有特定查询的情况下。例如,wumpus世界的智能体可以用递增前向链接算法(即新的事实可以被加入队列来启动新的推断)将它的感知告知知识库。对人类来说,当获取新信息后会出现一定数量的数据驱动推理。例如,如果我在屋子里听到外面开始下雨,则我可能会想到取消野餐;但是,我大概不会想到邻居花园里最大的一朵玫瑰的第17片花瓣会淋湿——人类会对前向链接进行精心地控制,以免被无关的结果淹没。
反向链接算法如其名称所示,从查询开始反向运作。如果查询q已知为真,则不需要做任何操作。否则,算法将在知识库中找寻结论为q的蕴涵式。如果这些蕴涵式的所有前提都可以(用反向链接)证明为真,则q为真。将反向链接算法用于图7-16的查询Q时,它反向地向图的下方运行,直到到达构成证明基础的已知事实集,即A和B。算法实质上与图4-11的And-Or-Graph-Search算法完全相同。与前向链接一样,它的高效实现的时间复杂性是线性的。
反向链接是一种目标导向推理(goal-directed reasoning)。它对于回答类似“我现在该做什么?”和“我的钥匙在哪里?”这样的特定问题非常有用。通常,反向链接的代价远小于知识库规模的线性变化,因为这个过程仅涉及相关的事实。
本节,我们介绍两种高效的、基于模型检验的一般命题推断的算法,其中一种是基于回溯搜索的,另一种则基于局部爬山搜索。这些算法是命题逻辑的“技术”部分。首次阅读本章时可以略过本节内容。
我们描述的算法是用于可满足性检验的,即SAT问题。(如7.5节所述,可以通过检验的不可满足性来检验蕴含
。)我们在7.5节中提到过找到满足逻辑语句的模型与找到约束满足问题的解的关系,因此这两种命题可满足性算法与6.3节的回溯算法和6.4节的局部搜索算法非常相似并不令人意外。尽管如此,这些算法本身还是极为重要的,因为许多计算机科学中的组合问题都可以被归为检验命题语句的可满足性。对可满足性算法的任何改进对于我们处理复杂性的能力都有巨大的作用。
我们要探讨的第一个算法常称为戴维斯-普特南算法(Davis-Putnam algorithm),得名于马丁·戴维斯(Martin Davis)和希拉里·普特南(Hilary Putnam)的重要论文(Davis and Putnam, 1960)。这个算法实际上采用的是戴维斯、洛吉曼和洛夫兰所描述的版本(Davis, Logemann, and Loveland, 1962),因此我们用所有4位作者姓氏的首字母DPLL命名这个算法。DPLL使用一个合取范式形式(即一个子句集)的语句作为输入。类似于Backtracking-Search和TT-Entails?,它本质上是递归地、深度优先地枚举可能的模型。它在TT-Entails?的基础上进行了3项改进。
● 提前终止:算法可以用部分完成的模型来检测语句是否必然为真或为假。如果任一文字为真则子句为真,即使其他文字还没有真值;这样,整条语句在模型完成之前就可以断定其真值。例如,若A为真则语句为真,无论B和C的值是什么。类似地,若任一子句为假,即其所有文字为假,则语句为假。同样,这种情形可能会在模型完成前很久就发生。提前终止避免了在搜索空间中检查全部子树。
● 纯符号启发式方法:纯符号是指在所有子句中“符号位”都相同的符号。例如,在3个子句、
和
中,A是纯符号,因为它只以正文字的形式出现;B也是纯符号,因为它总以负文字的形式出现。而C是不纯的。易知如果一条语句有模型,则存在一个模型对纯符号的赋值使其文字为真,因为这样做不会使子句为假。注意,在确定符号是否为纯时,算法可以忽略当前已构建的模型中已知为真的子句。例如,如果上述模型含有B=false,则子句
已经为真,且在剩余子句中C仅作为正文字出现,因此C变为纯符号。
● 单元子句启发式方法:之前对单元子句的定义是只有一个文字的子句。在DPLL中,它也指那些除了一个文字外,其余文字都被模型赋值为false的子句。例如,如果模型含有B = true,则简化为
,这是一个单元子句。显然,要使这个子句为真,C必须赋值为false。单元子句启发式方法在余下的部分出现分支前对所有这样的符号赋值。这种启发式的一个重要结果是,所有对知识库中的已有文字进行的证明(通过反证法)将立刻得证(见习题7. KNOW)。还要注意的是,对一个单元子句赋值可能会创建另一个单元子句,例如,当C被置为假,
也变成了单元子句,使得A被赋值为真。这种强制赋值的“级联”被称为单元传播(unit propagation)。这类似于确定子句的前向链接。实际上,如果CNF表达式仅含有确定子句,则DPLL本质上复制了前向链接。(见习题7. DPLL。)
DPLL算法如图7-17所示,它给出了搜索程序的主要结构,但并未实现其细节。
图7-17 用于检验命题逻辑语句可满足性的DPLL算法。Find-Pure-Symbol和Find-Unit-Clause背后的思路在正文中进行了介绍。这两个函数都返回一个符号(或返回空)以及要赋给这个符号的真值。和TT-Entails?一样,DPLL在部分模型上运行
图7-17没有展示使SAT求解器能够用于大规模问题的技巧。有趣的是,这些技巧实际上都很寻常,我们之前已经见过它们的其他形式。
(1)分量分析(如CSP中的塔斯马尼亚岛问题所见):当DPLL为变量赋真值时,子句集可能会被分割成不相交的子集,我们称之为分量,它们没有共同的未赋值变量。给定一个高效探测这一状况的方法,求解器就可以通过对每个分量独立求解来加快速度。
(2)变量排序与值排序(如在6.3.1节的CSP中所见):我们对DPLL的简单实现使用任意的变量顺序,并在赋值时总是先尝试赋真再尝试赋假。度启发式算法(6.3.1节)建议在所有剩余子句中优先选择最常出现的变量。
(3)智能回溯(如在6.3.3节的CSP中所见):许多用按时序回溯几小时都求解不了的问题,如果改用智能回溯直接回溯到导致冲突的相关点上,那么问题可以在几秒内求解。所有运用智能回溯的SAT求解器都使用冲突子句学习的某种形式来记录冲突,以避免在后续的搜索中重复出现。通常只保留有限大小的冲突集,丢弃极少使用的冲突。
(4)随机重启(在4.1.1节用于爬山法):有时单次运行似乎无法取得进展。此时,我们可以从搜索树的顶端重新开始,而非尝试继续搜索。重启后(对变量和值选取)进行不同的随机选择。第一次运行中学习到的子句在重启后依然被保留,这有助于对搜索空间进行剪枝。重启并不保证能更快地找到解,但它能够减小求解时间的方差。
(5)聪明索引(在许多算法中可以见到):DPLL和其他现代求解器用到的加速方法需要快速索引“Xi作为正文字出现的子句集合”。这一任务相当复杂,因为算法所感兴趣的只是先前的变量赋值尚未满足的子句,因此索引结构必须在计算过程中动态更新。
有了这些改进,现代求解器可以处理有数千万个变量的问题。它们为诸如硬件验证和安全协议验证这样的领域带来革命性的变化。在此之前,这些领域需要十分费力的、手动证明。
我们已经在本书中见过了一些局部搜索算法,包括Hill-Climbing(4.1.1节)和Simulated-Annealing(4.1.2节)。只要我们选择了正确的评价函数,这些算法可就以被直接用于可满足性问题。由于目标是找出满足所有子句的赋值,一个对未满足的子句进行计数的评价函数就可以胜任这项工作。实际上,这正是用于CSP的Min-Conflict算法所使用的量度(见6.4节)。这些算法都在完全赋值的空间采取动作,每次只翻转一个符号的真值。这个空间通常含有许多局部极小值,要跳出这些极小值,需要各种形式的随机方法。近年来,人们进行了大量实验,试图在贪婪性与随机性之间找到一个良好的平衡。
这些算法中最为简单和有效的算法之一是WalkSAT(如图7-18所示)。算法每次循环都选择一个未满足的子句,并在该子句中选择一个符号来翻转。选择要翻转的符号的方法有两种:(1)最小化新状态中未满足子句的数量的“最小冲突”方法;(2)随机挑选一个符号的“随机游走”方法。算法随机选取一种。
图7-18 通过随机翻转变量的值来检验可满足性的WalkSAT算法。这个算法有很多版本
当WalkSAT返回一个模型时,输入语句就是可满足的。但当它返回failure时,则有两种可能的原因:语句不可满足,或我们需要多给算法一些时间。如果我们设定且p
0,WalkSAT最终将返回一个模型(如果存在的话),因为随机游走步骤终将遇到一个解。如果max_flips为无穷大,而语句不可满足,则算法永远不会终止!
因此,当我们预计问题有解的时候,WalkSAT最为有用。例如,第3章和第6章讨论过的问题通常有解。但是,WalkSAT并不总是能检测到不可满足性,而对判定蕴含来说这是必备的。例如,wumpus世界中,一个智能体不能使用WalkSAT来可靠地证明一个方格是安全的。不过,它可以说:“我思考了一小时,都想不出存在一种这个方格不安全的可能世界。”这也许是个不错的经验性指示,表明方格是安全的,但它绝对不是一种证明。
某些SAT问题比其他要难。简单的问题可以用任意老算法求解,但由于我们知道SAT是NP完全的,至少有一些问题必须需要指数级的运行时间。在第6章中,我们见过一些针对某种问题的惊人发现。例如,对于回溯搜索算法,n皇后问题被认为是相当困难的,而对于局部搜索方法,如最小冲突法,求解这一问题却非常容易。这是由于在赋值空间中,解的分布非常密集,任意初始赋值都能保证在其附近存在解。因此,n皇后问题很简单,因为它是欠约束的(underconstrained)。
当我们考虑合取范式的可满足性问题时,一个欠约束的问题是约束变量的子句非常少的情形。例如,下面是一条随机生成的3-CNF语句,它有5个符号和5个子句:
在32个可能的赋值中,有16个是这条语句的模型。因此,平均而言,只需进行两次随机猜测就可以找到一个模型。与大部分这样的欠约束问题一样,这是一个简单的可满足性问题。但是,一个过约束的问题很可能没有解,因为相对于其变量数量,其子句数量过多。过约束问题通常很容易求解,因为这些约束将很快导致算法找出一个解,或进入无法逃离的死胡同。
要超越这些基本的直观理解,我们必须明确定义如何生成随机语句。记法CNFk(m, n)表示一个有m个子句、n个符号的k-CNF语句,其中子句是均匀地、独立地、无放回地从所有有k个文字的子句中选取的,文字的正负也是随机的。(一个符号在子句中不能多次出现,一个子句也不能在语句中多次出现。)
给定一个随机语句源,我们就可以测量可满足性的概率。图7-19a绘制了CNF3(m, 50)的概率,也就是有50个变量、每条子句有3个文字的语句,这一概率被绘制为子句/符号,即m/n的函数。如我们预期,对于较小的m/n,可满足性的概率接近0,而在较大的m/n处这一概率接近0。概率在m/n = 4.3左右急剧下降。经验上,我们发现这一“峭壁”出现在大致相同的位置(对于k = 3),并随着n的增长越来越陡峭。
理论上,可满足性阈值猜想(satisfiability threshold conjecture)表明对所有,存在一个阈值比rk,使得当n接近无穷时CNFk(rn, n)可满足的概率对于所有低于阈值的r接近于1,对于所有高于阈值的r接近于0。即便对于如k = 3这样的特例,这一猜想仍未被证明。不论这是不是一个定理,这样的阈值效应在可满足性问题和其他类型的NP困难问题中都是相当寻常的。
现在我们对可满足和不可满足问题分别会出现在什么地方有了很好的了解,接下来的问题是,困难的问题会出现在什么地方?其实它们也经常位于阈值处。图7-19b显示,阈值4.3处的50个符号的问题比阈值3.3处的相同问题大约难20倍。欠约束问题很好求解(因为很容易就能猜到一个解),而过约束问题不如欠约束问题简单,却仍然比恰好在阈值处的问题简单得多。
图7-19 (a)有n个符号的随机3-CNF语句的可满足概率图,概率是子句/符号比m/n的函数。(b)DPLL和WalkSAT在随机3-CNF语句上的(多次运行后测量的)运行时间中位数图。最为困难的问题的子句/符号比约为4.3
本节我们将目前所学的内容结合起来构建使用命题逻辑的wumpus世界智能体。首先我们要使智能体能够根据其历史感知对世界的状态尽可能地进行推导。这需要写出动作效果的完整逻辑模型。随后我们介绍智能体在wumpus世界中如何使用逻辑推断。我们还会介绍智能体如何在不查看每次推断的历史感知的情况下有效地跟踪世界的变化。最后,我们介绍在已知其知识库在实际世界中为真的情况下,智能体如何使用逻辑推断来构建能确保达到目标的规划。
如本章开头所述,逻辑智能体通过用关于世界的语句知识库推导接下来的动作来运作。知识库由公理(也就是关于世界如何运行的一般知识)和从智能体在某个特定世界获得的感知语句构成。本节,我们聚焦于推导wumpus世界的当前状态这一问题,如我在哪里、方格是否安全等。
我们从7.4.3节开始收集公理。智能体知道起始方格没有无底洞()也没有wumpus(
)。此外,对于每个方格,它知道当且仅当一个方格的相邻方格有无底洞,该方格有微风;当且仅当一个方格的相邻方格有wumpus,该方格有臭味。由此,我们引入了具有如下形式的大量语句:
智能体还知道恰恰只有一个wumpus。我们用两部分表示。首先,我们说至少有一个wumpus:
然后我们必须说最多只有一个wumpus。我们对每对方格添加一个语句,来表明其中至少一个方格没有wumpus:
到目前为止都还不错。现在让我们考虑智能体的感知。我们使用了S1,1来表示[1, 1]有臭味,那么我们可以只用一个命题Stench来表示智能体感知到臭味吗?遗憾的是,不行。如果在之前的时间步中没有臭味,就已经被断言,那么新的断言将与之矛盾。我们发现,如果感知只对当前时间的事情进行断言,这个问题就很容易求解。如此,假如时间步(与输入图7-1中Make-Percept-Sentence的一样)是4,则我们在知识库中添加Stench4而非Stench,这样就能轻松地避免与
矛盾。对微风、碰撞、闪光和惨叫等感知也同样处理。
这个将命题与时间步相关联的思路可以拓展到这个世界中所有随时间变化的部分。例如,最初知识库中有——智能体在时刻0位于[1, 1],以及FacingEast 0、HaveArrow 0和WumpusAlive0。
我们使用流(fluent,源于拉丁语fluens,意为流动)来表示世界随时间变化的部分。“流”与2.4.7节所述的对因子化表示的讨论中的“状态变量”同义。与世界的不变部分相关的符号不需要时间上标,它们有时被称为非时序变量(atemporal variable)。
我们可以将微风和臭味直接与体验到这些感知的方格的属性连接。[11]对任意时间步t和任意方格[x, y],我们断言
[11] 7.4.3节出于简便考虑,隐藏了这项要求。
当然,现在我们需要能够使智能体跟进像这样的流的公理。智能体采取动作会改变这些流,因此,用第3章的术语来说,我们需要将wumpus世界的转移模型写成逻辑语句的集合。
首先我们需要表示发生动作的命题符号。与感知一样,这些符号用时间索引。因此Forward 0表示智能体在时刻0执行前进动作。习惯上,给定时间步的感知先发生,然后是这个时间步上的动作,然后是到下一个时间步的转移。
为描述世界如何变化,我们可以试着写出指明动作在下一个时间步产生的结果的效应公理(effect axiom)。例如,如果智能体位于[1, 1],在时刻0时面朝东并向前走,结果是智能体位于方格[2, 1]且不再在[1, 1]:
(7-1)
对每个可能的时间步、16个方格中的每一个方格、4个方向中的每一个方向我们都需要类似这样的语句。对于其他动作,即抓取、射击、攀爬、左转、右转我们也需要类似的语句。
假设智能体在时刻0决定向前移动,并在其知识库对此进行了断言。给定式(7-1)的效应公理,结合时刻0时对状态的初始断言,智能体可以推得它位于[2, 1]。也就是,Ask。到目前为止,一切还好。遗憾的是,如果我们Ask(KB, HaveArrow1),答案会是假,也就是智能体无法证明它仍然有箭,它也无法证明它没有箭!信息丢失了,因为效应公理没有说明动作的结果未改变哪些状态。对这项功能的需求引出了框架问题。[12]框架问题的一个可能的求解办法是明确地添加断言所有不变命题的框架公理。例如,对于每个时刻t,我们有
[12] “框架问题”(frame problem)的名字来源于物理学中的参照系(frame of reference),也就是测量运动时假设的静止背景。电影的帧(frame)也借用了它的含义,其中前景变化时,大部分背景保持静止。
其中明确地提到了在采取前进动作时所有从时刻t到时刻t+1维持不变状态的命题。尽管智能体现在已经知道它在前进后仍然有箭,且wumpus没有死去或复活,但激增的框架公理似乎相当低效。在有m个不同动作和n个流的世界,框架公理集的大小为O(mn)。这种框架问题被称作表示框架问题。这个问题在人工智能史上扮演过重要的角色,我们在本章最后的参考文献与历史注释中将进行进一步探索。
表示框架问题很重要,因为即便保守来说,真实世界中的流也很多。幸运的是,对我们人类来说,每个动作改变的流通常不多于k个(k是某个较小的值),也就是说世界具有局部性。求解表示框架问题需要定义公理集大小为O(mk)而非O(mn)的转移模型。还有一个问题是推断框架问题:将t步动作规划的结果在O(kt)时间而非O(nt)时间内前向推进的问题。
问题的解是关注于写出关于流而非动作的公理。这样的话,对于每个流F,以时刻t时的所有流(包括F本身)和时刻t时可能发生的动作来定义Ft+1的真值的公理。现在,Ft+1的真值可以用两种方法之一来确定:一种是时刻t的动作导致F在t+1为真,另一种是F在时刻t已经为真而时刻t的动作没有导致它为假。这种形式的公理叫作后继状态公理(successor-state axiom),具有如下形式:
有箭(HaveArrow)的公理是最简单的后继状态公理。因为没有重新装填箭支的行动,ActionCausesFt部分可以去掉,所以我们有
(7-2)
对智能体的位置来说,后继状态公理要更为复杂。例如,如果(a)智能体在面向南方时从[1, 2],或面向西方时从[2, 1]向前移动,或者(b)已经为真且动作未产生移动(因为动作不是向前或动作导致撞墙),则
为真。用命题逻辑写出,就是
(7-3)
习题7.SSAX要求写出剩余的wumpus世界的流的公理。
给定完整的后继状态公理和本节开始列出的其他公理,智能体就能够询问和回答世界当前状态的所有可解答问题。例如,在7.2节,感知和动作的初始序列是
此时,有Ask,因此智能体知道它在什么位置。而且,Ask
和Ask
,因此智能体已经找到了wumpus和一个无底洞。对于智能体最重要的问题是一个方格是否能够进入,也就是这个方格是否没有无底洞也没有wumpus。为此添加公理很容易,形式如下:
最后,Ask,因此方格[2, 2]可以安全进入。实际上,给定一个如DPLL的可靠且完备的推断算法,智能体可以回答关于哪个方格安全的任意可解答问题,而且对于小型到中型的wumpus世界可以在几毫秒内完成回答。
求解表示框架问题和推断框架问题是一步重大的前进,但仍有一个亟待解决的问题:我们需要确认一个动作的所有必要的前提都成立才能保证结果效应。我们说过向前动作使智能体向前方移动,除非前方有墙,但也有许多其他意外会导致动作失败:智能体可能会被绊倒,会犯心脏病,会被巨型蝙蝠抓走,诸如此类。明确所有这些意外被称为资格问题(qualification problem)。它在逻辑学的范畴内没有完备的解,在决定要多么详细地明确模型以及要忽略哪些细节时,系统设计者必须做出很好的判断。我们将在第12章中看到,概率论允许以非显式的方式总结所有意外。
推导世界状态的多个方面的能力可以直接与条件-动作规则(见2.4.2节)以及第3章和第4章的问题求解算法结合,产生一个wumpus世界的混合智能体。图7-20展示了达成这个目标的一种可能方式。智能体程序维护并更新一个知识库和一个当前规划。初始知识库含有非时变公理——不依赖于时间t的公理,例如将方格的微风与无底洞的存在联系起来的公理。在每个时间步,新的感知和所有依赖于t的公理,如后继状态公理,被加入知识库。(7.7.3节将解释为何智能体不需要未来时间步的公理。)然后,智能体通过向知识库询问来使用逻辑推断,以找出哪些方格是安全的且未被访问过。
智能体程序的主体根据目标优先级降序创建一个规划。首先,如果存在闪光,则程序创建一个抓取金块、原路返回初始位置并爬出洞穴的规划。否则,如果没有当前规划,程序会规划一个前往最近的、未被访问过的安全方格的路线,并确保路线仅经过安全方格。
路径规划使用A*搜索算法完成,而没有用Ask。如果没有可探索的安全方格,下一步——如果智能体还有箭的话——就是试图对一个可能有wumpus的位置射击来创造一个安全方格。这是通过询问Ask在何处为假完成的,也就是智能体还不知道的没有wumpus的地方。函数Plan-Shot(图中未展示)使用Plan-Route规划一系列动作来完成这次射击。如果失败,则程序寻找尚未证明是不安全的方格,也就是询问Ask
返回假的方格。如果不存在这样的方格,则任务不可能完成,智能体撤退到[1, 1]并爬出洞穴。
图7-20 wumpus世界的一个混合智能体。它使用命题知识库来推断世界的状态,结合问题求解搜索和论域特定代码来选择动作。每次调用Hybrid-Wumpus-Agent,它都会将感知添加到知识库,然后依据先前定义的规划或创建一个新规划,弹出这个规划的第一步作为下一个要采取的动作
图7-20所示的智能体工作得不错,但它有一个重大弱点:随着时间流逝,涉及对Ask调用的计算开销不断增大。这主要是由于所需的推断不得不回到越来越早的时间点,并涉及越来越多的命题符号。显然,这是不可持续的——我们不能让一个智能体处理每次感知的时间随着其寿命的增长成比例地增加!我们真正需要的是常数更新时间,也就是,与t无关。一个显然的答案是保存或缓存(cache)推断的结果,以便下一个时间步的推断过程构建在先前的结果上,而非必须从零开始。
如我们在4.4节所见,感知的历史和所有其后果都可以用信念状态代替,即对所有可能的当前世界状态集合的某种表示[13]。在新感知到来时更新信念的过程被称为状态估计(见4.4.4节)。而在4.4节,信念状态是状态的显式列表,此处我们可以使用含有关于当前时间步的命题符号,以及非时变符号的逻辑语句。例如,逻辑语句
[13] 我们可以认为感知历史本身就是一个信念状态的表示,但它是一个随着历史变长使得推断代价逐渐增加的表示。
(7-4)
代表时刻1的所有状态的集合,这时wumpus还活着,智能体位于[2, 1],方格中有微风,[3, 1]或[2, 2]其中之一有无底洞或两个都有无底洞。
维护一个精确的、逻辑公式形式的信念状态并不简单。如果对于时刻t有n个流符号,则会有2n个可能的状态,也就是对这些符号的所有赋值。而现在,信念状态的集合是物理状态的超集(所有子集的集合)。总共有2n个物理状态,因此有个信念状态。即便我们对逻辑公式尽可能地使用紧凑的编码方式,即每个信念状态用一个二进制数表示,我们也需要
位来标记当前的信念状态。也就是说,精确的状态估计需要的逻辑公式的规模可能是符号数量的指数级别的。
一个用于近似状态估计的常见且自然的方法是用文字的合取式表示信念状态,即1-CNF公式。为此,智能体程序只需要在给定时刻t−1的信念状态的情况下,为每个符号X t证明X t和 (以及真值未知的非时变符号)即可。可证明文字的合取式成为了新的信念状态,先前的信念状态被丢弃。
要了解的是,随着时间流逝,这个方法可能会损失一些信息。例如,如果式(7-4)的语句是真正的信念状态,则P3,1和P2,2都无法被单独证明,也都不会出现在1-CNF信念状态中。(习题7.HYBR探索了这一问题的一个可行的解法。)另外,由于1-CNF信念状态中的每一个文字都是由前一信念状态证得的,而且初始信念状态是一个真实的断言,可得出整个1-CNF信念状态必然为真。因此,1-CNF信念状态所表示的可能状态的集合包含了给定全部感知历史时的所有确实可能的状态。如图7-21所示,1-CNF信念状态就是准确信念状态的一个外包络,即保守近似(conservative approximation)。我们可以在人工智能的许多领域反复见到复杂集合的保守近似这一概念。
图7-21 1-CNF信念状态(粗实线外轮廓)作为对准确信念状态(虚线轮廓的深色区域)的简单的、可表示的保守近似。每个可能世界都使用圆圈表示,深色圆圈与所有感知一致
图7-20所示的智能体使用逻辑推断来确定哪个方格是安全的,但使用了A*搜索来进行规划。本节展示如何通过逻辑推断来进行规划。它的思想非常简单。
(1)构建一个语句,它含有:
a. 对于初始状态的断言集Init0;
b. 到最大为时刻t为止的每一时间步的所有可能动作的后继状态公理
;
c. 目标在时刻t达成的断言。
(2)将所有语句提供给SAT求解器。如果求解器找到一个可满足的模型,则目标是可达成的;如果语句不可满足,则问题无解。
(3)假设找到了一个模型,从模型中提取代表动作并被赋值为true的变量。它们代表一个达成目标的规划。
图7-22展示了一个命题规划程序SATPlan。它实现了上述的想法,仅做了一点改变。由于智能体并不知道它需要多少步才能达成目标,算法会尝试每个可能的t步,直到某个可行的最大规划长度Tmax。这样,如果这一规划存在的话,它能够确保找到最短的规划。由于SATPlan搜索解的特定方式,它无法在部分可观测的环境中使用;SATPlan只能将不可观测的变量设定为它所需的值来求解。
图7-22 SATPlan算法。规划问题被转换为CNF语句,其中目标被断言在固定的时间步t时成立,到t为止的每个时间步都含有公理。如果可满足性算法找到了一个模型,则通过查看指向动作并在模型中被赋值为true的命题符号来提取规划。如果模型不存在,则将目标后移一步,重复这一过程
使用SATPlan的关键步骤是构建知识库。大体来看,7.7.1节所述的wumpus世界公理似乎足以构成上述步骤1中的a和b。但蕴含(正如用Ask来检验的那些)和可满足性对公理的要求有重要的区别。
例如,考虑智能体的位置初始为[1, 1],假设智能体的目标仅为在时刻1时移动到[2, 1]。初始知识库含有,目标为
。如果断言Forward0,则我们可以使用Ask证得
;如果被断言的是Shoot0,则我们无法证得
。现在,SATPlan会找到规划[Forward0],目前看起来没什么问题。
遗憾的是,SATPlan也会找到规划[Shoot0]。为什么会这样呢?要找出其原因,先检查一下SATPlan构建的模型:它包括赋值,也就是智能体可以在时刻0时就位于[2, 1]并进行射击,故而在时刻1时也会在[2, 1]。有人会问:“我们不是刚说过智能体在时刻0时位于[1, 1]吗?”的确如此,但我们没有告诉智能体它不能同时位于两个位置!对蕴含来说,
是未知的,因此不能被用于证明;而对于可满足性,
是未知的,因此可以被设定为任意有助于达成目标的值。
对知识库来说,SATPlan是很好的调试工具,因为它能够暴露出知识缺失的地方。在这个例子中,我们可以使用类似于用来断言恰恰只存在一个wumpus的语句集,来断言在每个时刻智能体只能位于一个位置,以修复知识库。或者,我们可以对除[1, 1]之外的所有位置断言;关于位置的后继状态公理用于处理之后的时刻。相同的修复方式也可以用于确保智能体在一个时刻有且仅有一个朝向。
但SATPlan还有更怪异的表现。首先是,它会找出含有不可能采取的动作的模型,例如在没有箭支的时候射击。要理解其原因,我们需要更为仔细地查看后继状态公理,如式(7-3),对于前提无法满足的动作的描述。公理的确正确地预测了执行这种动作不会产生任何结果(见习题7.SATP),但它没有表明这一动作不能被执行!要避免生成含有不合规动作的规划,我们必须加入表明动作的出现需要满足其前提的前提公理(precondition axiom)。[14]例如,我们需要说,对于每个时刻t,有
[14] 注意,加入前提公理意味着我们不再需要在后继状态公理中包含动作的前提条件。
这就确保了如果规划在某一时刻选择采取动作Shoot,则此时智能体必然有一支箭。
SATPlan的另一个怪异的行为是它会创建具有多个同时进行的动作的规划。例如,它会生成一个Fotward0和Shoot0都为真的模型,而这是不允许的。要解决这个问题,我们引入动作排除公理(action exclusion axiom):对于每对动作和
,我们加入公理
可能有人会提出同时向前走并射击并不是很困难,但如果是同时抓取并射击的话就相当不现实了。通过只对相互冲突的每对动作施以动作排除公理,可以使规划同时含有多个动作——而由于SATPlan能找出最短的合规规划,我们就可以确定它能够利用同时动作这个能力。
总之,SATPlan能对含有初始状态、目标、后继状态公理、前提公理和动作排除公理的语句找出模型。由于不再存在任何错误的“解”,我们可以证明这一公理集是充分的。所有满足命题语句的模型都将是原始问题的有效解。现代SAT求解技术使得这一方法相当实用。例如,一个DPLL风格的求解器可以毫不费力地生成图7-2所示的wumpus世界的解。
本节已经讲过构建智能体的一个陈述性方法:智能体通过结合在知识库中断言语句和执行逻辑推断运行。这种方法有一些弱点,它们就隐含于类似“对于每个时刻t”和“对于每个方格[x, y]”这样的表述中。对于所有实用的智能体,这些表述必须用从一般语句模式中自动生成实例的代码来实现,这些实例被用于插入知识库中。对于一个规模适中(相当于小型计算机游戏的大小)的wumpus世界,我们可能需要一个100×100的场地和1000个时间步,这样的话知识库中的语句就会有上亿条之多。
这种情况不仅相当不现实,也揭露了一个深层次的问题:我们对wumpus世界的理解(即它的“物理学”在所有方格和所有时刻都一样)不能直接用命题逻辑的语言来表示。要解决这个问题,我们需要更有表达能力的语言,也就是那种可以自然地写出像“对于每个时刻t”和“对于每个方格[x, y]”这种表述的语言。第8章所述的一阶逻辑就是一种这样的语言。在一阶逻辑中,任意大小、任意时长的wumpus世界都可以用大约10条逻辑语句来描述,而非1000万条乃至1万亿条。
我们已经介绍了基于知识的智能体,也展示了如何定义一种逻辑,以便使这种智能体能够对世界进行推理。本章重点如下。
● 智能体需要关于世界的知识来获得良好的决策。
● 知识包含在智能体中,其形式为存储于知识库中的、用知识表示语言表述的语句。
● 一个基于知识的智能体由一个知识库和一套推断机制组成。它的运作方式是在知识库中存储关于世界的语句,使用推断机制推断新语句,并使用这些语句来决定采取何种动作。
● 一种表示语言是用其语法和语义来定义的,语法规定了语句的结构,语义定义了每个可能世界或模型中每条语句的真值。
● 语句之间的蕴含关系对于我们对推理的理解非常重要。在所有为真的世界中
也为真,则语句
蕴含语句
。其等价定义包括语句
的有效性和语句
的不可满足性。
● 推断是从旧语句推得新语句的过程。可靠的推断算法只推出蕴含的语句,完备的算法则可以推得所有蕴含的语句。
● 命题逻辑是由命题符号和逻辑联结词构成的简单语言。它可以处理已知为真、为假或完全未知的命题。
● 给出固定命题词汇表的前提下,可能的模型的集合是有限的,因此蕴含可以用枚举模型来检验。用于命题逻辑的高效模型检验推断算法包括回溯和局部搜索方法,它们通常能快速求解大规模问题。
● 推断规则是可靠推断的模式,它可以用于证明。归结规则能产生一个用于知识库的完备推断算法,以合取范式的形式表示。前向链接和反向链接是霍恩形式知识库的非常自然的推理算法。
● 如WalkSAT这样的局部搜索方法可以用于问题求解。这种算法是可靠的,但不是完备的。
● 逻辑状态估计需要使描述可能状态集的逻辑语句与历史观测保持一致。每一步更新都需要使用环境的转移模型进行推断,转移模型是根据规定流的变化方式的后继状态公理构建的。
● 逻辑智能体内部的决策可以用求解SAT的方式进行:找出描述能达到目标的未来动作序列的可能的模型。这个方法仅能用于完全可观测或无传感器环境。
● 命题逻辑无法扩大到大小无限制的环境中,因为它有限的表达能力不能简洁地处理时间、空间和对象间关系的通用模式。
微信扫码关注【异步社区】微信公众号,回复“e59810”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在本章中,我们将注意到世界被赋予了许多对象,其中一些对象与另一些对象相关,而我们努力对其进行推理。
命题逻辑足以展示逻辑、推断和基于知识的智能体的基本概念。遗憾的是,命题逻辑的表达能力有限。本章我们介绍一阶逻辑,[1]它可以简洁地表达更多东西。我们在8.1节中总体上讨论表示语言,在8.2节中介绍一阶逻辑的语法和语义,然后在8.3节和8.4节中展示一阶逻辑在简单表示中的运用。
[1] 一阶逻辑也称为一阶谓词演算(first-order predicate calculus),可缩写为FOL或FOPC。
本节我们讨论表示语言的特性。编程语言(如C++、Java或Python)是常用的最大一类形式化语言。程序中的数据结构可以用来表示事实,例如,程序可以使用一个4×4数组表示wumpus世界的内容。这样的话,编程语言中的语句就是断言在方格[2, 2]中有无底洞的一种很自然的方式。将一系列这样的语句合起来,就足以对wumpus世界进行模拟。
编程语言欠缺的是从其他事实推导事实的通用机制:对数据结构的每次更新都要使用领域特定的过程,而过程中的具体细节是由程序员根据其自身所具有的该领域的知识进行推导的。这种过程性的方法可与命题逻辑的陈述性(declarative)特性相对比,在命题逻辑中知识与推断是独立的,而推断完全是领域无关的。SQL数据库融合了陈述性与过程性知识。
程序(以及数据库)中数据结构的另一个缺点是缺少简便的表示方式来描述像“在方格[2, 2]或[3, 1]中有无底洞”或“如果wumpus在[1, 1]中,则它不在[2, 2]中”这样的概念。程序可以为每个变量存储一个值,一些系统也允许这个值为“未知”,但它们缺乏直接处理部分信息的表达能力。
命题逻辑是说明性语言,因为它的语义是基于语句与可能世界之间的真值关系的。使用析取和否定,命题逻辑有了足够的表达能力来处理部分信息。命题逻辑还有一个在表示语言中很有用的特性,即合成性(compositionality)。在合成语言中,一条语句的含义是其各个组成部分的含义的一个函数。例如,“S1,4 ∧ S1,2”的含义与“S1,4”和“S1,2”的含义有关。如果“S1,4”表示方格[1, 4]有臭味,“S1,2”表示方格[1, 2]有臭味,而“S1,4 ∧ S1,2”却表示法国与波兰在上周的冰球资格赛1∶1打平,就显得非常奇怪。
然而,命题逻辑作为一种因子化表示,缺乏能够简洁描述具有多个对象的环境的表达能力。例如,我们不得不为每个方格分别写出关于微风和无底洞的规则,如:
而在英语中,我们似乎可以简单地用一句“Squares adjacent to pits are breezy.”(与无底洞相邻的方格有微风)来一举解决问题。英语的语法和语义使它能够简洁地描述环境:英语是结构化表示,一阶逻辑也是。
自然语言(如英语或西班牙语)确实富有表达能力。我们设法用自然语言写作这一整本书的几乎全部内容,只偶尔地转用其他语言(主要是数学和图表)。语言学和语言哲学将自然语言视为说明性知识表示语言由来已久。如果我们能够揭示自然语言的规则,我们就能将其用于表示和推理系统,并获益于数十亿页已经用自然语言写就的文字。
自然语言的现代观点是将其视作交流的媒介而非单纯的表示。当说者指向一处并说“看!”听者就会明白他说的是超人终于出现在房顶了。但我们不能说是语句“看!”表示了这一事实。实际上,语句的含义既取决于语句本身,也取决于说出这一语句时的语境。显然,如果不在知识库中存储语句语境的表示而是仅存储像“看!”这样的语句,我们就无法搞清其含义——这就引发了语境本身该如何表示的问题。
自然语言也受制于模糊性,这也是表示语言面临的问题。正如平克(Pinker, 1995)所述:“当人们想到spring时,他们绝对不会困惑于他们到底是想到了一个季节还是想到了那个发出‘啵嘤’声的东西——如果一个词语可以对应于两种思想,那么思想就不能是词语。”[2]
[2] 表示“春天”和“弹簧”的英语单词都是spring。——译者注
著名的萨丕尔-沃尔夫假说(Sapir-Whorf hypothesis)(Whorf, 1956)宣称,我们对世界的理解深受我们所说的语言的影响。不同的语言群体以不同的方式划分世界。对英语使用者来说,“chair”一词囊括法语中“chaise”和“fauteuil”两个单词的概念,但英语使用者可以轻易地认出fauteuil这个类别,并给它命名——大概是“扶手椅”(open-arm chair)。那么语言真的会对理解有影响吗?沃尔夫主要依靠直觉和猜测,他的想法也已经基本被摒弃,但多年以来我们其实有来自人类学、心理学和神经科学研究的真实数据。
例如,你是否还记得下列表述中的哪一个构成了8.1节的开头?
“本节我们讨论表示语言的特性……”
“本节讲述表示语言的相关知识……”
维纳(Wanner, 1974)进行了类似的实验并发现,实验对象做出正确选择的概率处于随机水平——大概为50%,但对阅读内容记忆的准确率却超过90%。这意味着,人们会解读其阅读过的文字并形成内在的非文字表示,而确切的用词并不重要。
当某个概念在一种语言里根本不存在时,情况就更加有趣。澳大利亚的土著语言Guugu Yimithirr的使用者没有词语来表示如前、后、左、右这样的相对(或自我中心)方向。他们只使用绝对方向,例如“我北边的胳膊有点疼”。这种语言上的区别就导致了行为的区别:Guugu Yimithirr使用者在开阔地形上的定向能力更好,而英语使用者则更擅长于将叉子放在盘子右侧。
语言似乎也会通过类似名词的性这种看起来毫无规律的文法特征来影响思维。例如,“桥”在西班牙语中是阳性词,而在德语中是阴性词。博罗迪茨基(Boroditsky, 2003)要求实验对象选取英语形容词来描述某座桥的照片。西班牙语使用者选择了大(big)、危险(dangerous)、坚固(strong)、耸立(towering),而德语使用者则选择了优美(beautiful)、优雅(elegant)、脆弱(fragile)、纤细(slender)。
词语可以充当我们感知世界的锚点。洛夫特斯和帕尔默(Loftus and Palmer,1974)向实验对象展示了汽车事故的影片,被问及“车辆接触时的车速是多少?”的实验对象报告的平均速度为51.5 km/h,而使用“撞击”替代问题中的“接触”后,对于同一部影片的同一辆车,被提问的实验对象报告的平均速度则为66 km/h。总体来看,不同语言的使用者在认知处理上有微小却可测出的区别,但并没有令人信服的证据能够说明这会引起世界观的重大区别。
在使用合取范式(CNF)的逻辑推理系统中,我们知道语言表达式“”和“
”是等价的,因为我们可以看到系统的内部,并能够了解到这两条语句是以完全相同的标准CNF形式存储的。而对人类的大脑进行类似的操作正在成为可能。米切尔等人(Mitchell et al., 2008)让实验对象进入功能性磁共振成像(fMRI)仪,然后向他们展示如“芹菜”之类的词语,并对他们的大脑进行成像。使用(词语, fMRI图像)数据对训练而成的机器学习程序能够在二选一任务(例如,是“芹菜”还是“飞机”)中达到77%的准确率。这套系统甚至能够对其先前从未见过fMRI图像的词语(通过考虑相关词语的图像)和从未见过的人(证明fMRI揭示了人脑的表示方式具有某种共性)达到超过随机猜测的准确率。尽管这类研究还相当原始,但fMRI以及其他成像技术,例如颅内电生理学(Sahin et al., 2009),有望将人类的知识表示形式探究得更为详尽。
从形式化逻辑的观点来看,用两种不同的方式表示相同的知识一点区别都没有,无论从何种表示出发都能推出相同的事实。但在实际中,从其中一种表示推出结论的步骤可能更少,这意味着资源有限的推理机只能从这一种表示得出结论,而非其他表示。对于类似从经验中学习这样的非演绎任务,其结果必然地依赖于其所使用的表示。我们在第19章阐述了当学习程序考虑两种关于世界的理论时,如果这两种理论与所有数据都是一致的,那么最为常见的破局方式就是选择最简洁的理论,而这取决于用来表示理论的语言。那么,对任何进行学习的智能体来说,语言对思想的影响就是不可避免的。
我们可以采用形式逻辑的基础——一种上下文无关的、无歧义的说明性、合成式语义——来构建一种更有表达能力的逻辑,同时又从自然语言中借鉴表示方法并避免其缺点。当我们考察自然语言时,最为显眼的元素就是指代对象的名词和名词性短语(方格、无底洞、wumpus)和动词与动词性短语以及表示对象关系的形容词和副词(有微风、相邻、射击)。这些关系当中有的是函数,即对于一个给定“输入”只有一个“值”的关系。很容易就能列出一些对象、关系和函数。
● 对象:人、房屋、数字、理论、麦当劳叔叔、颜色、棒球游戏、战争、世纪等。
● 关系:可以是一元关系或属性,如红色的、圆的、伪造的、主要的、多层的等,或更为普适的n元关系,如是……的兄弟、大于、在……里、是……的一部分、有……颜色、发生于……之后、拥有、在……中间等。
● 函数: ……的父亲、……最好的朋友、……的第三局比赛、比……多一个、……的开始等。
实际上,几乎所有断言都可以看作对对象和属性的指代或关系。下面是一些例子。
● “1加2等于3”。
对象:1、2、3、1加2。关系:等于。函数:加。(“1加2”是对对象“1”和“2”应用函数“加”后得到的对象的名称。“3”是这个对象的另一个名称。)
● “与wumpus相邻的方格有臭味”。
对象:wumpus、方格。属性:有臭味。关系:相邻。
● “邪恶的约翰国王在1200年统治英格兰”。
对象:约翰、英格兰、1200年。关系:统治。属性:邪恶的、国王。
一阶逻辑语言是围绕对象和关系构建的,我们于下一节定义其语法和语义。它对于数学、哲学和人工智能乃至人类生活的很多方面都非常重要,因为这些领域要处理的正是对象和对象之间的关系。一阶逻辑也可以表示关于全域中的一些和全部对象的事实。这就使我们可以表示各种法则和规则,例如陈述“与wumpus相邻的方格很臭”。
命题逻辑和一阶逻辑的主要区别在于其各自的本体论约定(ontological commitment),即它对真实世界性质的假设。数学上来说,这一约定是通过语句真值确定的形式化模型的性质来表示的。例如,命题逻辑假设世界中存在要么成立要么不成立的事实。每个事实都可以为真或假这两种状态中的一个,而每个模型为每个命题符号进行true或false的赋值(见7.4.2节)。一阶逻辑则进行了更多假设,它假设世界是由具有关系的对象组成的,这些关系要么成立要么不成立(见图8-1)。因此,一阶逻辑的形式化模型也就比命题逻辑更为复杂。
图8-1 形式化语言及其本体论约定和认识论约定
这种本体论约定是逻辑(包括命题逻辑和一阶逻辑)的强项,因为它允许我们从真实的陈述出发来推断其他真实的陈述。这对于每条命题都有清晰边界的领域非常有效,例如数学或wumpus世界。在wumpus世界中,一个方格要么有无底洞要么没有无底洞,那种有个像无底洞一样的大坑的方格是不存在的。但在真实世界中,许多命题的边界是模糊的:维也纳是大城市吗?那家餐厅的菜好吃吗?这个人高吗?这都取决于被你提问的人,而他们的回答可能是“还行吧”。
对此,一种解决办法是细化表示:如果将城市分为“大”和“不大”的标准太粗略,使我们上述的应用中存在太多疑问,那么我们可以增加分类的个数,或使用Population这样的函数符号。另一种解决方案来源于模糊逻辑(fuzzy logic),它使用的本体论约定使得命题具有在0到1之间的真实度(degree of truth)。例如,语句“维也纳是大城市”在模糊逻辑中可能真实度是0.8,而“巴黎是一个大城市”则可能真实度是0.9。这更符合我们对真实世界的直观理解,但也更难进行推断:不同于确定A∧B真值的唯一规则,模糊逻辑在不同领域需要不同的规则。还有一个解决办法(将在24.1节阐述)是在多维空间中为每个概念分配一个点,并测量概念“大城市”与概念“巴黎”或“维也纳”的距离。
不少特定用途的逻辑还进一步地进行了本体论约定,例如时态逻辑(temporal logic)假设事实在特定的时间成立,而这些时间(可能是时间点或时间区间)是有序的。这样,特定用途的逻辑就使某种对象(以及关于它们的公理)在这种逻辑内更“高级”,而非只是在知识库中对其进行定义。高阶逻辑(higher-order logic)将一阶逻辑中的关系和函数视作其自身的对象。这使我们能对所有关系进行断言,例如,我们可能想定义具有传递性的关系意味着什么。不同于大多数特定用途的逻辑,高阶逻辑的表达能力全面高于一阶逻辑,因为高阶逻辑的一些语句无法用有限数量的一阶逻辑语句来表示。
一种逻辑的特性还包括其认识论约定(epistemological commitment),即这种逻辑允许每个事实所具有的可能知识状态。在命题逻辑和一阶逻辑中,一条语句表示一个事实,智能体只能选择相信其为真、相信其为假或没有意见。因此,这两种逻辑对于任何语句都具有3种可能的知识状态。
而使用概率论(probability theory)的系统则可以有信任度或主观可能性,其值可以是从0(完全不信任)到1(完全信任)的任何值。千万不要将概率论中的信任度与模糊逻辑中的真实度搞混了。实际上,一些模糊系统允许对真实度具有不确定性(信任度)。例如,一个概率的wumpus世界智能体可能相信wumpus在[1, 3]中的概率是0.75,而在[2, 3]中的概率是0.25(尽管wumpus肯定在某一个特定的方格中)。
本节我们先更为确切地阐述一阶逻辑的可能世界是如何反映其关于对象和关系的本体论约定的。随后我们介绍这种语言的几个组成部分,并解释其语义。本节的主旨是弄清这种语言如何进行简洁的表示,以及其语义如何形成完备的推理过程。
第7章讲过,逻辑语言的模型是组成目前正在考虑的可能世界的形式化结构。每个模型都将逻辑语句的词汇表连接到可能世界的元素,使得任意语句的真值可以被确定。因此,命题逻辑的模型将命题符号连接到预定义的真值表。
一阶逻辑模型要有趣得多。首先,它们具有对象!模型的域(domain)是它包含的对象集或域元素的集合。域应当是非空的——每个可能世界至少要含有一个对象。(见习题8.EMTP了解关于空世界的讨论。)数学上来说,对象是什么无所谓——有意义的只是每个特定模型中有多少对象。但出于教学的考虑,我们会使用一个具体的例子。图8-2展示了一个具有5个对象的模型,这5个对象分别是英格兰1189年至1199年的国王狮心理查、1199年至1215年统治英格兰的邪恶的约翰国王(理查的弟弟)、理查的左腿、约翰的左腿和王冠。
图8-2 含有5个对象、2个二元关系(兄弟和在头顶)、3个一元关系(人、国王和王冠)和1个一元函数(左腿)的模型
这个模型中的对象可能有多方面的关系。图中,理查和约翰是兄弟。从形式上来看,关系就是相关对象的元组集。(一个元组是以固定顺序排列的一系列对象,使用尖括号将对象括起来表示。)这样,模型中的兄弟关系就是集合
(8-1)
(此处我们已经命名了对象,但如果你愿意的话,你可以用图片代替对象名称。)王冠在约翰国王的头顶,因此关系“在头顶”仅含有一个元组,〈王冠, 约翰国王〉。“兄弟”关系和“在头顶”关系都是二元关系,也就是说,它们关联了一对对象。该模型还含有一元关系,或称为属性:“人”属性对于理查和约翰都为真;“国王”属性仅对于约翰为真(假设此时理查已经去世);而“王冠”属性则仅对王冠为真。
最好将某些类型的关系视为函数,因为这样的话给定一个对象,它必然仅关联到一个对象。例如,每个人都有一条左腿,因此模型含有一个一元“左腿”函数,即从一个单元素元组到一个对象的映射,它包括如下的映射:
(8-2)
严格来说,一阶逻辑中的模型需要全函数(total function),也就是对于所有输入的元组都要有值。这样,王冠必须要有一条左腿,每条左腿也一样。对于这种尴尬的问题有一个技术解决方案,它需要增加一个“不可见”的对象来作为一切没有左腿的东西的左腿,包括它自己。幸运的是,只要没人对没有左腿的东西的左腿进行断言,这些技术细节就不重要。
目前为止,我们已经描述了组成一阶逻辑模型所需的元素。模型的另一个重要部分是这些元素与逻辑语句的词汇表的联系,我们接下来进行介绍。
我们现在来了解一阶逻辑的语法。不耐烦的读者可以通过图8-3获得对形式化文法的完整描述。
图8-3 包含等价关系的一阶逻辑语法,使用巴克斯-诺尔范式(如果你对此不熟悉,见附录B.1)。运算符优先级从高到低定义。量词的优先级为一个量词的优先级高于其右边的一切
一阶逻辑的基本语法元素是代表对象、关系和函数的符号。因此,符号分为3种:代表对象的常量符号(constant symbol)、代表关系的谓词符号(predicate symbol)和代表函数的函数符号(function symbol)。我们采用的习惯是用大写字母开头来书写这些符号。例如,我们可以使用常量符号Richard(理查)和John(约翰),谓词符号Brother(是兄弟)、OnHead(在头顶)、Person(是人)、King(是国王)和Crown(是王冠),函数符号LeftLeg(……的左腿)。与命题符号一样,如何命名完全取决于使用者的意愿。每个谓词和函数符号都有一个决定参数数量的元数(arity)。
每个模型必须提供所需的信息来确定任意给定语句为真还是为假。因此,除了它的对象、关系和函数,每个模型还要包含一套确切指明常量、谓词和函数符号指代的是哪个对象、关系和函数的解释(interpretation)。在我们的例子中,下面是一种可能的解释,也就是逻辑学家所说的预期解释(intended interpretation)。
● Richard指狮心理查,John指邪恶的约翰国王。
● Brother指兄弟关系,也就是式(8-1)给出的对象元组集,Onhead是连接王冠和约翰国王的关系,Person、King和Crown是识别人、国王和王冠的一元关系。
● LeftLeg指式(8-2)定义的“左腿”函数。
当然,模型还有很多种可能的解释。例如,一种解释将Richard映射到王冠而将John映射到约翰国王的左腿。模型中有5个对象,因此仅对常量符号Richard和John就有25种可能的解释。注意,并非所有对象都有名称。例如,预期解释并没有为王冠和腿命名。一个对象也可以有多个名称,在一种可能的解释中Richard和John都指代王冠。[3]如果你觉得这令人困惑,记住,在命题逻辑中,一个Cloudy(阴天)和Sunny(晴天)都为真的模型是完全可以存在的;排除与我们的知识不符的模型是知识库要做的事情。
[3] 在随后的8.2.8节,我们会考察一种语义,其中每个对象只能有一个名称。
总之,一阶逻辑中的模型包含一个对象集和一种解释,这种解释将常量符号映射到对象、将函数符号映射到关于这些对象的函数,将谓词符号映射到关系。与命题逻辑一样,蕴含、有效性等都是用所有可能模型来定义的。要大致了解可能模型集是什么样子的,见图8-4。图中显示,模型的区别在于它们包含的对象数量不同(从一到无穷多个),以及常量符号映射到对象的方式不同。
图8-4 含有两个常量符号的语言中全部模型的集合的部分成员、R和J以及一个二元关系符号。每种常量符号的解释用灰色箭头标明。每个模型中,相关的对象用箭头连接
由于一阶逻辑模型数量没有上限,我们无法通过枚举所有模型的方式(像我们对命题逻辑做的那样)来检验蕴含。即便对象的数量是有限的,其组合也会是巨量的。(见习题8.MCNT。)对图8-4中的例子来说,使用不超过6个对象就会产生137 506 194 466个模型。
项(term)是指代对象的逻辑表达式。常量符号是项,但对每个对象都使用不同的符号命名往往不太方便。在语言中我们使用表达“约翰国王的左腿”而不是给他的腿起个名称来称呼。这就是函数符号存在的意义:我们使用LeftLeg(John),而不是使用常量符号来命名这条腿。[4]
[4] 表达式(
-expression,lambda表达式)提供了一种很有用的记法,使得新的函数符号可以“即时”构建。例如,对参数进行平方操作的函数可以写作
,并可以像其他函数符号那样直接用于参数。一个
表达式也可以被定义为谓语符号并用作谓词符号。这与Lisp和Python中的lambda操作符的作用完全一致。注意,像这样使用
并不能增加一阶逻辑的形式化表达能力,因为所有含有
表达式的语句都能通过“插入”其参数的方式重写,生成一个等价的语句。
通常情况下,复合项的组成是一个函数符号后跟随一个括号,括号中是一系列项,作为该函数符号的参数。需要注意的是,复合项只是复杂一些的名称,而非“返回一个值”的“子程序调用”。并不存在以一个人作为输入,返回一条腿的LeftLeg子程序。我们甚至可以在不定义LeftLeg的情况下就进行关于左腿的推理(例如,陈述一条一般规则“每个人都有左腿”,并进而推导出约翰必然有左腿)。这是无法在编程语言中用子程序实现的。
项的形式化语义非常直白。考虑项f(t1, …, tn)。函数符号f指代模型中的某个函数(不妨称为F),参数项指代域中的对象(称为d1, …, dn)),整个项就指代将函数F应用于d1, …, dn产生的对象,即函数的值。例如,假设LeftLeg函数符号代表式(8-2)所示的函数,John代表约翰国王,则LeftLeg(John)代表约翰国王的左腿。这样,解释就确定了每个项的被指代物。
我们现在已经有了指代对象的项以及指代关系的谓词符号,将它们结合起来可以构成陈述事实的原子语句。原子语句(或简称原子)是由谓词符号以及其后可能存在的括号中的一系列项组成的,例如:
在先前给定的预期解释下,这条语句表明狮心理查是约翰国王的兄弟。[5]原子语句的参数可以是复合项,如
[5] 我们一般遵循P(x, y)读作“x是y的P”这样的参数排序习惯。
表明狮心理查的父亲娶了约翰国王的母亲(再次强调,在合适的解释下)。[6]
[6] 这个本体论认为每个人只有一位父亲和一位母亲。更为复杂的本体论可以识别出生物学母亲、生母、养母等。
如果谓词符号所指代的关系在参数所指代的对象之间成立,则在给定模型中原子句为真。
我们可以使用逻辑联结词构建更为复杂的语句,这与命题演算的语法和语义一样。下面是4条在我们的预期解释下在图8-2的模型中为真的语句:
当我们有了支持对象的逻辑后,就很自然地想要表达很多对象的整体属性而非根据名称逐个列举对象。量词能使我们达到这一目的。一阶逻辑含有两个标准量词——全称量词和存在量词。
回想我们在第7章用命题逻辑表示一般规则时面临的困难。像“与wumpus相邻的方格有臭味”和“所有国王都是人”这样的规则对一阶逻辑来说是最基本的。我们将在8.3节中解决第一条规则。而第二条规则“所有国王都是人”在一阶逻辑中写作
全称量词∀通常读作“对所有……”。[记住,上下颠倒的A表示“all”(所有)。]因此,这条语句表示“对所有x,如果x是国王,则x是人”。符号x被称为变量。习惯上,变量用小写字母表示。一个变量本身就是一个项,因此也可以作为函数的参数,例如LeftLeg(x)。一个没有变量的项被称为基本项(ground term)。
直观上来说,语句∀x P,其中P为任意逻辑语句,表明P对每个对象x都为真。更确切地说,如果P在根据一个模型的给定解释构建的所有可能扩展解释(extended interpretation)下为真,则∀x P在该模型中为真,其中每个扩展解释给出了x指代的域元素。
这听起来很复杂,但它实际上只是陈述全称量词的直观含义的一种严谨的方式。考虑图8-2所示的模型及其相应的预期解释。我们可以用5种方式扩展这个解释:
x→狮心理查
x→约翰国王
x→理查的左腿
x→约翰的左腿
x→王冠
全称量化语句在原模型中为真的前提是语句
在这5种扩展解释下都为真。也就是说,全称量化语句等价于如下5个断言:
狮心理查是一位国王⇒ 狮心理查是一个人
约翰国王是一位国王 ⇒ 约翰国王是一个人
理查的左腿是一位国王 ⇒ 理查的左腿是一个人
约翰的左腿是一位国王 ⇒ 约翰的左腿是一个人
王冠是一位国王 ⇒ 王冠是一个人
让我们仔细研究这些断言。在我们的模型中,由于约翰国王是唯一的国王,因而第二条语句断言他是人,正如我们所料。那么其他4条语句呢?那些声明了腿和王冠的语句呢?这也是“所有国王都是人”含义的一部分吗?实际上,其他4条断言在模型中都为真,但并未对腿、王冠乃至理查作为人的资格进行任何声明。这是因为这些对象都不是国王。回顾⇒的真值表(图7-8),我们可以看到当前提为假时蕴涵式为真——无论其结论的真值是什么。因此,通过断言全称量化语句——它等价于断言每一条蕴涵式,我们最终仅对前提为真的对象断言规则的结论,而对前提为假的对象什么也不说。因此,⇒的真值表定义被证明非常适合用来编写含有全称量词的一般规则。
即使是勤奋地将本节读了好几遍的读者也可能会犯的常见错误是使用合取式而非蕴涵式与全称量词搭配。语句
等价于断言
狮心理查是国王∧狮心理查是人
约翰国王是国王∧约翰国王是人
理查的左腿是国王∧理查的左腿是人
…
显然,这并不是我们想要表达的。
全称量词对所有对象进行陈述。反之,我们也可以对某些对象进行陈述而不需指明其名称。使用存在量词就可以实现这一点。例如,要说约翰国王的头顶有王冠,我们写作
∃x读作“存在x使得……”或“对于一些x……”。
直观上来说,语句∃x P说的是P至少对于一个对象x为真。更准确地说,如果P在至少一个将x分配给域元素的扩展解释下为真,则∃x P在给定模型中为真。也就是,下列语句中至少有一个为真:
狮心理查是王冠 ∧ 狮心理查在约翰的头顶
约翰国王是王冠 ∧ 约翰国王在约翰的头顶
理查的左腿是王冠 ∧ 理查的左腿在约翰的头顶
约翰的左腿是王冠 ∧ 约翰的左腿在约翰的头顶
王冠是王冠 ∧ 王冠在约翰的头顶
第五个断言在模型中为真,因此先前的存在量化语句在模型中为真。注意,根据我们的定义,这条语句在约翰国王戴了两顶王冠的模型中也为真。这与原始语句“约翰国王的头顶有王冠”完全不矛盾。[7]
[7] 存在量词有一个变种,通常写作∃1或∃!,意思是“恰好存在一个”。相同的含义可以用等词陈述表示。
正如⇒是能自然地与∀合用的联结词一样,∧是与∃自然合用的联结词。使用∧作为∀的主要联结词会导致前面示例中的过强陈述,而使用⇒搭配∃则会导致过弱的陈述。考虑如下语句:
表面来看,这似乎是对我们的语句的一种合理的表示。使用语义规则,我们发现该语句表达的是如下断言中至少一条为真:
狮心理查是一顶王冠 ⇒ 狮心理查在约翰的头顶