AI学人
首发于AI学人
人工智能的产品和工程视角

人工智能的产品和工程视角

每年暑期,创新工场举办的DeeCamp大学生人工智能训练营,我都会给学生们讲课。我是工程师出身,并不专精理论研究。何况,2019年的DeeCamp,我们请到了吴恩达、周志华、张潼、俞勇、孙剑等顶级学者来讲机器学习的理论与发展,更不需要我来班门弄斧。所以,我的课程更多是从人工智能的产品研发和系统工程角度,帮学生梳理一下,如何将一个前沿人工智能技术变成一个具有商业价值的产品或解决方案。这方面的方法论、知识体系,学生在学校期间并不能经常接触到。

我在2017年DeeCamp讲的课程,后来简单整理成了一篇《为什么 AI 工程师要懂一点架构?》,其中的架构讲解以离线的大数据流程和机器学习训练架构为主。2018年我在DeeCamp讲的课程则偏重人工智能的商业化路径,商业案例讲得比较多。今年,我把前次内容重新组织并大幅扩充、更新,变成两大主题:

  1. 产品视角:如何认识和管理人工智能的产品化路径
  2. 工程视角:与人工智能相关的系统架构有哪些典型的设计模式

总的来说,人工智能落地有两大难题,一是产品化和商业化路径,一是科研算法向工程领域的转化。因此,新课程的题目就叫《人工智能的产品和工程视角》。

一、从AI科研到AI商业化

今天,AI商业落地是一个反复被讨论甚至被质疑的话题。一方面,AI在许多场景和平台上实现了巨大的价值——Google、Facebook、Amazon、阿里、腾讯等早已熟练地在搜索引擎、广告推荐、商品推荐等领域广泛使用机器学习并创造巨大营收,另一方面,大批怀着科技改造世界的美好梦想,在医疗、金融、制造、零售、能源、交通、仓储等垂直领域耕耘的创业者们却发现:理解客户场景和需求难,找到技术和业务的结合点难,实验结果和客户需求之间差异巨大,单项AI技术难以解决客户的综合问题,概念验证(POC)或科研项目极难转化为实际采购需求,实际项目的实施复杂度和定制化程度远超预期,技术和产品的可复制性不强,难以形成稳定的产品和可持续的销售……

的确,科研与商业化存在巨大鸿沟。科研的关注点(技术突破、论文水平、数据指标等)与商业化的关注点(能不能赚钱,能不能持续赚钱,能不能轻松持续赚钱)之间,存在较大差异。从更本质的层面来分析,大概有两个原因:

第一,今天的AI技术有非常明显的边界:在涉及浅层信息到知识映射的任务时,或单纯的数据建模任务时,往往表现得性能出众甚至超过人类平均水平。例如,今天的AI可以轻松快速识别人脸, 可以快速完成语音到文字的转换,可以快速从大数据(如广告点击日志)中总结数学模型并用于预测(如广告点击率预估)。但是,在涉及深层知识表示和知识理解(或者说基于符号语义的建模任务)时,今天的AI幼稚得像一个两三岁的小孩。例如,今天最顶级的AI连预定一个餐厅这样的限定领域任务,都还需要人类配合才能完成(Google发布的Duplex辅助预定服务在效果上非常亮眼,但其实有相当一部分对话是在真人参与下完成的,参见纽约时报的报道:nytimes.com/2019/05/22/)。简单会话尚且如此,对于更复杂的知识理解和推理任务,我们可能需要相当长时间,才能看到AI的进步。

第二,今天的AI技术在搜索引擎、广告推荐等有限领域,可以真正成为核心业务的支柱技术。但在更广泛的领域里,很多AI公司的产品和解决方案还停留在帮助客户公司塑造一个“拥抱新技术”的良好形象,或为客户的非核心业务提供一些“有用但非亟需”的工具,而不是深入到客户的核心业务内部,帮助客户获得更大的盈利及成长空间。如何用技术帮助客户提升价值,这件事往往是学生和科研人员很难理解的——没有在商业环境打拼过,就很难意识到到底什么样的技术对企业的生存(或者说赚钱)最重要。因为这种认知,更多需要的不是计算机科学知识,而是具体行业内的领域知识。

因此,如何从产品视角来认识和管理人工智能产品或人工智能商业化的整个生命周期,这是本文要重点讨论的第一个问题。

另一方面,对计算机或相关专业的在校学生来说,学校里学到的学科知识和工程上实现一个真正可用、好用的人工智能系统之间,同样存在着不小的鸿沟。学科教学强调的是离散的知识点,而产业实践强调的是完整的系统工程,或者说完整的技术栈。学生们在校学过机器学习、计算机体系结构、操作系统和分布式系统……但如果没办法把这些知识融会贯通起来,构建一个解决真实问题的系统逻辑,那是没法将人工智能变成工程产品的。也只有接受过灵活运用学科知识解决真实问题的专业训练,学生们毕业后才能成为高水平的算法工程师、系统工程师或架构设计师。

真实人工智能产品或系统,往往由一个完整技术栈组成,大致会涵盖硬件架构、操作系统、分布式架构、核心算法、应用逻辑、部署和维护等多个层次的技术框架与技术组件,其中,每一个技术框架或组件又可能是由学校里学过的多种学科知识共同支撑的。比如我们要做一个图像识别系统用于超市的商品监控,缺乏经验的算法工程师可能认为,商品识别不过就是object detection和object classification这两个任务,这又可以借助一系列通用算法,如Faster R-CNN、YOLO、SSD等来完成。但一个有经验的系统工程师则会在算法之外,提出更多的问题,例如:

  • 我们需要多少训练数据?数据从哪里来?
  • 模型是否有定期或实时更新的需求?如何更新?
  • 推断计算(Inference)部署在哪里?终端上?还是云端?
  • 终端计算和存储能力是否有限制?是否需要对模型进行压缩?
  • AI算法本身是否有分布式的需求,如分布式的训练?
  • 图像如何采集?采集到的图像如何传输到运行算法的计算结点?
  • 识别结果和操作日志如何保存并用于后续的算法优化?
  • ……

这些问题看似是工程问题或系统架构问题,但其实也和AI算法本身的息息相关。

如何用一个专业系统架构师的视角看待AI系统的设计与实现,这是本文将重点讨论的另一个问题。

二、产品经理视角:数据驱动的产品研发

产品经理最重要的素质是严密的逻辑思维和系统化的方法论。不同领域的产品设计和产品管理,在方法论上不尽相同。对于人工智能和大数据相关的产品和解决方案,数据驱动的理念和方法论也许最为重要。

Eric Schmidt与Jonathan Rosenberg合著的《How Google Works》一书中提到了Google“依数据决策”(Decide with data)的做法,“互联网时代最有变革意义的发展之一是,我们具备了用定量的方式来分析商业流程中几乎每个层面的能力。……如果你没有数据,你就无法决策。……这就是为什么大多数Google的会议室都有两个投影仪的原因——其中一个用于不同办公室间的视频会议或投影会议记录,另一个用于展示数据。”

数据驱动的思路,从根本上说,就是用可度量的方式来指导产品定义、产品设计和产品开发。大数据工程师和AI算法工程师应该非常熟悉数据驱动的基本思想:在机器学习领域,为了验证一个新算法,需要有数据集,有方法和指标来度量算法在数据集上表现出的性能,有作为参照的基线(baseline)。机器学习领域有关数据驱动的核心思想完全可以用于指导产品管理——这差不多就是数据驱动的产品思维了。

实际执行角度讲,就是要在产品管理的每一个环节,用可度量的数据指标来指导产品决策:

  • 用户需求是否存在?我们需要精准的用户调研数据;
  • 市场空间是否足够大?我们需要客观的市场调研数据;
  • 产品是否应该包含某个功能特性?可以针对这个功能特性做小规模实验并收集实验数据;
  • 产品是否有可能在竞争中胜出?竞品分析数据同样重要;
  • 营销和推广渠道如何搭建?这就要做对比测试并获得客观的渠道转化率数据;
  • 产品的用户界面是否美观易用?这也可以通过对比实验的结果数据来判定。

数据驱动的核心是相信数据具有可评估、可管理、可改进、可持续的属性,与我们通过“拍脑袋”做的主观判定相比,数据更客观,也较少偏见。当然,熟悉统计和机器学习的同学很清楚,统计数据里貌似客观、实则偏颇的事情也挺多,比如著名的“幸存者偏差”。但严密的逻辑加上科学的度量方法,还是可以更大概率地保证数据的客观性,为决策提供更好的支持。

上图右边是维基百科对于ROC曲线相关的评估指标的一个总结,参见:

https://en.wikipedia.org/wiki/Receiver_operating_characteristicen.wikipedia.org

学过机器学习或统计学的同学对这个表格应该非常熟悉。其中,ROC曲线反映的是伪阳性率(FPR)和真阳性率(TPR)之间的关系。大家应该都清楚,在多数真实系统中,必须在算法的伪阳性率(假警报比率)和真阳性率(敏感度)之间做一个折中或权衡。

类似的,当我们用数据驱动的方式去思考一个产品定义或产品设计的时候,也需要懂得取舍或权衡的艺术。例如,一个知识社区类的产品,如果增加一个一句话吐槽(类似日式冷吐槽)的功能,那多半可以增加新注册的用户数量、活跃用户数量和平均用户使用时长;但这样偏娱乐向的功能,却多半会造成娱乐型用户占比的增加,这是否会进一步影响有价值知识内容的积累,或影响付费类知识课程的转化率,就需要产品经理通过对比实验,仔细收集分析数据,并做出最优的折中或权衡了。

一个典型的C端产品(直接面向最终用户且主要是个人使用的产品)的研发过程如上图所示。因为市场机会、市场容量、竞品态势瞬息万变,今天的互联网和移动互联网产品尤其强调快速迭代的产品研发模式。可以说,今天中国的C端产品市场里,根本没有所谓的“蓝海”,几乎每个战场/赛道初具规模的时候,就会有大批强有力的竞争者参与进来,形成“红海”。“红海之战”里,快速迭代的思想无论如何强调都不为过。因为快速迭代可以更早地获得用户反馈数据,更早地指导和修正产品设计,更早做出符合市场规律的正确决策。

具体执行层面,很多C端产品的产品经理都非常熟悉两件事:一个是“数据埋点”,一个是“A/B测试”。

“数据埋点”指的是在产品的前后端逻辑里,加入特定的日志代码,记录与用户操作或系统功能有关的事件。通过埋点所记录的信息被存储在系统的前后端日志中,而产品经理则经常需要从这些日志中寻找数据的规律,挖掘数据背后的价值。比如,一个电子商务网站或APP可以通过数据埋点,了解到某用户在浏览商品时,曾把一件商品加入购物车但后来又删除的行为,甚至可以有针对性地记录商品被加入购物车直到最终删除之间用户又执行了哪些操作,然后根据用户交互日志,分析在什么情况下用户更容易放弃一个订单,并据此改进产品设计,提高购物车中商品的实际转化率。知乎有关数据埋点的问题中有一些不错的答案值得参考:

数据埋点是什么?设置埋点的意义是什么?www.zhihu.com图标

“A/B测试”是指将不同版本或不同迭代周期的功能按照一定的用户触达比例同时发布,比如,针对一个实时通信工具,我们想在新版本迭代中测试一个根据用户输入提示合适的表情包的功能,但又不确定这个功能是否会得到用户认可。那我们可以通过前后端软件的设置,将特定比例(如1%)的用户使用流量导流到带有新功能的版本,剩余99%的用户流量仍然使用不含新功能的版本。将用户导流到不同版本时,既可以根据一个预先的条件(如某地域符合某年龄段的用户)来选择新版本的测试用户,也可以随机选择新版本的测试用户。这种有对比的测试,可以很容易得到新版本用户相对于旧版本用户的变化,例如聊天的平均时长和对话轮次有无提升,原有的输入功能是否受到影响,新功能的使用频次是否达到了预期等相关数据。

总体上,评估一个C端网站、APP或小程序产品的数据指标有很多,大致可以分为渠道转化效率、用户活跃度指标、用户使用率、用户留存率等几个大类,每个大类中又有一系列的常用指标。需要强调的是,不同类型的网站、APP或小程序,决定它们价值的核心逻辑并不一定是相同的。例如,对于一个搜索引擎来说,用户在产品上的停留时间(平均单次使用时长)并不一定能反应系统的真正价值,因为好的搜索引擎通常能更快地帮助用户找到目标,并将用户带到目标网站或APP,这时的平均使用时长反而较低。但对一个内容类的网站或APP,例如短视频应用、新闻聚合应用等,用户的平均使用时长就特别重要,这个时长再乘以用户的活跃度(例如月活跃用户MAU),然后再乘以一个平均的广告转化率,就大致是内容类应用最基本的收入模型了。

有关用户与产品数据采集的具体手段,可以参考诸葛io创始人孔淼的一个讲解:

孔淼:「分析数据」是找出关键驱动元素的好方法zhuanlan.zhihu.com图标

B端产品或解决方案指的是那些为企业或政府客户提供的,以企业或政府机构内部使用为主的软硬件系统。B端产品或解决方案的调研、立项、研发、实施、推广的整个流程与C端产品差异巨大。有关为什么B端产品与C端产品存在巨大差异,Blair Reeves与Benjamin Gaines在《Building Products for the Enterprise》一书中的一个讲解非常清晰,参见:

Building Products for the Enterprisewww.oreilly.com图标

B端研发具有客户需求导向和销售导向的特点,客户的实际采购与使用意愿实际上决定着B端产品或解决方案的成败,而这又是进一步由解决方案本身是否与客户需求契合,是否能融入客户现有业务流程并为客户业务增值来决定的。相比之下,技术是否先进,产品是否有创意,通常并不是决定性的因素。因此,B端解决方案对数据的依赖,强调的往往不是C端产品所关心的用户使用率、留存率等指标,而是对客户现有业务流程、商业模式和实际需求的精准分析。

举例来说,假设我们想用机器学习算法改进某零售客户的供应链管理,那如果向目标客户介绍说,我们的机器学习算法采用了多么前沿的技术,我们的相关算法论文在顶会发表,我们的算法曾在某某数据集上获得过第一名的结果——这些信息可以展示我们的技术实力,但几乎无法从根本上影响到客户的采购与使用意愿。真正有效的方法是深入到客户目前的供应链管理流程细节,或借助客户已积累的大数据资源,或帮助客户建立更有效的大数据流程,然后从中找到客户当前供应链管理效率最低的环节,并针对这个环节设计最实用(而不一定是最先进)的算法。

接下来,还必须在客户现场进行概念验证(POC)测试,比如,选取客户在某个省的供应链子系统,用算法根据历史数据预测该省未来三个月各项原料的采购数量、销售预期等。然后,定量评估POC系统为客户带来的价值提升,如节省了多少成本。如果在POC项目中获得了满意的结果,客户就有可能认可算法和系统的价值,并将POC合同转化为实际采购合同(通常还要通过竞标)。接下来在正式的系统实施、维护中,数据采集(特别是客户业务提升效果数据的采集)也非常重要,这会帮助我们进一步优化解决方案,并从中抽象出可以复用的模块或产品,并在同行业的其他客户中进行推广。

简单讲, B端产品或解决方案最根本的成功要素是,我们能否帮助客户提升业务价值。此外,解决方案是否具有行业代表性,是否能加快合同回款以获得良好的现金流,是否能大幅减少后期维护成本,是否能积累可复用的技术、产品等,都是衡量B端产品、解决方案的重要指标。

拿一个特定的AI技术(如手写数学公式的识别)来说,选择走C端路线,还是选择走B端路线,未来所必须经历的数据驱动的产品研发、管理过程是大不相同的。

如果主打C端产品,那我们就必须回答:一个手写数学公式APP或小程序的最终用户是谁?是学习数学的中学生、大学生?是准备数学课程的老师?还是辅导中小学生作业的家长?如果结合教育场景,推出一款智能帮老师、家长批改学生作业的APP,那这个APP的推广渠道、盈利模式是什么?简单通过在线软件商店的方式来推广,还是通过线上线下的运营渠道来推广?是通过在APP里插入广告来赚钱,还是通过APP向其他教育类业务导流来赚钱?在每个特定的商业模式下,市场规模有多大?预期的用户增长情况如何?竞争对手有多少?预期营收在三年或五年时间里的成长曲线会如何?等等。

如果主打B端解决方案或服务,那我们要回答的问题就大不相同:这个解决方案或服务是面向哪个行业的?如果是面向教育行业,我们的潜在客户是学校、教育机构还是有内部教育培训需求的企业?在我们的潜在客户的业务流程里,手写数学公式识别的功能是必须的吗?这个功能是否能够帮助客户建立一个新的业务增长点?如果不能,是否能够帮客户提升现有业务流程的效率,或降低现有业务的成本?这个解决方案的服务模式和收费模式如何?是基于云平台的API调用并按调用次数收费,还是定制化的软件服务并按软件授权来收费?等等。

总之,从产品经理的视角出发,要构建好的产品或解决方案,我们不能只懂技术或只懂AI,好的产品与技术团队必须同时具备对市场的分析能力、对目标客户/用户的触达能力以及对目标行业/业务的深入理解能力。

三、架构设计师视角:与AI相关的典型系统架构

技术团队里不同角色的技能应具有互补性。架构设计师擅长整体架构设计,前后端工程师擅长编程,AI算法研究员、算法工程师擅长机器学习算法的设计与实现。但我一直强调,每一类角色也都必须具备较广阔的技术视野,对自己专长以外的技术有一定的认识。拿算法研究员和算法工程师来说,对系统架构基础知识的了解和认知,就是必不可少的——这其中的原因主要有以下几点:

首先,算法实现并不等于问题解决,实验室环境的问题解决也不等于工程现场的问题解决。只要不是纯粹的科研问题,算法工程师就必须考虑工程实现层面对算法的支持或约束。

其次,对典型软硬件系统架构的理解,其实是一个系统工程中,科学家、算法工程师、前端工程师、后端工程师、大数据工程师、硬件工程师等不同角色之间,顺利沟通、高效交流的一门“通用语言”。很难想象一个完全不懂架构设计的算法工程师,能够与其他角色顺利合作,将自己的算法高效地集成进整体系统。

我曾问一位在Android APP上实现人体姿态检测算法的AI工程师,你的姿态检测代码在最终的系统中运行在哪里?是运行在用户的手机上,还是运行在云平台上作为API服务被APP调用?你训练出来的模型又是部署在哪个设备上,模型需要更新时会经由何种网络通道传送至目标设备?他回答说,我不知道呀,我实现了算法代码,他们(指其他前后端工程师)把我的代码拿去用不就行了。我接着问,那你是否想过,如果你的算法代码运行在手机端,你有没有针对手机NPU来优化你的算法性能?如果你的算法代码运行在云端,你有没有针对云平台上的GPU来调优你的算法?如果你的模型参数众多,每次更新都需要下载数百MB甚至几个GB的.pb文件,那最终用户体验会不会受影响?你有没有考虑过对模型进行压缩,以改进用户体验?

目前已经有不少AI功能(特别是演示性或娱乐性功能)被集成在Web应用或微信小程序里。就软件执行环境而言,这两者都是相当复杂的情况。算法工程师并不需要真的去编写微信小程序的脚本代码,或真的去学习JavaScript、Node.js、React之类,但至少要知道,当一个Web前端或一个微信小程序里需要嵌入一段机器学习算法时,算法代码的实际运行位置究竟有几个选择。否则,我们如何根据实际配置与使用场景进行算法优化,来获得工程上的最优效果呢?

真实世界里的AI算法,必然被集成在互联网、移动互联网世界最典型的系统架构里。例如,今天这个时代,云平台和AI成为了技术世界最重要的两个支柱。云平台提供基础架构,AI提供智能属性。二者愈来愈密不可分。其实,今天很多顶级的云平台就同时兼有AI平台的身份。Google Cloud提供了Cloud AutoML和TPU资源,Amazon AWS和阿里云提供了智能客服接口、GPU资源,等等。

我大致把真实世界里与AI相关的系统架构或者说典型设计模式分成五个大类:

  • 单机或终端系统;
  • 离线大数据处理任务;
  • 信息、内容密集型的联机系统;
  • 事务、交易密集型的联机系统;
  • 去中心化系统或协作型的任务。

下面,我们分别讨论一下这五类系统的大致特征,典型设计模式,以及它们与AI算法实现或部署方式之间的关系。

A)单机或终端系统

单机或终端系统中的AI计算模型相对简明和清晰,通常由硬件层、操作系统层、可选的虚拟层、AI框架层、AI应用层组成。

其实理论上说,AI框架层也并非必须,但今天大多数AI算法都依赖于TensorFlow、PyTorch等主流框架,事实上已经将AI框架变成了AI时代的“操作系统”。另一方面,以Docker容器为代表的轻量级的虚拟层,目前在云上和本地AI计算中的应用都非常普遍。虚拟层的存在方便了AI算法在异构平台上的部署。算法训练时,可以使用虚拟层来屏蔽宿主操作系统甚至加速芯片驱动层的差异,或自动适应Kubernetes这样的分布式部署环境。在算法的推断(Inference)阶段,其实目前也有许多系统使用虚拟层来简化部署。

但使用虚拟层或AI框架层这样的事情也是双刃剑,它们一方面为开发者提供了便利,另一方面也屏蔽了许多系统层面的知识,并不利于学生在学习阶段熟悉每一个技术环节。例如,有不少写算法很熟练的同学,并不会自己配置显卡驱动,也不理解为什么有的机器学习模型,或某些机器学习模型的某个特定部分并不适合用GPU来加速。还有一些同学在利用Docker封装AI算法时,很少有机会去思考Docker这样的虚拟层对系统性能的影响到底是怎样的。另一些同学只会使用框架提供的数据集接口来访问训练集与测试集,一旦转换到工业环境,面对数百万张小图片组成的训练集带来的存储和传输挑战,就手足无措了。

加速硬件方面,有关CPU和GPU在计算模型上的差异,推荐几篇小文章:

CPU 和 GPU 的区别是什么?www.zhihu.com图标CPU vs GPU in Machine Learningwww.datascience.com图标Google Cloud上如何选择CPU、GPU以及Google TPUcloud.google.com

从学习角度说,理解技术问题要越透彻越好,被屏蔽或封装起来的信息越少越好;从工程角度说,要尽量高效地使用现成框架、现成工具——这是学习和工程的差别,但这两件事并不矛盾:学习得越透彻,在工程实现时对框架、工具的使用就越高效。

通常说来,单机或终端上每一个真实世界的问题,都未必是一个单纯的AI算法问题,往往需要多种不同手段组合才能解决。举个例子,最近主流品牌的手机,如华为、OPPO、VIVO、小米等都陆续宣布拍照功能支持超暗光环境拍摄,其暗光拍摄能力甚至超过拥有高ISO特性的专业相机。很多AI研究者将这种强大的超暗光拍摄技术归功于AI算法的引入。这结论当然没问题,例如,2018年CVPR论文

Learning to see in the darkarxiv.org

应该是一篇里程碑式的论文,给出了用AI恢复暗光下的照片细节,去除暗光噪音的一个非常有效的算法。2019年旷视科技也有一篇论文

Learning Raw Image Denoising with Bayer Pattern Unification and Bayer Preserving Augmentationarxiv.org

将暗光拍摄的AI算法性能又推进了一步,还实际应用在了OPPO手机里。

但如果说暗光拍摄仅止是AI算法的功劳,那就有失偏颇了。暗光拍摄功能是由从硬件到软件的完整技术栈实现的。比如说,硬件层面,最近几年,手机镜头也普遍拥有了f/1.6或更大的光圈(当然,因为焦距限制,进光量无法和专业相机相比),一些手机厂商也使用类似RYYB的新型感光模式来提升画质(从专业角度讲,RYYB是否在所有情况下都能提高画质还有争论)。另外,光学防抖和智能防抖功能,也是暗光条件下尽量延长曝光时间,获得清晰成像的关键。今天的很多暗光拍摄程序也会利用拍摄多张照片然后用AI技术自动对齐、多张叠加的方法获得更清晰的图像。所以,在一系列软硬件技术中,AI暗光成像时的自动去噪或自动补全细节只是完整技术栈的一环。

简单说,AI算法解决的是单点技术问题,而真实世界里的系统级应用问题则需要完整技术栈的优化组合。

B)离线大数据处理任务

离线大数据处理任务指的是那些不需要实时响应用户的在线请求,不用实时返回处理结果的任务。

其实,大多数AI训练(Training)任务都是离线大数据处理任务。AI模型一般可以通过线下批量数据训练的方式获得,然后在线上场景使用。比如,要得到一个自动翻译系统的AI模型,就可以在线下用大量文本数据来训练。线下模型也需要更新,但像自动翻译系统这样的应用,每隔一段时间(甚至几个月或更长)再更新模型也完全没问题。再比如,对一个电子商务系统里的全部或部分历史交易日志进行离线分析,可以建立一个比较好的商品推荐模型或智能定价模型,这类模型也许需要较频繁的更新,但远未达到实时的程度,离线大数据处理任务完全满足要求。此外,搜索引擎的索引(indexing)任务传统上也是离线处理任务,除非我们特别强调索引的实时性。

典型的离线大数据处理任务所使用到的技术栈,大致如下图所示:

纵向看,自底向上是芯片、操作系统和驱动程序、虚拟层(如Docker)、分布式管理框架(如Kubernetes),最后是处理离线大数据的应用层。

横向看,从左到右,应用层大致可以分为数据采集、数据存储、数据处理、数据智能四个部分。

数据采集部分的技术相对更加多样性一些,搜索引擎常用的爬虫技术同时也是很多相关大数据系统的初始数据源。另外,今天这样的IoT时代里,越来越多的各类传感器其实也构成了一种海量信息的收集渠道。比如,自动驾驶汽车上的诸多传感器,如激光雷达、毫米波雷达、摄像头等,它们采集的路面环境信息,以及汽车每个控制系统采集到的控制信息,都会被后续的AI训练模块所使用。

AI技术本身就能在数据采集阶段发挥巨大价值。例如,能够智能将非结构化数据变成结构化数据的技术,从传统的OCR、语音识别,到智能还原一张打印格式报表中的结构化数据,再到智能分析并提取一篇文章中的要点信息,这些机器学习任务都可以帮助我们快速、有效地收集信息。这样的智能信息获取技术甚至可以单独成为有用的工具:微软的Office Lens工具、“扫描全能王”之类的APP、印象笔记的文档拍照功能等,就把OCR和白板/文档/名片的扫描功能结合起来,帮助我们快速数字化信息内容。

大数据存储是一个有相当长历史并充分发展的技术领域。从最基本的文件存储,数据库存储,发展到分布式场景下的分布式文件系统,如NFS,Google的GFS和开源的HDFS,再到基于key-value结构的大数据存储,如Google的BigTable和开源的HBase,以及为结构复杂的文档或对象定制的存储方案,如MongoDB。

知识图谱(Knowledge Graph)可以算是另一种信息的存储和组织方式,知识图谱的好处是可以高效表达实体间的关联关系。基于知识图谱可以完成诸如知识推理、知识问答等较复杂的智能任务。但知识图谱对于数据结构化、数据质量的要求很高,没有一定的结构化数据积累,或没有一套完整的数据质量优化方案,知识图谱的用处就要大大缩水。

数据处理方面的技术迭代也很快。历史上,搜索引擎为海量数据建立索引的过程,大概是第一个对分布式离线大数据处理提出较高要求的任务。现代意义上的离线大数据处理技术以及相应的框架或工具也大多诞生于Google、百度等搜索引擎公司。适用于批量计算的MapReduce及开源的Hadoop,适用于实时计算或多次数据迭代的Spark,以及适用于图计算的Amazon Neptune和Apache TinkerPop等,都是这些年常用且仍在不断演进迭代的技术框架。

数据采集、存储和处理的最终目的是数据智能。AI和AI算法就是基于大数据来建立模型,并基于模型完成预测、分类、聚类等任务的。可以说,离线大数据处理的完整技术栈,正是机器学习算法赖以发挥作用的坚实“地基”。

有关大数据处理的技术栈,推荐一篇扩展阅读的材料:

Big Data: Challenges, Opportunities and Realitiesarxiv.org

梳理具体的大数据处理技术框架之前,我们先简单总结一下最基本、最典型的三种分布式系统设计模式。通俗讲,所谓分布式系统,就是把任务分散在多个处理节点(通常是分布在一地或多地的多台计算设备)进行处理并获得结果的系统。分布设置的计算节点间的关系如何设计,就形成了不同的分布式系统设计模式。一般的分布式系统教材中,常会罗列五六种、八九种甚至更多的设计模式,但其中最重要,也最典型的其实是以下三种:

备份型节点的设计模式:这是最基本的有中心调度主机(负责负载均衡)的分布式模式,调度主机以外的其他节点地位平等,每台节点计算机所提供的服务和所拥有的数据也基本相同(实际应用场景中,各节点间的数据同步会允许一定的延迟范围,在这个范围内节点之间的最新数据可能不完全一致)。大规模用户请求被负载均衡服务近乎公平地分配给所有节点计算机,每台节点计算机以完全一致的方式处理用户请求并返回结果。

分片型节点的设计模式:这种有中心调度主机(负责负载均衡)的分布式模式将中心主机以外的所有节点按某种方式划分成不同的分片(shard),每个分片的一个或多个节点负责处理与该分片业务或数据有关的请求。例如,要为大量网页建立索引,可以根据网页的URL(实际使用的是URL的哈希值)将所有网页分成若干个shard,每个节点只处理一部分网页。再比如,12306这样的火车票订票系统,完全可以根据业务逻辑,把不同铁路局的票务分散在不同shard里,每个shard只处理一个特定铁路局的票务。

协作型或去中心化的设计模式:这种设计模式弱化中心调度服务的功能,而更加突出参与节点间的相互连接及相互通信。用户请求可能被多个任务节点同时处理,多个任务节点之间形成一种协作式的关系。例如,P2P下载或P2P视频传输系统,以区块链技术和比特币为代表的分布式加密货币网络等等。

Google的MapReduce虽然诞生于十几年前(在分布式架构的发展史里,已经算得上是老前辈了),但它的核心设计思路确实成为了后来许多优秀分布式系统的理论指导。要更深刻地理解MapReduce,最好从程序设计语言中的表处理功能出发,先理解单机版本的Map和Reduce,例如LISP语言中的#’map和#’reduce(以及分布式的版本#’LParallel:PMAP),或Python语言中的map和reduce(以及更受推荐的List Comprehensions)。进一步阅读可以参考Quora上的这个讨论:

https://www.quora.com/How-is-MapReduce-different-from-map-and-reduce-functions-in-lispwww.quora.com

MapReduce的本质是根据ID将数据分入不同的分片(shard)进行运算,每台工作节点(worker)只处理特定分片的数据。处理后的结果可以经由Shuffle过程,重新组织并输入到Reduce阶段。Reduce根据ID来聚合Map阶段的输出,并生成最终结果。Map-Shuffle-Reduce的过程甚至可以级联起来,组成相当庞大的MapReduce级联系统,来完成特别复杂的处理逻辑。许多离线大数据处理任务,包括许多机器学习的训练任务,都可以被抽象成MapReduce这种分布式设计模式。

MapReduce的经典论文值得仔细阅读:

MapReduce: Simplied Data Processing on Large Clustersresearch.google.com

Spark可以看做是MapReduce设计模式的一种扩展。针对实时性要求较高的数据处理任务,或需要对数据进行多次迭代的机器学习任务,MapReduce将中间数据保存到外部存储介质上或数据库中的做法就显得效率低下了。Spark最有代表性的设计——RDD机制(Resilient Distributed Dataset)可以在内存中提供每个分片数据的可持续存储,以响应实时性强或多次迭代访问的数据请求。

Spark和Hadoop(开源版本的MapReduce)之间一个简明的比较参见:

Hadoop vs. Spark: A Head-To-Head Comparisonlogz.io图标

今天学习深度学习的学生,大多还是在单机环境下学算法、做实验。从学术界走进工业界的话,几乎都会面临真实场景下需要用并发或分布式环境来处理大规模数据的情况。比如在Google Cloud环境里,可以通过GKE(Google Kubernetes Engine)申请管理一组GPU或TPU资源,然后将自己的深度学习任务封装在Docker image中,由GKE部署、调度和运行。今天的主流深度学习框架,如TensorFlow、PyTorch等,都提供了的对并发处理或分布式处理的支持。

参见通过Google GKE配置TPU的文档:

https://cloud.google.com/tpu/docs/kubernetes-engine-setupcloud.google.com

TensorFlow或PyTorch在并发或分布式支持上的核心思想并不新颖,只是基于分片(sharded)模式的一种扩展。当然,分片的方法可以选择不同的思路。一种是按照处理的数据不同来分片,这在TensorFlow推荐的分片模式中被称为数据并行(Data Parallel Training),另一种更为复杂的实现是将整个深度学习网络进行拆分,网络的不同部分在不同的处理器单元或不同的计算节点中运行,这在TensorFlow推荐的分片模式中被称为模型并行(Model Parallel Training)。——注:这里不特别区分并行计算(Parallel Computing)和分布式计算(Distributed Computing)的差异,因为从子任务划分的角度来说,两者之间可以共享类似的方法论。基于同样的原因,很多时候AI算法工程师并不像系统架构工程师那样严格区分并行计算和分布式计算这两个基本概念。

TensorFlow的经典论文明确给出了Data Parallel Training和Model Parallel Training二者的基础设计思路:

TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systemsdownload.tensorflow.org

具体实现过程中,按照数据并行(Data Parallel)的训练方式来做的人比较多,因为相对容易控制、实现和部署。模型并行(Model Parallel)的实现难度就要高不少。目前,Google Cloud上的TPU甚至都还不支持模型并行(cloud.google.com/tpu/do)。

有关分布式深度学习的理论问题及发展脉络,CMU张昊的文章可以作为一个很好的概览:

张昊:科普:分布式深度学习系统(一)zhuanlan.zhihu.com图标张昊:科普:分布式深度学习系统(二)zhuanlan.zhihu.com图标

张昊的文章里提到了一个大家经常遇到的尴尬情况,“比如,你用8台机器同时训练一个VGG19,可能只能获得2-3倍的加速;换句话说,你花8000刀买了8块显卡,最后发现你的系统实现让6000刀直接打了水漂。事实上,如果一个分布式系统用了8台机器实际只2-3台机器的收益,这个系统显然是不达标的。”

也就是说,如果不是充分理解分布式部署的情况下,网络通信、数据调度、参数同步等工作增加的额外负担,以及相应的解决方案,那只会事倍功半。

有关可扩展的深度学习系统的架构设计,尤其是有关如何在大规模GPU/TPU集群上建立高性能的深度学习架构,Google大神Jeff Dean在NIPS-17上的一个演讲非常值得参考(其中提到的有关Reinforcement Learning for Higher Performance Machine Learning Models的研究非常有趣,可以说是机器学习和架构设计的有机结合):

Jeff Dean, Machine Learning for Systems and Systems for Machine Learning, NIPS 17learningsys.org


C)信息/内容密集型的联机系统

信息/内容服务型的联机系统是大多数互联网网站、移动APP、微信小程序的主要应用场景,包括提供商业或个人信息的网站、搜索引擎、新闻客户端、短视频浏览、旅游信息查询、机器翻译、地图应用等等。

这一类Web服务的主要职能是根据用户请求,返回特定的信息或不同媒体形式的内容。从技术上说,此类应用的大部分用户请求对于后台数据存储来说,都是所谓的“只读请求”,即不需要实时修改或更新数据存储内容,只要简单返回数据结果的请求。

典型的信息/内容服务类Web服务的架构如上图所示。其中,负载均衡(包括DNS层面的负载均衡、Web前端的负载均衡、应用层的负载均衡等)与缓存服务(Caching)是辅助系统,同步或异步RPC通信(包括流行的REST协议、Google开源的gRPC、Apache Kafka等常用的消息队列,等等)是连接前后台各内部服务节点间的信息通道。实际的信息内容存储在后台的关系型数据库或文档/对象存储集群中。例如,搜索引擎的数据通常分为文档和索引两大部分,存储在GFS/HDFS或类似的存储集群内,也经常使用更高级别的key-value数据库或文档/对象数据库来管理数据。应用服务器集群根据前端服务器传来的用户请求,返回具体的信息内容。

少量的数据修改、更新操作可以在离线处理阶段完成,也可以在响应特定用户请求时完成。在数据存储集群(如数据库集群或HDFS集群)中,任何涉及数据更新的操作一般都首先发生在一个特定的支持读写(RW)操作的存储节点,然后经由数据同步服务,同步到所有其他只读(RO)节点。对大多数信息/内容类服务而言,不同存储节点间的数据同步有一个短时间的延迟,并不是太大的问题。

大多数基于Web服务接口提供的AI功能,都可以很容易地融入信息/内容服务类的联机系统中。AI模型的训练(Training)阶段通常属于离线大数据处理任务,无需并入联机系统。而联机系统中的应用服务所访问的,则是AI推断(Inference)功能的接口。例如,一个在线提供语音识别API的AI服务,语音识别的模型是离线训练出来的。用户可以通过HTTP或REST API访问联机系统的前端Web服务,前端Web服务通过应用服务调用(也可以直接调用)语音识别的后台服务。语音识别的后台服务在内存中加载模型并完成Inference计算,并将结果返回。根据系统的访问量指标(QPS),语音识别后台服务可以配置多台计算节点组成的集群。即便是集群情况下,模型更新的问题也不难解决,这和上面所说的由读写(RW)存储通过数据同步服务更新到所有只读(RO)存储的过程并没有什么两样。

D)事务、交易密集型的联机系统

事务/交易型的联机系统在数据一致性上有特别严格的需求。铁路购票系统12306就是一个特别好的例子。早期的12306系统在春运高峰时不堪重负,常常出现系统频繁掉线、长时间刷不出票或者刷出票了却无法下单的情形。记得当时程序员们还掀起过如何改进12306订票系统的大讨论。知乎上有一个关注度一度非常高的问题,特别有意思,值得所有系统架构师一看:

12306 外包给阿里巴巴、IBM 等大企业做是否可行?www.zhihu.com图标

为什么像银行的核心系统、淘宝等电子商务网站的订单管理和结算系统、12306网站的票务管理和结算系统如此难实现呢?这主要是受到了分布式计算理论中著名的CAP定理(CAP theorem)的限制。CAP定理讲的是在一个分布式的系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)这三个基本需求,最多只能同时满足其中的2个。有关CAP定理的严格证明和展开讨论参见:

Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Servicesgroups.csail.mit.edu
Perspectives on the CAP Theoremgroups.csail.mit.edu

更加直观的图形化证明和讨论参见:

An Illustrated Proof of the CAP Theoremmwhittaker.github.io

很多系统架构实践已经证明,基于传统关系型数据库(如OracleDB、MySQL等)搭建的系统,在多数情况下并不适合扩展到超大规模的服务集群或响应超大规模的用户请求,这是因为传统关系型数据库虽然具备高度的一致性和可用性,但因为CAP原理的限制,在分区容错性上难以尽如人意。像淘宝、12306那样大规模的交易网站,为了支持大规模的扩展能力,必然在选择分区容错性(P)的同时,在一致性和可用性二者中做出权衡;而由于商品交易行为对账目准确性的严格要求,这些系统又必然会选择一致性(C)而放弃高可用性(A)。

事实上,根据2013年的一则新闻报道,12306网站为了在支持大规模并发交易(如春运高峰)的同时保证一致性,已经选择了GemFire作为自己的底层事务/交易数据库,其实现效果达到了预期。

当然,对于完整的12306网站来说,票务交易相关的逻辑只是其中的一部分,其余涉及票务查询(如查找某日车次)的只读操作,则可以依据信息/内容型联机系统的一般性原则来设计。根据阿里云云栖社区的官方回答(12306 外包给阿里巴巴、IBM 等大企业做是否可行?),“目前阿里云已经与12306进行了合作,从2014年开始,12306就把网站访问量最大的查询业务分担到云端。从2014年开始,12306就把网站访问量最大的查询业务分担到云端。”

值得一提的是,那些对于数据一致性要求不高的读写交易,为了支持大规模的并发请求,完全可以在CAP中选择分区容错性(P)与高可用性(A),而放弃一致性(C),即,系统可以容忍某些数据在短时间内不一致(这时,在不同节点间同步数据的操作就可以用较为简单的技术方案实现)。例如,一个社交类的系统,不同用户在某个时间读到的评论信息有少量不一致,这并不会造成太坏的用户体验。有不少专门的非SQL数据库是针对这种情形来设计的。有兴趣的话,建议读一读Apache CouchDB讨论一致性的文档:

1.3. Eventual Consistencydocs.couchdb.org图标

典型的追求一致性(C)的数据库设计和部署方式如上图所示。更详细的情况,建议大家参考两个真实的基于云平台的分布式数据库系统的设计思路。一个数据库是Amazon的Aurora,另一个是阿里的PolarDB。Amazon和阿里既分别是美中最大的电子商务平台,也是两个市场里最大的商用云计算平台。这两家企业的技术团队,在云上分布式数据库设计方面的经验,无疑是业界最具代表性的:

Amazon Auroradocs.aws.amazon.com
阿里 PolarDBwww.alibabacloud.com图标

典型的电子商务系统的架构设计如上图所示。

今天的电子商务系统中,大多已经集成了基于机器学习的商品推荐模型、广告推荐模型等。这些机器学习系统与电子商务系统之间的集成,一般并不复杂,因为机器学习模型并不需要在交易的同时也用完全相同的速度保持更新且保证数据一致。即,我们虽然需要商品推荐模型根据用户的行为(购买行为、查询行为等)尽快更新,以便为用户推荐最合适的商品,但这种更新有一些时间延迟,或在不同计算节点间有一些不一致,并不会特别影响最终用户体验。在这种情况下,机器学习系统与电子商务系统的集成更像是为电子商务系统增加了另一个信息/内容型的业务模块,不一定需要用高一致性的数据库或存储方案来解决。

参考阿里的两篇有关商品推荐模型的论文:

Billion-scale Commodity Embedding for E-commerce Recommendation in Alibabaarxiv.org
Learning Tree-based Deep Model for Recommender Systemsarxiv.org


E)协作式或去中心化系统

P2P(下载或视频流)与区块链是我们熟悉的协作式或去中心化的系统设计,不过它们超出了本文的讨论范围,这里不细谈。有兴趣的同学可以关注一下机器学习技术与区块链技术的结合,比如这篇有趣的讨论:

Leveraging blockchain to make machine learning models more accessible - Microsoft Researchwww.microsoft.com图标

我们重点谈下AI协作式任务未来的一个重要发展方向:联邦学习(Federated Learning)。联邦学习的设计目标是在保障大数据交换时的信息安全、保护终端数据和个人数据隐私、保证合法合规的前提下,在多参与方或多计算结点之间开展高效率的机器学习。

例如,Google的联邦学习团队很早就将协作式模型训练的概念应用在了许多需要采集个人数据进行机器学习,同时又必须保护个人隐私或商业机密的场合。Google输入法Gboard为了精准预测用户输入,需要借助用户的个人数据来训练语言模型。在愈来愈强调个人隐私的时代,对用户个人数据最妥当的处理方式就是只在用户自己的设备上访问并处理数据,永不将原始个人数据传送到云端。联邦学习技术允许Gboard在个人手机端利用个人输入信息训练出一个“端上模型”,然后将训练后的模型(而不是原始个人信息)传递到服务端进行聚合,再将聚合后的模型传回供Gboard使用。

上图是一个联邦学习的系统架构图,来自微众银行2018年9月发布的《联邦学习白皮书 V1.0》:

联邦学习白皮书 V1.0www.fedai.org

上图是Google的论文Towards Federated Learning At Scale: System Design中有关联邦学习系统中,客户端与云端交互流程的详细设计。这张图比较详尽地阐释了手机等终端设备是如何与云端设备协作并分别负责不同的训练任务,然后再使用特定的协议、依据一定的时序完成模型聚合与同步的。

Towards Federated Learning At Scale: System Designarxiv.org

联邦学习有望成为下一代人工智能协同算法和协作网络的基础。我们创新工场人工智能工程院也在积极参与联邦学习技术的研究推进。2019年3月,创新工场南京国际人工智能研究院执行院长冯霁代表创新工场当选为IEEE联邦学习标准制定委员会副主席,着手推进制定AI协同及大数据安全领域首个国际标准。相信在未来的一段时间内,联邦学习无论在技术的成熟度方面,还是行业标准的制定与推广方面,都会取得更快更好的发展。

四、写在最后的几句话

我个人觉得,产业界选拔、判断一个AI算法研究员或AI算法工程师的标准,无外乎以下几点:

  • 是否对机器学习领域的前沿动态有足够的敏感性,且具备强烈的学习意愿?
  • 是否具备较强的动手能力,可以快速解决核心的机器学习问题?
  • 是否有能力根据系统工程或产品设计的要求,灵活选择最适合的技术解决方案?
  • 在无法同时满足算法性能、系统效率、系统稳定性、系统扩展性等多项要求的时候,能否做出正确的技术或产品取舍?
  • 是否有足够强的团队协作能力、沟通能力?
  • 是否对目标领域的用户或客户有足够的理解与认知,并善于将领域认知与技术认知结合起来?

创新工场每年举办的DeeCamp大学生人工智能训练营,就是要培养善于解决真实世界问题,擅长在产业界完成研发任务的AI生力军。要解决真实世界的问题,在知识积累上既需要专深,也需要广博——希望我的课程以及课后写成的这篇文章对学生们构建完整的知识技能体系有所帮助。

编辑于 2019-08-03

文章被以下专栏收录