⼈⼯智能与软件架构
本⽂转⾃微信号EAWorld。扫描下⽅⼆维码,关注成功后,回复“普元⽅法+”,将会获得热门课堂免费学习机会!
本⽂⽬录:
⼀、⼈⼯智能(AI)的⽬标是增强智能(IA),⽽不是替代⼈类
⼆、应对软件架构分⽽治之带来集成的挑战,探索智能的连接
三、从智能连接⼊⼿探索在软件架构中应⽤⼈⼯智能
四、总结
梅落繁枝千万片因为 AlphaGo 的出现,过去的 2016 年可谓是⼈⼯智能元年。记得当时我们正在苏州封闭研发The Platform,⼯作之余讨论到⼈机对战的真正意义,并不在于技术上的突破,⽽在于对⼈们固有知识的影响,⼈⼯智能的应⽤会如⾬后春笋般诞⽣,以后没有⼈⼯智能的软件你都不好意思开⼝了。
⼤家都在问,⾃⼰的⼯作与⼈⼯智能有什么关系,如何在⾃⼰的⼯作中应⽤⼈⼯智能,如何在软件中植
⼊⼈⼯智能的基因,使⽤⼈⼯智能应该从何处⼊⼿,学习⼈⼯智能应该从哪⾥开始,更深层次的问题是⼈⼯智能能否代替⼈类,作为⼀个程序员,在⼈⼯智能能否代替⼈类写程序的问题上,根据我们团队的实践介绍⼀下如何在软件中应⽤⼈⼯智能。
⼀、⼈⼯智能(AI)的⽬标是增强智能(IA),⽽不是替代⼈类
⼈⼯智能并不是⼀个新概念,40年代维纳的《控制论——关于在动物和机器中控制和通讯的科学》就是⼈⼯智能。但早年的⼈⼯智能受限于计算能⼒,更多在解决模型的计算速度和精度上,近年来随着云计算技术的发展,计算能⼒提⾼了,随着⼤数据的发展,更复杂的计算问题可以⽤更多的数据进⾏修正,⼈⼯智能的可⽤性⼤⼤提⾼。但是我们从⽬前⼈⼯智能应⽤的情况可以看到,⼈⼯智能并不能替代⼈类,例如在图像识别、语⾳⽅⾯的突破,仅仅是让机器更加聪明⽽已,还远远没有达到⼈类的程度,作为⼈类的智能助⼿更加合适。
不忘初心跟党走理清⼈⼯智能、机器学习、深度学习、统计等基本概念之间的关系
把⼈⼯智能的⽅法应⽤到软件中,我们先梳理清楚⼏个概念之间的关系:⼈⼯智能(Artificial Intelligence)是⼀个⼤的概念,是让机器像⼈⼀样思考甚⾄超越⼈类;⽽机器学习(Machine Learning)是实现⼈⼯智能的⼀种⽅法,机器学习最基本的做法,是使⽤算法来解析数据、从中学习,然后对真实世界中的事件做出决策和预测;深度学习(Deep learning)⼜是机器学习的⼀种实现
别墅玄关⽅式,他是模拟⼈神经⽹络的⽅式,⽤更多的层数,更多的神经元,然后给系统输⼊海量的数据,来训练⽹络。⽽统计学是机器学习和神经⽹络的⼀种基础知识,从传统分⼯来看,统计学⼀般是数学、统计等专业研究的⽅向,⽽机器学习是计算机科学的研究⽅向,但是⽬前⼤家的研究成果越来越殊途同归,有统计学的⼤师就认为统计实际上⼀直在从事机器学习的⼯作。
对于深度学习、统计的专家来说,他们更加关注于模型、算法等等,找到可以普适性解决问题的办法,
⽽对于我们应⽤来说,具体的算法实现不需要我们考虑太多,⽽是找到适合的场景、合适的模型、匹配的算法,所以,应⽤⼈⼯智能实际上是⼀个计算机、统计、知识⼯程、⾏业知识的⼀个交叉应⽤,在经常涉及到的应⽤中,我⼀般在处理结构化、半结构化数据时优先考虑传统统计学的⽅法,例如分类、数据相关性、回归等,⽽处理⾮结构化数据时(例如图像、视频、⽂本)优先考虑深度学习的⽅法,但这些⽅法也需要有统计学知识。所以,需要补课:线性代数、数理统计、Python,我觉得《机器学习实战》这书⼊门不错,上述⼏⽅⾯知识都介绍了。
应⽤⼈⼯智能实现增强智能的三个层⾯
应⽤⼈⼯智能的时候,⼈们会有⼀个误区,总是希望得到⼀个意想不到的结果,也就是希望探索出新知识。经常有⼈问我,得到的结果好像没有什么我不知道的,我说这就对了,因为你是专家,要是计算机得到的结果都是不可知的,你怎么能相信他,例如AlphaGo下的棋,绝⼤多数都是⼈类已知的,⾮常少⾮常少的情况下,下出⼀招另类,这已经是⼀个顶天星的⽔平了。很多⼈失望了,这还有啥意思,其实意义很⼤:
(1)计算机可以让常⼈快速获得以往专家才能具备的知识,例如有经验的客户经理,肯定⾮常了解客户的情况,谁是优质客户,谁需要什么产品等等,不需要计算机,但是通过⽤户画像等⼈⼯智能的⼿段,计算机可以让经验不够丰富的⼈,也具备了上述经验,这个做法价值就⾮常⾼,毕竟专家是少的;
(2)帮助专家减少重复性的⼯作,例如医⽣在做病理检测时,绝⼤多数没有⽣病的情况和有典型病理特征的情况,机器都可以提醒医⽣,节约医⽣的宝贵时间。如此看来,我们就会理解,⼈⼯智能不是替代⼈,⽽是给⼈类增加⼀个智能的助⼿,是增强智能(IA Intelligence Augmentation)。
计算机作为⼀个智能助⼿,可以在不同层⾯和⼿段帮助我们,我把他分为机械智能、实现意图的智能和创造意图的智能三个⽅⾯:
(1)机械智能,我们⽬前从事的主要⼯作都是这个,事先设定规则(代码也是规则),让计算机完成⼤量重复计算,充分利⽤计算机的计算能⼒,替代⼈的⼿⼯劳动,这是⼀个以规则为核⼼的模式,⽽这些规则来⾃于⼈现有的知识;
(2)实现意图智能,⼈知道最终结果是什么,但是并不告诉计算机采⽤什么样的规则计算,通过⼤量数据训练计算机找到规则,然后再让计算机完成⼤量重复计算,计算机究竟找到的规则是什么,有可能⼈并不⼀定能理解,其实往往也不需要理解,把计算机当成了⿊盒; (3)创造意图智能,也就是让计算机⾃⼰找到⼈并不知道的新知识,这也是我们最向往的场景。
从具体的实现层⾯看,第⼀种情况⽆疑是最多的,我们需要提炼总结规则,⽤好第⼀种情况很重要,第⼆种情况以前相对少⼀些,但恰恰是⽬前需要改进的,在第⼆种情况下我们往往优先⽤统计学的⽅法处理结构化、半结构化数据(例如格式化⽇志),⽤深度学习的⽅法处理⾮结构化数据,这就需要
让我们的团队具备⼈⼯智能的思维。
实践⼈⼯智能应⽤需要新思维,不能再⽤规则理解计算机实现智能的⽅式
实践⼈⼯智能,需要在在思维上进⾏调整。我们往往习惯于⽤制定规则的⽅式指挥计算机,输⼊、计算规则和输出结果都是已知的,也就是我上⾯说的机械智能⽅式。但后两种模式就不是规则⽅式了,因为规则是计算机找到的,这也就是经常说的数据训练。这⾥我举⼀个我们⾃⼰实现的例⼦,让⼤家理解⼀下什么是模型、算法和数据训练。
先说⼀个背景,我们在梳理现有企业数据架构的时候,需要建⽴数据间的关联,⽤⼈进⾏梳理费⼯费⼒,我们就打算⽤计算机⾃动完成⼀部分,然后⼈⼯修正,这就是⼀个增强智能(IA)的例⼦。这⾥⾯就有⼀个情况,如果数据库中没有建⽴外键,如何把这种实际的外键关系找出来,我们就⽤这个例⼦解释⼀下机械智能和实现意图智能的⽅法:
(1)⽤规则的⽅式查找外键关系。⾸先要定义规则,外键关联的规则包括字段类型⼀致、长度⼀致、包含相同数据等等,然后在所有数据中遍历,进⾏匹配。这种⽅式需要有完整的数据,⽽且是否外键关系的判断规则往往有些模糊,在没有得到全量数据时有⼀定局限性;热场小游戏
(2)⽤统计学⽅法查找外键关系。⾸先,我们定义出字段的特征(类似⽤户画像),字段特征是⼀
个向量,就是⼀个⼀维数组,包括表名、字段名、字段类型、注释、样例数据最⼤长度、样例数据最⼩长度等等,由于表名、字段名不是数值,我们要把他们变成数值,可以和同⼀个标准字符串作⽐较,也就是通过移位的⽅式把字符串移动成标准字符串,移动次数越少,相似度就越⾼,这样就得到了⼀个真正的⼀维数组(向量)了。
其次,我们拿出⼀部分已知关系的表和字段,作为训练样本,逐⼀计算两个字段之间的相关系数(相关系数的计算⽅法是现成的,我这⾥就不介绍了,⼀上公式我就晕,Python的发⾏版Anaconda⾥⾯就有,⽤了这个就体会到 Python 是最好的语⾔了),相关系数⾼的说明特征类似,认定为外键关系。这时候⼈⼯判断⼀下,如果结果不错,那这个模型就是正确的,如果结果不好就换⼀种相关系数计算⽅法,或者改变数据特征,或者对数据特征进⾏加⼯,总之,外键特征作为⼀个客观存在,⼀定能够找到符合的特征,这就是数据训练。通过数据训练,找到合适的字段特征(模型)和计算⽅法(算法),也可以交给计算机做处理了,把所有的外键找出来。迪士尼是哪个国家的
你看,这⾥没有定义规则,处理⽅法是通过数据训练的⽅式,让计算机⾃⼰找出来的,我不需要知道相关系数这玩意到底是什么意思,这就是上⾯说的,计算机是⼀个⿊盒。
需要说明的事,在上述例⼦中,我简化了不少动作,实际上最开始还找出来很多不是外键关系的字段,例如 createTime,我们还要把这种噪⾳字段的特征训练出来,剔除噪⾳。
这个⽰例说明了应⽤⼈⼯智能时不同的两种思维模式,简单的说不能再⽤创造规则的⽅式指挥计算机,⽽是训练计算机⾃⼰找出规律。
上⾯我们分析了⼈⼯智能相应的基本概念,⼈⼯智能的⼏种模式以及应⽤⼈⼯智能时需要的思维突破,下⾯我们从软件架构发展和⾯临的挑战,看看应⽤⼈⼯智能时的切⼊点在哪⾥,哪⾥更容易爆发出⼈⼯智能的⽕花。
⼆、应对软件架构分⽽治之带来集成的挑战,探索智能的连接
什么是软件架构,在InfoQ出版的《聊聊架构》中讲的很清楚(感谢⽼王,总结⾮常到位),软件架构就是(1)根据问题确定系统边界;(2)按⼀定原则进⾏切分;(3)建⽴不同模块间的沟通机制;(4)整体性交付软件功能。可见,架构的关键是分⽽治之的哲学,但切分是为了软件研发、运维⽅便,软件的⽬标是整体交付,分与合存在着⽭盾,这⼀⽭盾是由集成解决的,但是集成往往是复杂的,⼤家在架构⽅⾯的分享,也以如何切分居多,如何集成相对较少。
集成⼯作的复杂度影响了复杂系统的研发
Unix的实践⽆疑对软件架构有着巨⼤的影响,做⼀个事情,做到最好,⼀直是 Unix 风格所倡导的,但“在理想世界中,Unix程序员只愿意⼿⼯打造⼩巧完美的软件宝⽯,每个都那么⼩巧、那么优雅、那
么完美。然⽽现实中很不幸的是,太多复杂问题需要复杂的解决⽅案。仅仅⼗⾏的程序,再优雅也⽆法控制喷⽓式客机。那⼉有太多的装备、太多的通路和界⾯,太多不同的处理机,太多不同操作⼈员定义的⼦系统,他们甚⾄连基本的约定都⽆法统⼀。即使能够成功地将航空系统所有的个体软件部分做的优雅,但拼装结果很可能是⼀堆庞⼤、复杂、糟糕的代码… 喷⽓客机的复杂是必然的。过去有个尖锐的观点,不能为简单性⽽牺牲功能,因为飞机必须要能飞。正是这个事实,航空控制系统并不会产⽣关于复杂度的圣战—-Unix程序员往往敬⽽远之。“(摘⾃《Unix编程艺术》)。
不幸的是,我们⾯临的往往是复杂性的系统,⽚⾯理解Unix风格分⽽治之往往带来更⼤的集成难度。为了降低集成的难度,我们往往采⽤巨⽯型的系统架构,⽤⼀个⼤⼀统的⽅式设计系统,仅仅在系统内部进⾏模块的拆分,⽤codeba和规范进⾏约束,⾛上了和Unix风格背道⽽驰的道路。当性能和可维护性压⼒到来后,这样的系统⼜不得不进⾏拆分:我过去常常看到,当软件系统达到 100 万⾏代码规模时,⼈们会觉得维护困难,产⽣了强烈的拆分念头,当达到 300 万⾏代码规模时,⼈们往往再也按耐不住拆分的欲望,当达到 500 万⾏代码规模时,再保守的组织也会作出拆分的决定。
软件架构中复杂的集成⼯作需要利⽤⼈⼯智能⽅式简化下来
回顾⼀下解决集成问题的历史,我们会发现较早的集成架构模式来⾃于 Unix,就是众所周知的管道(Pipe)模式。Pipe模式将数据传递到⼀个任务序列中,管道扮演着流⽔线的⾓⾊,数据在这⾥被处
理然后传递到下⼀个步骤。管道模式作为⼀种最基本的⽅式,理论上可以解决所有集成问题,但涉及到具体问题时,就需要针对不同情况做应对,针对各种复杂的情况,可以总结出更多的模式,《企业集成模式》(EIP)⼀书中围绕消息集成,总结出若⼲集成模式,可谓是消息集成的集⼤成式总结。
但EIP的集成模式主要针对系统间后台服务的集成,SOA架构提出了以Portal(前端集成)、BPM(流程集成)、ESB(服务集成)、怎么做干冰
DI(数据集成)以及事件/消息集成的多层⾯集成体系,更加系统性的为集成⼯作提供指导。SOA的集成⽅式需要⼀系列的集成基础设施⽀持,属于⼀种中⼼化的集成⽅式,我们可以称之为MiddleBox的⽅式,在微服务架构提出后,我们会采⽤把集成逻辑与业务功能部署在⼀起的去中⼼化集成⽅式,可以称之为MiddlePipe的模式。
集成⽅式⼀路演进下来,主要是集成的⼿段上不断翻新,多种框架和基础设施越来越多的解决了⾮功能需求,例如 ESB 可以解决路由、安全、流控等问题,⼀定程度上减少了集成的⼯作量。但集成的业务复杂度还存在很多,这⾥我列举⼏个常见的问题:
(1)数据的查找问题。针对业务需求,需要使⽤已存在的数据和服务,但在企业环境中,系统、服务、数据众多(想象⼀下具有10多万服务、10多万数据标准的情况),想找到适⽤的服务和数据,不是⼀件容易的事情,⼀般我们都要依赖专家在这⽅⾯的知识,通过总体设计指定了数据的流向,这依
赖于专家的能⼒,专家的能⼒也是慢慢积累起来的。我们需要帮助业务更快速的找到数据和服务,帮助专家快速实现积累,减少重复劳动。
(2)数据的适配问题。通过服务⽅式进⾏集成,原⼦服务往往需要⼤量的输⼊参数。举个例⼦,调⽤⼀个发短信的接⼝,不仅仅是收信⼈电话号码和短信内容,还要包括很多业务含义的参数,例如发信⼈的姓名、组织、发信的系统、发信的原因、发信时和客户接触的渠道(客服渠道、⽹点渠道、⽹银渠道、⾃助终端等等)、发信时关联的产品,这些信息是可以⽤来计算成本、控制次数、避免重复骚扰客户;⽤户名、密码、验证码、发送时间等这是⽤作安全验证的;优先级、发送渠道等是⽤来做流量控制的;流⽔号、全局业务ID、请求ID、请求时间等等是⽤来做监控的。上述信息来⾃与每次发短信的上下⽂,在实际开发期间就要做很多的赋值、转换⼯作,将上下⽂的信息传递给服务,这种转换就像下图那样,典型的⾯多了加⽔,⽔多了加⾯。我们需要根据当前上下⽂和服务的特征,⾃动的进⾏⼀些适配,避免⼈⼯的重复性劳动。
(3)系统的联动问题。当⼀个业务事件产⽣时,有很多相关联的系统都会需要作出关联性反映,例如⼀个航班延误,就会涉及机票的改签、酒店的改期、接车服务的改期、会议安排的变更、⽇程计划的变更。⼀般我们会设计⼀个事件中⼼,为各个系统开发出监听的程序,当事件到来时判断上下⽂信息,决定产⽣的动作。如果事先没有设定的规则,就⽆法产⽣联动,我们期待更加⾃动化的建⽴这种联动关系,让计算机智能的产⽣动作⽽不仅仅通过⼈为设置。
类似问题还有很多,我们期待能够更加智能的集成。
需要集成的部分不只是软件本⾝,软件过程也是⼀个复杂的集成/协作⼯作
分⽽治之的软件需要通过集成⽅式整体交付,软件的⽣产过程也是⼀个多⼈、多组织协作的过程,也需要集成。把软件看成是⼀个产品,产品就有策划、研发、运营和退出各个阶段,每个阶段可能由不同的⼈或组织完成。软件的研发阶段就是⼀个⼀个项⽬的实施过程,包括⽴项、执⾏和完⼯。这样的过程组织起来,就是⼀条软件⽣产的流⽔线。从早期瀑布式的软件研发,到后来敏捷研发过程、CMM,到⽬前风头正劲的DevOps,都是在解决软件⽣产流⽔线不同阶段的协作问题,敏捷针对软件定义、设计、构建(开发)阶段的协作,持续集成是构建(开发)与测试阶段的协作,持续交付是从定义阶段到部署(交付)阶段的协作。
协作中⾯临的问题,就是集成的问题,我们可以想到很多,这⾥也举⼏个例⼦:
(1)需求、设计与构建(开发)的沟通问题。我们需要把需求/设计的知识图谱化、条⽬化,⾃动与开发⼯作做⼀定程度的适配,减少需求/设计到代码的转换⼯作;
(2)构建(开发)与测试的沟通问题。我们需要根据服务和数据特性以及积累的历史数据,⾃动产⽣测试⽤例和测试⽅法;
(3)运营的沟通问题。我们需要通过应⽤画像、资源画像等⽅式,服务与物理资源之间建⽴连接,快速定位问题,进⾏容量预测,实现更智能的运维。
在软件架构中应⽤⼈⼯智能的⽬标:通过增强智能⽅式实现软件系统与软件⼯程的智能连接
应对复杂集成的挑战,我们可以引⼊⼈⼯智能的思路,将⼈与软件、物体与软件之间、软件与软件之间、软件⽣产线各环节之间通过知识使能的⽅式集成起来,在传统完全依赖规则进⾏集成的⽅式基础上,采⽤新的集成⽅法:以上下⽂信息为输⼊,利⽤专家已有的知识,通过数据训练和强化学习的⽅式,让计算机能够理解集成的意图,成为我们的智能助⼿,帮助我们实现智能的连接,进⽽可以让计算机探索新的连接知识。这⾥,我把连接也分为三个层⾯:机械连接、基于知识连接、创造知识连接。
三、从智能连接⼊⼿探索在软件架构中应⽤⼈⼯智能
从何处⼊⼿,探索⼈⼯智能在软件中的应⽤,是⼤家最关注的话题,这⾥我把普元在探索⼈⼯智能初
期经历的⼏个案例,给⼤家做⼀个介绍。普元董事长刘亚东博⼠早年就从事神经⽹络的研究,他指出在⽬前并⾏计算等技术充分发展的今天,算法已经不是⼈⼯智能的瓶颈,应⽤⼈⼯智能需要有两个突破(1)找到⼈⼯智能应⽤的切⼊点(2)团队具备⼈⼯智能应⽤的思维。所以我们在应⽤⼈⼯智能的时候,不是成⽴⼀个专门的⼩组做研究,⽽是百花齐放的⽅式。了解普元的朋友会知道,普元的研发分为云计算&SOA、⼤数据、移动、⼯程效率与技术平台、产品⽀持中⼼⼏个团队,我们让每个团队从数据+连接⽅向上⼊⼿,各⾃探索⼈⼯智能在领域上的应⽤场景,通过找到切⼊点和初步实践,逐步建⽴团队的⼈⼯智能思维。其中云计算&SOA团队的⽅向是通过服务画像⽅式解决微服务的智能运维与智能匹配,⼤数据团队的⽅向是通过知识图谱实现数据⾃服务,移动团队的⽅向是UI的智能化开发,⼯程效率与技术平台团队的⽅向是深度学习在流程与智能制造的应⽤。由于篇幅有限,这⾥我把普元⼤数据团队和移动团队所做的⼯作做⼀个介绍。
案例⼀:基于知识图谱,实现数据的⾃服务能⼒
先简单介绍⼀下背景:⼤家经常会听到有⼈问我们有哪些数据,这些数据在哪⾥,如何获取数据的问题,能否建⽴⼀个平台,让我们象百度搜索⼀样,根据我们的知识(业务术语)找到相关的数据,提交申请,得到数据,这就是⼀个获取数据的⾃助服务。
以往数据在哪⾥往往通过⼈⼯梳理完成,我们希望能够⾃动化⼀些,为专家提供⼀个智能的助⼿,这⾥的⼯作分为三部分:
特征的英文
(1)建⽴知识图谱。⼈进⾏数据搜索是通过业务术语(知识)来搜索的,⽽知识之间是有相互联系的,例如⽔果和苹果是上下位关系(后者是前者的具体体现),搜索是除了要列出直接结果,还需要显⽰⼀些关联的知识,这就要建⽴知识图谱。简单说知识图谱就是概念、属性以及概念之间的关联关系, 这个关系可以⼿⼯建⽴,我们通过对政策、法规、需求、数据库comments、界⾯等多种来源,采⽤⾃然语⾔处理等⽅法,可以建⽴起部分的知识图谱,辅助专家的⼯作;
(2)梳理技术元数据。整理各个系统内部数据,以及数据之间的关系,形成数据地图。这⾥的难度是数据之间的关系,例如数据的⾎缘关系、影响度关系、关联关系、主数据关系等,这⾥我们采⽤字段特征的相关性、数据处理逻辑的词法/语法分析等⼿段,配合强化学习来完成,前⾯列举的查找外键⽰例,就是⼀部分;
(3)建⽴知识图谱与技术元数据之间的关系,这⾥就要通过分析界⾯/服务与代码之间的关联,建⽴起映射关系。最终效果就是,使⽤数据搜索,录⼊希望查找的业务术语,得到相关结果,查看样例数据,如果是需要的数据,提交使⽤申请,如果不是,继续根据相关知识进⾏数据探索。提供数据⾃服务能⼒,就是在应⽤的设计师、数据科学家或者业务分析师与数据之间建⽴起连接,我们的团队就是从连接的思路出发,找到了⼈⼯智能的切⼊点。实际上,数据⾃服务包含有找、获、⽤等众多环节,我这⾥说的是找的环节如何实现,这种找的⽅法,也不可能100%准确,还需要专家进⾏调整,以及通过强化学习等⼿段不断修正,可以看出,应⽤⼈⼯智能也是⼀个渐进完善的过程。
食断
案例⼆:通过深度学习,实现移动UI的智能化开发
移动UI的智能化开发,是我们移动团队应⽤⼈⼯智能的第⼀个尝试,现在看来,就是在UI设计师与开发⼯程师之间建⽴连接。⼤家会发现,设计师的设计在变成代码实现时总会有偏差,即使⼀个像素的差异,也会影响界⾯的效果,以往我们采取不同业务模板的⽅式,建⽴⼀些规范对设计和开发做约束,后来移动团队觉得,可以⽤深度学习的⽅式做⼀些尝试,寻找不同的界⾯设计效果,⾸先通过数据标签⽅式确定页⾯的风格,再通过图像⽚段的⽅式学习和识别设计稿中的组件,最终经过多次的处理,变成⼀个树状的结构,把这个树状结构与代码进⾏映射,就产⽣了和设计图⼀致的代码。