【Spark指南】- 高级分析和机器学习

第一部分 Spark介绍
第二部分 Spark的使用基础
第三部分 Spark工具箱
第四部分 使用不同的数据类型
第五部分 高级分析和机器学习
第六部分 MLlib应用
第七部分 图分析
第八部分 深度学习

本部分会更深入介绍一些可以在Spark上运行的更前沿的机器学习案例。除了大规模SQL分析和流,Spark也提供对大规模机器学习和图像分析的支持。这是我们常称之为“高级分析”的一部分。本书的该部分会介绍 Spark中 你可以用来进行高级分析的 不同部分,包括:

  • 预处理数据(数据清洗和特征工程)
  • 监督学习
  • 非监督学习
  • 推荐引擎
  • 图分析
  • 深度学习

这个特别的章节会 覆盖 高级分析的基础入门知识,一些使用案例,和 一个基本的高级分析工作流。在这些以后我们会 介绍前面的要点 并教你如何使用他们。

本书并不打算介绍所有你需要知道的有关机器学习的知识。我们不会研究严格的数学定义和公式——并非这些不重要 而是因为其中包含了大量内容。本部分不是一个算法指导 来叫你每个Spark提供的算法的数学基础, 也不设计 每个算法的深入实现策略。这部分只是一个用户指南来告诉你 使用Spark的高级分析能力 所必须了解和需要做的东西。


高级分析的简单介绍

在详细介绍之前,让我们更正式地定义高级分析,并提供一个简单的机器学习速成课程。

Gartner 在他们的IT术语中这样定义高级分析:
”高级分析是 使用复杂技术和工具 的 对数据或内容 的 自动或半自动检查,通常超越 传统的商业智能(BI),来发掘更深层的见解,以做出预测或给出建议。高级分析技术包括 数据/文本挖掘,机器学习,模式匹配,预测,可视化,语义分析,情感分析,网络与聚类分析,多变量统计,图像分析,仿真,复杂事件处理,神经网络。”

换句话说,高级分析是 一堆 用于 解决 在获得insights 和基于数据给出预测和建议 中的核心问题 的技术。
机器学习的最佳本体是基于您希望执行的任务构建的。最常见的任务:
1、监督学习,包括分类和回归
2、推荐引擎,基于行为或偏好推荐不同产品。
3、无监督学习,包括分类,异常检验和主题建模。
4、图像分析,比如 发现和理解图像中的关系结构。

在谈论Spark 和 介绍Spark 在这些问题领域的 功能 之前,让我们通过一些 常见的用例 来回顾 一下这些基本任务。这里的挑战是这些信息可能非常具有挑战性。当然,我们会尽量使这个介绍尽量温和,但有时你可能需要参考更多的例子或其他解释来理解材料。O 'Reilly也有一些关于以下主题的书,作为更详细的资料,它们是很好的参考。处于本书的目的,我们会在接下来的章节中参考三本书,因为他们可以在网上免费获得。对与想要更多地了解各个方法的人,它们是很好的资源。

• An Introduction to Statistical Learning by Gareth James, Daniela Witten, Trevor Hastie, and Robert Tibshirani.
We will refer to this book as "ISL".
• Elements of Statistical Learning by Trevor Hastie, Robert Tibshirani, and Jerome Friedman. We will refer to this
book as "ESL".
• Deep Learning by Ian Goodfellow, Yoshua Bengio, and Aaron Courville. We will refer to this book as "DLB".

监督学习

监督学习可能是你最熟悉的机器学习类型。其目的很简单,就是用 标记过的历史数据(常称为因变量),教算法预测标签的值。 如果算法预测错误,我们会调整算法(而不是调整训练数据) 然后在下一条数据上再试一次。在训练过算法之后,用其来预测 新的未来数据。
我们需要做很多不同的事情来解决这个问题,例如 在将模型用于实际之前 测量模型的准确性,其基本原理很简单。 在历史数据上进行训练,确认算法可以扩展到我们没有训练过的数据上,然后用算法进行预测。

我们可以根据我们希望预测的变量类型进一步组织监督学习。

分类

监督学习的 一个常见的任务就是 分类。分类是 用于预测 被分类(类别为离散的有限值)的因变量的 行为训练算法。最常见的情况 就是 二分类,只有两个组可以选择。一个标准例子就是垃圾邮件。我们可能有很多已经能被分为了两组的历史邮件,垃圾邮件和非垃圾邮件。使用这个历史数据,我们可以训练算法 分析历史邮件中的词汇 和任意数量的特性,并对其分类进行预测。当我们对其性能满意后,会用于预测算法没有见过的未来邮件数据。

另一个分类的例子 不是仅仅预测邮件是否为垃圾邮件,而会进一步尝试对邮件进行详细的分类。比如我们可能有四种不同的邮件类别:购物,私人,工作相关 及其他。相应的历史数据也分类到这四种类别中。我们会训练一个算法 基于邮件内容(或来源)来预测它们的类别,然后运用训练后的算法到新数据上。当我们正确地做了这些事后,算法可以帮助 组织 一个人的收件箱 到不同的组中。这个任务通常称为多类分类。

这有一些分类的用例:

  • 预测心脏疾病——医生或医院 会有 一组病人的关于行为了生理特征的历史数据集。 他们可以用历史数据来训练算法(并评估其准确性及潜在的伦理问题)并用来预测一个病人是否患有严重的心脏疾病。这可以作为一个二分类(健康,不健康)或多类分类(健康,比较健康,不健康)的例子。
  • 分类图像——有一些来自苹果,谷歌,facebook等公司的应用, 可以通过运行一个 根据你过去照片中的人物历史图像 所训练 人脸分类算法 来预测给定图片中的人是谁。 一个普遍一点的用力可能是对图像进行分类 或对图像中的事务进行标记。
  • 预测客户流失——一个更商业的应用案例 是预测客户流失。你可以用过去已经流失的客户数据 训练一个二分类器,用来尝试预测当前用户有没有可能流失。
  • 买还是不买——一个公司可能想要预测一个用户是否会在他们的网站上购买产品。他们可以使用用户的购买习惯信息来指导预测。

分类的不同用例 有很多,而这只是一些小例子。关键的要求 是你要有充足的数据 用来训练你的算法,并且你还要有适当的评估标准。这些会在分类的章节进行讨论。

回归

在分类中,我们看到因变量只有一个离散的值集。在回归中,我们会设法预测一个连续变量(一个实数)。用最简单的术语来描述,相比于预测一个类别,我们想要在数轴上预测一个数。这相比于二分类或多分类而言是一个更困难的工作,因为我们的结果可取自任意数量的值,而不只源于一个离散集。余下的基本都是相同的工作(这也就是为什么他们都是监督学习的一部分),我们会基于历史数据训练算法 来预测数据。

用例

  • 预测销售情况——一个商店可能会希望运用已有的历史数据估测给定时间段内的产品销量。这方面存在许多潜在的输入变量,但作为一个简单的例子,可以用最近一周的数据来预测接下来一天的数据。
  • 预测高度——基于父母的身高,可能希望预测他们子女的身高。
    预测一档节目的观众数——像Netflix这样的公司可能会基于以往节目的观众数目,来试图预测某档节目的观众数,以评判该节目的价值。

分类,如我们做提到的,比分类更复杂 但也更强大。

推荐系统

推荐任务是最直观的之一。通过学习人们的显性偏好(通过评级)或隐性偏好(通过观察行为),你可以在一个用户可能会喜欢什么的问题上 给出推荐,通过画出该用户和其他用户的相似之处。基于该结果,我们可以根据这个信息向另一个用户推荐。这是Spark的常用案例,并且非常适用大数据。

用例
推荐算法在现实世界中有广泛的应用。其中一个原因是构建一套历史的行为观测是非常简单的。此外,提供训练算法也很容易,其原因我们会在后面的部分进行讨论。

  • 电影推荐——Netflix使用Spark,通过学习用户喜欢的和不喜欢的电影,当用户登陆应用的时候向他们进行推荐电影。此外,还会考虑一个用户的评级与其他用户之间的相似程度,好为其推荐电影。
  • 产品推荐——Amazon为了增加销量而运用产品推荐的手段。例如,基于用户购物车中的商品,Amazon会推荐类似的其它商品给用户。另一项任务是通过协同过滤,通过人们的浏览行为来计算商品间的相似度。
非监督学习

非监督学习是 在给定的一组数据中寻找模式 或发现底层结构的 行为。
这不同于监督学习,因为没有可用来训练模型的因变量。这使它成为一种更困难的高级分析任务,因为很难来测试准确性。

用例
非监督学习的目的不同于其他的任务,因为没有一个简单地测试效果的方法可以用来 证明你的分析是正确的。通常,你不会运行一个非监督学习算法来进行预测,而是用于发现数据中的底层模式,并更好的理解用于定义数据中不同组的不同特性。

  • 主题建模——给一组文档,我们会对这些文档中的不同次进行分析,来看看这些文档之间是否有一些底层的关联。以本书的结构为例。通过在各章节上 运行主题模型算法,我们会发现流章节不同于机器学习章节,因为在这两部分有完全不同的词汇。
  • 异常检验——随着时间推移,给定的标准时间类型会经常发生,我们想要 在非标准类型时间发生时进行报告。
  • 用户分类——给定一组用户行为,我们想要更好地了解 某一用户与其他用户共享哪些属性。例如,议价游戏公司可能根据 如 在特定游戏上的游戏时长 等特性来对用户进行分类算法。算法可能解释了游戏A的晚间也可能经常完游戏B。这会推动将此结论正式用于推荐系统 来为晚间提供其他游戏的推荐。
图分析

不如之前的任务那么常见,图分析在高级分析用例中会看到。图分析可以 为上述任务提供 替代方法。不论如何,这不会使上述方法变得没有价值或被废除,应将其视为一个可替换 的 构建问题的不同方法。从根本上来说,图分析是对关系的学习,我们指定vertices为对象,edges代表对象之间的关系。通过观察vertices和edges的特性,我们可以更好地学习不同vertices和edges的关系和相似点。

图分析都是关于关系的

  • 欺诈预测——Capital One使用Spark的图形分析功能来更好地理解欺诈网络。这包括使用不同的诈骗电话号、地址、或其他信息连接不同的人,并利用新信息来发觉新的诈骗性信息(或可疑信息),提前与欺诈作斗争。
  • 异常检测——通过观察个体网络是如何相互连接,异常值和异常现象可以被标记 来进行人工分析。比如,如果在我们的数据中,一个定点通常有10条边,而有一个定点只有一条边,那么就很值得调查,因为这是值得研究的奇怪现象。
  • 分类——已知一些网络中给定定点的事实,你可以根据 与原始节点的连接 来对各节点分类。例如,如果给定个体被标记为 公共网络中的有影响者,我们可以将其他有类似网络结构的个体分类为 影响者。
  • 推荐——谷歌的原始网络推荐算法,PageRank,就是一个图算法,其可以分析网站关系 用以提供网页重要性排名。作为一个例子,如果一个网页有很多指向他的连接,其会被排名为比没有指向连接的网站更重要。


高级分析的流程

我们在前面快速介绍了一下不同的高级分析应用和用力,从推荐到回归。但这只是实际高级分析过程的一小部分。你可能会发现,选择一个任务或算法通常是最简单的部分。主要的挑战是围绕特定算法的一切。本部分会给出整个分析过程的结构,及我们必须要采取的步骤 而不是执行一整个任务,但客观的评估有效性是为了 理解我们是否应该将训练过的算法用到实际上。

【Spark指南】- 高级分析和机器学习_第1张图片
高级分析的流程

整个过程大体上遵循以下内容:
收集任务相关的数据。
清晰和检查数据 来更好地理解它。
执行特性工程,让算法能利用更多的信息。
使用一部分数据作为训练集 来训练一个或多个算法,得到一些候选模型。
通过 在同一份数据的一个子集上(没有被用来作为训练集的)客观地测试结果 来做为成功标准,以评估和比较各模型。
利用 上述过程得到的 模型能力 来进行预测、推荐、发觉异常或解决更多的一般业务挑战。

这对每格高级分析任务都是一样的吗?当然不是。然而,这确实可以作为一个通用框架,来帮助你知道 为了获得一个高级分析用力并从中得到价值 需要做什么。就像我们对在前面的各种高级分析所做的那样,让我们分解过程的每一步来更好地理解每个步骤的总体目标。

数据采集

不首先收集数据,自然很难创建训练数据。这通常意味着至少要收集 用来训练算法的数据集。Spark在这方面显然是一个卓越的工具,因为它可以同各种数据源进行对话,并处理大大小小的数据。

数据清洗

在收集了适合的数据后,你需要对其进行清理和检查,并沿着探索性数据分析 或 EDA 的路线 执行一些操作。EDA 在你视图更好地理解数据这个阶段 的一个合适的工具,它强调使用可视化方法来更好地理解数据的分布、相关性和其他细节。在这个过程中你会注意到你需要丢弃一些在数据上游 记录错误或丢失的数据。不论是哪种情况,对数据有更好的理解,并知道数据中有什么,都是一件好事,可以避免以后的错误。Structured APIs 中有许多函数可以提供清洗数据的简单方法。

特征工程

现在有了清洗过的数据集,是时候通过潜在的规范化数据来增强它了(如果有必要的话),增加变量来代表其他变量间的交互,操作类别变量来转化为适当的格式作为机器学习模型的输入。在MLlib中,所有变量必须以double型输入(不管他们实际代表什么)。这意味着你很可能必须用一些 类似单热编码类别变量和其他索引样式技术。Spark提供基本的 你会使用的各种机器学习特定的统计技术 来操作数据的基本要素。

模型训练

下面的两步(训练模型、模型校正和评估)并非所有用例情况都有。这是一个一般的工作流,根据最终实现目的的不同,会有很大的不同。

到流程的这一步,我们有一个可以用来训练模型的数据集。训练一个模型意味着我们会给模型一组数据,机器学习模型会尝试执行我们前面指定的任务。在这个过程中,模型内部的参数会根据损失函数进行调整,为了在给定任务上尽量表现得更好。例如,如果我们希望将垃圾邮件分类,我们的算法可能会找到某些词汇 能比其他词汇 更好地预测垃圾邮件。在我们的模型中,这些词会比那些没有相关性的词受到更大的影响。我们所说的模型就是算法的输出和数据。 一个模型是一个算法的校正版本,算法只是 可以用来洞悉好预测的简化版本。然后我们给模型输入行的数据,模型会相应的对数据进行操作。在分类的例子中,我们有一个关于垃圾邮件特征的模型,如果我们给模型一个新邮件,它会返回输出对该邮件是否为垃圾邮件的预测。
然而,训练一个算法不是目的——我们想用模型来获得洞察力。因此我们必须回答这个问题,我们怎样知道我们的模型在它应该做的事情上是好的? 这是模型校验和评估的内容。

模型校正和评估

你可能注意到,如上所述我们习惯将数据分为几个部分,而只用一个部分来训练。我们创建训练集而不是在全部数据集上训练的原因,是为了用其他的部分来校正模型或 与其他模型比较。这么做的原因很简单,当我们构建一个模型后,我们希望模型可以推广到新的数据或以前没有见过的数据上。用来测试模型有效性的那部分数据被称为测试机。将其想象成学校中的考试。其目的是查看模型是否理解了 该数据处理的基本原则,还是只注意到了训练集中特定的东西。在训练模型的过程中,我们还可能取另一个数据子集,并将其作为一个小的测试集(称为验证集),为了尝试不用的超参数或 可能影响其他参数的参数——本质上,模型的变型。
继续已分类案例为例。我们有三个数据集,一个训练集用来训练模型,一个验证集用来验证我们正在训练的模型的不同变型,基于一个测试集会在最后用来对不同模型变型的评估,看看那个模型表现的最好。

模型的利用

最后我们使用模型。可能是为了更好地了解顾客 或执行用户划分 或预测垃圾邮件。无论在哪种情况,这都是最终的目的。尝试解决的一个问题 并 更好地理解你的数据。

这个简要的工作流概述只是一个工作流的例子,并不包括所有的情况或可能的工作流。还有很多细节会很大的影响你的结果,


Spark的高级分析工具箱

Spark包含很多用来执行高级分析的核心包和很多第三方包。一个基本的包就是MLlib,其提供了用来构建机器学习管道的接口。其他的包我们在后面的章节进行介绍。

MLlib

是一个工具包,包含在Spark中,提供接口来:
收集和清洗数据
特征工程和特征选择
训练和校正大规模监督和非监督机器学习模型
在生产中使用这些模型
MLlib帮助完成整个过程的所有三个步骤,在前两个步骤中表现非常突出,原因我们稍后将讨论。

MLlib包含两个包 分别使用不同的核心数据结构。org.apache.spark.ml维护 提供给Spark DataFrame的接口。同时 为标准化执行上述步骤而构建的机器学习管道 维护高级别接口。低级别的包 org.apache.spark.mllib维护供Spark底层 RDD APIs 使用的接口。本书聚焦于DataFrame API。在本书编写的时候,RDD API是处于维护模式的底层接口(意味着其只接收错误修复,不接收新特性)。并且其被广泛包含在在其他书籍中,所以这里将其忽略。

什么时候及为什么你应该使用MLlib(相比于 scikit learn \ tensorfolw \ foo package)?

现在,你可能听说过很多其他机器学习包,比如可以python或各种R语言版本的,执行类似任务的scikit-learning包。你为什么吗还要使用MLlib呢?
有很多的工具可用来在单机上执行机器学习任务。他们在这方面做的都很好,并会继续称为更好的工具。然而,这些单机工具 在用来训练的数据大小上 和处理时间上都受到了限制。
在规模上受到限制的事实,使它们称为了互补工具,而不是竞争对手。当您遇到这些可伸缩性问题时,请利用Spark的功能。

有两种主要情况,你会想要利用Spark的规模特性。首先,在从大量数据中生成训练集和测试集时,你回想使用Spark来预处理和生成特征以减少这个过程所花费的时间。 接着,你可能会想利用单机的机器学习算法在这些给定数据上进行训练。 第二种情况是,当你的输入数据和模型规模 很难或不便于放在一台机器上时,使用Spark来承担这一重任。Spark使大数据机器学习变得容易。

对前面段落的一个重要警告是,虽然 训练和数据准备 都很简单,但仍然需要记住一些复杂性。比如,如果你在Spark集群上训练一个推荐系统,那么最终模型将会很大以至于难以在一台机器上运行预测,然而我们仍要做出预测来从模型中获得价值。另一个例子是在Spark训练一个逻辑回归模型。Spark的执行引擎不是一个低延迟的执行引擎,因此,即使在单机上,由于启动和执行一个Spark工作的花费,快速(<500ms)做出单一预测仍是有挑战的。一些模型对这个问题有很好的答案,另一些仍然是开放的问题。我们将在本章的最后讨论目前的技术状况。这是一个富有成果的研究领域,随着新系统的出现,对这个问题的解决也会改变。

高级别MLlib概念

在MLlib中,有很多基本的“结构”类型:transformers,estimators,evaluator和pipelines。
通过结构化,他们将定义你要做出的总体架构选择。下面是对一个整体工作流程例子的说明:

【Spark指南】- 高级分析和机器学习_第2张图片

Transformers是以某种方式转换原始数据的函数。其可能创建一个新的交互变量(从两个其他变量得到)、标准化一个列、或仅仅将其转换成double型作为模型的输入。一个transformer例子是 将字符串分类变量转换为可用于MLlib的数值。Transformers是预处理和特征生成中最先用到。

【Spark指南】- 高级分析和机器学习_第3张图片

Estimators是两种类型的操作之一。首先,estimators可以是一种初始化数据的transformer。一个例子是将一列转换为列的百分位表示——为了做到这点我们会基于列中的值进行初始化。然后,estimators是Spark中实际模型的名称(估计器),我们将对其进行培训并将其转换为模型,以便使用它们进行预测。
一个evaluator允许我们查看 一个给定estimator 是如何根据我们指定的标准,如ROC曲线,来执行的。一旦我们从测试模型中选择了最好的模型,就可以使用他来进行预测了。

在较高的层次上,我们可以逐个指定上面的每个步骤,然而在pipeline中指定个步骤为一个stages 往往更简单。这个pipeline类似于 Scikit-learn的Pipeline概念,transformations和estimators是一起制定的。

除了高级架构类型之外,还有很多底层事物你可以使用。最常见的是Vector。无论何时我们将一组特征输入给机器学习模型,我们都必须 以一个有Doubles构成的Vector 的形式给出特征。这个vector可以是稀疏的或稠密的。它们以不同的方式指定,一种是指定精确值(稠密的),另一种是指定总大小及哪些值非零(稀疏的)。你可能已经猜到的,当大量值为0时,稀疏向量作为比其他格式更扁平的形式 是更合适的。

%scala
import org.apache.spark.ml.linalg.Vectors
val denseVec = Vectors.dense(1.0, 2.0, 3.0)
val size = 3
val idx = Array(1,2) // locations in vector
val values = Array(2.0,3.0)
val sparseVec = Vectors.sparse(size, idx, values)
sparseVec.toDense
denseVec.toSparse

%python
from pyspark.ml.linalg import Vectors
denseVec = Vectors.dense(1.0, 2.0, 3.0)
size = 3
idx = [1, 2] # locations in vector
values = [2.0, 3.0]
sparseVec = Vectors.sparse(size, idx, values)

令人困惑的是,有一些类似的类型。其类似是指一些可以在DataFrame中使用,而另一些只能在RDDs中使用。RDD的实现在mllib包中,DataFrame的实现在ml包中。

你可能感兴趣的:(【Spark指南】- 高级分析和机器学习)