CodeWisdom

智能化软件开发沙龙是复旦大学CodeWisdom团队参与组织的专注于代码大数据与智能化软件开发的学术和技术沙龙,面向相关领域的学术界研究者和工业界实践者,通过各种线上和线下交流活动促进学术研究与实践技术的发展。微访谈是智能化软件开发沙龙依托沙龙微信群开展的线上交流活动,其形式是围绕某一具体话题邀请嘉宾进行在线访谈并与微信群成员互动。

AI软件架构实践

智能化软件开发微访谈·二十期

2022新年特辑

机器学习和深度学习模型已经被广泛应用于电子商务、社交网络、智能汽车、智能安防、金融服务等各种领域,形成了大量AI软件系统。在这种系统中,机器学习和深度学习模型与传统的软件模块紧密集成在一起并密切交互,形成了完整的软件系统。机器学习和深度学习模型具有数据驱动和不确定性等方面的特性,其开发、测试和演化与传统的软件模块有很大区别。另一方面,在软件系统层面上,如何设计整体架构,让不同的机器学习和深度学习模型及其不同版本与其他软件模块构成一个有机的整体并实现持续的部署、更新和运维,也是需要探索的问题。

针对这些问题,本次微访谈邀请了来自学术界和工业界的多位专家,围绕AI软件架构及开发实践这一主题展开讨论,总结业界实践、分析相关技术问题以及未来的发展方向。

彭鑫

复旦大学计算机科学技术学院教授

访

刘杨

南洋理工大学领导论坛首席教授

潘青华

讯飞研究院副院长、AI工程院院长

马雷

加拿大阿尔伯塔大学副教授

加拿大国家AI战略CIFAR AI Chair

余跃

国防科技大学副研究员

鹏城实验室开源研究所技术总师

陈碧欢

复旦大学计算机科学技术学院副教授,博导

冯洋

南京大学计算机系助理研究员

鞠剑勋

携程旅游研发部算法专家

访

AI软件架构实践

01

能否介绍下你所熟悉的一些典型的AI软件系统,这些系统采用了哪些机器学习和深度学习模型?用于实现什么样的能力?机器学习和深度学习模型之间以及与软件模块之间是什么样的交互和协作关系?是否存在一些通用的架构模式和策略,包括机器学习和深度学习模型及其不同版本与其他软件模块之间的组织结构和交互关系(类似于传统的软件设计模式、架构风格)?

02

当前AI软件系统中的机器学习和深度学习模型开发采用了什么样的软硬件技术栈?形成哪些技术生态?由此导致的环境和生态依赖对于AI软件开发带来了什么样的困难,与传统软件开发中的环境依赖和依赖管理有什么区别?

03

在企业开发实践中,机器学习和深度学习模型的功能和非功能性测试、分析和调试一般采用什么样的方法和技术?此外,在AI软件系统层面上的整体测试一般会采用什么样的策略和技术?

04

AI软件系统特别是其中的机器学习和深度学习模型是如何持续演化的,例如如何评估其效果、提出改进需求、实施改进和更新?AI软件系统特别是其中的机器学习和深度学习模型的版本如何管理?

05

在用户端和云端运行的AI软件系统一般都采用了什么样的部署结构和部署方式?云端的AI软件系统是否有采用当前流行的云原生和微服务架构?其中的机器学习和深度学习模型如何进行服务化封装、部署、动态更新和持续的运维管理?云原生和微服务系统中广泛采用的动态伸缩以及熔断、限流等可用性保障策略在AI软件系统中是否有所应用?

06

AI软件系统的架构设计及其开发、测试、运维和长期演化方面存在哪些问题和挑战?有哪些AI软件系统工程实践问题需要学术界进一步关注和探索?

访

Question 1

能否介绍下你所熟悉的一些典型的AI软件系统,这些系统采用了哪些机器学习和深度学习模型?用于实现什么样的能力?机器学习和深度学习模型之间以及与软件模块之间是什么样的交互和协作关系?是否存在一些通用的架构模式和策略,包括机器学习和深度学习模型及其不同版本与其他软件模块之间的组织结构和交互关系(类似于传统的软件设计模式、架构风格)?

刘杨:

以人脸匿名系统为例。人脸匿名(Face anonymization or Face De-ID)是一项通过去除人脸原有ID信息并生成新的ID信息的隐私保护技术,在有关隐私保护的软件系统(例如街景软件、疲劳驾驶检测软件)以及公开数据集(去除敏感ID信息)中有着广泛应用。

人脸匿名系统一般采用人脸检测、人体关键点检测和人脸生成等机器学习或深度学习模型。其中人脸检测是为了定位人脸区域的位置,方便后续的人脸替换;人体关键点检测是为了确定人体各关节(头部、双肩等)的位置,使新生成的人脸与原人体姿势相互协调一致;人脸生成则是合成一个自然逼真的新人脸,用以替换原有人脸。人脸检测和人体关键点检测既可以采用传统的机器学习模型,也可以采用深度学习模型;而人脸生成普遍采用目前广为流行的对抗生成网络(GAN)。

在人脸匿名系统中,各模型之间的交互和协作关系分为并行关系和串行关系两类。其中人脸检测和人体关键点检测是并行的关系,二者相互独立;人脸检测/人体关键点检测与人脸生成则是串行的关系,前者的输出(去除人脸区域的头部图像、人体关键点坐标)作为后者的先验信息,生成符合先验条件的人脸。

基于深度学习的软件系统根据具体任务的不同,有不同的的架构模式。以人脸匿名系统为例,由于它通常是本地操作,所以一般采用最常见的分层模式,即表示层,应用层,业务逻辑层,数据访问层。该模式用于构建可分解为多组子任务的程序,每个子任务都在某个抽象层,每个层对上一个更高层提供服务。对于简单的任务,例如单纯的人脸检测系统,通过构造端到端的深度学习模型,使模型自动学习人脸的检测策略。而对于复杂的任务,往往需要多个模型相互交互来完成,例如人脸匿名系统中三个模型之间是协作关系。

潘青华:

讯飞在AI领域做了很多年了,从语音到NLP,再到CV领域,很多方向都有涉及,已经积累很多AI软件系统。

以语音交互AIUI系统为例,是一套全双工语音交互解决方案,包括了麦克风阵列拾音、语音唤醒、语音识别、语义理解、对话管理和语音合成等核心技术模型,用系统性创新的思路进行贯穿,从而实现更自然的人机交互交互。

在讯飞的AI工程化中,我们分3个阶段。第一阶段是内核引擎工程,将机器学习和深度学习模型变成一个能力引擎模块,不同的版本也是按照软件版本的管理模式,关注新增feature,bugfix,以及性能优化等;第二阶段是平台工程化,分几个部分,第一部分是将能力引擎变成分布式服务,提供API/SDK方便快速接入,API的版本会跟着能力引擎的feature映射;第二部分是把多个能力引擎的分布式服务变成平台化,实现无服务架构,适配各类能力引擎,这个架构本身会有版本号;第三阶段是做大型应用软件工程,例如做一个人机交互系统,里面涉及到使用多种能力引擎服务,最终会形成新的API/SDK版本。

我们在这些软件系统的开发过程中,整体也是沿用了软件工程中的微服务架构范式,平台化部分参考无服务低代码的范式。

观点讨论

@彭鑫:刘杨老师的这个AI系统的实例已经包含多个模型之间的组合了。后面还可以看下AI模型与软件模块之间的交互关系。

潘青华老师讲的AI应用开发中的微服务架构和低代码很棒,后面可以展开讨论下。

@刘杨:已经有一些文章看model和框架的关系,尤其是debug的时候做错误定位。这些其实是很难的。

马雷:

我们早期 (2016~2019)工作主要聚焦在AI模型(Unit Level ) 层面,围绕着Model的质量,可靠性,安全,可解释等进行了一系列初步的探索。2020年开始,我们工作逐步转向关注AI复杂软件系统,也做了一些初步探索也; 对一些典型的AI软件系统有了一些了解。通常,一个AI软件系统会包含多个功能模块与支撑代码(chaining code),通常连接支撑代码一般是传统Rule based软件形式(对数据流进行预处理或后处理,或用来链接模块输入输出)。子功能模块通常根据具体系统任务与功能不同,可以是完全采用AI模型组合,或者是AI模型与传统Rule-based 软件模块结合的方式。

我们初步的了解是AI软件系统大体结构与传统软件既有相似又有不同,相似之处是AI也可以采用多种结构化,模块化构成方式。不同之处是处理的具体子任务模块通常是AI模型比传统软件模块块更具有优势的一些任务(比如,物体分类,障碍物检测)。此外,AI系统也可以采取end-to-end模式,整个系统都是由AI模型组成。

  • 我们在FSE 20的一个初期工作,A First Look at the Integration of Machine Learning Models in Complex Autonomous Driving Systems - A Case Study on Apollo 对百度apollo无人车系统做了一个初步架构的分析与探索。大体架构与工作采取了perception, planning, control等一个流程 (架构如下图所示), 其中 perception 过程中主要用来处理camera, lidar, radar信号感知车载周围环境,一共采用了20余个深度学习模型,模型之间有串联,并联 包括前后信号预处理与后处理,也包括信号整合fusion模块 (比如 Kalman filter),为后端环境感知(行人感知,障碍物检测,红绿灯检测等)以及planning 与control做支撑。在具体子任务中采取了不同专门设计的AI模型模块,但是预处理与后处理在apollo中也大量采用了大量传统软件方式。另外一种是类似Tesla无人驾驶系统采用的更为激进的做法,感知模块尽量采取end-to-end的方式,这样使得维护起来相对容易,但是也存在AI黑盒带来的安全可靠性等质量层面挑战。

  • 其次,我们也分析了语音语言等交互等系统,比如siri,alex,百度小度,DeepSppech Rasa等一般采取下图架构流程: 从语音识别, 自然语言理解, 语义关联与对应智能反馈文本生成,再到语音合成。每个步骤都是高度AI依赖任务模块,前后各模块子系统通过串接或并行连接,形成复杂复合任务AI软件系统。

  • 此外, 作为智能制造, 工业4.0的重要支撑,我们最近的ICSE-SEIP 2022 工作When Cyber-Physical Systems Meet AI: A Benchmark, an Evaluation, and a Way Forward中对AI-enabled cyber-physical system 尤其涉及到典型重工业领域AI(控制)系统进行了大规模调研,并对AI在智能制造为主的工业领域潜力进行了分析,建立了一套AI-CPS benchmark。 我们发现,在重工业工业过程中,大部场景都对系统质量,安全,可靠性有极高要求. 目前,AI模块一般在智能环境状态预测与智能控制和传统软件模块会采用冗余(Redundancy)方式,并行互补使用,一方面提升系统性能,同时降低安全与可靠性风险。我们也发现,AI软件系统在重工业领域应用还有许多技术值得进一步研究与探索。 比如下面 AI 风力控制系统。如何设计,开发,并为AI-CPS 提供质量,安全可靠性保障或许是一个重要方向。

余跃:

马老师这个太高级了,我说个简单点的吧。我个人日常也在用,我相信也是大家比较熟悉的,也是现在比较典型的AI软件系统:一类是我们现在常见的例如今日头条、大众点评等结合了UGC系统和推荐系统的这类软件。另外一类是带强化学习、博弈等模块的游戏,比如王者荣耀。里面的AI技术主要提供一个是精准建模用户和内容之间的关系,实现资源个性化推荐等功能。另一类就是模拟真实用户形成智能体,有点像在特点场景下的强人工智能。这些系统应该都是比较典型的人机协作的智能系统。对于模型和软件模块来说,数据其实是桥梁。一个是通过软件功能从用户侧或者系统侧产生各类数据,然后进入到AI模型持续提高模型能力,然后软件再结合模型的输出(比如推荐结果)与实际场景,去服务用户。这样形成一个闭环,其实这个软件、数据、算法与模型这种持续相互作用的模式还是很鲜明的。

观点讨论

@彭鑫:@马雷 AI应用软件应该也存在一些典型的参考架构和设计模式。

刘老师和马老师都提到了AI应用有时候适合采用end-to-end模式,即整个系统都是由一个AI模型组成,有时候适合采用多个模型同时与软件模块组合成完整系统。

另外,AI模型与传统Rule-based 软件模块也可以相互结合使用,后者虽然“智能性”略弱但是应该更加稳定、资源需求更低。

@马雷:非常赞同!

@陈碧欢:AI系统里应能有不少规则进行模型输出的修正。

@鞠剑勋:非常赞同,工业界很需要。

@刘杨:我们在做的一个题目就是把数学方法的决策和AI的决策的结合。这个很有意思。

@马雷:同意,对模型行为有更好的理解基础上,可以设计出更加可靠的规则。

@彭鑫:应该可以做一些值范围或取值关系检测,相当于对AI模块加了一点contract检测。

陈碧欢:

我们目前主要调研了百度无人驾驶系统Apollo和开源对话系统RASA。Apollo使用了基于CNN的模型进行目标检测、基于RNN的模型进行车辆、行人轨迹预测等。RASA使用了基于Transformer的模型进行命名实体识别、意图分类、上下文预测等。

模型之间的交互包括上下游关系与组合使用关系等。前者即一个或多个模型的输出作为后一个或多个模型的输入。后者包括针对不同场景使用不同模型、 以及多个模型的输出被综合使用。例如,Apollo针对不同的红绿灯(横的红绿灯、竖的红绿灯等)切换不同的模型进行识别,并使用Kalman Filter综合LiDAR、camera和 radar的检测障碍物结果。而模型与代码间的交互主要是代码模块对模型输入输出进行预处理与后处理,也有预先编写代码逻辑综合模型输出或根据场景切换模型。

冯洋:

目前我们团队主要在研究四种智能系统:自动驾驶系统,自然语言翻译系统,智能对话系统和语音识别系统。这些系统从架构和设计上各有特点。以智能对话系统和语音识别系统为例,这两种系统中通常采用循环神经网络模型 (RNN),包括RNN的变体如LSTM,GRU, BiLSTM 等等。RNN模型在智能对话系统中的主要功能是做语句的意图识别和实体槽位填充;RNN模型在语音识别系统中的主要功能是将输入的语音分类成对应的文本单词。对于大部分AI软件系统,机器学习/深度学习模型往往是作为一个核心的分类功能模块,而从系统接收到的数据信号,转化为模型可以读取的数据格式,还需要一系列预处理过程;系统基于模型输出的预测结果生成最终的输出,同样涉及到大量传统软件模块。因此,如果一个AI软件系统中嵌入了一个或多个已经训练好的模型,可以认为是一个或多个封装好的黑盒功能模块,AI软件系统内部的数据预处理模块、智能模型与其他处理模块之间都存在交互和协作关系。而对于自动驾驶系统,则相对更加复杂一些。自动驾驶系统是一个由感知,决策,预测,控制等多个模块组成的复杂系统。其中涉及到智能模块的组件主要是感知、预测、决策部分,其中感知部分相关的,而其中的感知又涉及到雷达,摄像头等传感器。深度学习模型在其中主要扮演的是一个获取外界信息输入的角色。

这是我们当时去调研了Apollo,Autoware等四个开源的自动驾驶系统之后,绘制的自动驾驶系统的reference architecture的图。我们发现这四个自动驾驶系统不仅架构很相似,甚至于包和模块的名字都很接近,但是代码还是有较大的差异。

鞠剑勋:

我介绍下两个AI软件系统。

其中之一是我们携程自主研发的客服机器人背后的对话系统,这套对话系统使用的对话框架和前面的嘉宾提到的开源框架:RASA,有一些相同点和不同点,我们的系统比RASA要早(RASA诞生于2017年,我们的系统诞生于2016年)。

我们的框架更适合企业应用,而RASA更通用,我主要介绍下我们的系统框架:

我们的系统主要有三个模块,NLU,DM和NLG,和RASA类似,整体上将NLU、DM、NLG模块进行了集成,通过pipeline进行功能整合

NLU:自然语言理解,主要包含意图识别和词槽抽取。意图识别,负责将自然语言解析成意图,采用了两种模型,基于预训练模型(比如BERT)的分类模型,和基于预训练模型的匹配模型,根据场景的不同而灵活选择。输入是对话文本,输出是意图的语义表示。词槽抽取,主要采用BERT+CRF,输入是对话文本,输出是词槽。

DM:对话管理,一般分为DST(Dialog State Tracking)和DPL(Dialog Policy Learning)两个子模块。DST接收NLU的结果并跟踪对话状态,DPL接收DST的当前状态并选择接下来采取的action,DST记录action并更新状态

DPL有两种模式,基于规则和基于模型,规则适配于开放式平台,相当于把对话流程控制权交给平台使用方,这种适合对话流程严格控制的场景。基于模型类似于RASA,使用模型来学习对话流程,通俗的讲就是训练一个有监督模型来预测机器人下一步对用户说什么,这种适合对话流程宽松的场景。两种模式适合不同的场景,不能说哪种更好,只能说哪种更合适

NLG:自然语言生成,主要负责答案生成。有三种模式,平台配置答案、知识图谱查询答案和算法生成答案,和对话管理类似,适合不同的场景。

三个模块都有使用机器学习或深度学习模型,在我们的架构里模型全部单独提供服务(RASA同样支持本地模型,也支持接入模型服务),遵从AI即服务的思想,单独在云端部署,即当前流行的微服务(Microservice)架构。

采用这种架构的原因是:

  1. 可以将算法建设和系统开发分离,算法迭代更新很快而系统相对稳定。

  2. 模型灵活可复用在其他场景。

  3. 最重要的一点:模型服务往往是python编写,而携程在线应用是java编写。通过Service Mesh  (简单通俗来讲,Service Mesh 是微服务时代的 TCP/IP 协议),服务可以用任何语言编写,只需和Service Mesh通信即可。

  4. 软件开发人员和算法研究人员各有所长,通过这种架构设计,使各发挥所长,高效协作,提高整个系统开发生命周期的开发效率。

模型是如何训练和部署的?

其中之一就是通过EMOSS,EMOSS是基于MLFlow,携程自主研发的系统。因为不是我们团队研发,所以我简单介绍下:

先说下MLFlow主要特点:

  1. 支持大部分现有的机器学习库

  2. 跟踪实验记录和比较参数和结果

  3. 模型打包,跨平台迁移

  4. 支持模型远程存储

  5. 支持模型管理和部署

  6. 提供模型生命周期管理

Tracking Server是MLFlow最核心和关键的组件,相当于模型管理中心。

训练阶段,训练好的模型序列化之后保存到Tracing Server,统一管理。

部署阶段,从Tracking Server下载模型文件并反序列化。

EMOSS在MLFlow基础上改进了模型部署,并增加了水平扩容、性能压测、监控告警和AB测试功能,更加适配于企业应用。

EMOSS的模型可以快速部署运行在docker,这样的好处是可水平扩展。Docker模型集群需要自主运维。

观点讨论

@彭鑫:@冯洋 听起来有点像传统软件工程中的软件产品线了。

刘杨: @冯洋 这个可以做对比分析,然后看看哪个系统更靠谱。

@冯洋: 谢谢刘老师指导~~~我们近期就开展相关工作。

@刘杨: 可以合作一下,我们有个地图生成工具,可以做黑盒测试用例生成。

@彭鑫: 看起来随着AI在各种软件系统中的深入应用,AI模型之间以及AI模型与软件模块之间都出现了很多典型的组合结构和交互方式,同时AI软件系统也开始大量采用微服务和云原生架构

@彭鑫: EMOSS、MLFlow等平台对AI模型的训练、部署甚至运维都有了支持,看起来AI模型的DevOps和AIOps有点那意思了。

Question 2

当前AI软件系统中的机器学习和深度学习模型开发采用了什么样的软硬件技术栈?形成哪些技术生态?由此导致的环境和生态依赖对于AI软件开发带来了什么样的困难,与传统软件开发中的环境依赖和依赖管理有什么区别?

刘杨:

当前AI软件系统采用的软硬件技术栈主要分为算力、数据和计算平台三类。其中算力属于硬件,比如CPU、GPU和TPU等;数据则是训练机器学习和深度学习模型所需要的数据信息,例如著名的ImageNet;计算平台则是运行或部署机器学习和深度学习模型的系统环境,例如TensorFlow、Pytorch、PaddlePaddle等。

Nvidia、Google、Facebook都围绕自家的AI产品形成了各自的技术生态。例如Nvidia以GPU为核心,形成了的技术生态包括:通用并行计算架构CUDA、专为模拟量子电路设计的加速库cuQuantum、用于实时全数据包检测的数据中心安全平台Nvidia Morpheus,用于企业级AI应用和服务的GUI工作流程驱动框架TAO,等等。Google和Facebook分别围绕TensorFlow和Pytorch都形成了各自的一系列技术产品。

环境和生态依赖给AI软件开发带来的困难:

  1. 与大厂深度绑定。例如深度学习所需要的算力几乎只能依赖NVIDIA的GPU;计算平台虽然百花齐放,但也都是各大厂商的产品。

  2. 开发成本巨大。例如OpenAI 在2020年发布的预训练语言模型GPT-3 具有 1750 亿参数, 训练所用的数据量达到 45TB, 训练费用超过 1200 万美元。

潘青华

刘老师说的很全面了,我站在讯飞角度说一下我们的现状和问题。

深度学习模型的开发,现在大多数还是依赖英伟达的GPU硬件,不过我们最近这几年也做了很多基于国产AI芯片的训练框架和工具的开发适配工作,比如在华为、寒武纪的AI加速卡上,已经取得了一些阶段性成果。

训练框架方面,讯飞内部会使用自研深度学习框架+各种主流开源框架,例如Pytorch、TF等,而模型推理端的实现跟目标硬件平台强相关,所以我们做了适配很多端NPU的深度神经网络推理引擎,另外我们也积累了语音、图像、NLP等领域的各种算法组件库,现在搭建一个新的AI软件,基本是使用一套框架,集成推理引擎和算法组件库。

不过,不论是端侧NPU还是国产化GPU,现在各家生态不兼容,而且生态还很不完善,导致根据硬件特性优化模型推理实现,有非常多的适配优化工作。

观点讨论

@彭鑫: @刘杨 讲的相当系统。

@马雷: 尽早实现多元化支持,尤其对AI底层软件国产生态系统至此太关键了。

@陈碧欢:如果有模型大数据,不知道有没有自动模型优化的可能。

@潘青华:自动模型优化,是一个值得探索的方向,现有的一些方法,还是偏“大力出奇迹”。

马雷

前面两位老师已经做了非常全面分析,我这里补充一下。

当前主流AI软件系统中的模型(监督式)开发主要包含了数据收集处理、标记(Labelling)、模型设计与训练等多个流程,训练好的模型对指定输入或场景进行预测与推断(inference)。为了支撑这一过程,目前AI深度学习模型开发一般采取一些主流的深度学习框架,如Tensorflow, PyTorch, PaddlePaddle,Mindspore等。机器学习模型开发过程通常与深度学习较为类似,也采取一些特定的平台框架或Library作为支撑(如Scikit-learn, Weka)。这些框架一方面简化开发流程,与learning library和底层GPU, NPU, CPU等硬件进行交互,形成自上而下的软件Stack (如下图):

我们近期也开展了一部分针对深度学习框架层面研究。与我们企业伙伴合作过程中,我们发现一个巨大的挑战就是过去几年整个软件Stack各层软件的版本迁移十分迅速,而stack的各层之间的依赖很难适应这种变化,导致版本兼容性比较差 (不同深度学习框架,不同CUDA版本,不同操作系统版本,不同硬件指令集版本等)。比如早期Tensorflow 2.0 比1.0版本进行了很大的调整,导致版本限制和约束明显,早期开发的AI模型很快就会随着新的框架版本迁移变得难以适用。

此外,AI高度的计算图与算子计算或许是和传统软件一个较大的区别,在AI全栈开发过程中,底层指令集和支持的算子也往往会因为企业自身的优势和考量优先选择级逐步开发,所以很容遇到一些模型在一个框架上工作性能指标很高,但是在更换一个框架,平台或者硬件时,包括准确性等性能指标会降低甚至断崖式下降。因此,构建AI stack 软件供应链依赖图谱,对安全,可靠性进行分析或许是一个重要方向。同时,针对深度学习stack设计专门的compiler或许也可以帮助减轻版本兼容问题,并大幅提升AI模型在各个平台与硬件的应用与适应性。

观点讨论

@彭鑫:看来AI模型可迁移性很差。

余跃:

补充一点吧,现在AI技术栈大概是:芯片-》编译与驱动-》集群-》计算框架-》领域框架-》算法。不同芯片对应的底层计算平台不一样,比如英伟达CUDA、华为昇腾CANN等,再有就是一些推理芯片,刚刚前面的专家也提到了比如寒武纪加速卡等。在此之上就是如何将芯片形成集群的系统软件,进而为用户提供单机多卡、多机多卡等并行训练的能力,以及实现智能计算集群虚拟化后的云服务能力。在上层就是计算框架,比如大家熟悉的pytorch、TensorFlow、paddlepaddle、mindspre等,还有计算框架之上方便编程的编程框架比如Keras、tensorlayer等。这些计算框架会跟硬件相关,比如华为mindspore对于昇腾芯片更友好。在一般意义上的计算框架之上呢,现在出现好的领域算法和模型框架,比如CV、NLP、AutoML等,比如商汤的OpenMMlab、MMDetection等,实现了很多一个领域的一些通用功能,比如图像分割。然后就是各类AI算法、网络与模型这些更广泛的生态。

另外,马老师的图很高级啊。

陈碧欢:

模型开发主要采用了NVIDIA GPU作为硬件设施,其它也有包括AMD GPU、Google TPU、华为昇腾芯片等。而软件栈自下而上包括操作系统和容器(Linux、Windows、Docker等)、GPU驱动(Nvidia GPU Driver、AMD GPU Driver)、并行计算平台(NVIDIA CUDA、AMD ROCm)、机器学习和深度学习开发加速库(cuDNN、cuFFT、cuBLAS、rocFFT、rocBLAS等)、开发语言运行时库(Python、Javascript、Java等)、DL开发框架(Tensorflow、PyTorch、MindSpore、PaddlePaddle)、以及上层应用和第三方工具库。形成了以GPU硬件平台为中心、Python语言为主流开发语言、以Tensorflow、PyTorch、MindSpore、PaddlePaddle等为流行开发框架的技术生态。

AI软件系统正处于快速增长阶段,不断有新的架构、新的功能、新的技术,从硬件到软件的迭代速度都非常快。厂商新出的硬件所需要的软件,从底层的硬件驱动和开发工具包,到上层的框架和模型代码,都需要AI软件生态版本迭代,快速跟进并支持新的功能,而厂商在快速支持新功能的同时也引入了后向兼容问题。例如,GPU硬件厂商NVIDIA因为GPU的架构不断推陈出新,对自家的显卡定义了“compute capability”用来评估显卡的计算能力,型号为GTX 1080的显卡compute capability为6.1,相应的并行计算平台CUDA如6.5,支持的compute capability范围为1.1到5.x,CUDA 10.0 支持的范围为3.0-7.5。也就是说在使用新的GPU硬件的同时,需要上层软件栈的同步更新才能配合使用。我们也试图在理解和刻画整个软硬件技术栈中的依赖关系,建立软硬件供应链网络进行分析,从而检测AI软件系统对环境依赖的耦合关系,从而预知不同的AI软件版本兼容性给系统带来的影响,包括系统的可靠性和运行结果的准确性。

观点讨论

@余跃: 这是Linux AI&DATA基金会的技术栈。

@刘杨: @余跃 这个太有意思了,未来5年的科研题目都包括了。

@马雷: @陈碧欢 最直接的感觉就是发展速度太快了,几个月就一个版本迭代。

冯洋:

各位专家从生态和系统方面都谈得很深入了,我就补充一点:相较于传统软件开发而言,机器学习和深度学习模型的开发工作对技术人员的统计知识、相关的深度学习算法等提出了更高的要求;此外,以Pytorch、Tensorflow为主流的人工智能模型开发框架也是当前连接人工智能软硬件技术栈的一个重要组成部分。

AI系统中智能模型更多的是数据驱动的编程范式,换言之,开发者需要的是根据数据分布、任务类型,结合自身的统计、人工智能技术知识,选择恰当的模型架构与模型迭代方法。

在我们的工作中,AI软件开发与传统软件开发最大的区别在于其构建过程高度依赖于数据。传统软件开发的依赖管理,通常是关注于环境依赖;而AI软件开发的则需要考虑数据依赖。同时,通常情况下,AI软件所依赖的数据量是非常大的,小则几个GB,大则数十个TB(例如雷达点云数据等)。我个人很关注数据方面的问题。我认为数据依赖的管理存在很多问题,例如,数据仓库的维护,清洗;数据的选择,标记等。这些问题也为我们软件工程的研究者带来了新的挑战。目前已经有一些相关的研究,来支撑各种模态数据的管理。

观点讨论

@冯洋: 我个人认为对数据的依赖,也是基于深度学习的软件系统开发的一个重要依赖因素。对数据的分析,管理,更新等,也是一个直接影响到深度学习系统质量的关键因素。前不久看到了一个study调研结果发现imagenet上也有4%左右的标注错误。这些问题我认为也是需要解决和处理的。

@鞠剑勋:同意,数据也是AI软件开发非常关注的一块。

@马雷: 同意,前几年都过度关注模型,一定程度上忽略了数据。

@冯洋: 从余老师发的图片上看,数据依赖位于第二层?也有相关的生态正在快速形成并成长。

@马雷: 这个好像分了好几个大模块,一层也有几个block。

直观看上去,好像数据是最大的一个block。

鞠剑勋:

前面几位专家基本上已经说的很完整了,我稍微补充几句。

AI软件开发与传统软件开发中的环境依赖和依赖管理的区别:传统软件开发依赖于系统及开发语言,AI软件开发更多依赖于生态。

目前生态很多,AI云平台诞生前:过多的生态使得选型变得困难,没有统一的管理方案。各生态彼此独立,迁移或者更换生态成本高。AI云平台诞生后,解决了上述问题,但各家云平台不互通,所以只能选取一家。较大的公司往往会选择自研,小公司只能采用大公司的平台。

Question 3

在企业开发实践中,机器学习和深度学习模型的功能和非功能性测试、分析和调试一般采用什么样的方法和技术?此外,在AI软件系统层面上的整体测试一般会采用什么样的策略和技术?

刘杨:

据我们所知,企业开发阶段还没有比较成熟或者标准的测试方法,而且主要是集中在模型级别。可能公司内部有些标准化流程,但是大多数公司还没有形成比较一致或者统一的方法。比如说,大部分公司仍然是基于测试数据来评估性能的。不同公司的测试数据来源可能有区别,有些数据是真实世界收集的,有些数据是标准数据集,有些可能是根据自己的场景生成的(比如语音识别,会生成各种场景的语音信息;无人车会直接在现实场景中去跑)。我们也收到了好多公司的咨询,主要是关于讨论现有的模型测试方法以及是否可以将其加入到公司内部的开发流程中。最近我们就在和新加坡一个做社交APP的公司合作,把我们的一些方法尝试集成到他们的pipline中,使得他们的AI算法有一定的保障。同时我们还在新加坡推进一些关于可信AI标准的制定,也是在尝试标准化这些流程。对于分析和调试,我所了解的目前还是靠人多一点,人去观察数据的好坏,试不同的模型以及参数,通过设置多种实验来去定位问题,比如需要补充哪些数据,需要去掉哪些数据等。

潘青华:

对于AI软件系统的测试,主要是模型的测试,特别是效果、效率这样的非功能性测试,因为软件一旦设计好,功能基本不会改变了,但是模型变化特别频繁,AI模型测试本质上是通过测试集验证模型的效果。AI模型测试与传统软件测试存在着比较大的差异。测试标准的不确定性和结果可解释性是AI模型测试和传统的软件测试主要的差异。传统的软件一般测试人员根据业务特点设计用例,输入输出是比较确定性的,AI模型测试的预期结果则存在着不确定性,不能像传统软件测试用每条用例的对错来衡量系统的正确性。

传统软件测试有一个完备的测试体系,但是AI模型目前没有一个良好的体系来保障它的质量。模型测试有两种不同的思路,一种是偏黑盒测试,在模型上运行验证数据集,计算效果指标(比如召准率,F1-score),这是目前行业主要的测试方法,这种测试主要挑战在于对数据集的把握以及badcase的分析,整体是把模型系统当做一个黑盒子在看待;另外一种是偏白盒测试,例如对抗测试是通过算法对样本增加一些扰动来生成新样本,以达到验证模型安全和鲁棒性的目的,这类白盒测试对验证数据集能很好进行优化和裁剪,同时对badcase的分析更具有针对性。

从另一个视角看,AI软件系统测试有两种,一种是分层的集成验证,包括集成模型后的引擎测试、集成引擎的服务测试和产品端的测试,每一层会有自己的侧重点,这种方式会保障各层的软件质量。另外一种是系统测试,从终态产物进行端到端的测试,这种测试对分层集成测试是一种很好的补充,有时能发现集成测试不能复现的效果问题(麦克风拾音影响等)。这个需要结合产品特点和阶段来综合考量。

观点讨论

@彭鑫: @刘杨 从测试到标准,以后AI软件要认证才能上线。

@余跃: 好像企业内部都有自己的AI开发平台,提供研发全生命期的能力保障,例如阿里PAI这样的平台。这是企业内部的工程化能力的体现。我也是准备听听企业专家的介绍,学习一下。

@彭鑫: @潘青华AI测试也有白盒测试方法了, 不过看起来跟传统的软件白盒测试方法还是很不一样的。

@余跃: 上次去讯飞参观,其实看到了很多AI的开发与测试工具。

@潘青华:讯飞内部也有AI研发平台和AI质量平台,基本实现一些流程的自动化。

@彭鑫: @潘青华看来AI软件也存在“集成”相关的bug。

@潘青华:不过我觉得真正自动化测试还没有实现,需要来自学术界更多的新技术新思想。

@余跃: @潘青华其实包括刚刚提到的很关键,数据与数据集,标注数据质量检测的工具和平台。

@曹峻铭:潘院长您好,工业界在对AI软件进行系统测试时,如何定义系统的测试覆盖度?因为系统不仅包括一般的代码模块,还有模型模块,会把模型覆盖度与传统的代码覆盖度指标综合考虑吗?

@潘青华: AI软件的测试覆盖度,更多是我刚才说的,作为模型输入的测试数据, 对于场景的输入的覆盖度。

@曹峻铭:好的,基于场景的输入覆盖度就需要领域知识,或者根据系统上线后的真实数据了。

@潘青华:我理解“模型覆盖度”其实是训练数据和测试数据在概率空间分布的匹配度,我们一般不直接去比较这个

@冯洋: 潘老师的这个思路太好了!我们后续会往这个方向进行探索。我们目前正在研究“概率空间分布的匹配度”的可行性。

@潘青华:以前不用深度学习的时候,考虑思考过这个问题,用深度学习之后,这个数据的分布不知道怎么表示了。

@刘杨: 那如何度量测试的效果好不好了?

@潘青华: 看最终统计指标。

@马雷:在开发每一轮迭代过程中是否有具体,比如指标提升的一些指导和建议呢? 还是黑盒训练或者finetune一下再看统计指标?

@潘青华:用开发集调参,黑盒训练,用不可见的测试集评估,不然肯定overfitting。

陈碧欢:

从学术界来看,目前对单一模型的测试与调试研究很多,而对整个AI软件系统端到端的测试与调试的研究较少。对模型的测试很大一部分是生成有效的测试数据,包括定义度量模型测试充分性的指标、提出新的测试数据生成技术、测试数据集约减技术等。这类测试检测出来的问题基本都是通过模型重训练解决。另外一部分是模型结构问题的检测,试图寻找出需要修改模型结构的问题。有着明确test oracle的模型结构问题包括shape bug、numerical bug,所以已经有一些静态、动态分析的方式去检测。另外一些问题没有那么明确的test oracle,跟ML训练的领域知识比较相关,例如ICSE2021的 AutoTrainer与DeepLocalize检测梯度、损失函数、网络层输出值等训练过程中的指标的异常情况,并提出一些常见的修复方式去尝试修复模型结构。

冯洋:

我最近和一些专家学者探讨关于AI系统质量保障的问题,其中谈到了一些指标的定义,我从这个角度出发讨论这个问题。现在基于机器学习和深度学习的软件质量评估,主要包括正确性和实时性;其中非功能特性包括鲁棒性、安全性、泛化性和可解释性。

正确性是指深度学习模型在规定的条件下、规定的时间内正确的完成预计功能且不引起模型失效或异常的可靠性。实时性是指实时嵌入式系统中,DNN模型推理运行时间应当小于该任务所指定的时限以及系统可以纳入新的数据并实时更新模型。鲁棒性旨在算法模型部分参数略微改变或控制量稍微偏离最优值时,算法仍然保持稳定性和有效性的能力;安全性旨在测试算法模型在受到外界攻击时,能否进行合理的防御和攻击检测;泛化性是指根据有限样本得到的网络模型对其他变量域也有良好的预测能力,验证算法模型在分布规律与训练数据有偏差的测试集上的预测准确性;可解释性是针对算法模型的黑盒特性,评估模型的输出是否具有高置信度,以及输出结果是否可靠。

在对模型进行测试分析时,一般根据模型结构、任务类型、数据格式,基于蜕变关系和领域规则生成大量测试用例,并根据一些预定义指标进行测试和分析。在进行AI软件系统层面上的测试时,一般是将训练好的智能模型封装为黑或者灰盒功能模块,根据系统的功能需求设计测试用例,评估系统的准确性、可靠性、稳定性。

目前的AI系统测试的技术方法还在构架中,近些年来有很多这方面的工作。但是我认为最基础的还是测试指标。当然这方面有很多的工作可以做,目前我们组也投入了大量的精力在这个方面。

我认为AI系统的质量保障,由于其原生的行为不确定性等特性,其质量保障相关工作更加困难;另外一方面,由于其通常被应用于安全攸关领域,其安全性也非常重要。

我个人认为,就AI 系统的测试充分性指标的构建而言,我们就可以从覆盖,多样性等多个角度入手进行分析讨论。

鞠剑勋:

我主要从事NLP领域,所以我只说下工业界在NLP领域的测试

带有深度学习模型的软件测试和传统软件测试的不同在于,深度学习更关注于模型效果测试,即对返回结果的准确率、精确率和召回率(或者别的指标)的测试。因为即使功能上没有问题,但如果模型预测的有很多错的,也无法满足需求。

首先会测试模型在提前准备好的标准测试集上的各项指标,其次会测试各自情况下模型的性能

除了利用测试集进行测试,为了精确还原线上的真实结果,某些情况还需要提供测试窗模拟真实环境进行效果测试,或者采用灰度测试。一般会采用抽样进行测试。

因为测试量巨大,因此会采用一些减少人工的方法,这里举两个非常现实的例子:

1、回归测试,已上线部分,每天定时在生产流量里边拿昨天不同类型的数据,运行模型服务,记录当前返回值和昨日返回值的对比结果

2、针对nlp模型,采用算法批量生成句子,作为测试句子输入,其他参数手动填写,批量跑,把结果输出,给测试工程师验收

观点讨论

@马雷: @陈碧欢 同意,感觉是个比较重要的方向。

@潘青华:冯老师高见,讯飞也是这么考虑的,以前叫AI测试,现在也重新定义了问题,叫AI质量。

@彭鑫: @潘青华 @冯洋AI模型存在不确定性,所以是不是更像是评测而不是测试?因为测试更像是有个确定性的标准,而评测则可以强调评价而非绝对的测试通过或不通过。

@鞠剑勋:@彭鑫 一般会定义一个达标的标准,就类似质量标准。

@潘青华:@彭鑫 也可以这么理解,不过我们定义好一个测试集之后,统计数据的指标也可以作标准,从这个统计结果可以代表软件性能。

@彭鑫: 我再追问一个问题:AI系统的系统级测试与传统软件系统的测试有什么区别?AI模型的测试存在不确定性,但到了AI系统级别是不是会更强调确定性?因为AI系统内部有多种AI模型、规则推理等其他补充性的决策模块以及一些异常处理模块,系统整体上会追求与传统软件系统类似的稳定性和确定性。

@潘青华:这里非常考验测试集的设计能力,是否能覆盖全应用场景。

@陈碧欢:@鞠剑勋 回归测试中,上一个版本预测对的但在当前版本预测错了,对于你们来讲是个问题哇?

@鞠剑勋:@陈碧欢 对于客服来说,需要保证线上给客人的答案的稳定性,保证服务质量,因此错误率不能有很大的波动

@冯洋:@彭鑫 彭老师高见,我个人认为这方面的测试/评测确实是一个很有意思的问题。目前的AI系统通常都集成了很多防御与适应性增强的机制,我认为在这个机制下,是可以通过设定一个比较高的标准,来完成测试或者评测某个AI系统是否达标,或者说是否健壮。

@冯洋: @潘青华 我个人认为这个问题有一定挑战难度,我们近期的研究发现现在AI系统的适应性都比较差。

@彭鑫: @鞠剑勋,错误率应该是个整体的概念,但是如果是整体错误率下降但某些个案(如某些具体的问题)上出现原来回答正确现在回答不正确的情况呢?

@鞠剑勋:每种场景的要求不一样,看具体的需求。如果对于模型预测答案非常严苛,那么需要达到不能有badcase的程度。如果是一个不严格的场景,比如情绪识别,这种情况是允许的。

@潘青华: 所以会出现,统计指标提升,但是增加一些不可接受的badcase...是个比较麻烦的问题。

@鞠剑勋:不可接受的badcase可以加入到固定的回归测试集。

@彭鑫:@潘青华 意味着不同的case预测正确与否的价值和重要性是不一样的?这样AI模型评测也许要考虑权重问题了。

@潘青华:@彭鑫 是的,我们定义有一些错误是一定不能出现的,比如我说不是,识别成是

@马雷: 不知道这样做是否可以有些学习到一些badcase规律, 感觉很难完全穷举所有badcase。

@鞠剑勋:@马雷 这确实是很多公司面临的挑战,之前也找冯洋博士交流过,希望学术界能有所突破。

Question 4

AI软件系统特别是其中的机器学习和深度学习模型是如何持续演化的,例如如何评估其效果、提出改进需求、实施改进和更新?AI软件系统特别是其中的机器学习和深度学习模型的版本如何管理?

刘杨:

我们可以根据传统软件工程思路来看AI软件系统,但是区别于传统软件设计流程,AI 软件系统面临新的挑战,例如AI模型的训练依赖于训练数据和不同的模型机构,AI模型部署到不同的平台上可能需要进行必要的网络压缩。 这些过程都有可能造成AI软件系统的缺陷。 为了使得AI软件系统能够实用落地,在设计流程中,我们主要关注AI软件系统评估、缺陷的分析与检测,及AI软件系统的修复 三个方面问题,并引入特殊的设计来解决AI软件系统特有的问题。例如在AI软件系统评估方面,我们主要是从软件测试思路出发,并考虑物理世界中可能出现的各种真实干扰 (例如,光照、相机成像和数据后处理方法),探索AI模型的鲁棒性评估问题,最终希望构建面向场景和用户定制的AI软件系统评估方法。  在需求和改进方面,我们尝试引入了AI领域最新的技术和理念例如自动化的数据增广和网络结构搜索等。

在AI软件系统版本管理方面,目前,有很多公开的平台,提供了AI模型库和标准测试结果,为广大的科研工作人员提供了方便的测试和实验基础。但是目前的模型库仅仅提供了最终的训练模型并没有提供模型版本管理的功能。区别于传统的软件版本管理,AI软件系统版本的更新应该要考虑训练数据的更新、模型结构的更新、以及训练数据的更新。这也是我们正在做的事情。

潘青华:

这是个好问题。一方面,新的深度神经网络模型在不断的被提出,新的模型优化技术(主动学习、预训练、少样本学习等)也在不断升级,这些演进离不开核心技术的前沿创新突破。另外一方面,基于数据涟漪效应(讯飞习惯的说法)的闭环迭代也是模型效果升级演进的重要一环。这些演进需要依据一些符合应用场景的评价标准来落地到工业界的软件系统中去。评价方法其实需要结合AI技术的应用场景来选择不同当时,举例来说,有时候需要构建贴合实际应用的离线测试集合进行测试验证,有时候需要进行线上的A/B Test,通过统计指标进行定量对比。那么怎么及时发现算法应该需要被改进呢?这个时候还是需要从产品、从用户使用的角度去定期的监测和分析我们已有算法的效果,提出需要改进的问题以及改进方向。

模型的更新与实施,其实和传统的软件系统相似,都需要关注兼容性、稳定性、模型版本等,做好相关的应急预案,比如灰度、回滚等。与传统软件系统相比,特别之处在于,模型结果有一定的不确定性,不是所有的结果都可能会满足用户期望,这是比较常见的情形。这个时候AI软件系统通常需要配套一些“人工干预”模式,以解决少量单点问题,而不似传统系统中直接组件回滚。

观点讨论

@彭鑫:与传统软件新版本往往可以取代老版本不同,AI模型的多个不同版本有时是不是有共存的价值?

@潘青华:我理解是有的,不过商用一般不敢这么干,多系统融合一般比单系统好,但费钱

@刘杨:@彭鑫 model和数据都需要做版本控制,数据比model可能更重要

@彭鑫:@潘青华 这个时候AI软件系统通常需要配套一些“人工干预”模式,以解决少量单点问题:这个是不是就是人机协作的智能了?

@潘青华:如果只是人工干预,我觉得只是  人机协作做到一半,人工干预之后,怎么驱动软件的迭代改进,完成整个迭代过程,才是完整的人机协作智能。

@彭鑫:就是类似的问题人工干预一次,机器举一反三,而不是次次都要靠人。

@潘青华:是的,对这个问题的认识,我们也是逐步加深的,包括一个不同的人工干预结果如何融合使用。

马雷:

首先Unit level,模型层面:

机器学习模型与深度学习模型是典型的Data-driven AI开发模式,Data, Source Code, Model 都是重要的软件Artifacts。因此持续演化也涉到Data, Source Code, Model等多个层面,持续演化在AI软件周期中或许比传统软件更加具有挑战。 这里引用EvidentlyAI公司的一个AI模型CI/CD过程中需求的考量和需要解决的各种问题与需求的概括图,比如 Data drift, concept drift 都是目前导致的模型性能下降的常见因素,因此通过演化维护连续提升也是紧急而迫切的需求。具体的评估指标也需要从多个角度,针对各类可能存在的问题与需求,进行迭代式提升。

在连续演化过程中,数据,代码,以及模型架构等或许都需要进行相应的调整,升级与维护。比如,在Matin Fowler近期的个人博客中对演变流程进行了相关讨论与总结,如下图,可以看出,开发,部署,动态监测,与持续的演变提升也是AI软件工程的重要生命周期阶段,同时不同开发阶段,也需要提出特定的各类技术方法,数据与评测指标,比如,数据层面会涉及到 训练数据演化,训练阶段测试数据演化,部署前测试数据变化,部署后实际应用数据检测与变化等等。

从AI System 系统level角度:

根据AI 采取架构的不同,也会存在多种演变方式。

  1. 如果采取完整end-to-end的AI模型架构,AI子模块之间通常有较强耦合性,通常可通过一次完整训练或者fine tune进行演化;

  2. 如果是类似智能语音系统这样复杂复合的AI系统,存在多个较为独立AI子系统模块,可以对每个模块单独提升;

  3. 如果AI系统采用AI模块与传统模块结合的架构,通常也可以采用(2) 的方式,对单模块或者临近相关模块进行组合提升,从而整体提升系统性能。

其中(1) (2) (3)各种架构演化的优缺点也都比较明显,(1) 对于开发维护人员相对容易,不需要对系统模块进行太多手动改动。 (2)(3)中,模块演化过程中一般也会需要临近模块进行相应的手动调整,模块较多的情况会比较难于维护。

AI软件系统尤其模型管理方面,早期也出现了ModelZoo, ModelDepot这样的平台对AI模型进行管理,方便模型搜索,推荐等。 版本管理则需要数据,代码,模型多方面同时从多个粒度进行管理,近期,有了一些初期的工具 比如DVC等在进行相关尝试。

余跃:

我快速想到的模型演化的方向主要有:

  • 新的数据进来之后,各类参数刷新。

  • 表达能力提升,比如NLP模型中的词表空间,再难一点持续增加参数、或者演化模型结构等。

  • 新的应用场景下,如何有效适配和迁移,如一开始的fine-tuning、prompt等。

  • 部署和应用环境的扩展,模型需要做比如压缩剪枝迁移等。

我们现在在做这样一种版本管理工具,做好了会开源出来:特定的代码或者算法,在特定数据集和运行环境(软硬件环境)下训练部署的模型,在特定测试集上的执行效果(比如AUC、MRR等)。这里其实设计到一组技术的组合,比如代码管理git、git-LFS、数据版本管理DVC等。我们会提供上面提到的《模型:代码、数据、训练环境、测试集》这样的版本。这个网站上面也给出了一些MLOps的思路,感兴趣的同行可以看看。https://ml-ops.org/

观点讨论

@彭鑫: 刚才大家谈到的版本管理似乎更多是训练前的模型和数据等的版本管理。那么训练后的模型是否也有版本管理呢,特别是结合容器化镜像。同一个静态模型是否会有多个训练好的模型备用?

@余跃:彭老师说的其实应该有的,训好的模型其实想复现还是挺困难的,应该把整个运行环境也纳入到版本当中。

@彭鑫:嗯,那应该可以连同运行环境一起做容器化镜像了。

@鞠剑勋:可以参考MLFlow,或者我们的EMOSS。

陈碧欢:

这个问题应该属于MLOps方向,最近出现了不少开源或商用的MLOps工具,包括KuberFlow、MLFlow等。它们的一个总体思路就是要将系统的每一次变动(包括模型、代码、数据)都进行版本化管理,接入CI/CD流程,自动化模型训练并评估功能与非功能指标,发布后持续监控模型并收集真实场景下的用户交互数据,对异常交互数据进行可解释性分析,从而针对性地改进模型结构或扩增训练数据。

版本管理主要为了可复现,可以对历史版本的指标进行对比并且支持回滚。已有的版本管理工具包括DVC、modelDB、pachyderm等。但是这些工具在实际AI系统中的使用情况还不太清楚,例如Apollo还是指定模型路径后加载模型,这样可能会带来版本管理问题。

观点讨论

@彭鑫:自动化模型训练并评估功能与非功能指标:这个相当于传统软件的CI中的自动构建和自动测试了。

冯洋:

我个人认为AI软件系统由于其核心功能模块往往是通过机器学习算法或者是深度学习算法在特定模型框架与模型算法下,基于大量数据训练构建的,通常被视为一个具有复杂内部逻辑结构的黑盒。因此对于AI软件中的机器学习和深度学习模型部分的迭代与更新,通常会从运算性能与数据分布差异两个角度出发。

AI系统对于已有功能需求,按照算法模型的最新研究发展情况,更改已有的模型结构重新训练并生成具有更强性能的新模型,进而实现核心功能的持续演化。例如,近年来新晋提出的基于自注意力机制的算法模型得到了广泛的关注,其通过减少对于外部环境信息的依赖,对于捕捉数据和特征的内部相关性有着更强的能力,因而实现了在多个文本处理任务上相较于已有方法的显著提升,因此被该领域的AI软件系统广泛应用。

另一方面,机器学习与深度学习模型的训练往往依赖于大量预先收集的训练数据,并基于训练数据与真实应用环境中的数据独立同分布(IID)的假设学习训练数据。因此,当真实环境由于时间或其他客观因素的影响发生了迁移,使得独立同分布假设部分或全部失效时,模型的核心功能可能会因此而失效。因此,AI软件的持续演化过程的另一个方向就是关注真实场景数据分布是否发现迁移,并通过主动学习等方法,通过对已有模型进行重训练等微调,实现模型的演化迭代。

目前我们团队在实验室内的版本管理还是一个比较棘手的问题,我就不对这个方面发表错误的意见了。

鞠剑勋:

我们携程的智能客服场景下的模型演化整体分为效果评测、数据监控和模型迭代这3部分。

效果评测对模型的性能进行评估,包括上线前评测和上线后监控。在模型上线前,首先评估其在标准测试集上的性能(包括precision、recall、f1-score);然后使用线上真实数据进行回归,比较与上个版本结果的差异度,分析产生差异的原因;只有当两次结果都不低于上个版本的,新模型才能上线。达到上线要求后,通过灰度实验实现模型版本更替。具体地,线上会存在多个版本的模型,各分配一定的流量,每天审核T-1数据,监控模型在线上的真实性能,只有当新版本模型优于旧版模型,才会100%接入新版模型。

此外每日会有专人对模型结果进行审核,基于审核数据,技术人员定期分析模型的badcase,从数据和算法两方面进行改进,持续提升线上模型效果。

而我们的EMOSS提供模型版本管理功能,前面已经说过。

观点讨论

@马雷:@鞠剑勋 在“分析产生差异的原因” 这块方便讲一下采用的方法吗? 或者是否采用了一些工具支持?

@鞠剑勋:据我的经验,80%的差异原因是训练数据产生的,因为需要对前后训练数据进行对比分析,可以人工核验,在nlp领域也可以用语义相似度模型来协助分析,查看数据是否存在语义上的偏差。

Question 5

在用户端和云端运行的AI软件系统一般都采用了什么样的部署结构和部署方式?云端的AI软件系统是否有采用当前流行的云原生和微服务架构?其中的机器学习和深度学习模型如何进行服务化封装、部署、动态更新和持续的运维管理?云原生和微服务系统中广泛采用的动态伸缩以及熔断、限流等可用性保障策略在AI软件系统中是否有所应用?

刘杨:

人工智能模型部署方式根据处理数据的实时性, 分为离线模型和在线模型。离线模型是最简单的模型部署方式,虽然出现最早但是目前仍被广泛使用。当在业务流程中 AI 模型 处理过程不需要实时完成时,根据需要隔一段时间运 行一次。离线模型对处理数据的时效性要求较低,所以对部署条件和实现的性能的要求比较宽松,也没有固定的部署模式,甚至可以将训练好的模型直接拿来使用,也是最早的AI模型使用方式。

在线模型部署后的运行管理方式也有很多种,目前最热门和有发展前景的就是云原生服务网格。一般的在线模型部署主要分为两个阶段,第一阶段是模型封装:将算法工程师训练好的模型重构或继续开发成 一个网络服务是在企业中比较常见的上线方式 。第二阶段是模型部署:对于封装好的模型可以直接部署在服务器中,但这种方式难以进行灵活的资源管理和调度,对于AI模型这种需要占用大量算力资源的服务,需要更灵活和自动化的方式进行管理,云原生和微服务则是非常适合AI模型的部署方案。

云原生是一种构建和运行程序的方法,被设计在云平台上运行,充分发挥其弹性和分布式的优势。云原生技术以容器的形式部署微服务并进行管理,基于微服务架构提高灵活性和可维护性,利用云平台设施实现弹性伸缩、动态调度、 优化资源利用率, 非常适合作为 AI 模型的部署方式。

潘青华:

用户端和云端在AI交付上,还是有比较大的差异的。

以讯飞为例,端侧部署模式一种是通用能力的SDK交付,比如讯飞开放平台的AI提供给开发者;另外一种相对复杂一些,需要通过模组形式交付,比如车机上的前端拾音,采用的是麦克风整列硬件模块直接交付;当然少量的场景,也会有本地service的方式部署,降低与应用间的耦合。

云端目前都是基于云原生微服务架构,讯飞的AI云平台从2017年开始就全面拥抱云原生微服务架构,规划了云原生智能计算系统架构飞云OS/图聆OS(分别面向公有化和私有化场景)。目前已经实现了原子AI能力的无服务全托管平台ASE(AI Service Engine),只需要适配百行代码将引擎模块插拔到系统中,并通过工具定义好API参数即可发布。该架构有点类似应用开发领域的PaaS平台Google APP Engine。目前平台上迭代551项能力服务,全部通过K8S+容器的模式做发布,可以理解为,我们至少有551项AI能力的微服务。

有了底层发布的标准化后,我们将异构的算力环境通过K8S管理起来,就能很好的实现弹性调度的扩展。目前我们在实时和非实时计算的混合调度任务上,实现了很好的削峰填谷,以长语音的转写为例,目前时效性覆盖了秒级、分钟级、小时级、以及24小时等,24小时任务错峰计算节省了30%以上的服务。

由于讯飞开放平台是一个开放 式的平台,承载几百万应用接入,平台的API经济模式需要实时统计这些APPID的使用次数,也需要对异常的大并发流量进行全局限流,当前我们飞云OS中也是专门实现了一个全局计量限流子系统,实现了多可用区的秒级限流,我们也能很轻松的通过监控,来查看某项AI能力的APPID TopN 实时并发。

总的来说,软件领域的云原生、微服务已经全面惠及到AI软件系统。

观点讨论

@彭鑫:我们从开发、测试、演化谈到部署和运维了。@刘杨 云原生和微服务则是非常适合AI模型的部署方案,看来我们可以探索下。@潘青华 通过云API实现的AI模型消费应该会越来越多。

马雷:

对这几个问题我们还在初期探索学习中,希望跟各位老师与专家学习前沿一线经验。

(同意彭老师观点,无论是AI软件本身微服务化还是AI用来做微服务系统服务都是重要的方向, 我们还在努力学习中。)

余跃:

这个问题就再上个图给大家,相信专家都能在里面找到云原生的AI能力部署方式。

https://landscape.cncf.io/

陈碧欢:

这个问题我们了解的比较少,希望跟各位企业专家多多学习。不过,前面提到的开源对话系统RASA有个微服务架构的版本,叫RASA X,它基于RASA提供了系统部署、监控、持续改进等服务,或许可以作为切入口开展相关研究。

冯洋:

我个人对用户端和云端部署的AI软件系统了解不是很深入(我个人也是一个用户端和云端部署的AI软件系统的用户而不是研发者),我就不对这个问题发表非专业的意见了。同时我认为AI软件系统最主要的时间与成本花销都体现在数据收集、预处理以及模型训练上,而当模型训练结束后,一个训练好的机器学习或是深度学习模型完全可以视作传统软件中一个具体的功能模块。因此实际上,AI软件与传统软件的差异更多体现在功能需求的实现方法上,对于实现之后的部署阶段而言,代码逻辑实现的功能需求或是算法模型实现功能需求并不会在部署以及运维管理的方法上有显著差异。我认为最大的区别可能是系统与数据的运维。

鞠剑勋:

根据实际情况现有生态都支持用户端和云端部署;云端AI的服务模式和现有的服务架构差别不大,AI即服务,是可以嫁接到现有的一些成熟的服务架构的;其中的AI服务遵循上面说提到的更新迭代流程;原有的一些成熟的熔断,流量管理等高可用策略都可以在AI系统中使用。

机器学习和深度学习模型使用EMOSS进行服务化封装、部署、动态更新和持续的运维管理。

使用微服务的好处,我上面提过而我们的EMOSS提供模型版本管理功能,前面已经说过:

  1. 可以将算法建设和系统开发分离,算法迭代更新很快而系统相对稳定。

  2. 模型灵活可复用在其他场景。

  3. 支持多语言,通过Service Mesh。

观点讨论

@潘青华:@冯洋 如果考虑AI软件的人机协同和自进化,那么部署运维管理会出现新的挑战。

@冯洋:@潘青华 谢谢潘老师!这也是我们重点学习与研究的点,我们前两年的工作主要是希望可以用软件工程的方法来扩展AI系统的适应性。现在我们正在研究如何在人机协同的场景下,降低AI软件系统的开发,测试,维护的成本。

@鞠剑勋:@冯洋 可以利用用户的反馈信息。

@彭鑫:@潘青华 是否还有一些自动化的adaptation?例如监控发现问题后,改变不同AI模型、同一AI模型的不同版本、AI模型与其他模块(如规则判断模块)之间的协作关系。甚至还可以自动调度模型的补充训练然后进行替换调整。

@潘青华: 我们之前做过一些这方面的尝试,后来发现系统搞的很复杂。。。用微服务之后,可以实现比较迅速的动态扩容。

@彭鑫:@潘青华 对,还有人的看护,这个有点像牧羊?大多数时候羊群自主吃草,偶尔人要干预一下,但重要的是羊群要从人的干预中学到点规律否则反复被人赶就显得很笨了。

@彭鑫:看来AI模型也广泛采用了云原生和微服务化的部署,CI/CD和灰度发布等实践也有所应用。动态伸缩、可用性保障等方面大家谈的不多,也许管理策略跟普通微服务可能区别不大。

扩容解决的是性能和负载问题?如果是预测准确性等其他问题呢?

@潘青华: 是解决性能和负载问题。对于模型准确性的问题,因为没有自动化检测手段,所以还不能实现动态监控,一般是离线分析(我们部分服务是每天自动分析一些日志结果),所以我们的AI平台后面跟着一个大数据平台。

@鞠剑勋:模型不会自己发现自己是错的,除非引入别的模型,或者有用户反馈。

@彭鑫:嗯,AI模型准确性问题可能不像普通软件故障,不需要马上处理。

@潘青华:@彭鑫 对于网络抖动或一些软件bug引起的性能和负载的问题,我们已经实现自动化运维处理。想要及时处理AI模型准确性的问题,必须要有个性化AI服务的能力,在此基础上,结合用户反馈通过人机协同的架构设计实现快速处理。

Question 6

AI软件系统的架构设计及其开发、测试、运维和长期演化方面存在哪些问题和挑战?有哪些AI软件系统工程实践问题需要学术界进一步关注和探索?

刘杨

问题和挑战还是挺多的。从我个人角度来讲,虽然现在都在推AI,但是还仅仅是开始。比如上期大家讨论的,如果发现性能不好的还在依靠算力以及大规模参数在试。总体来看,我觉得这部分内容还是需要和工业界紧密结合,做工业界真正需要的技术,这样有助于学术界理清研究方向。我分别从这几个问题讨论一下我的看法:

  • 开发:这块可能和AI领域的研究者关系更大点。我个人认为如何能够把推理和逻辑考虑进来是一个重要的问题。当前还是依赖数据,学习数据中的一些固定模式,所以大部分时候都过拟合。我们最近的一些研究就发现我们领域在code learning这块,虽然好多时候结果还不错,但过拟合确实很多,好多时候仅仅是依靠一些token就做决策。所以如何真正让AI学到逻辑和推理,是一个很重要的问题。

  • 测试:目前软工提出了很多测试方法,包括测试标准,工具,测试数据筛选等。也有一些论文指出了这些方法的不足,比如基于structural神经元的测试标准。我个人看法觉得这里的主要问题是大部分时候还是黑盒,人很难理解。所以未来测试这部分也应该和可解释性挂钩,让人能理解在测试什么,这样才能更好理解到这些测试数据发现的问题,才能更进一步的分析和解决问题。另外测试方法的度量也是个问题,比如单纯看覆盖率和找到的错误数目是否有意义?如何定义更好的度量标准?在测试过程中数据质量是否考虑?这些都是学术界可以考虑的研究点。

  • 运维和长期演化:我所了解的是模型的版本不像传统软件的版本维护的那样清晰。好多时候如果新的模型效果好,旧模型可能就直接扔掉了。未来如何系统的对AI系统尤其在模型这部分进行版本管理与演化(比如AI定制化的Github)是一个比较有意思的问题。这里就有一些问题需要考虑了:如何比较两个版本?上一个版本是否一定不如新版本?如何对这些模型做回归测试?此外,还需要对数据和模型都要考虑,数据的版本在更新与演化,模型也在更新演化,如何把这两部分结合起来是非常有意义的事情。数据这部分可能在数据工程领域已经有很多工作,从软件工程的角度来看,如何管理他们的演化,如何评估他们对于整个系统迭代过程的影响都是一些比较有意思的问题。

潘青华:

我们觉得面临的挑战还是很多的,在系统架构方面,由于深度学习相关算法还在快速演进发展,既要保障功能规格的相对稳定,又要具备新系统、新方案的快速验证和投产的应用能力。因此对架构的灵活设计和AI功能、非功能的应用论证提出了更高的挑战。在测试方面,由于深度学习的较弱可解释性和高泛化特性,如何构建系统的模拟业务场景的端到端测试方法以及如何在预研阶段即可评估功规和投入是需要进一步探索的问题。在长期演化方面,如何通过隐私计算、联邦学习等技术,在强化数据隐私保护的同时,提高数据的利用价值;以及在人工智能技术进一步普及和应用的形势下,模型的对抗性和防御、深度学习可解释性等可信人工智能范畴也需要系统的技术和方法。

马雷:

目前,学术界和工业界已经对AI (ML) System Lifecycle (MLSE) 某些特定阶段有了一些初步探索与尝试,比如针对模型层面的测试,分析,验证,理解,针对深度学习支撑框架和深度学习编译器的质量保障工作等,然而目前各种单独被提出的技术在整个AI系统开发演化全生命周期的宏观作用与影响还没有得到足够的关注。 MLSE的各个阶段engineering 的技术支持与工具链还不足,如何工程化与将具体技术工程化嵌入ML系统开发周期仍需要持续的研究,探索与实践。 我们之前的研究的大方向是希望能够提供MLSE全生命周期的质量,可靠性,安全保障,可解释等技术方法,以及探索如何有效应用到各个工业领域中应用都面临诸多挑战和值得进一步研究探索的问题。

下图是我的一些初步理解进行了简单总结。与传统软件类似,我们需要从需求,设计,开发,测试,部署,演化等全阶段进针对AI软件系统进行更为工程化的研究与探讨,让整个MLSE生命周期变得更加Engineerable。目前软工与系统早期相关研究大部分都集中在模型测试与验证相关方向,近几年针对MLSE个生命周期阶段如需求工程等研究也在逐渐提出,MLSE整体上仍面临巨大挑战,非常值得进一步深入探索。 比如模型开发生命周期工程化方法,质量与可靠性保障方法;有效模型与系统架构设计pattern,各种MLSE全周期开发工程化量化指标与具体技术与指导性建议(Guideline)等,如下图中的一些例子:

  1. 从AI 模型,到Integration,再到AI系统;

  2. 从应用层AI系统,到底层AI 框架与软件硬件Stack支撑;

  3. 再到广泛的AI系统在各领域的应用过程中需要提出的针对特定领域的新技术与方法。

或许都是需要进一步探索比较exciting的方向,也需要跨领域多学科间的合作,产学界的共同努力。

余跃:

前面专家讲的非常充分了。其实想想马老师这个图,AI系统非常复杂,如何支撑这样系统持续运行100年,这是个非常挑战的事儿。从复杂角度来说,“成长性构造、适应性演化”仍然可以指导我们去开展研究工作。例如,在开发过程中考虑系统的成长性,那么模型应该具备持续接受反馈并升级的能力。还有就是彭老师刚刚提到的微服务架构,其实也是提高这类系统“成长性构造、适应性演化”的能力。另外,这个问题也涉及到上面谈的人机协作,如何提高人机协作过程的“流畅度”,提高人在回路中的智能系统的构造与演化效率。

陈碧欢:

对整个AI软件系统端到端的测试与调试可能是一个挑战,多个模型间的交互模式以及模型与软件代码间的交互模式都会影响测试的结果,例如在多模型组合的情况下,传统的单个模型测试中发现的问题可能就不一定存在了。在此基础上,发现问题后的定位分析也就变得复杂了。另外一方面,针对AI系统开发的全生命周期管理也需要进一步探索,目前不少工具(例如google的TFX、facebook的FBLearner Flow)都是针对特定DL框架编写的AI系统,处于百家争鸣的阶段,还缺乏比较系统的认识和工具支持。

冯洋:

AI模型的输出结果具有较弱的可解释性,同时开发测试方法与传统的软件系统均有较大的差异。因此传统软件工程中的测试、运维和维护等技术可能并不适用于AI驱动的软件系统。现阶段的AI软件在调用智能模型时,通常只能当作黑盒的功能模块来处理,而难以对其输出结果的可信性、稳定性、正确性做出分析判断,即使测出模型处理某个输入用例时出现错误的预测结果,也很难对其进行修复,因为修改模型内部的参数,或者将bug用例反馈给模型进行重训练,都会导致模型处理其他数据时结果发生变化,依然不能保证模型在真实应用场景下具有100%的准确率,这些都是AI软件系统的在开发和测试方面存在的问题和挑战。在运维和长期演化方面,智能模型的演化涉及到模型的训练、调参、优化,需要不断收集更新高质量的训练数据,以及高性能的机器保障训练过程的稳定;如果更换了智能模型后数据格式、类型发生变化,所有数据处理的功能模块也要持续更新。

从我个人的研究出发,我就对测试这个方向提一些我个人认为存在的挑战:

  1. 度量指标问题。如何设计一个合适的度量指标,来引导相关测试任务;如何针对不同的模型与数据模态,构建测试数据选择与生成方法?

  2. 数据管理问题。如何完成数据的更新?bad case的管理与重训练?模型的动态更新如何解决等?

我认为由于目前AI模型的种类,架构,以及应用场景,对应的输入数据,都多种多样,这些方面的问题都需要逐个解决和处理,这也是我们目前在开展的主要工作之一。

鞠剑勋:

1.  AI软件系统的生态如何统一;

2. 模型逐渐庞大,需要通过工程和算法优化,满足高并发的调用。为了满足工业界要求,复杂的模型需要做性能优化的探索。目前性能优化技术已经比较成熟,但还有提升空间;

3. 模型迭代频繁,涉及人员众多(开发 算法 运营 运维等等),需要设置各种机制,保证整体系统的稳定性;

4. 如何取代人工做大规模模型测试,这个需要期待冯洋博士的研究成果,大家可以持续关注。

访谈结束

欢迎关注CodeWisdom,Codewisdom平台由复旦大学软件工程实验室运营,提供智能化软件开发平台及线上沙龙相关资讯,关注可了解更多智能化软件开发的最新消息~

智能化软件开发微访谈·第二十期暨2022新年特辑:AI软件架构实践相关推荐

  1. 智能化软件开发微访谈·第二十四期 大模型时代的智能化软件生态(讨论汇编)...

    CodeWisdom "智能化软件开发沙龙是由CodeWisdom团队组织的围绕智能化软件开发.数据驱动的软件开发质量与效能分析.云原生与智能化运维等相关话题开展的线上沙龙,通过微信群访谈交 ...

  2. 智能化软件开发微访谈·第二十一期:可观测性与智能化运维

    CodeWisdom "智能化软件开发沙龙是由CodeWisdom团队组织的围绕智能化软件开发.数据驱动的软件开发质量与效能分析.云原生与智能化运维等相关话题开展的线上沙龙,通过微信群访谈交 ...

  3. 活动预告 | 智能化软件开发微访谈·第二十一期:可观测性与智能化运维

    CodeWisdom 智能化软件开发沙龙是复旦大学CodeWisdom团队参与组织的专注于代码大数据与智能化软件开发的学术和技术沙龙,面向相关领域的学术界研究者和工业界实践者,通过各种线上和线下交流活 ...

  4. 智能化软件开发微访谈·第二十二期 代码预训练模型

    CodeWisdom 代码预训练模型微访谈 · 活动预告 背景介绍 随着代码数据的增长以及人工智能技术的发展,基于深度学习的代码推荐和生成已经成为软件智能化开发领域的热点研究问题.近几年,基于Tran ...

  5. 智能化软件开发微访谈·第十九期暨2022新年特辑:软件智能化开发:进展与挑战...

    CodeWisdom 智能化软件开发沙龙是复旦大学CodeWisdom团队参与组织的专注于代码大数据与智能化软件开发的学术和技术沙龙,面向相关领域的学术界研究者和工业界实践者,通过各种线上和线下交流活 ...

  6. 活动预告 | 智能化软件开发微访谈·第十九期暨2022新年特辑:软件智能化开发:进展与挑战...

    CodeWisdom 智能化软件开发沙龙是复旦大学CodeWisdom团队参与组织的专注于代码大数据与智能化软件开发的学术和技术沙龙,面向相关领域的学术界研究者和工业界实践者,通过各种线上和线下交流活 ...

  7. 开发者论坛一周精粹(第二十期) :晒往期云栖大会的照片或感想,赢2017杭州云栖大会门票...

    第二十期(2017年8月21日-2017年8月27日 ) 2017杭州云栖大会即将震撼来袭,如果你参与过往期的云栖大会,不妨晒出你的参会照片和感想,我们将挑选10个优秀的分享送出2017杭州云栖大会的 ...

  8. Csdn视频第二十期 : 测试工具与流程讨论

    Csdn视频第二十期 : 测试工具与流程讨论 http://live.csdn.net/Issue22/LivePlay.aspx

  9. 数据库管理-第二十期(20210304)

    数据库管理 2021-03-04 第二十期 RWP 1 CPU占用率 2 统计信息比你想象中的更重要 3 干同一件事情应当批量处理 4 Arry和Inmemory 5 SQL Monitor 6 如何 ...

最新文章

  1. Linux下 curl 代理设置注意事项--curl proxy
  2. 皮一皮:碰到这样的领导怎么办...
  3. java xxtea加密,base64和Xxtea的加密和解密
  4. Android应用程序内部启动Activity过程(startActivity)的源代码分析
  5. matlab模拟光栅,matlab对光栅的仿真代码
  6. TCP-IP 用户态编程
  7. 刚刚,蚂蚁金服荣膺“中国金融大数据领军企业”称号 1
  8. C++中的cin.getline()和getline()函数的区别
  9. 什么是Csrss.exe进程?此进程有何作用?
  10. C#员工考勤管理系统源码 考勤工资管理系统源码
  11. 趋势科技发文挑衅VB100 金山对此不以为然
  12. 12306车站信息爬取(1)——实现站点所有信息的查询
  13. PHP爬虫的三种方法
  14. 【数模】整数规划模型
  15. linux jpg图片转base64,html中的图片直接使用base64编码后的字符串代替
  16. 计算机c盘能分区吗,电脑C盘还可以分盘吗?
  17. 用于ip伪装身份的网络爬虫
  18. DELPHI BULK INSERT
  19. Leetcode-元素和小于等于阈值的正方形的最大边长(python)
  20. 近红外荧光染料Pep-1/MMPs-PEG-ICG,细胞穿膜肽Pep-1/基质金属蛋白酶MMPs-聚乙二醇-吲哚菁绿

热门文章

  1. 标准USB设备请求命令
  2. IDS USB Manipulator Tools
  3. 努力学习打卡Day02
  4. php处理mp3,在PHP中自动剪裁MP3
  5. 使用html+js实现视频播放器
  6. 科学计算机如何锁定,华为计算器怎么才能固定竖屏和调出科学计算器?取消自动旋转操作介绍...
  7. 全国首例!某度起诉“文库下载神器”,老惨了.....
  8. 关于一些快速获取游戏素材的方式
  9. Framebuffer之fset工具(二十八)
  10. 博途PLC1200/1500PLC S型速度曲线变频器控制应用(SCL完整源代码)