《Spark 框架实战》课程

Spark 是当前大数据行业内的事实标准,是由 UC Berkeley AMP lab (加州大学伯克利的 AMP 实验室)开源的类 Hadoop MapReduce 的通用并行框架,Spark 拥有 Hadoop MapReduce 所具有的优点,但不同于 MapReduce 的是 Job 中间结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 算法。Spark  是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。Spark 主要有三个特点:首先,高级 API 剥离了对集群本身的关注,Spark 应用开发者可以专注于应用所要做的计算本身。其次,Spark 很快,支持交互式计算和复杂算法。最后,Spark 是一个通用引擎,可用它来完成各种各样的运算,包括 SQL 查询、文本处理、机器学习等,而在 Spark 出现之前,我们一般需要学习各种各样的引擎来分别处理这些需求。

Spark模型在Uber机器学习平台应用

Evolving Michelangelo Model Representation for Flexibility at Scale
Evolving Michelangelo Model Representation for Flexibility at Scale

Michelangelo 是 Uber 的机器学习(ML)平台,可以训练并服务于整个公司范围内生产环境中的数千种模型。该平台被设计成了一个端到端的工作流,目前支持经典的机器学习、时间序列预测和深度学习模型,可以涵盖大量的用例,从 生成市场预测、响应客户支持工单 到 准确计算预计到达时间(EAT) 以及使用自然语言处理(NLP)模型在驾驶员 App 中提供 一键式聊天功能。

大多数 Michelangelo 模型都是基于 Apache Spark MLlib 的,这是一个可伸缩的 Apache Spark 机器学习库。为了处理高 QPS 的在线服务,Michelangelo 最初仅通过内部定制的模型序列化和表示支持 Spark MLlib 模型的一个子集,这使得客户无法灵活地试验任意复杂的模型管道,限制了 Michelangelo 的扩展速度。为了解决这些问题,我们改进了 Michelangelo 对 Spark MLlib 的使用,特别是在模型表示、持久性和在线服务方面。

在 Michelangelo 中改进 Spark MLlib 用法的动机

我们最初开发 Michelangelo 是为了为生产环境提供可扩展的机器学习模型。它对基于 Spark 的数据摄取调度、模型训练和评估以及批量和在线模型服务部署提供端到端的支持,在 Uber 获得了广泛的认可。

为了将 Spark 用于数据预处理和低延迟服务,并使用 GPU 进行分布式深度学习训练,Michelangelo 针对深度学习用例使用了一致的 Spark 管道架构。
为了将 Spark 用于数据预处理和低延迟服务,并使用 GPU 进行分布式深度学习训练,Michelangelo 针对深度学习用例使用了一致的 Spark 管道架构。

最近,Michelangelo 已经发展到可以处理更多的用例,包括提供在核心 Michelangelo 之外训练过的模型。例如,深度学习模型的扩展和端到端加速训练需要在不同环境中执行操作步骤,以便利用 Spark 的分布式计算转换、Spark Pipelines 在 CPU 上的低延迟服务以及使用 Horovod(Uber 的分布深度学习框架)在 GPU 集群上的分布式深度学习训练。为了使这些需求更容易实现,并保证训练和服务的一致性,有一个一致的架构和模型表示很重要,它可以利用我们现有的低延迟的基于 JVM 的模型服务基础设施,同时提供正确的抽象来封装这些需求。

具有活动 Spark 会话的外部环境可以无缝地反序列化来自 Michelangelo 的经过训练的管道模型,并序列化供 Michelangelo 生态系统的其余部分使用的模型。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标识并不意味着 Apache 软件基金会的认可。
具有活动 Spark 会话的外部环境可以无缝地反序列化来自 Michelangelo 的经过训练的管道模型,并序列化供 Michelangelo 生态系统的其余部分使用的模型。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标识并不意味着 Apache 软件基金会的认可。

另一个动机是使数据科学家能够使用 PySpark 在熟悉的 Jupyter 笔记本(数据科学工作台)中构建和试验任意复杂的模型,同时仍然能够利用 Michelangelo 生态系统可靠地进行分布式训练、部署和服务。这也为 集成学习 或 多任务学习 技术所需的更复杂的模型结构提供了可能性,同时让用户可以动态地实现数据操作和自定义评估。

因此,我们回顾了 Michelangelo 对 Spark MLlib 和 Spark ML 管道 的使用,概括了其模型持久性和在线服务机制,目的是在不影响可伸缩性的情况下实现可扩展性和互操作性。

Michelangelo 最初推出的是一个统一的架构,它负责管理紧耦合的工作流和用于训练和服务的 Spark 作业。Michelangelo 对每种支持的模型类型都有特定的管道模型定义,并使用内部定制的 protobuf 表示经过训练的服务模型。离线服务通过 Spark 处理;在线服务使用添加到 Spark 内部版本的自定义 API 来处理,以实现高效的单行预测。

向本地 Spark 序列化和反序列化转变在模型持久化管道阶段(Transformer/Estimator)层面上实现了灵活性和跨环境兼容性。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标识并不意味着 Apache 软件基金会的认可。
向本地 Spark 序列化和反序列化转变在模型持久化管道阶段(Transformer/Estimator)层面上实现了灵活性和跨环境兼容性。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标识并不意味着 Apache 软件基金会的认可。

最初的架构支持通用机器学习模型(如广义线性模型 GLM 和梯度增强决策树模型 GBDT)的大规模训练和服务,但是自定义的 protobuf 表示使添加对新 Spark 转换器的支持变得困难,并排除了在 Michelangelo 之外训练的模型。当新版本的 Spark 可用时,Spark 的自定义内部版本也使得每次的升级迭代变得复杂。为了提高对新转换器的支持速度,并允许客户将自己的模型引入 Michelangelo,我们考虑了如何改进模型表示并更加顺畅地添加在线服务接口。

Michelangelo 的架构和模型表示法的演变

Michelangelo 的架构必须处理由不同功能需求带来的复杂性,并保持训练和服务环境之间的一致性。 Uber 的机器学习工作流通常很复杂,涉及不同的团队、库、数据格式和语言;为了使模型表示和在线服务接口可以恰当地演化,我们需要考虑所有这些维度。
Michelangelo 的架构必须处理由不同功能需求带来的复杂性,并保持训练和服务环境之间的一致性。

Uber 的机器学习工作流通常很复杂,涉及不同的团队、库、数据格式和语言;为了使模型表示和在线服务接口可以恰当地演化,我们需要考虑所有这些维度。

部署并提供机器学习管道模型服务包括模型前面的所有转换和操作步骤。
部署并提供机器学习管道模型服务包括模型前面的所有转换和操作步骤。

要部署用于服务的机器学习模型,需要部署整个管道,包括模型前面的转换工作流。通常还需要打包数据转换、特征提取、预处理甚至预测后转换。原始预测通常需要解释或转换回标签,在某些情况下需要转换到不同的维度空间,比如日志空间,以便下游服务使用。它也可以用于通过额外的数据加强原始预测,如它们的置信区间,通过 概率校准 来校准概率。我们想要一个能够反映 Spark MLlib 模型固有管道步骤的模型表示,并允许 Michelangelo 与外部工具进行无缝交互。

选择一种最新的模型表示

在评估可供选择的模型表示时,我们评估了不同的需求,包括:

  • 表示广义转换序列的能力(必需)
  • 处理在线用例的轻量级服务的可扩展性(必需)
  • 支持使用非 Michelangelo 原生 Spark 工具替换存储在 Michelangelo 中的模型(必需)
  • 训练时和服务时的模型解释偏差风险低(非常想要)
  • Spark 更新速度要快,并且易于编写新的估计器 / 转换器(非常想要)

我们考虑的一种方法是使用 MLeap,这是一个独立的库,它通过一个专用的运行时来执行管道,提供了管道和模型序列化(到 Bundle.ML)和反序列化支持。MLeap 具有所需的表达能力和对轻量级在线服务的支持。但是,它有自己专有的持久化格式,这限制了与序列化和反序列化普通 Spark MLlib 模型的工具集的互操作性。

MLeap 还引入了服务时行为偏离训练时评估的风险,因为在技术上,正在提供服务的模型加载时的格式与训练时内存中的格式不同。MLeap 还降低了 Spark 更新的速度,因为除了 Spark MLlib 本地使用的方法之外,还必须为每个转换器和估计器添加单独的 MLeap 保存 / 加载方法。Databricks 的 ML 模型导出 dbml-local 提供了类似的方法。

我们考虑的另一种方法就是将训练模型导出到一个标准的格式,如 预测模型标记语言(PMML) 或 可移植分析格式(PFA),它们都具备我们需要的表达能力并且可以和 Spark 交互,Spark 直接提供了 PMML 支持,而 aardpfark 可以将 Spark 模型导出为 PFA。然而,这些表示还是存在服务时行为偏离方面的风险,我们认为这一风险高于 MLeap,因为一般标准在特定的实现中通常会有不同的解释。这些标准在 Spark 更新速度方面也带来了更大的阻碍,因为根据 Spark 变化的性质,标准本身可能需要更新。

我们发现,最直接的方法是使用标准的 Spark ML 管道序列化来表示模型。Spark ML 管道展示了我们想要的表达能力,允许与 Michelangelo 之外的 Spark 工具集交互,展现出了低风险的模型解释偏差,对 Spark 的更新速度影响较小。它还有助于编写自定义的转换器和估计器。

我们看到,使用 Spark 管道序列化的主要挑战是它与在线服务需求的不兼容性(Nick Pentreath 在 2018 年的 Spark AI 峰会 上也讨论了这一点)。这种方法会启动一个本地 Spark 会话,并用它来加载一个训练好的 Spark MLlib 模型,这相当于在单台主机上运行一个小型集群,内存开销和延迟都很大,使它不适合许多在线服务场景要求的 p99 毫秒级延迟。虽然现有的用于提供服务的 Spark API 集在性能上还不足以满足 Uber 的用例,但我们发现,我们可以在这种开箱即用的体验中进行许多直接的更改,以满足我们的需求。

为了提供用于在线服务的轻量级接口,我们将 anOnlineTransformer添加 到可以提供在线服务的转换器中,包括利用低级 Spark 预测方法的单个方法和小型方法列表。我们还调整了模型加载的性能,以满足我们的目标开销要求。

使用增强型转换器和估计器的管道

为了实现一个可以由 Michelangelo 在线训练并提供服务的 Transformer 或 Estimator,我们构建了一个 OnlineTransformer 接口,它扩展了开箱即用的 Spark Transformer 接口,并执行两个方法:1)Transform(instance: Dataset[Any]) ;2)ScoreInstance(instance: Map[String, Any])。

Transform(instance: Dataset[Object]) 作为分布式批处理服务的入口,提供了开箱即用的基于数据集的执行模型。ScoreInstance(instance: Map[String, Object]): Map[String, Object] 作为较为轻量级的 API,用于低延迟、实时服务场景中出现的针对单一特征值映射集的单行预测请求。ScoreInstance 背后的动机是提供一个更轻量级的 API,它可以绕过依赖于 Spark SQL Engine 的 Catalyst Optimizer 的 Dataset 所带来的巨大开销,从而对每个请求进行查询规划和优化。如上所述,这对于实时服务场景(如市场营销和欺诈检测)非常重要,其中 p99 延迟的 SLA 通常是毫秒级的。

当加载 Spark PipelineModel 时,任何具有相似类(包含 OnlineTransformer 特性)的 Transformer 都会映射到该类。这使得现有的训练好的 Spark 模型(由支持的转换器组成)获得了提供在线服务的能力,而且没有任何额外的工作。注意,OnlineTransformer 还实现了 Spark 的 MLWritable 和 MLReadable 接口,这为 Spark 免费提供了对序列化和反序列化的本地支持。

保持在线和离线服务一致性

转向标准的 PipelineModel 驱动的架构,通过消除 PipelineModel 之外的任何自定义预评分和后评分实现,进一步加强了在线和离线服务准确性之间的一致性。在每个管道阶段,实现自定义评分方法时的标准实践是首先实现一个公共评分函数。在离线转换中,它可以作为 DataFrame 输入上的一组 Spark 用户定义函数(UDF)运行,相同的评分函数也可以应用于在线 scoreInstance 和 scoreInstances 方法。在线和离线评分一致性将通过单元测试和端到端集成测试进一步保证。

性能优化

我们最初的度量结果显示,与我们自定义的 protobuf 表示的加载延迟相比,原生 Spark 管道加载延迟非常高,如下表所示:

这种序列化模型加载时间上的性能差异对于在线服务场景是不可接受的。模型实际上被分片到每个在线预测服务实例中,并在每个服务实例启动时、新模型部署期间或接收到针对特定模型的预测请求时加载。在我们的多租户模型服务设置中,过长的加载时间会影响服务器资源的敏捷性和健康状况监控。我们分析了加载延迟的来源,并进行了一些调优更改。

影响所有转换器加载时间的一个开销来源是 Spark 本地使用 sc.textFile 读取转换器元数据;从一个小的单行文件生成一个字符串 RDD 非常慢。对于本地文件,用 Java I/O 替换这段代码要快得多:

[loadMetadata in src/main/scala/org/apache/spark/ml/util/ReadWrite.scala]

在我们的用例中(例如,LogisticRegression、StringIndexer 和 LinearRegression),影响许多转换器的另一个开销来源是对与转换器相关的少量数据使用 Spark 分布式 read/select 命令。对于这些情况,我们使用 ParquetUtil.read 代替 sparkSession.read.parquet;直接进行 Parquet read/getRecord 大大降低了转换器的加载时间。

树集成(Tree ensemble)转换器有一些特殊的调优机会。加载树集成模型需要将序列化到磁盘的模型元数据文件读取到磁盘,这会触发小文件的 groupByKey、sortByKey 以及 Spark 的分布式 read/select/sort/collect 操作,这些操作非常慢。我们直接用更快的 Parquet read/getRecord 代替了它们。在树集成模型保存方面,我们合并了树集成节点和元数据权重 DataFrame,以避免写入大量读起来很慢的小文件。

通过这些调优工作,我们能够将基准示例的本地 Spark 模型加载时间从 8 到 44 倍减少到仅比从自定义 protobuf 加载慢 2 到 3 倍,这相当于比 Spark 原生模型快 4 到 15 倍。考虑到使用标准表示的好处,这种水平的开销是可以接受的。

需要注意的是,Michelangelo 在线服务创建了一个本地的 SparkContext 来处理任何未加密的转换器的负载,因此,在线服务不需要 SparkContext。我们发现,当没有模型加载处于活动状态时,让 SparkContext 继续运行会对性能产生负面影响并导致延迟,例如,通过 SparkContext 清理器的操作。为了避免这种影响,我们在没有运行负载时停止 SparkContext。

可服务管道的灵活结构

使用管道模型作为 Michelangelo 的模型表示,用户可以灵活地组合和扩展可服务组件单元,使它们在线和离线服务时保持一致。然而,这并没有完全封装管道模型在机器学习工作流的各个阶段使用时的操作需求差异。有些操作步骤或概念本质上与机器学习工作流的特定阶段相关,而与其他阶段完全无关。例如,当用户对模型进行评估和迭代时,常常需要进行超参数优化、交叉验证以及生成模型解释及评估所需的特定元数据等操作。这些步骤允许用户帮助生成模型、与模型交互以及评估管道模型,但是一旦准备好进行产品化,就不应该将这些步骤合并到模型服务中。

同时,在机器学习工作流不同阶段的需求差异,促使我们开发了一个基于通用编排引擎的工作流和操作员框架。除了组合自定义可服务管道模型的灵活性之外,这还允许用户以有向图或工作流的形式组合和编排自定义操作的执行,以实现最终的可服务管道模型。

Michelangelo 基于 Operator Framework 的工作流提供了另一种程度的灵活性,通过优化的执行计划来方便地定制操作,从而生成可服务的、序列化的 Michelangelo 管道模型以及有用的工件。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标记并不意味着 Apache 软件基金会的认可。Docker 和 Docker 标识是 Docker 公司在美国和 / 或其他国家的商标或注册商标。Docker 公司及其他各方也可以在本协议中使用的其他条款中享有商标权。本标记的使用并不意味着 Docker 的认可。TensorFlow、TensorFlow 标识及任何相关标识均为谷歌公司的商标。
Michelangelo 基于 Operator Framework 的工作流提供了另一种程度的灵活性,通过优化的执行计划来方便地定制操作,从而生成可服务的、序列化的 Michelangelo 管道模型以及有用的工件。Apache Spark 是 Apache 软件基金会在美国和 / 或其他国家的注册商标。使用这个标记并不意味着 Apache 软件基金会的认可。Docker 和 Docker 标识是 Docker 公司在美国和 / 或其他国家的商标或注册商标。Docker 公司及其他各方也可以在本协议中使用的其他条款中享有商标权。本标记的使用并不意味着 Docker 的认可。TensorFlow、TensorFlow 标识及任何相关标识均为谷歌公司的商标。

未来展望

在这一点上,Spark 原生模型表示已经在 Michelangelo 生产环境中运行了一年多,作为一种健壮且可扩展的方法,在我们公司范围内提供 ML 模型。得益于这种演变和 Michelangelo 平台的其他更新,Uber 的技术栈可以支持新的用例(如灵活的试验和在 Uber 的 数据科学工作台 中训练模型)、Jupyter 笔记本环境以及使用 TFTransformers 的端到端深度学习。为了介绍我们的经验并帮助其他人扩展他们自己的 ML 建模解决方案,我们在 2019 年 4 月的 Spark AI 峰会 上讨论了这些更新,并提交了 SPIP 和 JIRA,把我们对 Spark MLlib 的更改开源。

Spark 团队开源全流程机器学习平台:MLflow

Spark 和 Mesos 的核心作者兼 Databrick 首席技术专家 Matei Zaharia 宣布推出开源机器学习平台 MLflow,这是一个能够覆盖机器学习全流程(从数据准备到模型训练到最终部署)的新平台,旨在为数据科学家构建、测试和部署机器学习模型的复杂过程做一些简化工作。Matei 表示,研究工作主要围绕着 ——

如何为开发者提供类似谷歌 TFX、Facebook FBLearner Flow 等平台类似的好处,但是要以开放的方式——不仅在开源的意义上开放,而且是可以使用任何工具和算法的意义上开放

的想法展开。

每个做过机器学习开发的人都知道机器学习的复杂性,除了软件开发中常见的问题之外,机器学习还存在很多新的挑战。作为一家大数据解决方案公司,Databricks 与数百家使用机器学习的公司合作,所以能够清楚地了解他们的痛点,比如工具太过复杂、难以跟踪实验、难以重现结果、难以部署模型。由于这些挑战的存在,机器学习开发必须变得与传统软件开发一样强大、可预测和普及。为此,很多企业已经开始构建内部机器学习平台来管理机器学习生命周期。例如,Facebook、谷歌和优步分别构建了 FBLearner Flow、TFX 和 Michelangelo 来进行数据准备、模型训练和部署。但这些内部平台存在一定的局限性:典型的机器学习平台只支持一小部分内置算法或单个机器学习库,并且被绑定在公司内部的基础设施上。用户无法轻易地使用新的机器学习库,或与社区分享他们的工作成果。

Databricks 认为应该使用一种更好的方式来管理机器学习生命周期,于是他们推出了 MLflow,一个开源的机器学习平台。MLflow 的 alpha 版本包含了三个组件:

其中,MLflow 的跟踪组件支持记录和查询实验数据,如评估度量指标和参数。MLflow 的项目组件提供了可重复运行的简单包装格式。最后,MLflow 的模型组件提供了用于管理和部署模型的工具。

GitHub地址项目 GitHub 地址

机器学习库选型

选择一个机器学习(ML)库来解决预测问题,是个说起来容易做起来难的事情 —— 可选择性太多了。每一个库对于它擅长的特定问题都有着良好的特性与优势。 即使对于在机器学习和数据科学领域具有相当经验的人来说,逐个检查所有不同的方案也是一种煎熬。Mayukh Bhaowal —— Salesforce Einstein 的产品管理总监,负责自动化机器学习;向我们分享了关于机器学习库的最重要的五个特征,科研工作者可以在决定使用哪个库时进行参考。

1.编程模式

大多数机器学习库,在高级设计模式中分为两个模式:符号式(Symbolic)和命令式(Imperative)。

  • 在符号式程序中,科研工作者可以从功能上定义复杂的数学计算,而无需实际执行。它通常采用计算图的形式。你把所有的东西放在一起,并用抽象的方式把它们连接起来,当把真值作为输入数据传进去时,它才会真正实现计算。这种模式的最大优点是可组合性和抽象性,从而使开发人员能够专注于更高层次的问题。效率是另外一大优势,因为将这些函数并行化执行相对来说容易一些。Apache Spark 的 ML 库,Spark MLlib 以及任何基于 Spark 的库,比如 Microsoft 的 MMLSpark 和 Intel 的 BigDL,都遵循这种模式。有向无环图(DAG)是计算图的表示形式。符号式编程机器学习库的其他例子有CNTK,具备静态计算图;Caffe2,使用网络结构类Net(操作符 Operator 的计算图);H2O.ai;以及Keras。
  • 在命令式编程中,一切都是先执行的。你写下一行代码,当编译器读取这行并执行它时,就会发生真实的数值计算,然后移到下一行代码。这种风格使得创建模型原型更容易,因为它往往更灵活,更容易调试,易于排除故障。 Scikit-learn 是一个流行的 Python 库,属于这个类别。其他库,如 auto sklearn 和 TPOT 是 Scikit-learn 的高阶抽象层,也遵循这种范式。 PyTorch 是另一种支持动态计算图的主流选择,动态计算图让整个计算流程是命令式的。

显然,这两种方法互有胜负,究竟选择哪种好,是随着用例不同而不同的。命令式编程非常适合研究,因为它天然支持更快速的原型设计 —— 允许重复迭代,试错和和快速反馈循环 —— 而符号式编程更适合于生产环境的应用。

有一些库结合了这两种方法,创建了一种混合风格。最好的例子是 MXNet,它允许符号式编程中的回调函数中插入命令式代码,或者把符号式编程作为命令式程序的一部分。另一个更新的发展是来自 Google 的 TensorFlow 的 Eager Execution。尽管最初,它只是一个具备符号式计算范式的 Python 库(一个张量的静态计算图),但是 Eager Execution 并不需要一个图,而且可以立即执行。

  • 符号式:Spark MLlib,MMLSpark,BigDL,CNTK,H2O.ai,Keras,Caffe2
  • 命令式:scikit-learn,auto sklearn,TPOT,PyTorch
  • 混合式:MXNet,TensorFlow

2.机器学习算法

监督学习,无监督学习,推荐系统深度学习是我们所采用的机器学习算法中常见的分类。我们需要再次强调,应用场景(用例)将决定使用哪个库最好。例如,如果科研工作者正在进行大量自定义的图像处理,如果其他条件相同的话,Caffe2 将是一个不错的选择。它是 Caffe 的进化版,Caffe 一开始把 CNN 应用于图像分类。 CNTK 将是自然语言处理的一个合理选择,因为 CNTK 框架诞生于微软的语言服务部门。另一方面,如果大多数用例是监督学习和非监督学习,Spark MLlib,scikit-learn,H2O.ai 和 MMLSpark 也都是很好的选择,因为它们支持大量的监督和非监督算法。除此之外, Spark MLlib,H2O.ai 和 Mahout 还通过提供协作过滤算法对推荐系统提供支持。

随着深度学习(DL)的兴起,许多较老的库现在已经显得力不从心。 TensorFlow 是首批向数据科学家提供深度学习的计算库之一。今天,我们还有很多其他的专注于深度学习的框架可以选择,其中包括PyTorch,Keras,MXNet,Caffe2,CNTK 和 BigDL。还有其他一些算法库支持 DL 算法,但 DL 不是它们的主要功能,比如 MMLSpark(用于图像和文本学习)和 H2O.ai(通过 Deepwater 插件提供对 DL 的支持)。

  • 有监督和无监督:Spark MLlib,scikit-learn,H2O.ai,MMLSpark,Mahout
  • 深度学习:TensorFlow,PyTorch,Caffe2(用于处理图片),Keras,MXNet,CNTK,BigDL,MMLSpark(用于处理图片和文字),H2O.ai(通过 Deepwater 插件提供支持)
  • 推荐系统:Spark MLlib,H2O.ai(通过 Sparkling Water 插件提供支持),Mahout

3.硬件和性能

计算性能是为科研项目选择合适的库的关键标准之一。这一项对于专精于 DL 算法的库更为重要,因为它们往往是计算密集型的。

推动 DL 开发的最大趋势之一是 GPU 的进步,以及 GPU 提供了对大型矩阵运算的支持。所有 DL 库(如TensorFlow,Keras,PyTorch 和 Caffe2)都支持 GPU,不过许多通用库(如 MMLSpark,H2O.ai 和Apache Mahout)也提供了对 GPU 的支持。CNTK 和 MXNet 拥有自动化多 GPU 和多服务器支持,允许用户进行快速地进行跨多个 GPU 的分布式训练,而且无需任何配置。然而,TensorFlow 由于比其他的 DL 平台计算速度慢,而得到了一些负面评价。作为一种弥补,TensorFlow 在其新的定制 AI 芯片 Tensor Processing Unit(TPU)上大肆宣传。其缺点是,TPU 是非商品化的硬件,只能与 TensorFlow 一起工作,这导致了供应商锁定的现象。

Caffe2,MXNet 和 TensorFlow 同时也因对移动计算支持而脱颖而出。所以,如果科研项目需要在移动设备上进行机器学习训练,那它们就会是你最好的选择。

关于性能方面值得一提的是,大部分基于 Spark 构建的库都能够依靠内存缓存中间数据,靠这一点利用Spark 进行并行集群计算,使本质上需要『迭代』的机器学习算法运行得更快。 Apache Mahout 是一个例外,它直到最近才支持 Hadoop MapReduce,并且要进行对计算而言开销很大的磁盘 I / O 操作,因此它对于迭代算法来说速度较慢。 Mahout 现在在 Spark,H2O.ai 和 Apache Flink 上增加了对Scala语言的支持。 BigDL 在Spark 的生态系统中使用 CPU 实现 DL 的方法是一种新颖的方式,与传统的利用 GPU 加速的 DL 库有所不同,BigDL 使用英特尔的 MKL 和多线程编程。

  • CPU:Spark MLlib,scikit-learn,auto sklearn,TPOT,BigDL
  • GPU:Keras,PyTorch,Caffe2,MMLSpark,H2O.ai,Mahout,CNTK,MXNet,TensorFlow
  • 移动计算:MXNet,TensorFlow,Caffe2

4.可读性

ML 软件与传统软件的区别在于,其预测行为本身或产出的结果不是那么可预期的。与基于规则的引擎不同,这种软件能不断学习到新的规则。深度学习面临的最大挑战之一,是如何持续不断地建立对机器学习应用的信任和信心。为什么预测影响因子 X 有更高的可能性转化客户,而影响因子 Y 在转化率方面引入的可能性较低?数据集中驱动算法进行某些预测的数据模式是什么?我们能否将机器学习模型的这种洞察力转化为商业行动?

对这个问题的其他衍生问题包括,计算图执行时对算法评价指标的可视化,观察数据流并对它们进行优化,手工模型和/或调试模型质量。

这是一个在机器学习中相对不成熟的领域,只有少数库试图解决这个问题。 H2O.ai 推出了机器学习可解释性,解决了这个问题的某些方面。 TensorFlow 有一个称为 TensorBoard 的可视化工具,它帮助数据科学家理解、优化和调试大量的深度神经网络。Keras 也通过其自身的模型可视化解决了这个问题。

虽然这些都是朝着正确方向的很好的步骤,但是为了鼓励 ML 被更广泛的接纳,可解释性领域还需要我们投注更多的新学,让机器学习更加透明,减少它的黑盒性。

  • 可读性:TensorFlow(TensorBoard),H2O.ai(机器学习可解释性),Keras(模型可视化)

5.自动化机器学习

可以这样说:机器学习中最大的创新领域之一,就是自动化的机器学习。真实世界中的机器学习不仅仅是构建模型,还涉及到构造数据管线,其中包括 ETL,特征工程,特征选择,模型选择(包括超参数调优),模型更新和模型部署。

工作流程中的许多步骤在各种应用和数据集处理中都是通用的,并且往往有重复的倾向,这就意味着存在对流程进行优化和自动化的机会。除此以外,某些工作流程特别需要数据科学和机器学习方面的直觉和领域知识,比如特征工程或深度模型调优。这些领域对于无法获得博士学位的人来说难以进入。实现许多步骤的自动化,可以加快数据科学家的工作效率,能够帮助他们在几个小时而不是几个月内帮助构建机器学习应用。

Auto sklearn,TPOT 和 H2O.ai 就是建立在这个前提下的,而且针对的是有监督分类问题。Auto sklearn 使用了贝叶斯优化进行自动化模型选择和超参调整。 TPOT 正在使用遗传算法编程进行超参调整。 TPOT 和 H2O.ai 都包含了几种不同级别的特征工程自动化。 MMLSpark 针对图像和文本的特征,具备自动化模型选择,以及一定程度的自动化特征工程。

无论是从广度(数据管线中的不同阶段自动化)还是深度(单一一个数据处理阶段上的智能自动化)上,这类工具可以说是供不应求。

  • 超参数调整:auto sklearn(贝叶斯优化),TPOT(遗传编程)
  • 有限的自动特征工程:TPOT,H2O.ai,MMLSpark

其他注意事项

尽管机器学习模型在可用前需要在数据集上进行训练,但是在某些情况下,我们可以访问全球通用的数据集。比如,像 ImageNet 这种通用图像数据集,完全足够用于建立一个通用的图像分类模型,这也被称为预训练的模型。这样的模型可以作为插件来引入,这意味着不需要数据或者训练。 MMLSpark,CNTK,TensorFlow,PyTorch,Keras 和 BigDL 都为通用分类任务提供预训练的模型。值得注意的是,这样的模型对于定制化用例是没有用的。

例如,一个通用的图像分类模型,如果需要从作物田地的航拍图像中对农作物的类型进行分类的话,效果就会很差,但是它能很好地将猫与狗分类。这是因为,尽管 ImageNet 中存在农作物相关的图像,但是对于特定种类的作物,以及患上不同疾病的作物的训练数据是不足的,而那些数据可能刚好是化肥公司所关心的。

CNTK 附带一些方便的功能,如数据集自动化随机提取,以及实时在线训练。尽管 MMLSpark 是一个Scala 库,但它支持自动生成其他语言,也就是 PythonR 的接口。

  • 预训练模型:MMLSpark,CNTK,TensorFlow,PyTorch,Keras,BigDL
  • 实时培训:CNTK
  • 多语言支持:MMLSpark 支持从Scala自动生成 Python / R 的接口

小结

将 ML 构建到科学研究项目中时,有多种 ML 库供科研工作者选择。尽管可能没有一个完美的选择,但考虑上述因素,有助于确保科研项目的特定需求选择最佳解决方案。对于拥有数千家企业客户的企业公司来说,还有许多市场尚未涉足的其他挑战 ——

标签泄漏,也被称为数据泄漏,一直是 ML 库的致命弱点。这一点的发生是由于存在未知的业务流程,导致用于模型训练的数据集具有代表实际标签的字段。检查数据是否存在泄漏,并将泄露的字段从数据中删除是得到理想模型的关键。

多租户是另一个关键点 —— 我们如何共享机器学习平台和资源,为多个用户提供服务,每个用户都有自己独特的数据集,并导致完全不同的模型被训练?随着数据/模型规模的不同,这个问题也不同。随着行业继续面临这样的挑战,一个完整、详尽开发的自动 ML 解决方案,虽然现在暂时不存在,在将来可能被证明是成功的关键。

大数据企业级仿真科研教学实践环境

大数据工程实践系统环境
工程实践系统环境 —— 大数据企业级仿真科研教学实践环境

大数据企业级仿真科研教学实践环境,是跨象乘云公司专门为高校教师与学生定制化的设计的企业级大数据项目开发综合环境,可供大数据专业学生或项目开发小组完成大数据全生命周期的工程实践及实验操作。厂家工程师在工程实践系统环境内部,对应相关课程模块教学与实验需求,预装包含:系统环境,功能连接中间件,应用数据库,SQL 结构化大数据数据库,NoSQL 非结构化数据库,教学用示例数据资源,以及面向专业类开发,管理,调优等功能组件及应用软件,满足相关教学与实验所需的应用场景。完整的大数据生态部件包括:

  • Airflow – ELT数据采集、导入、处理管道
  • Crunch – 编写、测试、运行MapReduce管道的JAVA框架
  • Flume – 分布式海量日志流采集架构
  • HBase – Hadoop数据库,面向分布式可扩展的大数据存储
  • HCatalog – 对接不同数据处理工具的Hadoop表与存储管理接口
  • Hive – 使用SQL语法读取、写入分布式存储大数据集的数据仓库
  • HttpFS – 支持所有Hadoop文件系统读写操作的HTTP网关服务器
  • Hue – 可视化大数据分析工作平台
  • Impala – Hadoop本地分析数据库
  • Jupyter Notebook – Web应用程序,创建和共享包含实时代码,方程式,可视化和叙述文本的文档。同时可实现数据清理和转换,数值模拟,统计建模,数据可视化,机器学习等。
  • Kafka – 用于构建实时数据管道和流式应用程序
  • kxcyViz – 跨象乘云™可视化数据统计与多维分析探索平台
  • Llama – 协调、管理和监控Impala和YARN之间的集群资源
  • Mahout – 提供分布式线性代数的机器学习与数据挖掘框架
  • Oozie – 管理Hadoop作业的工作流调度程序系统
  • Open Refine – 数据清理与处理,格式转换工具,支持Web服务和外部数据扩展
  • Pig – 大型数据集并行分析平台
  • Rapid Miner – 数据科学团队工作平台,集成机器学习和预测模型部署
  • R &. RStudio – 统计运算与数据可视化环境及工作平台
  • Search (Solr) – 企业级分布式索引,检索,复制与负载均衡查询平台
  • Sentry – Hadoop集群数据和元数据细粒度角色授权系统
  • Snappy – 高效数据压缩/解压缩库
  • Spark – 最流行的用于大规模数据处理的高速通用引擎
  • Sqoop – 用于在Hadoop和结构化数据存储/关系数据库之间高效传输批量数据的工具
  • Whirr – 运行大数据云服务的库
  • ZooKeeper – 分布式服务器开发与运维协调枢纽