关于机器学习算法框架的语言选择问题,因为今天很多的大数据框架都是基于 Hadoop/Spark 这一套的,都是 JVM 上的东西,因此基于 JVM 从整体来说接入生态是比较容易的,但其实有三点理由让我们选择 C++而不是基于 JVM 去做这件事情。 首先我们前面讲过,目前虽然计算能力对传统应用来说井喷,我们经常说 CPU 过剩、GPU 过剩。但是对于高维机器学习过程来说,依然是资源非常紧张的,这里面包括计算、网络、内存等多个方面,我们看 Spark 的 Project Tungsten 也做了大量堆外内存管理的工作以提升数据的处理效率,但是对机器学习来说,基本上整个过程都需要对内存和计算过程进行精细控制,以及避免不可控的 GC 过程。 其次,C++的一些语言特性,比如运算符重载机制也可以使得框架上层的算法应用的语法比较简单优雅,不会变成巨大的一坨,而大规模机器学习很多时候和字符串组成的离散特征打交道,C++对字符串处理的效率也要高出 JVM-Based 语言非常多。 再次,Spark 目前的机制和 Parameter Server 的结合很难做到优雅和完美,强行对接 PS 会破坏 Spark 自身的灾备、任务调度等特性。如果不对接,那么就基本上只能靠降低模型大小来确保效率,和高维度的目标南辕北辙。所以综合考虑,我们还是选择 C++来实现整个一套的系统,而将和大数据框架的对接以及开发门槛降低这个任务交给整个机器学习系统的架构。 整体架构 上面讲了很多机器学习算法框架,但有过实践经验的朋友都知道,光有一个算法框架只相当于汽车有了发动机,离开起来还很远。我们总结一个完整的机器学习系统需要有如下部分: 数据引入和预处理 特征工程 模型训练算法(支持参数灵活调整和二次开发) 模型评估 模型上线(批量预估、实时 API 调用、线上特征实时计算) 那么对于这所有的部分,我们开发了一个叫『先知』的整体平台产品,我们先看一下先知的整体架构图:
整体来说,先知平台由界面层、调度管理层、集群适配层、集群任务执行层,另外外加一个线上的预估服务云。 这套架构能够给我们带来如下几个优势: 1. 把整个机器学习过程作为一个整体来看待,做到各模块的深度整合。下面是我们产品的一个截图:
可以看到,通过一个 DAG 图的描述,可以将大数据的处理过程(SQL/PySpark/数据拆分)和机器学习的过程(特征工程、模型训练、模型评估)整体结合起来,用户不再需要去开发脚本去处理复杂的模块和模块之间的对接以及输入输出的各种判断。 同时呢,这个 DAG 图的背后我们还做了很多工作,一个比较有意思的就是对存储的抽象和适配。我们有的客户是用 AWS 作为基础设施,而有的客户用阿里云做基础设施,有的客户则选择在 IDC 内构建自己的机房。这里面就有块存储、云盘、SSD、内存盘等多种存储服务。 另外,一个完整的机器学习过程,往往还要从数据库里面导入数据,最终要把数据导出到某个指定的位置。导数据在逻辑上的复杂性和由于某些开源模块不支持内存缓存和 SSD 导致的性能的低下都是困扰数据科学家的问题。 对此设计了一个两层的存储抽象层 API,第一层是一个开源项目 alluxio,就是以前的 tachyon,alluxio 这个东西是非常好的,好在哪里呢?他用一套解决方案一下子解决了几个问题,第一是可以支持很多分布式的文件系统,包括 S3、Ceph 等。第二还能够比较透明的解决内存和 SSD 加速的问题。针对 Alluxio 这个项目,我们将整个的数据处理、模型训练、预估体系,包括我们自己开发的 GDBT 框架都和 alluxio 做了深度的融合集成,也针对开源的产品在访问调度、吞吐、SSD 优化上做了一些增强和修补的工作。 (责任编辑:本港台直播) |