Spark高级数据分析(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-09-12 13:50:40

点击下载

作者:(美)桑迪·里扎(Sandy Ryza), (美)于里·莱瑟森(Uri Laserson), (英)肖恩·欧文(Sean Owen), (美)乔希·威尔斯(Josh Wills)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Spark高级数据分析(第2版)

Spark高级数据分析(第2版)试读:

前言

作者:桑迪 • 里扎

我不希望我的人生有很多遗憾。2011 年,某个慵懒的时刻,我正在绞尽脑汁地想如何把高难度的离散优化问题最优地分配给计算机集群处理,真是很难想到有什么好方法。我的导师跟我讲,他听说有个叫 Apache Spark 的新技术,可我基本上没当回事。Spark 的想法太好了,让人觉得有点儿不靠谱。就这样,我很快又回去接着写 MapReduce 的本科毕业论文了。时光荏苒,Spark 和我都渐渐成熟,不过令我望尘莫及的是,Spark 已然成为冉冉之星,这让人不禁感叹“Spark”(星星之火)这个双关语是多么贴切。若干年后,Spark 的价值举世皆知!

Spark 的前辈有很多,从 MPI 到 MapReduce。利用这些计算框架,我们写的程序可以充分利用大量资源,但不需要关心分布式系统的实现细节。数据处理的需求促进了这些技术框架的发展。同样,大数据领域也和这些框架关系密切,这些框架界定了大数据的范围。Spark 有望更进一步,让写分布式程序就像写普通程序一样。

Spark 能大大提升 ETL 流水作业的性能,并把 MapReduce 程序员从每天问天天不灵、问地地不应的绝望痛苦中解救出来。对我而言,Spark 的激动人心之处在于,它真正打开了复杂数据分析的大门。Spark 带来了支持迭代式计算和交互式探索的模式。利用这一开源计算框架,数据科学家终于可以在大数据集上高效地工作了。

我认为数据科学教学最有效的方法是利用实例。为此,我和同事一起编写了这本关于实际应用的书,希望它能涵盖大规模数据分析中最常用的算法、数据集和设计模式。阅读本书时不必一页一页地看,可以根据工作需要或按兴趣直接翻到相关章节。本书内容

第 1 章结合数据科学和大数据分析的广阔背景来讨论 Spark。随后各章在介绍 Spark 数据分析时都自成一体。第 2 章通过数据清洗这一使用场景来介绍用 Spark 和 Scala 进行数据处理的基础知识。接下来几章深入讨论如何将 Spark 用于机器学习,介绍了常见应用中几个最常用的算法。其余几章则收集了一些更新颖的应用,比如通过文本隐含语义关系来查询 Wikipedia 或分析基因数据。第2版说明

自本书第 1 版出版以来,Spark 进行了一次重大的版本更新:使用了一个全新的核心 API; MLlib 和 Spark SQL 两个子项目也发生了翻天覆地的变化。第 2 版根据新版 Spark 的最佳实践,对样例代码和所使用的资料进行了大量更新。使用代码示例

补充材料(代码示例、练习、勘误表等)可以从 https://github.com/sryza/aas 下载。

本书是要帮你完成工作的。一般来说,如果本书提供了示例代码,你可以把它用在你的程序或文档中。除非你使用了很大一部分代码,否则无须联系我们获得许可。比如,用本书的几个代码片段写一个程序就无须获得许可,销售或分发 O'Reilly 图书的示例光盘则需要获得许可;引用本书中的示例代码回答问题无须获得许可,将书中大量的代码放到你的产品文档中则需要获得许可。

我们很希望但并不强制要求你在引用本书内容时加上引用说明。引用说明一般包括书名、作者、出版社和 ISBN。比如:“Advanced Analytics with Spark by Sandy Ryza, Uri Laserson, Sean Owen, and Josh Wills (O'Reilly). Copyright 2015 Sandy Ryza, Uri Laserson, Sean Owen, and Josh Wills, 978-1-491-91276-8.”

如果你觉得自己对示例代码的用法超出了上述许可的范围,欢迎你通过 permissions@oreilly.com 与我们联系。O'Reilly Safari

Safari(前身为 Safari Books Online)是为企业、政府、教育机构和个人提供的会员制培训和参考平台。

会员可以访问来自 250 多家出版商的上千种图书、培训视频、学习路径、互动教程和精选播放列表。这些出版商包括 O'Reilly Media、Harvard Business Review、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Adobe、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology,等等。

欲知更多信息,请访问 https://www.safaribooksonline.com/。联系我们

请把对本书的评价和问题发给出版社。

美国:

  O'Reilly Media, Inc.

  1005 Gravenstein Highway North

  Sebastopol, CA 95472

中国:

  北京市西城区西直门南大街 2 号成铭大厦 C 座 807 室(100035)

  奥莱利技术咨询(北京)有限公司

O'Reilly 的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:

  http://shop.oreilly.com/product/0636920056591.do

对于本书的评论和技术性问题,请发送电子邮件到:

  bookquestions@oreilly.com

要了解更多 O'Reilly 图书、培训课程、会议和新闻的信息,请访问以下网站:

  http://www.oreilly.com

我们在 Facebook 的地址如下:

  https://facebook.com/oreilly

请关注我们的 Twitter 动态:

  https://twitter.com/oreillymedia

我们的 YouTube 视频地址如下:

  https://www.youtube.com/oreillymedia致谢

如果没有 Apache Spark 和 MLlib,就没有本书。所以我们应该感谢开发了 Spark 和 MLlib 并将其开源的团体,也要感谢那些添砖加瓦的数以百计的代码贡献者。

我们还要感谢本书的每一位审阅者,感谢他们花费了大量的时间来审阅本书的内容,感谢他们的专业视角,他们是 Michael Bernico、Adam Breindel、Ian Buss、Parvis Deyhim、Jeremy Freeman、Chris Fregly、Debashish Ghosh、Juliet Hougland、Jonathan Keebler、Nisha Muktewar、Frank Nothaft、Nick Pentreath、Kostas Sakellis、Tom White、Marcelo Vanzin 和另一位 Juliet Hougland。谢谢你们所有人!我们欠你们一个大人情!你们的努力大大改进了本书的结构和质量。

我(桑迪)还要感谢 Jordan Pinkus 和 Richard Wang,你们帮助我完成了风险分析章节的原理部分。

感谢 Marie Beaugureau 和 O'Reilly 出版社在本书出版和发行过程中贡献的宝贵经验和大力支持!第1章大数据分析作者:桑迪 • 里扎(数据应用)就像香肠,最好别看见它们是怎么做出来的。——Otto von Bismarck● 用数千个特征和数十亿个交易来构建信用卡欺诈检测模型● 向数百万用户智能地推荐数百万产品● 通过模拟包含数百万金融工具的投资组合来评估金融风险● 轻松地操作成千上万个人类基因的相关数据以发现致病基因

5~10 年前想要完成上述任务几乎是不可能的。我们说生活在大数据时代,意思是指我们拥有收集、存储、处理大量信息的工具,而这些信息的规模以前我们闻所未闻。这些能力的背后是许多开源软件组成的生态系统,它们能利用大量普通计算机处理大规模数据。Apache Hadoop 之类的分布式系统已经进入主流,并被广泛部署在几乎各个领域的组织里。

但就像锉刀和石头本身并不构成雕塑一样,有了工具和数据并不等于就可以做有用的事情。这时我们就需要数据科学了。雕刻是利用工具将原始石材变成普通人都能看懂的雕塑,数据科学则是利用工具将原始数据变成对不懂数据科学的普通人有价值的东西。

通常,“做有用的事情”指给数据加上模式并用 SQL 来回答问题,比如:“注册过程中许多用户进入到第三个页面,其中有多少用户年龄超过 25 岁?”如何架构一个数据仓库,并组织信息来回答此类问题,涉及的面很广,本书不对其细节过多赘述。

有时候“产生价值”需要多付出一些努力。SQL 可能仍扮演重要角色,但为了处理数据的特质或进行复杂分析,人们需要一个更灵活、更易用的,且在机器学习和统计方面功能更丰富的编程模式。本书将重点讨论此类型的分析。

长久以来,人们利用 R、PyData 和 Octave 等开源框架可以在小数据集上进行快速分析和建模。只需不到 10 行代码,就可以利用数据集的一部分数据构建出机器学习模型,再利用该模型预测其余数据的分类。如果多写几行代码,我们还能处理缺失数据,尝试多个模型并从中找出最佳模型,或者用一个模型的结果作为输入来拟合另一个模型。但如果数据集巨大,必须利用大量计算机来达到相同效果,我们该怎样做呢?

一个可能正确的方法是简单扩展这些框架,使之能运行在多台机器上,保留框架的编程模型,同时重写其内核,使之在分布式环境下能顺利运行。但是,分布式计算难度大,我们必须重新思考在单机系统中的许多基本假设,在分布式环境下是否依然成立。比如,由于集群环境下数据需要在多个节点间切分,网络传输速度比内存访问慢几个数量级,如果算法涉及宽数据依赖,情况就很糟糕。随着机器数量的增加,发生故障的概率也相应增大。这些实际情况要求编程模式适配底层系统:编程模式要防止不当选项,并简化高度并行代码的编写。

当然,除了像 PyData 和 R 这样在软件社区里表现优异的单机工具,数据分析还用到其他工具。在科学领域,比如常常涉及大规模数据的基因学,人们使用并行计算框架已经有几十年的历史了。今天,在这些领域处理数据的人大多数都熟悉 HPC(high-performance computing,高性能计算)集群计算环境。然而,PyData 和 R 的问题在于它们很难扩展。同样,HPC 的问题在于它的抽象层次较低,难于使用。比如要并行处理一个大 DNA 测序文件,人们需要手工将该文件拆成许多小文件,并为每个小文件向集群调度器提交一个作业。如果某些作业失败,用户需要检查失败并手工重新提交。如果操作涉及整个数据集,比如对整个数据集排序,庞大的数据集必须流入单个节点,否则科学家就要用 MPI 这样底层的分布式框架。这些底层框架使用难度大,用户必须精通 C 语言和分布式 / 网络系统。

为 HPC 环境编写的工具往往很难将内存数据模型和底层存储模型独立开来。比如很多工具只能从单个流读取 POSIX 文件系统数据,很难自然并行化,不能用于读取数据库等其他后台存储。最近,Hadoop 生态系统提供了抽象,让用户使用计算机集群就像使用单台计算机一样。该抽象自动拆分文件并在多台计算机上分布式存储,自动将工作拆分成若干粒度更小的任务并分布式执行,出错时自动恢复。Hadoop 生态系统将大数据集处理涉及的许多琐碎工作自动化,并且启动开销比 HPC 小得多。1.1 数据科学面临的挑战

数据科学界有几个硬道理是不能违背的,Cloudera 数据科学团队的一项重要职责就是宣扬这些硬道理。一个系统要想在海量数据的复杂数据分析方面取得成功,必须明白这些硬道理,至少不能违背。

第一,成功的分析中,绝大部分工作是数据预处理。数据是混乱的,在让数据产生价值之前,必须对数据进行清洗、处理、融合、挖掘和许多其他操作。特别是大数据集,由于人们很难直接检查,为了知道需要哪些预处理步骤,甚至需要采用计算方法。一般情况下,即使在模型调优阶段,在整个数据处理管道的各个作业中,花在特征提取和选择上的时间比选择和实现算法的时间还要多。

比如,在构建网站欺诈交易检测模型时,数据科学家需要从许多可能的特征中进行选择。这些特征包括必填项、IP 地址信息、登录次数、用户浏览网站时的点击日志等。在将特征转换成适用于机器学习算法的向量时,每个特征可能都会有不同的问题。系统需要支持更灵活的转换,远远不止是将二维双精度数组转换成一个数学模型那么简单。

第二,迭代是数据科学的基础之一。建模和分析经常需要对一个数据集进行多次遍历。这其中一方面是由机器学习算法和统计过程本身造成的。常用的优化过程,比如随机梯度下降和最大似然估计,在收敛前都需要多次扫描输入数据。数据科学家自身的工作流程也涉及迭代。在初步调查和理解数据集时,一个查询的结果往往给下一个查询带来启示。在构建模型时,数据科学家往往很难在第一次就得到理想的结果。选择正确的特征,挑选合适的算法,运行恰当的显著性测试,找到合适的超参数,所有这些工作都需要反复试验。框架每次访问数据都要读磁盘,这样会增加时延,降低探索数据的速度,限制了数据科学家进行试验的次数。

第三,构建完表现卓越的模型不等于大功告成。数据科学的目标在于让数据对不懂数据科学的人有用。把模型以许多回归权值的形式存成文本文件,放在数据科学家的计算机里,这样做根本没有实现数据科学的目标。数据推荐引擎和实时欺诈检测系统是最常见的数据应用。这些应用中,模型作为生产服务的一部分,需要定期甚至是实时重建。

在这些场景中,有必要区别是试验环境下的分析还是生产环境下的分析。在试验环境下,数据科学家进行探索性分析。他们想理解工作数据集的本质。他们将数据图形化并用各种理论来测试。他们用各种特征做试验,用辅助数据源来增强数据。他们试验各种算法,希望从中找到一两个有效算法。在生产环境下,构建数据应用时,数据科学家进行操作式分析。他们把模型打包成服务,这些服务可以作为现实世界的决策依据。他们跟踪模型随时间的表现,哪怕是为了将模型准确率提高一个百分点,他们都会精心调整模型并且乐此不疲。他们关心服务 SLA 和在线时间。由于历史原因,探索性分析经常使用 R 之类的语言,但在构建生产应用时,数据处理过程则完全用 Java 或 C++ 重写。

当然,如果用于建模的原始代码也可用于生产应用,那就能节省每个人的时间。但像 R 之类的语言运行缓慢,很难将其与生产基础设施的技术平台进行集成,而 Java 和 C++ 之类的语言又很难用于探索性分析。它们缺乏交互式数据操作所需的 REPL(read-evaluate-print-loop,读取 - 计算 - 打印 - 循环)环境,即使是简单的转换,也需要写大量代码。人们迫切需要一个既能轻松建模又适合生产系统的框架。1.2 认识Apache Spark

该介绍 Apache Spark 了。Spark 是一个开源框架,作为计算引擎,它把程序分发到集群中的许多机器,同时提供了一个优雅的编程模型。Spark 源自加州大学伯克利分校的 AMPLab,现在已被捐献给了 Apache 软件基金会。可以这么说,对于数据科学家而言,真正让分布式编程进入寻常百姓家的开源软件,Spark 是第一个。

了解 Spark 的最好办法莫过于了解相比于它的前辈,即 Apache Hadoop 的 MapReduce,Spark 有哪些进步。MapReduce 革新了海量数据的计算方式,为运行在成百上千台机器上的并行程序提供了简单的编程模型。MapReduce 引擎几乎可以做到线性扩展:随着数据量的增加,可以通过增加更多的计算机来保持作业时间不变。而且 MapReduce 是健壮的。故障虽然在单台机器上很少出现,但在数千个节点的集群上却总是出现。对于这种情况,MapReduce 也能妥善处理。它将工作拆分成多个小任务,能优雅地处理失败的任务,并且不影响任务所属作业的正确执行。

Spark 继承了 MapReduce 的线性扩展性和容错性,同时对它做了一些重量级扩展。首先,Spark 摒弃了 MapReduce 先 map 再 reduce 这样的严格方式,Spark 引擎可以执行更通用的有向无环图(directed acyclic graph,DAG)算子。这就意味着,在 MapReduce 中需要将中间结果写入分布式文件系统时,Spark 能将中间结果直接传到流水作业线的下一步。在这方面,它类似于 Dryad(https://www.microsoft.com/en-us/research/project/dryad/)。Dryad 也是从 MapReduce 衍生出来的,起源于微软研究院。其次,它也完善了这种能力,通过提供许多转换操作,用户可以更自然地表达计算逻辑。Dryad 更加面向开发人员,其流式 API 可以做到用几行代码表示复杂的流水作业。

再次,Spark 扩展了前辈们的内存计算能力。它的 Dataset 和 DataFrame 抽象使开发人员将流水处理线上的任何点物化在跨越集群节点的内存中。这样后续步骤如果需要相同数据集就不必重新计算或从磁盘加载。这个特性使 Spark 可以应用于以前分布式处理引擎无法胜任的应用场景中。Spark 非常适用于涉及大量迭代的算法,这些算法需要多次遍历相同的数据集。Spark 也适用于反应式(reactive)应用,这些应用需要扫描大量内存数据并快速响应用户的查询。

或许最重要的是,Spark 契合了前面提到的数据科学领域的硬道理。它认识到构建数据应用的最大瓶颈不是 CPU、磁盘或者网络,而是分析人员的生产率。通过将预处理到模型评价的整个流水线整合在一个编程环境中,Spark 大大加速了开发过程。这一点尤为值得称赞。Spark 编程模型富有表达力,在 REPL 下包装了一组分析库,省去了多次往返 IDE 的开销。而这些开销对诸如 MapReduce 等框架来说是无法避免的。Spark 还避免了采样和从 Hadoop 分布式文件系统(the Hadoop distributed file system,HDFS) 来回倒腾数据所带来的问题,这些问题是 R 之类的框架经常遇到的。分析人员在数据上做实验的速度越快,他们从数据中挖掘出价值的可能性就越大。

在数据处理和 ETL 方面,Spark 的目标是成为大数据界的 Python 而不是大数据界的 MATLAB。作为一个通用的计算引擎,它的核心 API 为数据转换提供了强大的基础,它独立于统计学、机器学习或矩阵代数的任何功能。它的 Scala 和 Python API 让我们可以用表达力极强的通用编程语言编写程序,还可以访问已有的库。

Spark 的内存缓存使它适用于微观和宏观两个层面的迭代计算。机器学习算法需要多次遍历训练集,可以将训练集缓存在内存里。在对数据集进行探索和初步了解时,数据科学家可以在运行查询的时候将数据集放在内存中,也很容易将转换后的版本缓存起来,这样就节省了访问磁盘的开销。

最后,Spark 在探索型分析系统和操作型分析系统之间搭起一座桥梁。我们经常说,数据科学家比统计学家更懂软件工程,比软件工程师更懂统计学。基本上讲,Spark 比探索型系统更像操作型系统,比操作型系统中常见的技术更善于数据探索。Spark 从根本上是为性能和可靠性而生的。由于构建于 JVM 之上,它可以利用 Java 技术栈里的许多操作和调试工具。

Spark 还紧密集成 Hadoop 生态系统里的许多工具。它能读写 MapReduce 支持的所有数据格式,可以与 Hadoop 上的常用数据格式,如 Apache Avro 和 Apache Parquet(当然也包括古老的 CSV),进行交互。它能读写 NoSQL 数据库,比如 Apache HBase 和 Apache Cassandra。它的流式处理组件 Spark Streaming 能连续从 Apache Flume 和 Apache Kafka 之类的系统读取数据。它的 SQL 库 SparkSQL 能和 Apache Hive Metastore 交互,而且通过 Hive on Spark,Spark 还能替代 MapReduce 作为 Hive 的底层执行引擎。它可以运行在 Hadoop 集群调度和资源管理器 YARN 之上,这样 Spark 可以和 MapReduce 及 Apache Impala 等其他处理引擎动态共享集群资源和管理策略。1.3 关于本书

本书接下来的部分不会讨论 Spark 的优缺点。还有其他一些话题本书也不会涉及。本书会介绍 Spark 的流式编程模型和 Scala 基础知识,但它不是 Spark 参考书或参考大全,不会讲 Spark 技术细节。它也不是机器学习、统计学、线性代数的参考书,但在讲到这些知识的时候,许多章节会提供一些背景知识。

另一方面,本书将帮助读者建立用 Spark 在大规模数据集上进行复杂分析的感觉。我们会讲述整个处理过程:不但涉及模型的构建和评价,也会讲述数据清洗、数据预处理和数据探索,并会花费笔墨描述怎样将结果变成生产应用。我们认为最好的教学方法是运用实例,所以在快速介绍完 Spark 及其生态系统之后,本书其余各章分别讨论了在不同领域使用 Spark 进行数据分析的实例,每个实例都自成一体。

如果可能的话,我们要做的不只是提供解决方案。我们会描述数据科学的整个工作流程,包括它所有的迭代、无解以及需要重新开始的情况。本书将有助于读者熟悉 Scala、Spark、机器学习和数据分析。但这都是为了一个更大的目标服务,我们希望本书首先教会读者如何完成本章开头部分提到的任务。每一章虽然只有薄薄的 20 来页,但我们会力求把怎样构建一个此类数据应用讲清楚、讲透彻。1.4 第2版说明

2015 年和 2016 年 Spark 变化很大,2016 年 7 月 Spark 发布了 2.0 版本。其中改变最大的是 Spark 的核心 API。在 Spark 2.0 以前的版本中,Spark 的 API 主要围绕一个可以跨节点分布的、延迟实例化对象集合的弹性分布式数据集(Resilient Distributed Dataset,RDD)而构建。

虽然 RDD 使用了一套强大而富有表达力的 API,但是仍然存在两个主要的问题。第一,RDD 难以高效且稳定地执行任务。由于依赖 Java 和 Python 对象,RDD 对内存的使用效率较低,而且会导致 Spark 程序受长时间垃圾回收的影响。它们还将执行计划(execution plan)与 API 捆绑到了一起,给用户优化应用程序造成了沉重的负担。例如,传统 RDBMS(关系数据库管理系统)可以根据关联表的大小来选择最优的关联策略(join strategy),而 Spark 需要用户自己来做这个选择。第二,Spark 的 API 忽视了一个事实——数据往往能用一个结构化的关系形式来表示;当出现这种情况的时候,API 应该提供一些原语,使数据更加易于操作,比如允许用户使用列的名字来访问数据,而不是通过元组中的序数位置。

Spark 2.0 用 Dataset 和 DataFrame 替换掉 RDD 来解决上述问题。Dataset 与 RDD 十分相似,不同之处在于 Dataset 可以将它们所代表的对象映射到编码器(encoder),从而实现了一种更为高效的内存表示方法。这就意味着 Spark 程序可以执行得更快、使用更少内存,而且执行时间更好预测。Spark 还在数据集和执行计划之间加入了一个优化器,这意味着 Spark 能对如何执行做出更加智能的决策。DataFrame 是 Dataset 的子类,专门用于存储关系型数据(也就是用行和固定列表示的数据)。为了理解列的概念,Spark 提供了一套更干净的、富有表达力的 API,同时也加入了很多性能优化。举个例子,如果 Spark 知道了仅其中一部分列会被用到,它就能避免将用不到的列载入内存中。还有许多转换操作之前需要使用用户定义函数(user-defined function,UDF)来表示,现在可以在 API 中直接调用了。这对于 Python 用户来说十分有用,因为 Spark 在内部执行这些转换操作比 Python 中定义的函数要快得多。DataFrame 还可以与 Spark SQL 互相操作,这意味着用户可以写一个 SQL 查询来获取一个 DataFrame,然后选择一种 Spark 支持的语言对这个 DataFrame 进行编程操作。尽管新 API 与旧 API 看起来十分相似,但是很多细节发生了改变,因此几乎所有的 Spark 程序都要更新。

除了核心 API 的变化以外,Spark 2.0 还见证了机器学习 API 和统计分析 API 的巨大变化。在之前的版本中,每个机器学习算法都有一套自己的 API。如果用户想要准备算法需要的输入数据,或者将一个算法的输出提供给另外一个算法,都需要写一套它们自己的自定义编制代码。Spark 2.0 包含了 Spark ML API,它引入了一个框架,可以将多种机器学习算法和特征转换步骤管道化。这个 API 受 Python 的流行框架 Scikit-Learn API 启发,以评估器(estimator)和转换器(transformer)为中心,转换器从数据中学习参数,然后用这些参数来转换数据。Spark ML API 与 DataFrame API 高度集成,使得在关系型数据上训练机器学习模型变得更容易。例如,用户可以通过名字访问特征,而不用数组下标。

总体来说,Spark 的这些变化导致本书第 1 版中的很多内容都过时了。因此,第 2 版更新了所有的章节,并尽可能地使用最新的 API。此外,我们还删除了一些无关的章节。例如,第 1 版附录介绍了 API 的细节,第 2 版中将其删除了,一定程度上是因为现在 Spark 可以自动处理,无须用户干预。随着 Spark 进入了一个成熟而稳定的新时代,我们希望通过第 2 版的这些更新,本书在今后几年内会保持对 Spark 数据分析的参考价值。第2章用Scala和Spark进行数据分析作者:乔希 • 威尔斯

世上无难事,只要肯耐烦。——David Foster Wallace

数据清洗是数据科学项目的第一步,往往也是最重要的一步。许多灵巧的分析最后功败垂成,原因就是分析的数据存在严重的质量问题,或者数据中某些因素使分析产生偏见,或使数据科学家得出根本不存在的规律。

尽管数据清洗很重要,但数据科学相关的许多教材和课程都不讲述数据清洗,抑或一笔带过。造成这种现象的原因其实很简单:数据清洗实在是很琐碎。然而“磨刀不误砍柴工”,只有事先做了这种沉闷乏味的工作,后面你才能领略到应用机器学习算法解决新问题时的酣畅淋漓。许多道行尚浅的数据科学家往往急于求成,对数据草草处理就进行下一步工作,等到运行算法后,却发现数据有严重的质量问题(可能是计算量太大),或最后得出的结果完全不合理。“垃圾进垃圾出”这样浅显的道理大家都明白,危害更大的是:数据看似合理却有很严重(但第一眼看不出来)的质量问题,你根据这样的数据也得到了看似合理的答案。许多数据科学家丢饭碗,往往就是因为这样错误地得出了重要结论。

数据科学家最为人称道的是在数据分析生命周期的每一个阶段都能发现有意思、有价值的问题。在一个分析项目的早期阶段,你投入的技能和思考越多,对最终的产品就越有信心。

当然,说起来容易做起来难。对于数据科学行业来说,这就像是告诉小孩子要多吃蔬菜。相比数据清洗,摆弄 Spark 之类新潮的工具,用它们构建花哨的机器学习算法,开发流式数据处理引擎和分析海量图数据,要好玩得多。如果要介绍如何用 Spark 和 Scala 进行数据处理,有没有一种比练习数据清洗更好的方法呢?2.1 数据科学家的Scala

对数据处理和分析,数据科学家往往都自己钟爱的工具,比如 R 或者 Python。除非不得已,数据科学家常常会坚持用他们所钟爱的工具,对于手头上的工作,他们总想方设法地沿用这些工具。即使情况再顺利,想让数据科学家采用新的工具、学习新语法和新使用模式,都困难重重。

为了能在 R 或 Python 里直接用 Spark,Spark 上开发了专门的类库和工具包。Python 有个非常好用的工具包叫作 PySpark,第 11 章有几个例子介绍了它的用法。但是本书大部分例子还是用 Scala 语言编写的。Spark 框架是用 Scala 语言编写的,在向数据科学家介绍 Spark 时,采用与底层框架相同的编程语言有很多好处。● 性能开销小

为了能在基于 JVM 的语言(比如 Scala)上运行用 R 或 Python

编写的算法,我们必须在不同环境中传递代码和数据,这会付出

代价,而且在转换过程中信息时有丢失。但是,如果数据分析算

法用 Spark Scala API 编写,你会对程序正确运行更有信心。● 能用上最新的版本和最好的功能

Spark 的机器学习、流处理和图分析库全都是用 Scala 写的,而

新功能对 Python 和 R 绑定支持可能要慢得多。如果想用 Spark

的全部功能(而不用花时间等待它移植到其他语言绑定),恐怕

你必须学点儿 Scala 基础知识,如果想扩展这些 Spark 已有功能

来解决你手头上的新问题,就更要深入了解 Scala 了。● 有助于你了解Spark的原理

即使在 Python 或 R 中调用 Spark,API 仍然反映了底层计算原

理,它是 Spark 从其开发语言 Scala 继承过来的。如果你知道如

何在 Scala 中使用 Spark,即使你平时主要还是在其他语言中使

用 Spark,你还是会更理解系统,因此会更好地“用 Spark 思

考”。

学习在 Scala 中用 Spark 还有一个好处。由于 Spark 不同于其他任何一种数据分析工具,这个好处解释起来会有点儿困难。如果你曾经用过 R 或 Python 从数据库读取数据并分析,肯定经历过用一种语言(SQL)读取和操作大量存储在远程集群的数据,然后用另一种语言(Python 或 R)来操作和展现存储在你本地机器上的信息。如果想把一部分计算通过 SQL UDF 放到数据库引擎中,你需要切换到另一种编程环境(如 C++ 或者 Java),并且还要了解数据库的内部细节。如果你一直这么做,时间长了你可能都不会再想这种方式有没有问题。

使用 Spark 和 Scala 做数据分析则是一种完全不同的体验,因为你可以选择用同样的语言完成所有事情。借助 Spark,你用 Scala 代码读取集群上的数据。接着,你把 Scala 代码发送到集群上完成相同的转换,这些转换跟你刚刚对本地数据所做的转换完全一样,但数据却在集群上——这就是精妙之处。即便用 Spark SQL 这样的高阶语言,也可以写好内联 UDF,用 Spark SQL 引擎注册,然后使用 UDF——根本不用切换环境。

在同一个环境中完成所有数据处理和分析,不用考虑数据本身在何处存放和在何处处理,这简直妙不可言。这种感觉只有你亲身经历才体会得到。我们也想确保书中的示例能够让你感受到我们首次使用 Spark 时体验到的那种魔术般的感觉。2.2 Spark编程模型

Spark 编程始于数据集,而数据集往往存放在分布式持久化存储之上,比如 HDFS。编写 Spark 程序通常包括一系列相关步骤。

(1) 在输入数据集上定义一组转换。

(2) 调用 action,可以将转换后的数据集保存到持久化存储上,或者把结果返回到驱动程序的本地内存。

(3) 运行本地计算,处理分布式计算的结果。本地计算有助于你确定下一步的转换和 action。

从 1.2 版本到 2.1 版本,Spark 变得成熟了,处理上述步骤的工具的数量和质量也大大提升。在完成分析任务时,你可以搭配使用复杂 SQL 查询、机器学习库以及自定义代码。Spark 社区这几年开发了各种高阶抽象,利用这些抽象,你可以花更少的时间来解决更多的问题。但是所有这些高阶抽象都是基于存储与执行的相互作用,从 Spark 诞生起就一直是这样。Spark 优美地搭配这两类抽象,可以将数据处理管道中的任何中间步骤缓在内存里以备后用。了解这些原则可以帮助你更好地利用 Spark 做数据分析。2.3 记录关联问题

本章我们要研究的主题在许多文献和实践中被冠以许多不同的名称:身份解析、记录去重、合并 - 清除,以及列表清洗。想了解这个主题的方案和技术概况,我们需要参考这个主题的所有相关研究论文。但是由于不同文献和实践中同一个概念使用不同的名称,我们很难找到所有相关论文。在搞清楚数据清洗这个问题之前,我们得请数据科学家把与数据清洗这个概念相关的令人混淆的许多不同名称给去去重。这真让人觉得讽刺!为了方便本章余下部分论述,我们把这个问题称为记录关联(record linkage)。

问题的大概情况如下:我们有大量来自一个或多个源系统的记录,其中多种不同的记录可能代表相同的基础实体,比如客户、病人、业务地址或事件。每个实体有若干属性,比如姓名、地址、生日。我们需要根据这些属性找到那些代表相同实体的记录。不幸的是,有些属性值有问题:格式不一致,或有笔误,或信息缺失。如果简单地对这些属性作相等性测试,就会漏掉许多重复记录。举个例子,我们看看表 2-1 列出的几家商店的记录。表 2-1:记录关联问题的难点名称地址城市州电话West 1234 Sunset (213)-555Josh's Coffee ShopHollywooCABoulevard-1212d1234 Sunset HollywooJosh CoffeeCA555-1212Blvd WestdCoffee Chain 1400 Sunset Hollywoo206-555-CA#1234Blvd #2d1212Coffee Chain 1400 Sunset HollywooCaliforn206-555-Regional OfficeBlvd Suite 2dia1212

表中前两行其实指同一家咖啡店,但由于数据录入错误,这两项看起来是在不同城市(West Hollywood 和 Hollywood)。相反,表中后两行其实是同一家咖啡连锁店的不同业务部门,尽管它们有相同的地址:地址 1400 Sunset Blvd #2 是咖啡店的实际地址,另一个地址 1400 Sunset Blvd Suite 2 则是公司在当地的一个办公室地点。后两项给的都是公司 Seattle 总部的官方电话号码。

这个例子清楚地说明了记录关联为什么很困难:即使两组记录看起来相似,但针对每一组中的条目,我们确定它是否重复的标准不一样。这种区别我们人类很容易理解,计算机却很难了解。2.4 小试牛刀:Spark shell和SparkContext

我们的样例数据集来自加州大学欧文分校机器学习资料库(UC Irvine Machine Learning Repository),这个资料库为研究和教学提供了大量非常好的数据源,这些数据源非常有意义,并且是免费的。我们要分析的数据集来源于一项记录关联研究,这项研究是德国一家医院在 2010 年完成的。这个数据集包含数百万对病人记录,每对记录都根据不同标准来匹配,比如病人姓名(名字和姓氏)、地址、生日。每个匹配字段都被赋予一个数值评分,范围为 0.0 到 1.0,分值根据字符串相似度得出。然后这些数据交由人工处理,标记出哪些代表同一个人,哪些代表不同的人。为了保护病人隐私,创建数据集的每个字段的原始值被删除了。病人的 ID、字段匹配分数、匹配对标记(包括匹配的和不匹配的)等信息是公开的,可用于记录关联研究。

首先我们从资料库中下载数据,请在命令行中输入:$ mkdir linkage$ cd linkage/$ curl -L -o donation.zip https://bit.ly/1Aoywaq$ unzip donation.zip$ unzip 'block_*.zip'

如果手头有 Hadoop 集群,可以先在 HDFS 上为块数据创建一个目录,然后将数据集文件复制到 HDFS 上:$ hadoop fs -mkdir linkage$ hadoop fs -put block_*.csv linkage

本书示例和代码假定读者使用 Spark 2.1.0。可以在 Spark 项目网站(https://spark.apache.org/downloads.html)获取各个版本的 Spark 软件。想了解如何在集群或本地机器上安装 Spark 环境,请参考 Spark 官方文档。

现在准备工作就绪,可以启动 spark-shell 了。spark-shell 是 Scala 语言的一个 REPL 环境,它同时针对 Spark 做了一些扩展。如果这是你第一次见到 REPL 这个术语,可以把它看成一个类似 R 的控制台:可以在其中用 Scala 编程语言定义函数并操作数据。

如果你有一个 Hadoop 集群,并且 Hadoop 版本支持 YARN,通过为 Spark master 设定 yarn 参数值,就可以在集群上启动 Spark 作业:$ spark-shell --master yarn --deploy-mode client

如果你是在自己的计算机上运行示例,可以通过设定 local[N] 参数来启动本地 Spark 集群,其中 N 代表运行的线程数,或者用 * 表示使用机器上所有可用的核数。比如,要在一个 8 核的机器上用 8 个线程启动一个本地集群,可以输入以下命令:$ spark-shell --master local[*]

在本地环境下,书中示例同样能运行。不过,这时传入的文件路径是本地路径,而不是以 hdfs:// 开头的 HDFS 路径。注意,还需要通过 cp block_*.csv 将文件复制到指定的本地目录,而不是用包含解压文件的目录,因为该目录不仅包含 .csv 文件,还包含许多其他文件。

本书其他 spark-shell 示例中不会出现 --master 参数,但根据环境通常需要设定该参数。

为了 Spark shell 能充分利用资源,可能还需要额外设定一些参数。比如,当 Spark 运行于本地 master 模式,可以用 --driver-memory 2g,这样就设定了一个本地进程使用 2 GB 内存。YARN 内存设置会更复杂,相关的选项(如 --executor-memory 等参数)设置可以参考 Spark on YARN 的官方文档(https://spark.apache.org/docs/latest/running-on-yarn.html)。

运行完上述命令后,可以看到 Spark 在初始化过程中的日志消息。与此同时,也能看到一点儿 ASCII 艺术体字样,之后又是一段日志和提示符:Spark context Web UI available at http://10.0.1.39:4040Spark context available as 'sc' (master = local[*], app id = ...).Spark session available as 'spark'.Welcome toUsing Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60)Type in expressions to have them evaluated.Type :help for more information.scala>

如果你是第一次用 Spark shell(或任何类似的 Scala REPL),可以运行 :help 命令,该命令列出了 shell 的所有命令。运行 :history 或 :h?,可以帮你找到之前在某个会话中写过,但一时又想不起来的变量或函数名称。运行 :paste,可以帮你插入剪贴板中的代码,这是学习本书和使用本书源代码必需的。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载