Spark 大规模机器学习(一)

何小豆儿在此  金牌会员 | 2024-8-19 23:26:36 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 513|帖子 513|积分 1539

原文:zh.annas-archive.org/md5/7A35D303E4132E910DFC5ADB5679B82A
  译者:飞龙
  协议:CC BY-NC-SA 4.0
  前言

机器学习的核心是关注将原始数据转化为可操作智能的算法。这一毕竟使得机器学习非常适合于大数据的预测分析。因此,假如没有机器学习,要跟上这些大规模信息流险些是不可能的。相对较新且新兴的技能 Spark 为大数据工程师和数据科学家提供了一个强盛的响应和同一的引擎,既更快速又易于使用。
这使得来自多个范畴的学习者可以或许以更大规模地交互办理他们的机器学习问题。本书旨在使数据科学家、工程师和研究职员可以或许开发和部署规模化的机器学习应用步伐,以便他们学会如安在数据密集型情况中处理大数据集群,构建强盛的机器学习模型。
本书的内容是从 Spark 和 ML 底子开始以自下而上的方式编写的,探索了特性工程中的数据,构建可扩展的 ML 管道,通过调整和适应新的数据和问题范例,终极进行模型构建和部署。为了更清楚,我们以这样一种方式提供了章节大纲,以便具有最基本的机器学习和 Spark 编程知识的新读者可以或许跟随示例,并朝着一些真实的机器学习问题及其办理方案迈进。
本书内容包罗以下内容

第一章,使用 Spark 进行数据分析简介,本章介绍了 Spark 的概述、计算范式、安装,并帮助我们开始使用 Spark。它将扼要描述 Spark 的重要组件,并专注于其具有弹性分布式数据集(RDD)和数据集的新计算进展。然后,它将专注于 Spark 的机器学习库生态系统。在扩展到 Amazon EC2 之前,将演示使用 Spark 和 Maven 安装、配置和打包简单的机器学习应用步伐。
第二章,机器学习最佳实践,提供了对统计机器学习(ML)技能的概念介绍,旨在带领新手从对机器学习的最基本知识到成为纯熟的从业者。本章的第二部门偏重于为根据应用范例和要求选择合适的机器学习算法提供一些建议。然后,它将介绍应用大规模机器学习管道时的一些最佳实践。
第三章,通过相识数据来明白问题,详细介绍了用于处理结构化数据的数据集和弹性分布式数据集(RDD)API,旨在提供对可用数据进行基本明白的机器学习问题。末了,您将可以或许轻松处理基本和复杂的数据操作。将提供使用 RDD 和基于数据集的数据操作的基本抽象的一些比力,以展示在编程和性能方面的收益。此外,我们将指导您走上精确的门路,以便您可以或许使用 Spark 将 RDD 或数据对象持久化在内存中,从而在后期的并行操作中有效地重复使用。
《第四章》《通过特性工程提取知识》解释了相识应该用于创建预测模型的特性不仅至关重要,而且可能是一个须要深入相识问题范畴的难题。可以主动选择数据中对或人正在处理的问题最有用或最相关的特性。考虑到这些问题,本章详细介绍了特性工程,解释了应用它的原因以及特性工程中的一些最佳实践。
除此之外,还将讨论应用于大规模机器学习技能的特性提取、转换和选择的理论描述和示例,使用 Spark MLlib 和 Spark ML API。
《第五章》《通过示例进行监督和无监督学习》将提供围绕怎样快速而有力地将监督和无监督技能应用于可用数据办理新问题的实际知识,这些知识是基于前几章的一些广泛使用的示例。这些示例将从 Spark 的角度进行演示。
《第六章》《构建可扩展的机器学习管道》解释了机器学习的终极目标是使机器可以或许在不须要繁琐和耗时的人工参与和交互的情况下主动从数据中构建模型。因此,本章将指导读者通过使用 Spark MLlib 和 Spark ML 创建一些实用和广泛使用的机器学习管道和应用。将详细描述这两个 API,而且还将涵盖基线用例。然后,我们将专注于扩展 ML 应用步伐,使其可以或许应对不断增加的数据负载。
《第七章》《调整机器学习模型》表明,调整算法或机器学习应用可以简单地被视为一个过程,通过这个过程优化影响模型的参数,以使算法表现最佳。本章旨在指导读者进行模型调整。它将涵盖用于优化 ML 算法性能的重要技能。技能将从 MLlib 和 Spark ML 的角度进行解释。我们还将展示怎样通过调整多个参数(如超参数、MLlib 和 Spark ML 的网格搜刮参数、假设查验、随机搜刮参数调整和交织验证)来改善 ML 模型的性能。
《第八章》《调整您的机器学习模型》涵盖了使算法适应新数据和问题范例的高级机器学习技能。它将重要关注批处理/流处理架构和使用 Spark 流处理的在线学习算法。终极目标是为静态机器学习模型带来动态性。读者还将看到机器学习算法怎样渐渐从数据中学习,即每次算法看到新的练习实例时,模型都会更新。
第九章《使用流式和图形数据进行高级机器学习》解释了怎样利用 Spark MLlib 和 Spark ML 等工具在流式和图形数据上应用机器学习技能,例如在主题建模中。读者将可以或许利用现有的 API 从流数据源(如 Twitter)构建及时和预测性应用步伐。通过 Twitter 数据分析,我们将展示怎样进行大规模交际情感分析。我们还将展示怎样使用 Spark MLlib 开发大规模影戏推荐系统,这是交际网络分析的一个隐含部门。
第十章《配置和使用外部库》指导读者怎样使用外部库来扩展他们的数据分析。将给出使用第三方包或库在 Spark 核心和 ML/MLlib 上进行机器学习应用的示例。我们还将讨论怎样编译和使用外部库与 Spark 的核心库进行时间序列分析。如约定的,我们还将讨论怎样配置 SparkR 以改进探索性数据操作。
本书所需内容

软件要求:
第 1-8 章和第十章须要以下软件:Spark 2.0.0(或更高版本)、Hadoop 2.7(或更高版本)、Java(JDK 和 JRE)1.7+/1.8+、Scala 2.11.x(或更高版本)、Python 2.6+/3.4+、R 3.1+和已安装的 RStudio 0.99.879(或更高版本)。可以使用 Eclipse Mars 或 Luna(最新版本)。此外,还须要 Maven Eclipse 插件(2.9 或更高版本)、用于 Eclipse 的 Maven 编译器插件(2.3.2 或更高版本)和用于 Eclipse 的 Maven 汇编插件(2.4.1 或更高版本)。最重要的是,重复使用 Packt 提供的pom.xml文件,并相应地更改先条件到的版本和 API,一切都会得到办理。
对于第九章《使用流式和图形数据进行高级机器学习》,险些全部先条件到的所需软件都是必需的,除了 Twitter 数据收集示例,该示例将在 Spark 1.6.1 中展示。因此,须要 Spark 1.6.1 或 1.6.2,以及友好的 Maven pom.xml文件。
操作系统要求:
Spark 可以在多个操作系统上运行,包罗 Windows、Mac OS 和 LINUX。然而,Linux 发行版更可取(包罗 Debian、Ubuntu、Fedora、RHEL、CentOS 等)。更具体地说,例如对于 Ubuntu,建议使用 14.04/15.04(LTS)64 位完整安装或 VMWare player 12 或 Virtual Box。对于 Windows,建议使用 Windows(XP/7/8/10),对于 Mac OS X(10.4.7+)也是如此。
硬件要求:
为了顺利使用 Spark,建议使用至少核心 i3 或核心 i5 处理器的计算机。然而,为了得到最佳结果,核心 i7 将实现更快的数据处理和可伸缩性,至少须要 8GB RAM(建议)用于独立模式,至少须要 32GB RAM 用于单个 VM,大概用于集群的更高内存。此外,须要充足的存储空间来运行繁重的任务(取决于您将处理的数据大小),最好至少有 50GB 的免费磁盘存储空间(用于独立和 SQL 仓库)。
本书适合对象

由于 Python 和 R 是数据科学家常用的两种流行语言,因为有大量的模块或软件包可用来帮助他们办理数据分析问题。然而,这些工具的传统用法通常有限,因为它们在单台机器上处理数据,大概使用基于主存储器的方法处理数据,数据的移动变得耗时,分析须要抽样,而且从开发到生产情况的转换须要大量的重新设计。为了办理这些问题,Spark 提供了一个强盛且同一的引擎,既快速又易于使用,这使您可以或许以交互方式办理机器学习问题,而且规模更大。
因此,假如您是学术界人士、研究职员、数据科学工程师,甚至是处理大型和复杂数据集的大数据工程师。此外,假如您想要加速数据处理管道和机器学习应用的扩展,这本书将是您旅程中的合适伴侣。此外,Spark 提供了许多语言选择,包罗 Scala、Java 和 Python。这将帮助您将机器学习应用步伐置于 Spark 之上,并使用这些编程语言之一进行重塑。
您应该至少熟悉机器学习概念的底子知识。相识开源工具和框架,如 Apache Spark 和基于 Hadoop 的 MapReduce,会很有帮助,但并非必需。我们盼望您具备踏实的统计学和计算数学背景。此外,相识 Scala、Python 和 Java 是明智的。然而,假如您熟悉中级编程语言,这将有助于您明白本书中的讨论和示例。
约定

在这本书中,您会发现许多差别风格的文本,用以区分差别范例的信息。以下是一些这些风格的例子,以及它们的含义解释。
文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄表现如下: “我们可以通过使用 include 指令来包含其他上下文。”
在 Windows 情况中创建 Spark 会话的代码块设置如下:
  1. [default]
  2. SparkSession spark = SparkSession
  3.                   .builder()
  4.                   .appName("JavaFPGrowthExample")
  5.                   .master("local[*]")
  6.                   .config("spark.sql.warehouse.dir", "E:/Exp/")                  .getOrCreate();
复制代码
大概从输入数据集创建简单的 RDD 设置如下:
  1. [default]
  2.             String filename = “input/dataset.txt”;
  3.             RDD<String> data = spark.sparkContext().textFile(fileName, 1);
复制代码
任何命令行输入或输出都以如下方式编写:
  1. $ scp -i /usr/local/key/my-key-pair.pem  /usr/local/code/FPGrowth-0.0.1-SNAPSHOT-jar-with-dependencies.jar ec2-user@ec2-52-18-252-59.eu-west-1.compute.amazonaws.com:/home/ec2-user/
复制代码
新术语重要单词以粗体表现。您在屏幕上看到的单词、菜单或对话框中的单词等都会以这样的方式出如今文本中: “点击 下一步 按钮将您移动到下一个屏幕”。
注意

告诫或重要说明会出如今这样的框中。
提示

提示和技巧会出如今这样。
第一章:Spark 数据分析简介

本章概述了 Apache Spark、其计算范式和安装开始。它将扼要描述 Spark 的重要组件,并专注于其新的计算进展。将讨论弹性分布式数据集RDD)和数据集作为本书其余部门的底子知识。然后将专注于 Spark 机器学习库。然后演示怎样安装和打包一个简单的机器学习应用步伐与 Spark 和 Maven。简而言之,本章将涵盖以下主题:


  • Spark 概述
  • 具有 Spark 的新计算范式
  • Spark 生态系统
  • Spark 机器学习库
  • 安装和开始使用 Spark
  • 打包您的应用步伐与依赖项
  • 运行一个简单的机器学习应用步伐
Spark 概述

本节介绍了 Spark(spark.apache.org/)的底子知识,然后介绍了传统并行和分布式计算的问题,接着介绍了 Spark 的演变,以及它为大数据处理和分析带来了新的计算范式。此外,我们还介绍了一些令人高兴的 Spark 功能,这些功能很容易吸引大数据工程师、数据科学家和研究职员,包罗:


  • 数据处理和计算的简单性
  • 计算速度
  • 在大规模数据集上的可伸缩性和吞吐量
  • 对各种数据范例的复杂性
  • 使用差别的集群管理器轻松进行集群计算和部署
  • 与各种大数据存储和泉源的工作能力和支持
  • 广泛使用和新兴编程语言编写的多样化 API
Spark 底子知识

在称赞 Spark 及其许多长处之前,有须要进行扼要概述。Apache Spark 是一个快速、内存中的大数据处理和通用集群计算框架,具有一系列复杂的高级 API,用于高级数据分析。与基于 Hadoop 的 MapReduce 只实用于批处理作业的速度和易用性差别,Spark 可以被以为是一个实用于对静态(批处理)和及时数据应用高级分析的通用实行引擎:


  • Spark 最初是在加州大学伯克利分校的 AMPLab 基于弹性分布式数据集RDDs)开发的,它为内存集群计算设施提供了容错抽象。然而,厥后 Spark 的代码库被捐赠给了 Apache 软件基金会,使其成为开源,自那时起,开源社区不绝在照顾它。Spark 提供了一个接口,通过其高级 API(Java、Scala、Python 和 R 编写)在整个集群上以规模实行数据分析,具有隐式数据并行性和容错性。
在 Spark 2.0.0 中,实现了提升的库(最广泛使用的数据分析算法),包罗:


  • 用于查询和处理大规模结构化数据的 Spark SQL
  • SparkR 用于统计计算,使用 R 语言进行分布式计算规模化
  • MLlib 用于机器学习(ML)应用步伐,内部门为两部门;MLlib 用于基于 RDD 的机器学习应用步伐开发和 Spark ML 用于开发完整的计算数据科学和机器学习工作流的高级抽象
  • 用于大规模图形数据处理的 GraphX
  • Spark Streaming 用于处理大规模及时流数据,为静态机器学习提供动态工作情况
自其首个稳定版本发布以来,Spark 已经履历了戏剧性和迅速的发展,并得到了全球范围内各种 IT 办理方案提供商、开源社区和研究职员的积极倡导。近来,它已成为大数据处理和集群计算范畴最活跃、最大的开源项目之一,不仅因为其广泛的接纳,还因为全球范围内 IT 职员、数据科学家和大数据工程师对其部署和调查。正如 Spark 的首创人、Databricks 的 CTO Matei Zaharia 在Big Data analytics消息网站上所说:
   这是一件有趣的事情。在商业上并没有引起太多噪音,但实际的开发者社区通过实际办法投票,人们实际上正在完成工作并与项目相助。
  只管许多科技巨头如雅虎、百度、Conviva、ClearStory、Hortonworks、Gartner 和腾讯已经在生产中使用 Spark,另一方面,IBM、DataStax、Cloudera 和 BlueData 为企业提供了商业化的 Spark 分发。这些公司已经热情地在规模庞大的集群上部署了 Spark 应用步伐,共同处理了数百 PB 的数据,这是已知的最大的 Spark 集群。
Spark 的长处

您计划开发机器学习(ML)应用步伐吗?假如是这样,您可能已经有一些数据在练习模型之前进行预处理,终极,您将使用练习好的模型对新数据进行预测以查看适应性。这就是您须要的全部吗?我们料想不是,因为您还必须考虑其他参数。显然,您盼望您的 ML 模型在准确性、实行时间、内存使用、吞吐量、调整和适应性方面都能完美运行。等等!还没有竣事;假如您盼望您的应用步伐可以或许处理大规模的练习和新数据集呢?大概作为数据科学家,假如您可以构建您的 ML 模型,以克服这些问题,从数据整合到练习和错误再到生产的多步旅程,通过在大集群和个人计算机上运行雷同的机器学习代码而不会进一步崩溃?您可以简单地依靠 Spark 并闭上眼睛。
Spark 相对于其他大数据技能(如 MapReduce 和 Storm)具有几个优势。起首,Spark 提供了一个全面同一的引擎,以满足各种数据集(文本、表格、图形数据)和数据源(批处理和及时流数据)的大数据处理需求。作为用户(数据科学工程师、学者或开发职员),您可能会从 Spark 的快速应用步伐开发中受益,因为它具有简单易懂的 API,可用于批处理、交互和及时流应用步伐。
使用 Spark 进行工作和编程是简单易行的。让我们来展示一个例子。雅虎是 Spark 的贡献者和早期接纳者之一,他们用 120 行 Scala 代码实现了一个 ML 算法。仅仅 30 分钟的大型数据集练习,包含 1 亿条记载,Scala ML 算法就预备好投入使用了。令人惊讶的是,之前使用 C++编写雷同算法须要 15000 行代码(请参考以下网址获取更多信息:www.datanami.com/2014/03/06/apache_spark_3_real-world_use_cases/)。您可以使用 Java、Scala、R 或 Python 开发您的应用步伐,并使用 100 多个高级操作符(大多数在 Spark 1.6.1 发布后支持)来转换数据集,并熟悉数据框 API,以操作半结构化、结构化和流数据。除了 Map 和 Reduce 操作,它还支持 SQL 查询、流数据、机器学习和图数据处理。此外,Spark 还提供了用 Scala 和 Python 编写的交互式 shell,用于次序实行代码(如 SQL 或 R 风格)。
Spark 之所以迅速被接纳的重要原因是因为两个重要因素:速度和复杂性。Spark 为许多应用步伐提供了数目级的性能,使用粗粒度、不可变和复杂的数据,称为弹性分布式数据集,这些数据集分布在集群中,而且可以存储在内存或磁盘中。RDD 提供了容错性,即一旦创建就无法更改。此外,Spark 的 RDD 具有从其血统中重新创建的属性,假如在计算过程中丢失,它可以重新创建。此外,RDD 可以通过分区主动分布到集群中,而且可以保存您的数据。您还可以通过 Spark 的缓存机制将数据保存在内存中,而且这种机制使得基于 Hadoop 的 MapReduce 集群中的大数据应用步伐在内存中实行时速度提高了 100 倍,甚至在基于磁盘的操作中提高了 10 倍。
让我们来看一下关于 Spark 及其计算能力的一个令人惊讶的统计数据。近来,Spark 通过完成 2014 年 Gray Sort Benchmark 中的 100 TB 类别,取代了基于 Hadoop 的 MapReduce,这是一个关于系统可以或许多快地对 100 TB 数据(1 万亿条记载)进行排序的行业基准(请参考spark.apache.org/news/spark-wins-daytona-gray-sort-100tb-benchmark.html和sortbenchmark.org/)。终极,它成为了用于对 PB 级数据进行排序的开源引擎(请参考以下网址获取更多信息databricks.com/blog/2014/11/05/spark-officially-sets-a-new-record-in-large-scale-sorting.html)。相比之下,之前由 Hadoop MapReduce 创下的世界记录须要使用 2100 台机器,实行时间为 72 分钟,这意味着 Spark 使用了 10 倍少的机器,以三倍的速度对雷同的数据进行了排序。此外,您可以无缝地结合多个库来开发大规模机器学习和数据分析管道,以在各种集群管理器(如 Hadoop YARN、Mesos 或通过访问数据存储和源(如 HDFS、Cassandra、HBase、Amazon S3 甚至 RDBMs)在云中实行作业。此外,作业可以作为独立模式在当地 PC 或集群上实行,甚至在 AWS EC2 上实行。因此,将 Spark 应用步伐部署到集群上非常容易(我们将在本章后面展示如安在集群上部署 Spark 应用步伐)。
Spark 的其他长处是:它是开源的,平台无关的。这两点也是它的最大优势,即可以免费使用、分发和修改,并在任何平台上开发应用步伐。开源项目也更安全,因为代码对每个人都是可访问的,任何人都可以在发现错误时修复错误。因此,Spark 发展得如此迅速,以至于它已成为涉及大数据办理方案的最大开源项目,拥有来自 200 多个构造的 750 多名贡献者。
具有 Spark 的新计算范式

在本节中,我们将展示 Spark 的发展历程,以及它怎样成为大数据处理和集群计算的革命。除此之外,我们还将扼要描述 Spark 生态系统,以更详细地相识 Spark 的特点和功能。
传统分布式计算

传统的数据处理范式通常被称为客户端-服务器模型,人们过去经常将数据移动到代码中。数据库服务器(或简称服务器)重要负责实行数据操作,然后将结果返回给客户端-服务器(或简称客户端)步伐。然而,当须要计算的任务数目增加时,各种操作和客户端设备也开始呈指数级增长。因此,服务器中的计算端点也开始渐渐复杂起来。因此,为了保持这种计算模型,我们须要增加应用步伐(客户端)服务器和数据库服务器的平衡,以存储和处理增加的操作数目。因此,节点之间的数据流传和网络中来回传输的数据也急剧增加。因此,网络本身成为性能瓶颈。因此,在这种计算范式中,性能(无论是可伸缩性还是吞吐量)也无疑会降落。如下图所示:

图 1:传统分布式处理的实际应用。
在生命科学中成功完成人类基因组计划后,及时物联网数据、传感器数据、移动设备数据和网络数据正在创造数据洪流,并为大数据做出贡献,这在很大水平上推动了数据密集型计算的发展。如今,数据密集型计算正在以一种新兴的方式不断发展,这须要一个集成的底子设施或计算范式,以便将计算资源和数据带入一个共同的平台,并在其上进行分析。原因是多样的,因为大数据在复杂性(容量多样性速度)方面确实非常庞大,从操作角度来看,另有四个 ms(即移动管理合并整理)。
此外,由于本书将讨论大规模机器学习应用步伐,我们还须要考虑一些额外的关键评估参数,如有效性、真实性、代价和可见性,以促进业务增长。可见性很重要,因为假设你有一个大小为 1PB 的大数据集;但是假如没有可见性,一切都是一个黑洞。我们将在接下来的章节中更详细地解释大数据代价。
在单个系统中存储和处理这些大规模和复杂的大型数据集可能是不可行的;因此,它们须要被分区并存储在多台物理机器上。大型数据集被分区或分布,但为了处理和分析这些严格复杂的数据集,数据库服务器和应用步伐服务器可能须要增加,以增强盛规模的处理能力。同样,多维度中出现的性能瓶颈问题最糟糕,须要一种新的、更数据密集的大数据处理和相关计算范式。
将代码移动到数据

为了克服先条件到的问题,迫切须要一种新的计算范式,这样我们就可以将代码或应用步伐移动到数据中,实行数据操作、处理和相关计算(也就是说,数据存储的地方)。由于您已经相识了动机和目标,如今可以将反转的编程模型称为将代码移动到数据并在分布式系统上进行并行处理,可以在以下图表中可视化:

图 2:新的计算(将代码移动到数据并在分布式系统上进行并行处理)。
为了明白图 2中所示的工作流程,我们可以假想一个新的编程模型,描述如下:


  • 使用您在个人计算机上启动的应用步伐实行大数据处理(让我们称之为驱动步伐),它在集群、网格或更开放地说是云中远程和谐实行。
  • 如今你须要做的是将开发的应用步伐/算法/代码段(可以使用命令行或 shell 脚本调用或取消)转移到具有大容量存储、主存储器和处理能力的计算/工作节点。我们可以简单地想象要计算或操作的数据已经存储在这些计算节点中,作为分区或块。
  • 可以明白的是,由于网络或计算瓶颈,大容量数据不再须要传输(上传/下载)到驱动步伐,而是仅在其变量中保存数据引用,基本上是一个地点(主机名/IP 地点和端口),用于在集群中定位存储在计算节点中的物理数据(固然,也可以使用其他办理方案进行大容量上传,例如可扩展的配置,将在后面的章节中讨论)。
  • 那么远程计算节点有什么?它们既有数据,也有实行数据计算和须要处理以实现输出或修改数据的代码,而不脱离它们的家(更准确地说是计算节点)。
  • 末了,根据您的哀求,只有结果可以通过网络传输到您的驱动步伐进行验证或其他分析,因为原始数据集有许多子集。
值得注意的是,通过将代码移动到数据,计算结构已经发生了巨大变革。最有趣的是,网络传输的数据量显著减少。这里的来由是,您只会将一小部门软件代码传输到计算节点,并收到原始数据的一个小子集作为返回的结果。这是 Spark 为我们带来的大数据处理最重要的范式转变,它引入了 RDD、数据集、DataFrame 和其他有利特性,这意味着在大数据工程和集群计算历史上有着巨大的革命。然而,为了简洁起见,下一节我们将只讨论 RDD 的概念,其他计算特性将在接下来的章节中讨论。
RDD - 一种新的计算范式

为了明白新的计算范式,我们须要相识弹性分布式数据集RDDs)的概念及 Spark 怎样实现数据引用的概念。因此,它已经可以或许轻松地将数据处理扩展。RDD 的基本特点是它帮助您险些像处理任何其他数据对象一样处理输入数据集。换句话说,它带来了输入数据范例的多样性,这是您在基于 Hadoop 的 MapReduce 框架中极度缺失的。
RDD 以一种弹性的方式提供了容错能力,一旦创建就无法更改,Spark 引擎将尝试在操作失败时迭代操作。它是分布式的,因为一旦实行了分区操作,RDD 会主动通过分区在集群中分布。RDD 允许您更多地处理输入数据集,因为 RDD 也可以快速而稳健地转换为其他情势。同时,RDD 也可以通过操作转储并在逻辑上相关或计算上同质的应用步伐之间共享。这是因为它是 Spark 通用实行引擎的一部门,可以得到大规模的并行性,因此险些可以应用于任何范例的数据集。
然而,为了在输入数据上进行 RDD 和相关操作,Spark 引擎要求您在数据指针(即引用)和输入数据本身之间创建明显的界限。基本上,您的驱动步伐不会保存数据,而只会保存数据的引用,数据实际上位于集群中的远程计算节点上。
为了使数据处理更快、更容易,Spark 支持可以在 RDD 上实行的两种操作:转换和操作(请参考图 3)。转换操作基本上是从现有数据集创建一个新数据集。另一方面,操作在成功计算远程服务器上的输入数据集后,将一个值实现为驱动步伐(更确切地说是计算节点)。
由驱动步伐启动的数据实行方式构建了一个有向无环图DAG)样式的图表;其中节点表示 RDD,转换操作由边表示。然而,实行本身直到实行操作之前不会在 Spark 集群中的计算节点中开始。然而,在开始操作之前,驱动步伐将实行图(表示数据计算流水线或工作流的操作方式)和代码块(作为特定范畴的脚本或文件)发送到集群,每个工作节点/计算节点从集群管理节点吸收一个副本:

图 3:RDD 的操作(转换和操作操作)。
在继续下一节之前,我们建议您更详细地相识操作和转换操作。虽然我们将在第三章中详细讨论这两种操作,但如今 Spark 支持两种范例的转换操作。第一种是窄转换,其中数据混合是不须要的。典型的 Spark 窄转换操作使用filter()、sample()、map()、flatMap()、mapPartitions()等方法进行。宽转换对于对输入数据集进行更广泛的更改是必不可少的,以便将数据从多个数据分区中的共同节点中带出。宽转换操作包罗groupByKey()、reduceByKey()、union()、intersection()、join()等。
动作操作通过触发实行作为有向无环图DAG)样式返回 RDD 计算的终极结果到驱动步伐。但实际上,材料化的结果实际上是写在存储中的,包罗数据对象的中间转换结果,并返回终极结果。常见的动作包罗:first()、take()、reduce()、collect()、count()、saveAsTextFile()、saveAsSequenceFile()等。在这一点上,我们相信您已经掌握了 RDD 的基本操作,因此我们如今可以以自然的方式界说 RDD 和相关步伐。Spark 提供的典型 RDD 编程模型可以描述如下:


  • 从情况变量中,Spark 上下文(Spark shell 或 Python Pyspark 为您提供了一个 Spark 上下文,大概您可以本身创建,这将在本章后面描述)创建一个初始数据引用 RDD 对象。
  • 通过转换初始 RDD 以创建更多的 RDD 对象,遵循函数式编程风格(稍后将讨论)。
  • 将代码/算法/应用步伐从驱动步伐发送到集群管理器节点。然后集群管理器为每个计算节点提供一个副本。
  • 计算节点在其分区中保存 RDD 的引用(同样,驱动步伐也保存数据引用)。然而,计算节点也可以由集群管理器提供输入数据集。
  • 在转换之后(通过窄转换或宽转换),生成的结果将是全新的 RDD,因为原始的 RDD 不会被改变。末了,通过动作将 RDD 对象或更多(具体数据引用)实现为将 RDD 转储到存储中。
  • 驱动步伐可以哀求计算节点为步伐的分析或可视化结果哀求一部门结果。
等等!到如今为止,我们一切顺利。我们假设您将把应用步伐代码发送到集群中的计算节点。但是您仍旧须要上传或发送输入数据集到集群中以分发给计算节点。纵然在大量上传期间,您也须要通过网络传输数据。我们还以为应用步伐代码和结果的大小是可以忽略不计的。另一个停滞是,假如您/我们盼望 Spark 进行规模计算的数据处理,可能须要起首从多个分区合并数据对象。这意味着我们须要在工作节点/计算节点之间进行数据洗牌,通常通过partition()、intersection()和join()转换操作来完成。
坦率地说,数据传输并没有完全消除。正如我们和你明白的那样,特殊是对于这些操作的大量上传/下载所贡献的开销,它们对应的结果如下:

图 4:RDD 的操作(缓存机制)。
好吧,我们已经受到了这些负担的影响是毕竟。然而,使用 Spark 的缓存机制可以显著减少或办理这些情况。想象一下,您将在雷同的 RDD 对象上多次实行操作,这些对象具有很长的血统;这将导致实行时间的增加以及计算节点内部的数据移动。您可以使用 Spark 的缓存机制(图 4)来消除(或至少减少)这种冗余,该机制将 RDD 的计算结果存储在内存中。这样就可以消除每次的重复计算。因为当您在 RDD 上进行缓存时,其分区将加载到主内存中,而不是节点的磁盘(但是,假如内存空间不足,将使用磁盘)。这种技能使得 Spark 集群上的大数据应用步伐在每一轮并行处理中明显优于 MapReduce。我们将在第三章中详细讨论 Spark 数据操作和其他技能,通过相识数据来明白问题
Spark 生态系统

为了提供更多增强和额外的大数据处理能力,Spark 可以配置并在现有基于 Hadoop 的集群上运行。正如已经提到的,只管 Hadoop 提供了Hadoop 分布式文件系统HDFS)以便廉价高效地存储大规模数据;然而,MapReduce 提供的计算完全基于磁盘。MapReduce 的另一个限定是;只能使用高耽误批处理模型实行简单计算,大概更具体地说是静态数据。另一方面,Spark 的核心 API 是用 Java、Scala、Python 和 R 编写的。与 MapReduce 相比,Spark 具有更通用和强盛的编程模型,还提供了几个库,这些库是 Spark 生态系统的一部门,用于大数据分析、处理和机器学习范畴的冗余功能。如图 5所示,Spark 生态系统包罗以下组件:

图 5:Spark 生态系统(停止 Spark 1.6.1)。
正如我们已经提到的,可以无缝地结合这些 API 来开发大规模的机器学习和数据分析应用步伐。此外,可以通过访问 HDFS、Cassandra、HBase、Amazon S3 甚至 RDBMs 等数据存储和源,在各种集群管理器上实行作业,如 Hadoop YARN、Mesos、独立或云端。
然而,Spark 还具有其他功能和 API。例如,近来思科宣布向 Spark 生态系统投资 1.5 亿美元,用于思科 Spark 混合服务(www.cisco.com/c/en/us/solutions/collaboration/cloud-collaboration/index.html)。因此,思科 Spark 开放 API 可以提高其在开发职员中的受接待水平(高度安全的协作和将智能手机系统毗连到云端)。除此之外,Spark 近来集成了 Tachyon(ampcamp.berkeley.edu/5/exercises/tachyon.html),这是一个分布式内存存储系统,可以经济地适应内存,进一步提高 Spark 的性能。
Spark 核心引擎

Spark 本身是用 Scala 编写的,它是一种功能性的面向对象编程语言,运行在 JVM 之上。此外,如图 5 所示,Spark 的生态系统是创建在通用和核心实行引擎之上的,该引擎在差别语言中实现了一些可扩展的 API。较低级别的层或较高级别的层也使用 Spark 核心引擎作为通用实行作业实行引擎,并在其上提供全部其他功能。Spark Core 已经提到是用 Scala 编写的,而且在 Java 虚拟机上运行,高级 API(即 Spark MLlib、SparkR、Spark SQL、Dataset、DataFrame、Spark Streaming 和 GraphX)在实行时使用核心。
Spark 已经使内存计算模式得到了很大的可见度。这个概念(内存计算)使得 Spark 核心引擎可以或许通过通用实行模型来提高速度,从而开发多样化的应用步伐。
用 Java、Scala、R 和 Python 编写的通用数据计算和机器学习算法的低级实现对大数据应用步伐开发非常容易。Spark 框架是基于 Scala 构建的,因此在 Scala 中开发 ML 应用步伐可以访问最新的功能,这些功能最初可能在其他 Spark 语言中不可用。然而,这并不是一个大问题,开源社区也关注全球开发者的需求。因此,假如您须要开发特定的机器学习算法,并盼望将其添加到 Spark 库中,您可以向 Spark 社区做出贡献。Spark 的源代码在 GitHub 上是公开可用的。您可以提交拉取哀求,开源社区将在将其添加到主分支之前检察您的更改或算法。有关更多信息,请查看 Spark Jira confluence 网站。
Python 从前是数据科学家的强盛工具,Python 在 Spark 中的贡献也不例外。这意味着 Python 也有一些优秀的用于数据分析和处理的库;然而,它相对较慢。另一方面,R 具有丰富的情况,用于数据处理、数据预处理、图形分析、机器学习和统计分析,这可以帮助提高开发者的生产力。对于来自 Java 和 Hadoop 背景的开发者来说,Java 绝对是一个不错的选择。然而,Java 也有与 Python 类似的问题,因为 Java 也比 Scala 慢。
近来在 Databricks 网站上发布的一项调查表现,Spark 用户中有 58%使用 Python,71%使用 Scala,31%使用 Java,18%使用 R 来开发他们的 Spark 应用步伐。然而,在本书中,我们将尽量以 Java 为重要示例,须要时会使用少量 Scala 来简化。这是因为许多读者非常熟悉基于 Java 的 MapReduce。然而,我们将在附录中提供一些在 Python 或 R 中使用雷同示例的提示。
Spark SQL

Spark SQL 是用于查询和结构化数据处理的 Spark 组件。需求是显而易见的,因为许多数据科学工程师和商业智能分析师也依赖于交互式 SQL 查询来探索来自 RDBMS 的数据。从前,企业经常使用 MS SQL 服务器、Oracle 和 DB2。然而,这些工具不具备可扩展性或交互性。因此,为了使其更容易,Spark SQL 提供了一个称为 DataFrames 和数据集的编程抽象,它们作为分布式 SQL 查询引擎,支持在现有部署和数据上实行未修改的 Hadoop Hive 查询,速度提高了 100 倍。Spark SQL 与 Spark 生态系统的其他部门强盛地集成在一起。
近来,Spark 提供了一个新的实验性接口,通常称为数据集(将在下一节中详细讨论),它提供了与 RDD 雷同的好处,可以强盛地使用lambda函数。Lambda 源自 Lambda 演算(en.wikipedia.org/wiki/Lambda_calculus),指的是计算机编程中的匿名函数。这是现代编程语言中的一个灵活概念,允许您快速编写任何函数而不给它们定名。此外,它还提供了一种写闭包的好方法。例如,在 Python 中:
  1. def adder(x):
  2.     return lambda y: x + y
  3. add6 = adder(6)
  4. add4(4)
复制代码
它返回结果为10。另一方面,在 Java 中,假如一个整数是奇数还是偶数,可以类似地编写:
  1. Subject<Integer> sub = x -> x % 2 = 0; // Tests if the parameter is even.
  2. boolean result = sub.test(8);
  3. true since 8 is divisible by 2.
复制代码
请注意,在 Spark 2.0.0 中,Spark SQL 在 SQL 2003 支持的底子上大幅改进了 SQL 功能。因此,如今 Spark SQL 可以实行全部 99 个 TPC-DS 查询。更重要的是,如今原生 SQL 解析器支持 ANSI_SQL 和 Hive QL。原生 DDL 是一个可以实行的命令,它如今也支持 SQL 的子查询和规范化支持的视图。
DataFrames 和数据集的同一

在最新的 Spark 2.0.0 版本中,在 Scala 和 Java 中,DataFrame 和数据集已经同一。换句话说,DataFrame 只是行数据集的范例别名。然而,在 Python 和 R 中,由于缺乏范例安全性,DataFrame 是重要的编程接口。对于 Java,不再支持 DataFrame,而只支持基于数据集和 RDD 的计算,DataFrame 已颠末时(请注意,它已颠末时 - 而不是被折旧)。虽然为了向后兼容性保存了 SQLContext 和 HiveContext;然而,在 Spark 2.0.0 版本中,替代 DataFrame 和数据集 API 的新入口点是 SparkSession。
Spark Streaming

您可能盼望您的应用步伐可以或许处理和分析不仅是静态数据集,另有及时流数据。为了使您的愿望更容易实现,Spark Streaming 提供了将应用步伐与流行的批处理和流数据源集成的功能。最常用的数据源包罗 HDFS、Flume、Kafka 和 Twitter,它们可以通过它们的公共 API 使用。这种集成允许用户在流和历史数据上开发强盛的交互式和分析应用步伐。除此之外,容错特性是通过 Spark Streaming 实现的。
图计算 - GraphX

GraphX是创建在 Spark 之上的弹性分布式图计算引擎。GraphX 为盼望以大规模交互方式构建、转换和推理图结构化数据的用户带来了革命。作为开发职员,您将享受到简单性,以便使用少量 Scala、Java 或 Python 代码表示大规模图(交际网络图、普通网络图或天体物理学)。GraphX 使开发职员可以或许充实利用数据并行和图并行系统,通过简单快速地表达图计算。GraphX 柜中增加的另一个美丽之处是,它可以用于构建及时流数据上的端到端图分析管道,其中图空间分区用于处理具有与每个顶点和边相关的属性的大规模有向多图。为了实现这一点,使用了一些基本的图操作符,如子图、joinVertices 和 aggregateMessages,以及 Pregel API 的优化变体。
机器学习和 Spark ML 管道

传统的机器学习应用步伐是使用 R 或 Matlab 构建的,存在可扩展性问题。Spark 引入了两个新兴的 API,Spark MLlib 和 Spark ML。这些 API 使得机器学习成为了工程大数据的可行见解,以消除可扩展性束缚。创建在 Spark 之上,MLlib 是一个可扩展的机器学习库,拥有众多高质量的算法,具有高精度性能,重要实用于 RDD。Spark 为开发职员提供了许多语言选项,包罗 Java、Scala、R 和 Python,以开发完整的工作流程。另一方面,Spark ML 是一个 ALPHA 组件,它增强了一组新的机器学习算法,让数据科学家可以快速组装和配置基于 DataFrames 的实用机器学习管道。
统计计算 - SparkR

SparkR 是一个专为熟悉 R 语言并盼望分析大型数据集并从 R shell 交互式运行作业的数据科学家设计的 R 包,支持全部重要的 Spark DataFrame 操作,如聚合、过滤、分组、摘要统计等。同样,用户还可以从当地 R 数据框或任何 Spark 支持的数据源(如 Hive、HDFS、Parquet 或 JSON)创建 SparkR 数据框。从技能上讲,Spark DataFrame 的概念类似于 R 的本机 DataFrame(cran.r-project.org/web/packages/dplyr/vignettes/data_frames.html),另一方面,在语法上类似于dplyr(一个 R 包,参见cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html),但存储在集群设置中。
Spark 机器学习库

在本节中,我们将描述两个重要的机器学习库(Spark MLib 和 Spark ML)以及最广泛使用的实现算法。终极目标是让您对 Spark 的机器学习宝藏有所相识,因为许多人仍旧以为 Spark 只是一个通用的内存大数据处理或集群计算框架。然而,情况并非如此,相反,这些信息将帮助您相识使用 Spark 机器学习 API 可以做些什么。此外,这些信息将帮助您探索并增加使用 Spark MLlib 和 Spark ML 部署实际机器学习管道的可用性。
使用 Spark 进行机器学习

在 Spark 期间之前,大数据建模者通常使用统计语言(如 R 和 SAS)构建他们的机器学习模型。然后数据工程师通常会重新在 Java 中实现雷同的模型以部署在 Hadoop 上。然而,这种工作流程缺乏服从、可伸缩性、吞吐量和准确性,实行时间也较长。使用 Spark,可以构建、接纳和部署雷同的机器学习模型,使整个工作流程更加高效、稳健和快速,从而提供及时洞察力以提高性能。Spark 机器学习库的重要目标是使实际的机器学习应用可扩展、更快速和更容易。它包罗常见和广泛使用的机器学习算法及其实用工具,包罗分类、回归、聚类、协同过滤和降维。它分为两个包:Spark MLlib(spark.mllib)和 Spark ML(spark.ml)。
Spark MLlib

MLlib 是 Spark 的机器学习库。它是一个分布式的低级库,使用 Scala、Java 和 Python 针对 Spark 核心运行时编写。MLlib 重要关注学习算法及其适当的实用工具,不仅提供机器学习分析能力。重要的学习工具包罗分类、回归、聚类、推荐系统和降维。此外,它另有助于优化用于开发大规模机器学习流水线的通用原语。正如前面所述,MLlib 带有一些令人高兴的 API,使用 Java、Scala、R 和 Python 编写。Spark MLlib 的重要组件将在以下部门中描述。
数据范例

Spark 提供了支持存储在单台机器上的当地向量和矩阵数据范例,以及由一个或多个 RDD 支持的分布式矩阵。当地向量和矩阵是简单的数据模型,用作公共接口。向量和矩阵操作严重依赖于线性代数运算,建议在使用这些数据范例之前先获取一些背景知识。
基本统计

Spark 不仅提供了对 RDD 进行列摘要和基本统计的功能,还支持计算两个或多个数据系列之间的相关性,大概更复杂的相关性操作,例如在许多数据系列之间的成对相关性,这是统计学中的常见操作。然而,如今仅支持 Pearson 和 Spearman 的相关性,未来 Spark 版本将添加更多相关性。与其他统计函数差别,Spark 还支持分层抽样,而且可以在 RDD 的键值对上实行;但是,一些功能尚未添加到 Python 开发职员。
Spark 仅提供 Pearson 卡方查验用于假设查验的拟合优度和声明假设的独立性,这是统计学中的一种强盛技能,用于确定结果是否在统计上显著以满足声明。Spark 还提供了一些在线实现的测试,以支持诸如 A/B 测试之类的用例,通常在及时流数据上实行显著性测试。Spark 的另一个令人高兴的功能是生成随机双重 RDD 或向量 RDD 的工厂方法,这对于随机算法、原型、性能和假设查验非常有用。当前 Spark MLib 中的其他功能提供了从样本 RDD 计算核密度估计的计算功能,这是一种用于可视化经验概率分布的有用技能。
分类和回归

分类是一个典型的过程,它帮助新的数据对象和组件根据练习数据进行构造、区分和明白,大概以某种方式属于某种方式。在统计计算中,存在两种范例的分类,二元分类(也经常被称为二项分类)和多类分类。二元分类是将给定观察的数据对象分类为两组的任务。支持向量机SVMs)、逻辑回归、决议树、随机丛林、梯度提升树和质朴贝叶斯已经实现到 Spark 的最新版本。
多类分类,另一方面,是将给定观察的数据对象分类到两组以上的任务。逻辑回归、决议树、随机丛林和质朴贝叶斯被实现为多类分类。然而,更复杂的分类算法,如多级分类和多类感知器尚未被实现。回归分析也是一种估计变量或观察之间关系的统计过程。除了分类过程,回归分析还涉及多种建模和分析数据对象的技能。如今,Spark MLlib 库支持以下算法:


  • 线性最小二乘
  • 套索
  • 岭回归
  • 决议树
  • 随机丛林
  • 梯度提升树
  • 等渗回归
推荐系统开发

智能和可扩展的推荐系统是一种新兴的应用,如今许多企业正在开发,以扩大他们的业务和本钱,以实现对客户的推荐主动化。协同过滤方法是推荐系统中最广泛使用的算法,旨在补充用户-项目关联矩阵的缺失条目。例如,Netflix 就是一个例子,他们成功地减少了数百万美元的影戏推荐。然而,如今 Spark MLlib 的实现只提供了基于模型的协同过滤技能。
基于模型的协同过滤算法的长处是用户和产品可以通过一小组潜在因向来描述,使用交替最小二乘ALS)算法来预测缺失的条目。缺点是用户评分或反馈不能被考虑在内以预测兴趣。有趣的是,开源开发职员也在努力开发一种基于内存的协同过滤技能,以纳入 Spark MLib 中,其中用户评分数据可以用于计算用户或项目之间的相似性,使得机器学习模型更加多功能。
聚类

聚类是一种无监督的机器学习问题/技能。其目的是根据某种相似性概念将实体的子集彼此分组,通常用于探索性分析和开发分层监督学习管道。Spark MLib 提供了对各种聚类模型的支持,如 K 均值、高斯矩阵、幂迭代聚类PIC)、潜在狄利克雷分配LDA)、二分 K 均值和来自及时流数据的流式 K 均值。我们将在接下来的章节中更多地讨论监督/无监督和强化学习。
降维

处理高维数据既酷又须要满足与大数据相关的复杂性。然而,高维数据的一个问题是不须要的特性或变量。由于全部丈量的变量可能对创建模型并不重要,为了回复感兴趣的问题,您可能须要减少搜刮空间。因此,基于某些考虑或要求,我们须要在创建任何模型之前减少原始数据的维度,而不损害原始结构。
MLib API 的当前实现支持两种降维技能:奇异值分解SVD)和主身分分析PCA),用于存储在面向行的格式中的高瘦矩阵和任何向量。SVD 技能存在一些性能问题;然而,PCA 是降维中最广泛使用的技能。这两种技能在大规模 ML 应用中非常有用,但它们须要对线性代数有很强的背景知识。
特性提取和转换

Spark 提供了差别的技能,通过词频-逆文档频率TF-IDF)、Word2Vec标准缩放器ChiSqSelector等,使特性工程易于使用。假如您正在从事或计划从事文本挖掘范畴的工作,TF-IDF 将是 Spark MLlib 中一个有趣的选项。TF-IDF 提供了一种特性向量化方法,以反映术语对语料库中文档的重要性,这对开发文本分析管道非常有帮助。
此外,您可能对在文本分析的 ML 应用中使用 Word2Vec 计算机分布式词向量表示感兴趣。Word2Vec 的这一特性终极将使您在新颖模式范畴的泛化和模型估计更加健壮。您还可以使用 StandardScaler 来通过基于列摘要统计的单元方差缩放或去除均值来规范提取的特性。在构建可扩展的 ML 应用步伐的预处理步调中通常在练习数据会合实行。假设您已通过这种方法提取了特性,如今您须要选择要纳入 ML 模型的特性。因此,您可能还对 Spark MLlib 的 ChiSqSelector 算法进行特性选择感兴趣。ChiSqSelector 在 ML 模型构建过程中尝试识别相关特性。显然,其目的是减少特性空间的大小以及树状方法中的搜刮空间,并改善强化学习算法中的速度和统计学习行为。
频繁模式挖掘

在开始构建 ML 模型之前,分析大规模数据集通常是挖掘频繁项、最大频繁模式/项集、连续频繁模式或子序列等的第一步。Spark MLib 的当前实现提供了 FP-growth 的并行实现,用于挖掘频繁模式和关联规则。它还提供了另一个流行算法 PrefixSpan 的实现,用于挖掘序列模式。但是,您将须要根据须要定制算法来挖掘最大频繁模式。我们将在即将到来的章节中提供一个可扩展的 ML 应用步伐,用于挖掘隐私并保存最大频繁模式。
Spark ML

Spark ML 是一个 ALPHA 组件,它为用户提供了一组新的机器学习 API,让用户可以快速组装和配置实用的机器学习管道,基于 DataFrames。在赞扬 Spark ML 的特性和优势之前,我们应该相识可以应用和开发到各种数据范例的 DataFrames 机器学习技能,例如向量、非结构化(即原始文本)、图像和结构化数据。为了支持各种数据范例,使应用步伐开发更容易,近来,Spark ML 接纳了来自 Spark SQL 的 DataFrame 和 Dataset。
数据框架或数据集可以从支持基本和结构化范例的对象的 RDD 隐式或显式创建。Spark ML 的目标是提供一组同一的高级 API,构建在数据框架和数据集之上,而不是 RDD。它帮助用户创建和调整实际的机器学习管道。Spark ML 还提供了用于开发可扩展 ML 管道的特性估计器和转换器。Spark ML 系统化了许多 ML 算法和 API,使得更容易将多个算法组合成单个管道或数据工作流,使用数据框架和数据集的概念。
特性工程中的三个基本步调是特性提取、特性转换和选择。Spark ML 提供了几种算法的实现,使这些步调更容易。提取提供了从原始数据中提取特性的功能,而转换提供了从提取步调中找到的特性进行缩放、转换或修改的功能,选择则帮助从第二步的较大特性会合选择子集。Spark ML 还提供了几种分类(逻辑回归、决议树分类器、随机丛林分类器等)、回归(线性回归、决议树回归、随机丛林回归、生存回归和梯度提升树回归)、决议树和树集成(随机丛林和梯度提升树)以及聚类(K 均值和 LDA)算法的实现,用于在数据框架之上开发 ML 管道。我们将在第三章中更多地讨论 RDD 和数据框架及其底子操作,通过相识数据来明白问题
安装和开始使用 Spark

Spark 是 Apache Hadoop 的继任者。因此,最好将 Spark 安装和工作到基于 Linux 的系统中,纵然您也可以尝试在 Windows 和 Mac OS 上。还可以配置 Eclipse 情况以将 Spark 作为 Maven 项目在任何操作系统上运行,并将应用步伐作为具有全部依赖项的 jar 文件捆绑。其次,您可以尝试从 Spark shell(更具体地说是 Scala shell)运行应用步伐,遵循与 SQL 或 R 编程雷同的方式:
第三种方法是从命令行(Windows)/终端(Linux/Mac OS)开始。起首,您须要使用 Scala 或 Java 编写您的 ML 应用步伐,并预备具有所需依赖项的 jar 文件。然后,可以将 jar 文件提交到集群以计算 Spark 作业。
我们将展示怎样以三种方式开发和部署 Spark ML 应用步伐。但是,第一个条件是预备好您的 Spark 应用步伐开发情况。您可以在许多操作系统上安装和配置 Spark,包罗:


  • Windows(XP/7/8/10)
  • Mac OS X(10.4.7+)
  • Linux 发行版(包罗 Debian、Ubuntu、Fedora、RHEL、CentOS 等)
注意

请查看 Spark 网站spark.apache.org/documentation.html获取与 Spark 版本和操作系统相关的文档。以下步调向您展示如安在 Ubuntu 14.04(64 位)上安装和配置 Spark。请注意,Spark 2.0.0 运行在 Java 7+、Python 2.6+/3.4+和 R 3.1+上。对于 Scala API,Spark 2.0.0 使用 Scala 2.11。因此,您须要使用兼容的 Scala 版本(2.11.x)。
步调 1:Java 安装
在安装 Spark 时,应将 Java 安装视为安装的强制要求之一,因为基于 Java 和 Scala 的 API 须要在系统上安装 Java 虚拟机。尝试以下命令验证 Java 版本:
  1. $ java -version
复制代码
假如 Java 已经安装在您的系统上,您应该看到以下消息:
  1. java version "1.7.0_80"
  2. Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
  3. Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
复制代码
假如您的系统上没有安装 Java,请确保在进行下一步之前安装 Java。请注意,为了使用 lambda 表达式支持,建议在系统上安装 Java 8,最好同时安装 JDK 和 JRE。只管对于 Spark 1.6.2 和之前的版本,Java 7 应该充足:
  1. $ sudo apt-add-repository ppa:webupd8team/java
  2. $ sudo apt-get update
  3. $ sudo apt-get install oracle-java8-installer
复制代码
安装后,请不要忘记设置JAVA_HOME。只需应用以下命令(我们假设 Java 安装在/usr/lib/jvm/java-8-oracle):
  1. $ echo "export JAVA_HOME=/usr/lib/jvm/java-8-oracle" >> ~/.bashrc
  2. $ echo "export PATH=$PATH:$JAVA_HOME/bin" >> ~/.bashrc
复制代码
您可以在主目录中的.bashrc文件中手动添加这些情况变量。假如找不到文件,可能是隐蔽的,因此须要进行探索。只需转到视图选项卡并启用表现隐蔽文件
步调 2:安装 Scala
Spark 本身是用 Scala 编写的,因此您的系统上应该安装了 Scala。通过使用以下命令查抄这一点非常简单:
  1. $ scala -version
复制代码
假如 Scala 已经安装在您的系统上,您应该在终端上收到以下消息:
  1. Scala code runner version 2.11.8 -- Copyright 2002-2016, LAMP/EPFL
复制代码
请注意,在编写此安装过程时,我们使用的是最新版本的 Scala,即 2.11.8。假如您的系统上没有安装 Scala,请确保安装 Scala,因此在进行下一步之前,您可以从 Scala 网站www.scala-lang.org/download/下载最新版本的 Scala。下载完成后,您应该在下载文件夹中找到 Scala tar文件:

  • 通过从其位置提取 Scala tar文件来提取,大概在终端中键入以下命令来提取 Scala tar 文件:
  1. $ tar -xvzf scala-2.11.8.tgz
复制代码

  • 如今将 Scala 分发移动到用户的透视图(例如,/usr/local/scala)通过以下命令或手动实行:
  1. $ cd /home/Downloads/
  2. $ mv scala-2.11.8 /usr/local/scala
复制代码

  • 设置 Scala 主目录:
  1. $ echo "export SCALA_HOME=/usr/local/scala/scala-2.11.8" >>
  2.         ~/.bashrc
  3. $ echo "export PATH=$PATH:$SCALA_HOME/bin" >> ~/.bashrc
复制代码

  • 安装完成后,您应该使用以下命令进行验证:
  1. $ scala -version
复制代码

  • 假如 Scala 已成功配置到您的系统上,您应该在终端上收到以下消息:
  1. Scala code runner version 2.11.8 -- Copyright 2002-2016, LAMP/EPFL
复制代码
步调 3:安装 Spark
从 Apace Spark 网站spark.apache.org/downloads.html下载最新版本的 Spark。对于此安装步调,我们使用了最新的 Spark 稳定版本 2.0.0 版本,预先构建为 Hadoop 2.7 及更高版本。下载完成后,您将在下载文件夹中找到 Spark tar文件:

  • 从其位置提取 Scala tar文件,大概在终端中键入以下命令来提取 Scala tar文件:
  1. $ tar -xvzf spark-2.0.0-bin-hadoop2.7.tgz
复制代码

  • 如今将 Scala 分发移动到用户的透视图(例如,/usr/local/spark)通过以下命令或手动实行:
  1. $ cd /home/Downloads/
  2. $ mv spark-2.0.0-bin-hadoop2.7 /usr/local/spark
复制代码

  • 安装完 Spark 后,只需应用以下命令:
  1. $ echo "export SPARK_HOME=/usr/local/spark/spark-2.0.0-bin-hadoop2.7" >>
  2.       ~/.bashrc
  3. $ echo "export PATH=$PATH:$SPARK_HOME/bin" >> ~/.bashrc
复制代码
步调 4:使全部更改永世生效
使用以下命令对~/.bashrc文件进行源操作,以使更改永世生效:
  1. $ source ~/.bashrc
复制代码
假如实行$ vi ~/. bashrc命令,您将在bashrc文件中看到以下条目如下:
  1. export JAVA_HOME=/usr/lib/jvm/java-8-oracle
  2. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin: /usr/lib/jvm/java-8-oracle/bin
  3. export SCALA_HOME=/usr/local/scala/scala-2.11.8
  4. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin: /bin
  5. export SPARK_HOME=/usr/local/spark/spark-2.0.0-bin-hadoop2.7
  6. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin: /bin
复制代码
步调 5:验证 Spark 安装
Spark 安装的验证表现在以下截图中:

图 6:Spark shell 确认了成功安装 Spark。
写以下命令以打开 Spark shell,以验证 Spark 是否已成功配置:
  1. $ spark-shell
复制代码
假如 Spark 安装成功,您应该看到以下消息(图 6)。
Spark 服务器将在本田主机的端口4040上启动,更确切地说是在http://localhost:4040/(图 7)。只需转到那边,以确保它是否真的在运行:

图 7:Spark 作为当地 Web 服务器运行。
干得好!如今您已经预备幸亏 Spark shell 上开始编写 Scala 代码。
使用依赖项打包您的应用步伐

如今我们将向您展示如安在 Eclipse 大将应用步伐打包为带有全部必需依赖项的 Java 存档(JAR)文件,这是一个集成开发情况IDE)和一个用于 Java 开发的开源工具,是 Apache Maven 项目(maven.apache.org/)。Maven 是一个软件项目管理和明白工具,就像 Eclipse 一样。基于项目对象模型POM)的概念,Maven 可以管理项目的构建、报告和文档体例,从一个中央信息中。
请注意,可以使用命令提示符将用 Java 或 Scala 编写的 ML 应用步伐导出为存档/可实行的 jar 文件。但是,为了简化和加快应用步伐开发,我们将使用与 Eclipse 雷同的 Maven 项目,以便读者可以享受雷同的便利性将应用步伐提交到主节点进行计算。如今让我们转到讨论怎样将频繁模式挖掘应用步伐导出为带有全部依赖项的 jar 文件。
步调 1:在 Eclipse 中创建一个 Maven 项目
成功创建示例 Maven 项目后,您将在 Eclipse 中看到以下项目结构,如图 8所示:

图 8:Eclipse 中的 Maven 项目结构。
步调 2:应用步伐开发
创建一个 Java 类,并将以下源代码复制到src/main/java目录下,用于挖掘频繁模式。在这里,输入文件名已经通过命令行参数或手动指定源代码来指定文件名字符串。如今,我们只提供了行注释,但是您将从第三章中相识详细信息,通过相识数据来相识问题以及之后的内容:
  1. import java.util.Arrays;
  2. import java.util.List;
  3. import org.apache.spark.api.java.JavaRDD;
  4. import org.apache.spark.api.java.function.Function;
  5. import org.apache.spark.mllib.fpm.FPGrowth;
  6. import org.apache.spark.mllib.fpm.FPGrowthModel;
  7. import org.apache.spark.rdd.RDD;
  8. import org.apache.spark.sql.SparkSession;
  9. public class JavaFPGrowthExample {
  10.   public static void main(String[] args) {
  11.    //Specify the input transactional as command line argument  
  12.    String fileName = "input/input.txt";  
  13.    //Configure a SparkSession as spark by specifying the application name, master URL, Spark config, and Spark warehouse directory
  14.   SparkSession spark = SparkSession
  15.                   .builder()
  16.                   .appName("JavaFPGrowthExample")
  17.                   .master("local[*]")
  18.                   .config("spark.sql.warehouse.dir", "E:/Exp/")
  19.                   .getOrCreate();
  20.    //Create an initial RDD by reading the input database  
  21.    RDD<String> data = spark.sparkContext().textFile(fileName, 1);
  22.    //Read the transactions by tab delimiter & mapping RDD(data)
  23.    JavaRDD<List<String>> transactions = data.toJavaRDD().map(
  24.                    new Function<String, List<String>>(){
  25.                    public List<String> call(String line) {
  26.                           String[] parts = line.split(" ");
  27.                           return Arrays.asList(parts);
  28.                                  }
  29.                              });
  30.   //Create FPGrowth object by min. support & no. of partition     
  31.   FPGrowth fpg = new  FPGrowth()
  32.                        .setMinSupport(0.2)
  33.                        .setNumPartitions(10);
  34.   //Train and run your FPGrowth model using the transactions
  35.   FPGrowthModel<String> model = fpg.run(transactions);
  36.   //Convert and then collect frequent patterns as Java RDD. After that print the frequent patterns along with their support
  37.     for (FPGrowth.FreqItemset<String> itemset :      
  38.           model.freqItemsets().toJavaRDD().collect()) {   
  39.        System.out.println(itemset.javaItems()  
  40.                              + "==> " + itemset.freq());
  41.       }
  42.     }   
  43.   }  
复制代码
步调 3:Maven 配置
如今您须要配置 Maven,指定相关依赖项和配置。起首,编辑您现有的pom.xml文件,将每个 XML 源代码片段复制到<dependencies>标记内。请注意,根据 Spark 版本,您的依赖项可能会有所差别,因此请相应更改版本:

  • Spark 核心依赖项用于 Spark 上下文和配置:
  1.       <dependency>
  2.       <groupId>org.apache.spark</groupId>
  3.       <artifactId>spark-core_2.11</artifactId>
  4.       <version>2.0.0</version>
  5.      </dependency>
复制代码

  • Spark MLib 依赖项用于 FPGrowth:
  1.     <dependency>
  2.       <groupId>org.apache.spark</groupId>
  3.       <artifactId>spark-mllib_2.11</artifactId>
  4.       <version>2.0.0</version>
  5.      </dependency>
复制代码
如今您须要添加构建要求。将以下代码片段立即复制到</dependencies>标记之后。在这里,我们将<groupId>指定为 maven 插件,<artifactId>指定为 maven shade 插件,并使用<finalName>标记指定 jar 文件定名约定。确保您已经指定了源代码下载插件,设置了编译器级别,并为 Maven 设置了装配插件,如下所述:

  • 使用 Maven 指定源代码下载插件:
  1.        <plugin>
  2.         <groupId>org.apache.maven.plugins</groupId>
  3.         <artifactId>maven-eclipse-plugin</artifactId>
  4.         <version>2.9</version>
  5.         <configuration>
  6.           <downloadSources>true</downloadSources>
  7.           <downloadJavadocs>false</downloadJavadocs>
  8.         </configuration>
  9.       </plugin>  
复制代码

  • 为 Maven 设置编译器级别:
  1.       <plugin>
  2.         <groupId>org.apache.maven.plugins</groupId>
  3.         <artifactId>maven-compiler-plugin</artifactId>
  4.         <version>2.3.2</version>         
  5.       </plugin>
  6.       <plugin>
  7.         <groupId>org.apache.maven.plugins</groupId>
  8.         <artifactId>maven-shade-plugin</artifactId>
  9.         <configuration>
  10.           <shadeTestJar>true</shadeTestJar>
  11.         </configuration>
  12.       </plugin>
复制代码

  • 设置 Maven 装配插件:
  1.       <plugin>
  2.         <groupId>org.apache.maven.plugins</groupId>
  3.         <artifactId>maven-assembly-plugin</artifactId>
  4.         <version>2.4.1</version>
  5.         <configuration>
  6.           <!-- get all project dependencies -->
  7.           <descriptorRefs>
  8.             <descriptorRef>jar-with-dependencies</descriptorRef>
  9.           </descriptorRefs>
  10.           <!-- MainClass in mainfest make a executable jar -->
  11.           <archive>
  12.             <manifest>              <mainClass>com.example.SparkFPGrowth.JavaFPGrowthExample</mainClass>            </manifest>
  13.           </archive>
  14.           <property>
  15.             <name>oozie.launcher.mapreduce.job.user.classpath.first</name>
  16.             <value>true</value>
  17.           </property>
  18.           <finalName>FPGrowth-${project.version}</finalName>
  19.         </configuration>
  20.         <executions>
  21.           <execution>
  22.             <id>make-assembly</id>
  23.             <!-- bind to the packaging phase -->
  24.             <phase>package</phase>
  25.             <goals>
  26.               <goal>single</goal>
  27.             </goals>
  28.           </execution>
  29.         </executions>
  30.       </plugin>
复制代码
完整的pom.xml文件,输入数据和 Java 源文件可以从我们的 GitHub 存储库github.com/rezacsedu/PacktMLwithSpark下载。请注意,我们使用了 Eclipse Mars Eclipse IDE for Java Developers,而且版本是 Mars Release (4.5.0)。您可以选择这个版本或其他发行版,比如 Eclipse Luna。
步调 4:Maven 构建
在本节中,我们将描述如安在 Eclipse 上创建一个 Maven 友好的项目。在您按照全部步调后,您将可以或许成功运行 Maven 项目。步调应按照以下时间次序进行:

  • 将您的项目作为 Maven 安装运行。
  • 假如您的代码和 Maven 配置文件没有问题,那么 Maven 构建将成功。
  • 构建 Maven 项目。
  • 右键单击您的项目,运行 Maven 项目为Maven 构建…,并在Goals选项中写入clean package。
  • 查抄 Maven 依赖项。
  • 睁开 Maven 依赖树,并查抄是否已安装所需的 jar 文件。
  • 查抄 jar 文件是否生成了依赖项。
  • 如我们所指定的,您应该在/target目录树下找到两个 jar 文件(参考图 9)。打包文件应该与<finalName>标签中指定的名称完全雷同。如今将您的代码(jar 文件)移动到与我们的实验对齐的目录(即/user/local/code)和您的数据(即/usr/local/data/)。我们将在后期使用这个 jar 文件在 AWS EC2 集群上实行 Spark 作业。我们将在下一步讨论输入数据集。

图 9:在 Eclipse 上生成了全部必需依赖项的 Maven 项目的 jar。
运行一个样本机器学习应用步伐

在本节中,我们将描述怎样从 Spark shell 在当地机器上以独立模式运行一个样本机器学习应用步伐,末了我们将向您展示怎样使用 Amazon EC2(aws.amazon.com/ec2/)部署和运行应用步伐。
从 Spark shell 运行 Spark 应用步伐

请注意,这只是一个查抄安装和运行样本代码的练习。有关机器学习应用步伐开发的详细信息将从第三章开始,通过相识数据来明白问题,到第九章使用流和图数据进行高级机器学习
如今我们将进一步进行一种流行的机器学习问题,也称为频繁模式挖掘,使用频繁模式增长或 FP-growth。假设我们有一个如下表所示的交易数据库。每行表示特定客户完成的交易。我们的目标是从数据库中找到频繁模式,这是计算关联规则(en.wikipedia.org/wiki/Association_rule_learning)的先决条件,从客户购买规则中。将此数据库保存为input.txt,不包罗交易 ID,在/usr/local/data目录中:
交易 ID交易12345678910A B C D FA B C EB C D E FA C D EC D FD E FD EC D FC FA C D E 表 1:交易数据库。
如今让我们通过指定主机和要使用的计算核心数目来移动到 Spark shell,作为独立模式(这里有四个核心,例如):
  1. $ spark-shell
  2. --master "local[4]"
复制代码
第 1 步:加载软件包
加载所需的 FPGrowth 软件包和其他依赖软件包:
  1. scala>import org.apache.spark.mllib.fpm.FPGrowth
  2. scala>import org.apache.spark.{SparkConf, SparkContext}
复制代码
第 2 步:创建 Spark 上下文
要创建一个 Spark 上下文,起首须要通过提及应用步伐名称和主 URL 来配置 Spark 会话。然后,您可以使用 Spark 配置实例变量来创建一个 Spark 上下文,如下所示:
  1. val conf = new SparkConf().setAppName(s"FPGrowthExample with $params")
  2. val sc = new SparkContext(conf)
复制代码
第 3 步:读取交易
让我们在创建的 Spark 上下文(sc)大将交易作为 RDDs 读取(参见图 6):
  1. scala> val transactions = sc.textFile(params.input).map(_.split(" ")).cache()
复制代码
第 4 步:查抄交易数目
这是用于查抄交易数目的代码:
  1. Scala>println(s"Number of transactions: ${transactions.count()}")
  2. Number of transactions: 22
  3. Scala>
复制代码
第 5 步:创建 FPGrowth 模型
通过指定最小支持阈值(也请参阅en.wikipedia.org/wiki/Association_rule_learning)和分区数来创建模型:
  1. scala>val model = new FPGrowth()
  2. .setMinSupport(0.2)
  3. .setNumPartitions(2)
  4. .run(transactions)
复制代码
第 6 步:查抄频繁模式的数目
以下代码解释了怎样查抄频繁模式的数目:
  1. scala> println(s"Number of frequent itemsets:
  2.     ${model.freqItemsets.count()}")
  3. Number of frequent itemsets: 18
  4. Scala>
复制代码
第 7 步:打印模式和支持
打印频繁模式及其相应的支持/频率计数(参见图 10)。Spark 作业将在本田主机上运行(参见图 11):
  1. scala> model.freqItemsets.collect().foreach { itemset => println(itemset.items.mkString("[", ",", "]") + ", " + itemset.freq)}
复制代码

图 10:频繁模式。
在当地集群上运行 Spark 应用步伐

一旦用户应用步伐被打包为 jar 文件(用 Scala 或 Java 编写)或 Python 文件,它可以使用 Spark 分发中 bin 目录下的spark-submit脚本启动。
根据 Spark 网站提供的 API 文档spark.apache.org/docs/2.0.0-preview/submitting-applications.html,此脚本负责设置带有 Spark 及其依赖项的类路径,而且可以支持 Spark 支持的差别集群管理器和部署模型。简而言之,Spark 作业提交语法如下:
  1. $spark-submit [options] <app-jar | python-file> [app arguments]
复制代码
在这里,[options]可以是:--class <main-class>``--master <master-url>``--deploy-mode <deploy-mode>,以及许多其他选项。
更具体地说,<main-class>是主类名称,是我们应用步伐的入口点。<master-url>指定了集群的主 URL(例如,spark://HOSTORT用于毗连给定的 Spark 独立集群主节点,local 用于在当地运行具有没有并行性的一个工作线程的 Spark,local [k]用于在具有 K 个工作线程的当地运行 Spark 作业,这是您计算机上的核心数,local
  • 用于在具有与计算机上逻辑核心一样多的工作线程的当地运行 Spark 作业,mesos://IPORT用于毗连到可用的 Mesos 集群,甚至您可以将作业提交到 Yarn 集群-有关更多信息,请参见spark.apache.org/docs/latest/submitting-applications.html#master-urls)。
    <deploy-mode>用于在工作节点(集群)上部署我们的驱动步伐,大概作为外部客户端(client)在当地部署。<app-jar>是我们刚刚构建的 jar 文件,包罗全部依赖项。<python-file>是使用 Python 编写的应用步伐重要源代码。[app-arguments]可以是应用步伐开发职员指定的输入或输出参数:

    图 11:在本田主机上运行的 Spark 作业
    因此,对于我们的情况,作业提交语法将如下所示:
    1. $./bin/spark-submit --class com.example.SparkFPGrowth.JavaFPGrowthExample --master local[4] FPGrowth-0.0.1-SNAPSHOT-jar-with-dependencies.jar input.txt
    复制代码
    在这里,JavaFPGrowthExample是用 Java 编写的主类文件;local 是主 URL;FPGrowth-0.0.1-SNAPSHOT-jar-with-dependencies.jar是我们刚刚通过 maven 项目生成的应用步伐jar文件;input.txt是作为文本文件的事件数据库,output 是要生成输出的目录(在我们的情况下,输出将表现在控制台上)。如今让我们提交此作业以在当地实行。
    假如成功实行,您将找到以下消息,包罗图 12中的输出(摘要):

    图 12:终端上的 Spark 作业输出。
    在 EC2 集群上运行 Spark 应用步伐

    在前一节中,我们说明了如安在当地或独立模式下提交 spark 作业。在这里,我们将描述如安在集群模式下运行 spark 应用步伐。为了使我们的应用步伐在 spark 集群模式下运行,我们考虑亚马逊弹性计算云EC2)服务,作为底子设施即服务IaaS)或平台即服务PaaS)。有关订价和相关信息,请参阅此网址aws.amazon.com/ec2/pricing/。
    步调 1:密钥对和访问密钥配置
    我们假设您已经创建了 EC2 帐户。第一个要求是创建 EC2 密钥对和 AWS 访问密钥。EC2 密钥对是您在通过 SSH 进行安全毗连到 EC2 服务器或实例时须要的私钥。要创建密钥,您必须通过 AWS 控制台 docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#having-ec2-create-your-key-pair。请参考图 13,表现了 EC2 帐户的密钥对创建页面:

    图 13:AWS 密钥对生成窗口。
    一旦下载并保存在当地机器上,请将其定名为my-key-pair.pem。然后通过实行以下命令确保权限(出于安全目的,您应该将此文件存储在安全位置,比如/usr/local/key):
    1. $ sudo chmod  400  /usr/local/key/my-key-pair.pem
    复制代码
    如今您须要的是 AWS 访问密钥,您的帐户凭据,假如您想要使用 spark-ec2 脚本从当地机器提交您的 Spark 作业到计算节点。要生成和下载密钥,请登录到您的 AWS IAM 服务 docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey。下载完成后(即/usr/local/key),您须要在当地机器上设置两个情况变量。只需实行以下命令:
    1. $ echo "export AWS_ACCESS_KEY_ID=<access_key_id>" >> ~/.bashrc
    2. $ echo " export AWS_SECRET_ACCESS_KEY=<secret_access_key_id>" >> ~/.bashrc
    复制代码
    步调 2:在 EC2 上配置 Spark 集群
    Spark 分发(即/usr/local/spark``/ec2)提供了一个名为spark-ec2的脚本,用于从当地机器(驱动步伐)在 EC2 实例上启动 Spark 集群,帮助启动、管理和关闭 Spark 集群。
    注意

    请注意,在 AWS 上启动集群将耗费款项。因此,当计算完成时,克制或销毁集群始终是一个好习惯。否则,将产生额外的费用。有关 AWS 订价的更多信息,请参阅此 URL aws.amazon.com/ec2/pricing/。
    一旦您实行以下命令启动新实例,它将主动在集群上设置 Spark、HDFS 和其他依赖项:
    1. $./spark-ec2 --key-pair=<name_of_the_key_pair> --identity-file=<path_of_the key_pair>  --instance-type=<AWS_instance_type > --region=<region> zone=<zone> --slaves=<number_of_slaves> --hadoop-major-version=<Hadoop_version> --spark-version=<spark_version> launch <cluster-name>
    复制代码
    我们相信这些参数是不言自明的,大概,也可以在spark.apache.org/docs/latest/ec2-scripts.html上查看详细信息。对于我们的情况,应该是这样的:
    1. $./spark-ec2 --key-pair=my-key-pair --identity-file=/usr/local/key/my-key-pair.pem  --instance-type=m3.2xlarge --region=eu-west-1 --zone=eu-west-1a --slaves=2 --hadoop-major-version=yarn --spark-version=1.6.0 launch ec2-spark-cluster-1
    复制代码
    如下截图所示:

    图 14:集群主页。
    成功完成后,spark 集群将在您的 EC2 帐户上实例化两个工作(附属)节点。这个任务可能须要大约半个小时,具体取决于您的互联网速度和硬件配置。因此,您可能须要喝杯咖啡休息一下。在集群设置成功完成后,您将在终端上得到 Spark 集群的 URL。
    要查抄集群是否真的在运行,请在浏览器上查抄此 URL https://<master-hostname>:8080,其中主机名是您在终端上收到的 URL。假如一切正常,您将发现您的集群正在运行,参见图 14中的集群主页。
    步调 3:在 Spark 集群上运行和部署 Spark 作业
    实行以下命令毗连到 SSH 远程 Spark 集群:
    1. $./spark-ec2 --key-pair=<name_of_the_key_pair> --identity-file=<path_of_the _key_pair> --region=<region> login <cluster-name>
    复制代码
    对于我们的情况,应该是这样的:
    1. $./spark-ec2 --key-pair=my-key-pair --identity-file=/usr/local/key/my-key-pair.pem --region=eu-west-1 login ec2-spark-cluster-1
    复制代码
    如今通过实行以下命令将您的应用步伐(我们在 Eclipse 上生成的 Maven 项目的 jar 包)复制到远程实例(在我们的情况下是ec2-52-48-119-121.eu-west-1.compute.amazonaws.com)(在新终端中):
    1. $ scp -i /usr/local/key/my-key-pair.pem  /usr/local/code/FPGrowth-0.0.1-SNAPSHOT-jar-with-dependencies.jar ec2-user@ec2-52-18-252-59.eu-west-1.compute.amazonaws.com:/home/ec2-user/
    复制代码
    然后,您须要通过实行以下命令将您的数据(在我们的情况下是/usr/local/data/input.txt)复制到同一远程实例:
    1. $ scp -i /usr/local/key/my-key-pair.pem /usr/local/data/input.txt ec2-user@ec2-52-18-252-59.eu-west-1.compute.amazonaws.com:/home/ec2-user/
    复制代码

    图 15:Spark 集群中作业运行状态。
    干得好!您已经快完成了!如今,末了您须要提交您的 Spark 作业,让从节点或工作节点进行计算。要这样做,只需实行以下命令:
    1. $./bin/spark-submit --class com.example.SparkFPGrowth.JavaFPGrowthExample --master spark://ec2-52-48-119-121.eu-west-1.compute.amazonaws.com:7077 /home/ec2-user/FPGrowth-0.0.1-SNAPSHOT-jar-with-dependencies.jar /home/ec2-user/input.txt
    复制代码
    作业计算成功完成后,您应该在端口 8080 上看到作业的状态,就像图 15一样(输出将表现在终端上)。
    第四步:暂停和重新启动 Spark 集群
    要克制您的集群,请从当地机器实行以下命令:
    1. $./ec2/spark-ec2 --region=<ec2-region> stop <cluster-name>
    复制代码
    对于我们的情况,将会是:
    1. $./ec2/spark-ec2 --region=eu-west-1 stop ec2-spark-cluster-1
    复制代码
    要稍后重新启动集群,请实行以下命令:
    1. $./ec2/spark-ec2 -i <key-file> --region=<ec2-region> start <cluster-name>
    复制代码
    对于我们的情况,将会是以下内容:
    1. $./ec2/spark-ec2 --identity-file=/usr/local/key/my-key-pair.pem --region=eu-west-1 start ec2-spark-cluster-1
    复制代码
    提示

    要停止您的 Spark 集群:$./spark-ec2 destroy <cluster-name>
    在我们的情况下,将是:$./spark-ec2 --region=eu-west-1 destroy ec2-spark-cluster-1
    假如您盼望您的应用步伐针对大规模数据集进行扩展,最快的方法是将它们从 Amazon S3 或 Amazon EBS 设备加载到节点上的 Hadoop 分布式文件系统(HDFS)中。我们将在后面的章节中通过实际的机器学习示例讨论这种技能。
    参考文献



    • 弹性分布式数据集内存集群计算的容错抽象Zaharia,Mosharaf Chowdhury,Tathagata Das,Ankur Dave,Justin Ma,Murphy McCauley,Michael J. Franklin,Scott Shenker,Ion Stoica。NSDI 2012。2012 年 4 月。
    • Spark使用工作集进行集群计算Matei Zaharia,Mosharaf Chowdhury,Michael J. Franklin,Scott Shenker,Ion Stoica,HotCloud 2010。2010 年 6 月。
    • Spark SQLSpark 中的关系数据处理Michael Armbrust,Reynold S. Xin,Cheng Lian,Yin Huai,Davies Liu,Joseph K. Bradley,Xiangrui Meng,Tomer Kaftan,Michael J. Franklin,Ali Ghodsi,Matei Zaharia,SIGMOD 2015。2015 年 6 月。
    • 离散化流规模化的容错流计算Matei Zaharia,Tathagata Das,Haoyuan Li,Timothy Hunter,Scott Shenker,Ion Stoica。SOSP 2013。2013 年 11 月。
    • 离散化流大规模集群上流处理的高效容错模型Matei Zaharia,Tathagata Das,Haoyuan Li,Scott Shenker,Ion Stoica。HotCloud 2012。2012 年 6 月。
    • GraphX同一数据并行和图并行分析Reynold S. Xin,Daniel Crankshaw,Ankur Dave,Joseph E. Gonzalez,Michael J. FranklinIon Stoica。OSDI 2014。2014 年 10 月。
    • MLlibApache Spark 中的机器学习Meng 等人。*arXiv:1505.06807v1,[cs.LG],2015 年 5 月 26 日。
    • 推荐系统协同过滤技能分析Christopher R. Aberger斯坦福出书物,2014 年
    总结

    这竣事了我们对 Spark 的相称快速的介绍。我们已经尝试涵盖了 Spark 的一些最基本的特性,它的计算范式,并通过安装和配置开始使用 Spark。假如 Spark ML 适合机器学习流水线概念(例如特性提取、转换和选择),则建议使用它,因为它在 DataFrame 和 Dataset 方面更加灵活多变。然而,根据 Apache 的文档,他们将继续支持和贡献 Spark MLib,并与 Spark ML 的积极开发一起。
    另一方面,数据科学开发职员应该熟悉使用 Spark MLlib 的特性,并等待将来有更多的特性。然而,一些算法如今尚不可用,大概有待添加到 Spark ML 中,尤其是降维。只管如此,开发职员可以无缝地将这些在 Spark MLib 中找到的技能实现与 Spark ML 中找到的其他算法结合起来,作为混合或可互操作的机器学习应用。我们还展示了一些在集群和云服务上部署机器学习应用的基本技能,只管您也可以尝试其他可用的部署选项。
    提示

    有关更多更新,请感兴趣的读者参考 Spark 网站spark.apache.org/docs/latest/mllib-guide.html获取发布日期、API 和规范。由于 Spark 的开源社区和来自全球各地的开发职员不断丰富和更新实现,因此最好保持更新。
    在下一章(第二章,机器学习最佳实践),我们将讨论在使用 Spark 开发高级机器学习时的一些最佳实践,包罗机器学习任务和类、一些实际的机器学习问题及其相关讨论、机器学习应用开发中的一些最佳实践、选择适合 ML 应用的精确算法等。
    第二章:机器学习最佳实践

    本章的目的是为那些在典型的统计培训中可能不会接触到这些方法的人提供统计机器学习(ML)技能的概念介绍。本章还旨在通过几个步调,将新手从对机器学习的最小知识带到相识的实践者。本章的第二部门偏重于根据应用范例和要求选择合适的机器学习算法的一些建议。然后,它将引导人们在应用大规模机器学习流程时遵循一些最佳实践。简而言之,本章将讨论以下主题:


    • 什么是机器学习?
    • 机器学习任务
    • 实际机器学习问题
    • Spark 中的大规模机器学习 API
    • 实际机器学习最佳实践
    • 为您的应用选择合适的算法
    什么是机器学习?

    在本节中,我们将尝试从计算机科学、统计学和数据分析的角度界说机器学习这个术语。然后我们将展示分析机器学习应用的步调。末了,我们将讨论一些典型和新兴的机器学习任务,并枚举一些须要办理的实际机器学习问题。
    现代文献中的机器学习

    让我们看看机器学习著名教授 Tom Mitchell 是怎样界说机器学习这个术语的。他是 CMU 机器学习系主任,也是卡内基梅隆大学的教授。在他的文献中(Tom M. Mitchell, The Discipline of Machine Learning, CMU-ML-06-108, July 2006,www.cs.cmu.edu/~tom/pubs/MachineLearning.pdf)中界说了机器学习这个术语:
       机器学习是计算机科学和统计学交织的自然产物。我们可以说,计算机科学的界说性问题是“我们怎样构建办理问题的机器,哪些问题本质上是可解的/不可解的?”统计学的界说性问题重要是“在数据加上一组建模假设的情况下,可以推断出什么,以及推断的可靠性是什么?”机器学习的界说性问题创建在这两者之上,但它是一个独特的问题。计算机科学重要关注怎样手动编程计算机,而机器学习关注的是怎样让计算机本身编程(从经验中加上一些初始结构)。统计学重要关注从数据中可以推断出什么结论,而机器学习还包罗关于怎样最有效地捕获、存储、索引、检索和合并这些数据的计算架构和算法,以及如安在更大的系统中和谐多个学习子任务,以及计算可解性的问题。
      我们相信 Tom 教授的这个界说是不言自明的。然而,我们将在接下来的两个小节中从计算机科学、统计学和数据分析的角度提供对机器学习的更清楚的明白。
    提示

    感兴趣的读者应该查阅其他资源,以获取有关机器学习及其理论视角的更多见解。在这里,我们提供了一些链接如下:机器学习:en.wikipedia.org/wiki/Machine_learning。
    机器学习:它是什么,为什么重要 - www.sas.com/en_us/insights/analytics/machine-learning.html。
    机器学习的初步介绍:www.youtube.com/watch?v=NOm1zA_Cats。
    什么是机器学习,它是怎样工作的:www.youtube.com/watch?v=elojMnjn4kk。
    使用机器学习进行数据分析入门:www.youtube.com/watch?v=U4IYsLgNgoY。
    机器学习和计算机科学

    机器学习是计算机科学的一个分支,研究可以从开导式学习中学习的算法,这通常源自于模式识别和人工智能中的计算学习理论。艾伦·图灵脑海中出现了一个有趣的问题,即机器能思考吗?实际上,有一些很好的来由相信一个充足复杂的机器有一天可以通过无限定的图灵测试;让我们推迟这个问题,直到图灵测试通过。然而,机器至少可以学习。随后,阿瑟·塞缪尔是第一个在 1959 年将术语机器学习界说为一种研究范畴,使计算性可以或许在没有明确编程的情况放学习的人。典型的机器学习任务包罗概念学习、预测建模、分类、回归、聚类、降维、推荐系统、深度学习以及从大规模数据会合找到有用模式。
    终极目标是通过改进学习方式使其变得主动化,以至于不再须要人类干预,大概尽可能减少人类干预的水平。只管机器学习偶然与知识发现和数据挖掘KDDM)混淆,但后者更专注于探索性数据分析,被称为无监督学习 - 例如聚类分析、异常检测、人工神经网络ANN)等。
    其他机器学习技能包罗监督学习,其中学习算法分析练习数据并生成可用于映射新示例进行预测的推断函数。分类和回归分析是监督学习的两个典型示例。另一方面,强化学习受行为主义心理学(参见en.wikipedia.org/wiki/Behaviorism)的开导,通常关注软件署理怎样通过最大化嘉奖函数在新的情况中实办法作。动态规划和智能署理是强化学习的两个示例。
    典型的机器学习应用可以分为科学知识发现和更多商业应用,从机器人或人机交互HCI)到反垃圾邮件过滤和推荐系统。
    统计学和数据分析中的机器学习

    机器学习是研究和构建算法的学科(参见en.wikipedia.org/wiki/Algorithm),这些算法可以从开导式学习(参见en.wikipedia.org/wiki/Learning)并对数据进行故意义的预测。然而,为了进行数据驱动的预测或决议,这些算法通过从练习数据会合构建模型(参见en.wikipedia.org/wiki/Mathematical_model)来操作,比严格遵循静态步伐或指令更快。机器学习也与计算统计学密切相关并经常重叠。另一方面,计算统计学是统计学的一个应用范畴,专注于通过计算机化方法进行预测。此外,它与数学优化有着密切的关系,提供了方法和计算任务以及理论和应用范畴。由于对数学背景知识的强烈需求,数学中不可行的任务最适合机器学习,并可以作为替代方法应用。
    另一方面,在数据分析范畴,机器学习是一种用于设计复杂模型和算法的方法,这些模型和算法朝着预测未来结果的方向发展。这些分析模型允许研究职员、数据科学家、工程师和分析师通过从过去的关系(开导式)和数据中的趋势中学习来产生可靠、可重复和可再现的结果,并挖掘隐蔽的见解。我们再次引用 Tom 教授的著名界说,他在文献中解释了从计算机科学的角度来看学习的真正含义(Tom M. Mitchell, The Discipline of Machine Learning, CMU-ML-06-108, July 2006, www.cs.cmu.edu/~tom/pubs/MachineLearning.pdf):
       假如一个计算机步伐在某类任务 T 上的表现,根据性能度量 P,随着经验 E 的积聚而提高,那么就可以说它在任务 T 上从经验 E 中学习。
      因此,我们可以得出结论,计算机步伐或机器可以:


    • 从数据和历史中学习
    • 可以通过经验进行改进
    • 交互式地增强模型,以用于预测问题的结果
    此外,以下图表帮助我们明白机器学习的整个过程:

    图 1:一览机器学习。
    典型的机器学习工作流程

    典型的机器学习应用包罗从输入、处理到输出的几个步调,形成了一个科学工作流程,如图 2 所示。典型的机器学习应用涉及以下步调:

    • 加载样本数据。
    • 将数据解析成算法的输入格式。
    • 预处理数据并处理缺失值。
    • 将数据分成两组,一组用于构建模型(练习数据集),另一组用于测试模型(测试数据集或验证数据集)。
    • 运行算法来构建或练习您的机器学习模型。
    • 使用练习数据进行预测并观察结果。
    • 使用测试数据测试和评估模型,大概使用第三个数据集(验证数据集)使用交织验证技能验证模型。
    • 调整模型以得到更好的性能和准确性。
    • 扩展模型,以便将来能处理大规模数据集。
    • 在商业化中部署机器学习模型:

    图 2:机器学习工作流程。
    通常,机器学习算法有一些方法来处理数据会合的偏斜;这种偏斜偶然可能非常严重。在第 4 步中,实验数据集通常被随机分成练习集和测试集,这被称为抽样。练习数据集用于练习模型,而测试数据集用于评估最佳模型的性能。更好的做法是尽可能多地使用练习数据集,以提高泛化性能。另一方面,建议只使用测试数据集一次,以避免在计算预测毛病和相关指标时出现过拟合和欠拟合问题。
    提示

    过拟合是一种统计特性,描述了除了正常和底子关系之外的随机毛病和噪音。当超参数相对于观察值或特性的数目过多时,它通常会发生。另一方面,欠拟合是指既不能对练习数据建模,也不能对新数据进行泛化,以适应模型评估或适应性。
    然而,这些步调包罗几种技能,我们将在第五章中详细讨论这些技能。第 9 步和第 10 步通常被以为是高级步调,因此它们将在后面的章节中讨论。
    机器学习任务

    机器学习任务或机器学习过程通常根据学习系统可用的学习反馈的性质分为三类。监督学习、无监督学习和强化学习;这三种机器学习任务在图 3中表现,并将在本节中讨论:

    图 3:机器学习任务。
    监督学习

    监督学习应用步伐基于一组示例进行预测,其目标是学习将输入映射到与现实世界划一的输出的一般规则。例如,用于垃圾邮件过滤的数据集通常包含垃圾邮件和非垃圾邮件。因此,我们可以知道练习会合哪些消息是垃圾邮件或非垃圾邮件。然而,我们可能有机会使用这些信息来练习我们的模型,以便对新的和未见过的消息进行分类。图 4 表现了监督学习的示意图。
    换句话说,在这种情况下,用于练习机器学习模型的数据集带有感兴趣的值标签,而且监督学习算法会寻找这些值标签中的模式。算法找到所需的模式后,这些模式可以用于对未标记的测试数据进行预测。这是最流行和有用的机器学习任务范例,对于 Spark 也不例外,其中大多数算法都是监督学习技能:

    图 4:监督学习实例。
    无监督学习

    无监督学习中,数据点没有相关的标签,大概换句话说,在无监督学习的练习数据会合,精确的类别是未知的,如图 5所示。因此,类别必须从非结构化数据会合推断出来,这意味着无监督学习算法的目标是通过描述其结构来对数据进行预处理。
    为了克服无监督学习中的这一停滞,通常使用聚类技能来基于某些相似性度量对未标记的样本进行分组,挖掘隐蔽模式以进行特性学习。更技能上地说,我们可以编写一个生成模型,然后告诉数据找到解释数据的参数。如今,假如我们对这种阐释的可能性不满意,接下来会发生什么?答案是,我们应该告诉数据再做一次,直到我们使用一些有效的算法或技能为止。
    如今你可能会产生一个新的问题,为什么我们必须在数据上贴标签?大概我们不能只欣赏当前次序的数据,熟悉到每个数据都是独特的,就像雪花一样?换句话说,通过一点监督,我们的数据可以成长为任何它想成为的东西!那么为什么未标记的数据也应该被考虑进来呢?
    嗯,关于这个问题另有一些更深层次的问题。例如,数据中的大部门变革来自于与我们所盼望的标记方案无关的征象。一个更现实的例子是 Gmail 怎样使用监督学习技能将电子邮件分类为垃圾邮件和正常邮件,其中数据可能使用其参数来解释其语义,而我们关心的只是其句法属性:

    图 5:无监督学习。
    强化学习

    强化学习是一种技能,模型本身从一系列行为或行为中学习。在强化学习中,数据集的复杂性或样本复杂性对于算法成功学习目标函数非常重要。此外,为了实现终极目标,与外部情况互动时应确保最大化嘉奖函数,如图 6所示。为了使最大化更容易,嘉奖函数可以通过惩罚不良行为或嘉奖精良行为来利用。
    为了得到最高的嘉奖,算法应该通过策略进行修改,也允许机器或软件署理定期学习其行为。这些行为可以一劳永逸地学习,大概随着时间的推移,机器学习模型可以不断适应:

    图 6:强化学习。
    例如,强化学习在机器人技能中很常见;算法必须基于一组传感器读数选择机器人的下一个动作。它也是物联网IoT)应用的自然选择,其中计算机步伐与动态情况进行交互,必须实现某个目标,而没有明确的导师。另一个例子是游戏Flappy Bird,它已经被练习成本身玩。
    推荐系统

    推荐系统是一种新兴应用,是信息过滤系统的子类,用于预测用户通常对项目提供的评分或偏好。近来几年推荐系统的概念变得非常普遍,并随后应用于差别的应用步伐。最流行的可能是产品(例如影戏、音乐、册本、研究文章、消息、搜刮查询、交际标签等)。推荐系统通常可以分为四类:


    • 协同过滤系统,其中斲丧者的偏好和对其他用户的推荐是基于行为模式的相似性积聚。
    • 基于内容的系统,其中使用监督机器学习来说服分类器区分用户感兴趣和不感兴趣的项目。
    • 混合推荐系统是近来的研究和混合方法(即,结合协同过滤和基于内容的过滤)。Netflix 是这样一个推荐系统的精良例子,它使用受限玻尔兹曼机RBM)和一种矩阵分解算法来处理大型影戏数据库,如 IMDb。这种推荐,通过比力相似用户的观看和搜刮习惯简单地推荐影戏或戏剧或流媒体,被称为评分预测。
    • 基于知识的系统,其中使用有关用户和产品的知识来推理满足用户需求的内容,使用感知树、决议支持系统和基于案例的推理。
    半监督学习

    监督学习无监督学习之间,有一个小小的地方是半监督学习;在这种情况下,机器学习模型通常吸收不完整的练习信号。更具体地说,机器学习模型吸收到一组目标输出部门缺失的练习集。半监督学习更多地基于假设,而且通常使用三种假设算法作为未标记数据集的学习算法。使用以下假设:平滑性、聚类和流形假设。
    换句话说,半监督学习还可以被称为弱监督自举技能,用于利用未标记示例的隐蔽财产来增强从少量标记数据中学习。新兴示例包罗半监督盼望最小化和人类认知中的概念学习以及传递 SVM
    实际机器学习问题

    机器学习到底是什么意思?我们在本章的开头已经看到了一些令人佩服的对这个术语的界说,以及术语“学习”的含义。然而,机器学习本身的界说取决于要办理的问题。在本节中,我们将起首强调机器学习的类别,然后枚举一些现实世界中广为人知和广泛使用的机器学习问题的例子。典型的类别包罗分类、聚类、规则提取和回归,这些都将被讨论。
    此外,我们还将讨论基于标准机器学习问题的重要分类法的问题。这很重要,因为相识我们可能面临的问题范例可以让我们考虑我们须要的数据。另一个重要的毕竟是,在相识一些实际的机器学习问题之前,你可能会在开发机器学习应用步伐的想法上遇到困难。换句话说,要知道问题,我们起首须要相识数据。因此,本章将讨论算法的范例及其优化问题;数据处理将在第三章中进行讨论,通过相识数据来明白问题
    机器学习类别

    我们上面提到的问题类别是我们在日常生存中使用和应用机器学习技能时所指的大多数问题的标准。然而,仅仅知道机器学习类别是不够的,我们还须要知道机器正在学习什么范例的问题,因为你会发现许多问题只是简单的问题办理,并没有帮助机器学习模型或署理进行学习。
    当你以为一个问题是一个机器学习问题时,更准确地说,你在考虑一个须要从数据中建模的决议问题,这可以被称为一个机器学习问题。换句话说,作为数据科学家或人类专家,假如你有充足的时间通过相识可用的数据集来回复一个特定的问题,你可以或多或少地应用一个合适的机器学习问题。因此,我们可以假设使用一些机器学习算法可以办理的问题重要有两个部门 - 数据本身,可以用来指向问题的特定观察结果,以及可用办理方案的质量的定量丈量。一旦你成功地将一个问题确定为机器学习问题,你可能可以或许思考怎样轻松地制定出什么范例的问题,大概你的客户将会要求什么样的结果,大概须要满足什么样的要求。正如上面所述,更常用的机器学习类别包罗:分类、聚类、回归和规则提取。我们如今将对每个类别进行扼要概述。
    分类和聚类

    假如实验数据集已经标记,这意味着已经为其分配了一个类别。例如,在垃圾邮件检测中的垃圾邮件/非垃圾邮件,大概在信用卡欺诈识别中的欺诈/非欺诈。然而,假如基本决议的数据集是未标记的,新的标签须要手动或算法地制作。这可能很困难,可以被视为一个判定问题。相反,雕刻出几个群体之间的差异或相似之处可能在计算上更加困难。
    另一方面,聚类处理的是未标记或无标记的数据。然而,它仍旧可以根据相似性和数据中的自然结构的其他度量来分成组。将数字相册中的图片仅按面目构造起来而不带有姓名可能是一个例子,人类用户必须手动为组分配名称。同样,手动标记多个图像文件可能会产生雷同的计算复杂性;我们将在后面的章节中提供一些示例,说明 Spark 怎样提供多个 API 来办理这些问题。
    规则提取和回归

    从给定的数据会合,可以通过条件和结论以if…then的方式生成命题规则,界说了机器学习署理的行为。这种规则生成技能通常被称为规则提取。你可能会想知道这样的规则是否存在,然而,它们通常不是有针对性的。这意味着用于发现数据中属性之间的统计显著或统计相关关系的方法。
    规则提取的一个例子是在面向业务的事件性数据库中挖掘项目之间的关联规则。非技能上,一个实际的例子可能是发现啤酒购买和尿布购买之间的关系或关联,这说明了顾客的愿望和机会。然而,可能会出现一些预测不肯定直接涉及规则或数据的情况。
    如今让我们谈谈回归,其中数据带有实际值的标签。更确切地说,一些浮点值而不是数据中的标签。明白一个例子的最简单方法是时间序列数据,类似于股票或货币随时间变革的价格。在这些范例的数据中,回归任务是通过一些回归建模技能对新的和不可预测的数据进行预测。
    最广泛使用的机器学习问题

    你会发如今日常生存中使用机器学习相关问题的大量例子,因为它们办理了广泛使用的技能或算法中的困难部门。我们经常使用许多桌面或基于网络的应用步伐,纵然不知道使用了哪些底子技能,也可以办理你的问题。你会惊讶地发现,其中许多实际上使用了广泛使用的机器学习算法,使你的生存更轻松。周围有许多机器学习问题。在这里,我们将提到一些真正代表机器学习的例子问题:


    • 垃圾邮件检测或垃圾邮件过滤:给定收件箱中的一些电子邮件,任务是识别哪些电子邮件是垃圾邮件,哪些好坏垃圾邮件(通常称为正常)电子邮件。如今具有挑战性的部门是开发一个可以应用的 ML 应用,以便它只能识别非垃圾邮件电子邮件留在收件箱中,并将垃圾邮件移动到相应的垃圾邮件文件夹中,大概永世从电子邮件帐户中删除它们。一个典型的例子可能是在使用 Gmail 时手动实行的操作,但假如你有一个 ML 应用步伐,该应用步伐将主动实行。
    • 异常检测或异常值检测:异常检测涉及识别数据会合意外或不符合预期模式的项目、事件或观察结果;换句话说,是怀疑模式的识别。最常见的例子是使用一些机器学习应用进行网络异常检测。如今具有挑战性的任务是开发一个可以成功应用于简单识别网络中流传的异常数据点的 ML 应用。
    • 信用卡欺诈检测:信用卡欺诈如今非常普遍。从网上购物中盗取信用卡相关信息,并以非法方式使用在许多国家都有发生。假设你有一个客户一个月的交易数据库。如今具有挑战性的任务是开发一个机器学习应用步伐,以识别客户本身进行的交易和他人非法进行的交易。
    • 语音识别:识别声音并将其转换为相应的文本命令,然后实行一些操作,就像智能署理一样。最常用的应用包罗苹果的 Siri,三星的 S-Voice,亚马逊的 Echo(斲丧范畴)和微软的 Cortana(特殊是因为 Cortana 具有用于可扩展性和集成等的 SDK)。另一个例子是使用识别的声音来锁定或解锁智能手机。
    • 数字/字符识别:假设你有一个手写的邮政编码、地点或信件,如今数字/字符识别的任务是识别和分类每个差别人写的手写字符的数字或字符。一个高效的机器学习应用可以帮助阅读和明白手写的邮政编码或字符,并按地理区域或更技能上的说法,按图像分割对信封内容进行分类。
    • 物联网:大规模传感器数据分析,用于及时流数据的预测和分类。例如,智能客堂监控,包罗水位检测,室温检测,家用电器控制等。
    • 游戏分析:用于预测升级贩卖和针对应用内购买和修改的体育、游戏和基于控制台的游戏档案分析
    • 人脸检测:给定数百或数千张照片的数字相册,任务是识别与给定人相似的照片。在这种情况下,高效的机器学习应用可以帮助按职员构造照片。
    • 产品推荐:根据客户的购买历史和大量的产品库存,目标是识别客户可能有兴趣购买的产品。亚马逊、Facebook 和 Google Plus 等商业和科技巨头为用户提供了这一推荐功能。
    • 股票交易:根据股票市场的当前和历史价格,预测是否应该买入或卖出股票,以便利用机器学习系统赢利。
    以下是一些新兴的机器学习示例和当前研究的需求:


    • 隐私保护数据挖掘:从面向业务的零售数据库中挖掘最大频繁模式和关联规则,以增加未来的购买
    • 作者姓名消歧:使用手动验证从给定出书物集合的作者列表的聚类结果中的随机样原来评估消歧性能
    • 推荐系统:基于点击流数据的推荐系统,使用关联规则挖掘
    • 文本挖掘:例如,从给定的文本语料库中查抄抄袭
    • 情感分析:如今许多商业和科技公司的决议都是基于他人的意见,这将是创新机器学习的好地方
    • 语音明白:给定用户的话语,目标是识别用户提出的具体哀求。这个问题的模型将允许步伐明白并尝试满足该哀求。例如,iPhone 的 Siri 和三星的语音记载器在会议模式下都实现了这个功能
    其中一些问题是人工智能、自然语言处理和计算机视觉中最困难的问题,可以使用机器学习算法来办理。同样,我们将尝试开发一些强调这些问题的机器学习应用步伐,在接下来的章节中进行讨论。
    Spark 中的大规模机器学习 API

    在本节中,我们将描述 Spark 机器学习库(Spark MLlib 和 Spark ML)引入的两个关键概念,以及与我们在上述部门讨论的监督和无监督学习技能相划一的最常用的实现算法。
    Spark 机器学习库

    如前所述,在 Spark 期间之前,大数据建模者通常使用统计语言(如 R、STATA 和 SAS)构建他们的机器学习模型。然后数据工程师通常会重新用 Java 等语言实现雷同的模型,以部署在 Hadoop 上。
    然而,这种工作流程缺乏服从、可扩展性、吞吐量和准确性,以及延长的实行时间。
    使用 Spark,可以重新构建、接纳和部署雷同的机器学习模型,使整个工作流程更加高效、稳健和快速,从而使您可以或许提供及时洞察力以提高性能。Spark 机器学习库分为两个包:Spark MLlib(spark.mllib)和 Spark ML(spark.ml)。
    Spark MLlib

    MLlib 是 Spark 的可扩展机器学习库,它是 Spark Core API 的扩展,提供了一系列易于使用的机器学习算法库。算法是用 Java、Scala 和 Python 实现和编写的。Spark 支持存储在单台机器上的当地向量和矩阵数据范例,以及由一个或多个 RDD 支持的分布式矩阵:
    Spark MLlibML 任务离散连续监督分类:逻辑回归及其正则化变体线性支持向量机质朴贝叶斯决议树随机丛林梯度提升树回归:线性回归及其正则化变体线性最小二乘 Lasso 和岭回归等距回归无监督聚类:K 均值高斯矩阵幂迭代聚类(PIC)潜在狄利克雷分配(LDA)二分 K 均值流式 K 均值降维、矩阵分解:主身分分析奇异值分解交替最小二乘强化N/AN/A推荐系统协同过滤:Netflix 推荐N/A 表 1:一览 Spark MLlib。


    • 图例:连续:对连续变量进行预测,例如,预测未来几天的最高温度
    • 离散:将离散的类标签分配给特定观察结果作为预测的结果,例如,在天气预报中,可以预测晴天、雨天或雪天
    Spark MLlib 的美好之处在于众多。例如,使用 Scala、Java 和 Python 实现的算法具有高度可扩展性,并利用 Spark 处理大量数据的能力。它们设计快速,用于并行计算,基于内存的操作比 MapReduce 数据处理快 100 倍(它们还支持基于磁盘的操作,比 MapReduce 普通数据处理快 10 倍),使用 Dataset、DataFrame 或基于有向无环图(DAG)的 RDD API。
    它们也是多样的,因为它们涵盖了用于回归分析、分类、聚类、推荐系统、文本分析、频繁模式挖掘的常识趣器学习算法,显然也涵盖了构建可扩展机器学习应用步伐所需的全部步调。
    Spark ML

    Spark ML 添加了一组新的机器学习 API,让用户可以快速组装和配置实用的机器学习管道,构建在数据集之上。Spark ML 旨在提供一组同一的高级 API,构建在 DataFrame 而不是 RDD 之上,帮助用户创建和调整实用的机器学习管道。Spark ML API 标准化了机器学习算法,使学习任务更容易将多个算法组合成单个管道或数据工作流,供数据科学家使用。
    Spark ML 使用 DataFrame 的概念(只管在 Java 中已颠末时,但仍旧是 Python 和 R 中的重要编程接口),这是在 Spark 1.3.0 版本中从 Spark SQL 引入的机器学习数据集。数据集包含各种数据范例,例如存储文本、特性向量和数据的真实标签的列。除此之外,Spark ML 还使用转换器将一个 DataFrame 转换为另一个,反之亦然,其中估计器的概念用于在 DataFrame 上拟合以生成新的转换器。另一方面,管道 API 可以将多个转换器和估计器一起束缚,以指定一个 ML 数据工作流。参数的概念是在开发 ML 应用步伐期间引入的,用于指定全部转换器和估计器在一个同一的 API 下共享一个公共 API:
    Spark MLML 任务离散连续监督分类:逻辑回归决议树分类器随机丛林分类器梯度提升树分类器多层感知分类器一对多分类器回归:线性回归决议树回归随机丛林回归梯度提升树回归生存回归无监督聚类:K 均值潜在狄利克雷分配(LDA)树集成:随机丛林梯度提升树强化N/AN/A推荐系统N/AN/A 表 2:一览 Spark ML(图例与表 1 雷同)。
    如表 2 所示,Spark ML 还提供了几种分类、回归、决议树和树集成,以及用于在 DataFrame 上开发 ML 管道的聚类算法。正在积极实行的优化算法称为正交有限内存拟牛顿OWL-QN),这也是一种高级算法,是 L-BFGS 的扩展,可以有效处理 L1 正则化和弹性网(也请参阅 Spark ML 高级主题,spark.apache.org/docs/latest/ml-advanced.html)。
    从业者的重要说明

    然而,如今仅支持 Pearson 和 Spearman 的相关性,而且将在未来的 Spark 版本中添加更多。与其他统计函数差别,Spark 还支持分层抽样,可以在 RDD 上作为键值对实行;但是,一些功能尚未添加到 Python 开发职员。如今在 Spark 机器学习库中没有强化学习算法模块(请参阅表 1表 2)。Spark MLlib 的当前实现提供了 FP-growth 的并行实现,用于挖掘频繁模式和关联规则。但是,您将须要根据须要自界说算法来挖掘最大频繁模式。我们将在即将到来的章节中提供一个可扩展的 ML 应用步伐,用于挖掘隐私保护的最大频繁模式。
    另一个毕竟是,Spark 中协同推荐系统的当前实现不支持及时流数据的使用,然而,在后面的章节中,我们将尝试基于点击流数据使用关联规则挖掘来展示一个实际的推荐系统(参见 Mitchell, Tom M. 机器学习的学科,2006 年,www.cs.cmu.edu/。CMU. Web. 2014 年 12 月)。然而,一些算法尚未添加到 Spark ML 中,最值得注意的是降维是一个例子。
    然而,开发职员可以无缝地将 Spark MLlib 中找到的这些技能的实现与 Spark ML 中找到的其他算法结合起来,作为混合或可互操作的 ML 应用步伐。 Spark 的神经网络和感知是基于大脑的学习算法,涵盖了多类、双类和回归问题,这些问题在 Spark ML API 中尚未实现。
    实际机器学习最佳实践

    在本节中,我们将描述在开发特定兴趣的机器学习应用步伐之前须要遵循的一些精良的机器学习实践,如图 7所示:

    图 7:机器学习系统化流程。
    可扩展和准确的 ML 应用需求,须要从问题界说到呈现结果的开发中遵循系统化的方法,可以总结为四个步调:问题界说和制定、数据预备、寻找适合的机器学习算法,末了,在机器学习模型部署后呈现结果。嗯,这些步调可以如图 6所示。
    在开发 ML 应用步伐之前的最佳实践

    机器学习系统的学习可以被公式化为表示、评估和优化的总和。换句话说,根据 Pedro D 等人的说法(Pedro Domingos,关于机器学习的一些有用的东西,homes.cs.washington.edu/~pedrod/papers/cacm12.pdf):
    学习=表示+评估+优化
    考虑到这个公式,我们将在进入 ML 应用步伐开发之前为从业者提供一些建议。
    精良的机器学习和数据科学代价巨大

    那么,在开发有效的机器学习应用步伐之前,我们须要什么?实际上,在开始开发 ML 应用步伐之前,我们须要四种武器,包罗:


    • 数据基元(或更坦率地说,实验数据)。
    • 管道综合工具(用于明白机器学习步调中的数据和控制流)。
    • 有效和健壮的错误分析工具。
    • 验证或验证工具(用于验证或验证 ML 模型的预测准确性或性能)。然而,最重要的是,假如没有一些具有精良数据科学的强盛理论底子,整个过程将是徒劳的。毕竟上,许多数据科学家和机器学习专家经常引用类似于这样的声明:假如你能将你的问题提出为一个简单的优化问题,那么你险些已经完成了(见数据分析与 R,advanceddataanalytics.net/2015/01/31/condensed-news-7/)。
    这意味着在开始机器学习之前,假如你能确定你的问题是一个机器学习问题,你将可以或许找到一些合适的算法来一起开发你的 ML 应用。固然,在实践中,大多数机器学习应用无法转化为简单的优化问题。因此,像你这样的数据科学家的职责是管理和维护复杂的数据集。之后,你将不得不处理其他问题,比如在工程化机器学习管道时出现的分析问题,以办理我们之条件到的那些问题。
    因此,最佳实践是使用 Spark MLlib、Spark ML、GraphX 和 Spark Core API 以及最佳实践的数据科学开导式方法来共同开发您的机器学习应用步伐。如今你可能会想从中获益;是的,好处是显而易见的,它们如下:


    • 内置的分布式算法
    • 内存和基于磁盘的数据计算和处理
    • 迭代工作负载的内存能力
    • 算法的准确性和性能
    • 更快的数据清理、特性工程和特性选择、练习和测试
    • 预测结果的及时可视化
    • 朝着更好的性能调整
    • 适应新数据集
    • 随着数据集的增加而扩展性
    最佳实践-特性工程和算法性能

    在最佳实践中,特性工程应被视为机器学习中最重要的部门之一。关键是在实验数据会合非技能性地找到特性的更好表示。与此同时,使用哪些学习算法或技能也很重要。参数调整固然也很重要,但终极的选择更多取决于您将要开发的 ML 模型的实验。
    在实践中,通过“开箱即用”方法(也称为功能性或 OOTB,是指产品安装或配置后立即可用的功能)和精良的数据预处理,轻松掌握灵活的性能基线是微不足道的。因此,您可能会不断地这样做,以相识基线在哪里,以及这种性能是否达到了令人满意的水平或充足满足您的要求。
    一旦您练习了全部的开箱即用方法,总是建议而且是一个好主意将它们一起尝试。此外,为了办理 ML 问题,您可能经常须要知道计算上困难的问题(例如第二部门中所示)须要范畴特定的知识或大量挖掘数据或两者兼而有之。因此,广泛接受的特性工程技能和范畴特定知识的结合将有助于您的 ML 算法/应用/系统办理与预测相关的问题。
    简而言之,假如您拥有所需的数据集和一个强盛的算法,可以利用数据集学习复杂的特性,险些可以保证您会成功。此外,偶然范畴专家在选择好的特性时可能会出错;因此,多个范畴专家(问题范畴专家)、更结构化的数据和 ML 专业知识的整合总是有帮助的。
    末了但同样重要的是,偶然我们建议考虑错误率而不仅仅是准确性。例如,假设一个 ML 系统的准确率为 99%,错误率为 50%,比起准确率为 90%,错误率为 25%的系统更糟糕。
    注意过拟合和欠拟合

    初学者数据科学家经常犯的一个常见错误是在构建 ML 模型时受到过拟合问题的影响,这可能是由于听而不是泛化。更具体地说,假如您在练习数据上评估模型而不是测试或验证数据,您可能无法确定您的模型是否过拟合。常见的症状包罗:


    • 用于练习的数据的预测准确性可能过高(偶然甚至达到 100%)
    • 而且与新数据相比,模型可能会轻微好一些
    偶然 ML 模型本身对特定调整或数据点变得欠拟合,这意味着模型变得过于简单。我们的建议(我们相信其他人也是如此)如下:


    • 将数据集分为两组以检测过拟合情况,第一组用于练习和模型选择,称为练习集;第二组是用于评估模型的测试集,取代了 ML 工作流程部门中所述的模型。
    • 大概,您还可以通过使用更简单的模型(例如,线性分类器优先于高斯核 SVM)或通过增加 ML 模型的正则化参数(假如可用)来避免过拟合。
    • 调整模型的参数值以避免过拟合和欠拟合
    另一方面,Hastie 等人(Hastie Trevor,Tibshirani Robert,Friedman Jerome,《统计学习的要素:数据挖掘、推断和预测》,第二版,2009 年)建议将大规模数据集分为三组:练习集(50%)、验证集(25%)和测试集(25%)(大抵)。他们还建议使用练习集构建模型,并使用验证集计算预测毛病。建议使用测试集来评估终极模型的泛化毛病。
    假如在监督学习期间可用的标记数据量较小,则不建议拆分数据集。在这种情况下,使用交织验证或练习拆分技能(将在第七章中讨论,调整机器学习模型,并附有几个示例)。更具体地说,将数据集分为大抵相等的 10 部门,然后对这 10 部门中的每一部门进行迭代练习分类器,并使用第十部门来测试模型。
    保持关注并将 Spark MLlib 与 Spark ML 结合使用

    管道设计的第一步是创建构建模块(作为由节点和边构成的有向或无向图)并在这些模块之间创建接洽。然而,作为数据科学家,您还应专注于扩展和优化节点(基元),以便在后期处理大规模数据集时可以或许扩展应用步伐,使您的 ML 管道始终保持高性能。管道过程还将帮助您使您的模型适应新数据集。然而,其中一些基元可能会明确界说为特定范畴和数据范例(例如文本、图像、视频、音频和时空数据)。
    除了这些范例的数据之外,基元还应实用于通用范畴的统计学或数学。将您的 ML 模型转换为这些基元的情势将使您的工作流程更加透明、可解释、可访问和可解释。近来的一个例子是 ML-Matrix,它是一个可以在 Spark 之上使用的分布式矩阵库:

    图 8:保持关注并使 ML、MLlib 和 GraphX 互操作。
    正如我们在前一节中已经提到的,作为开发职员,您可以无缝地将 Spark MLlib 中的实现技能与 Spark ML、Spark SQL、GraphX 和 Spark Streaming 中开发的算法结合起来,作为基于 RDD、DataFrame 和 Datasets 的混合或可互操作的 ML 应用步伐,如图 8 所示。例如,可以使用混合模型开发基于物联网的及时应用步伐。因此,建议您与您周围的最新技能保持同步,以改进您的 ML 应用步伐。
    使 ML 应用步伐模块化并简化管道合成

    在构建 ML 管道时的另一个常用做法是使 ML 系统模块化。一些监督学习问题可以使用常称为广义线性模型的非常简单的模型来办理。然而,这取决于您将要使用的数据,有些数据可能不实用于这些模型。
    因此,要将一系列简单的线性二元分类器合并成一个轻量级的模块化架构。这可能是在工作流程或算法级别。优势是显而易见的,因为应用步伐的模块化架构以并行和分布式的方式处理大量数据流。因此,我们建议您接纳文献中提到的三种关键创新机制:加权阈值抽样、逻辑校准和智能数据分区(例如,Yu Jin;Nick Duffield;Jeffrey Erman;Patrick Haffner;Subhabrata Sen;Zhi Li Zhang,《大型网络中基于流级流量分类的模块化机器学习系统》,ACM 数据发现知识交易,V-6,Issue-1,2012 年 3 月)。目标是在实现高吞吐量的同时,实现 ML 应用/系统预测结果的高准确性。虽然原语可以作为构建块,但您仍须要其他工具来使用户可以或许构建 ML 管道。
    随后,工作流程工具如今变得更加普遍,这些工具实用于数据工程师、数据科学家,甚至实用于业务分析师,如 Alteryx、RapidMiner、Alpine Data 和 Dataiku。在这一点上,我们评论并强调业务分析师,因为在末了阶段,您的目标客户将是一家器重您的 ML 模型的商业公司,对吧?Spark 的最新版本配备了用于构建机器学习管道的 Spark ML API,并制定了范畴特定语言(参见en.wikipedia.org/wiki/Domain-specific_language)用于管道。
    思考一个创新的 ML 系统

    然而,为了开发算法以利用可用数据连续学习 ML 模型,机器学习背后的观点是主动化分析模型的创建。不断发展的模型产生越来越积极的结果,并减少了对人类干预的需求。这使得 ML 模型可以或许主动产生可靠且可重复的预测。
    更具体地说,假设您计划使用 ML 算法开发推荐系统。那么,开发该推荐系统的目标是什么?在机器学习产品开发方面有哪些创新的想法?这两个问题在您开始开发 ML 应用步伐或系统之前应该考虑。连续的创新可能具有挑战性,特殊是在推动新想法的同时,明白最大长处地点也可能很困难。机器学习可以通过各种途径提供创新,例如确定当前产品的弱点、预测分析或识别从前隐蔽的模式。
    因此,您将不得不考虑大规模计算来离线练习您的 ML 模型,随后您的推荐系统必须可以或许像传统的搜刮引擎分析一样进行在线推荐。因此,假如您的系统:


    • 可以使用您的机器学习应用步伐预测购买商品
    • 可以进行产品分析
    • 可以作为生产中的新趋势
    思考并变得更加智慧,以应对大数据的复杂性

    如图 9 所示,新的商业模式是可利用数据的不可避免的延伸,因此考虑大数据及其商业代价可以使业务分析师的工作、生存和思维更加智能,从而使您的目标公司为客户提供代价。除此之外,您还须要调查(更准确地说是分析)竞争对手或更好的公司。
    如今的问题是,你怎样收集和使用企业数据?大数据不仅仅是关于大小(容量),它还与速度、真实性、多样性和代价有关。对于这些范例的复杂性,例如,速度可以使用 Spark Streaming 来办理,因为基于流的数据也是须要及时分析的大数据。其他参数,如容量和多样性,可以使用 Spark Core 和 Spark MLlib/ML 来处理大数据处理。
    好吧,你必须想方设法管理数据。假如你可以或许管理数据,那么从数据中得到的见解可以真正改变企业运营的方式,利用大数据的有用特性:

    图 9:大数据最佳实践中的机器学习。
    在这一点上,仅有数据是不够的(参见 Pedro Domingos,《关于机器学习的一些有用知识》,homes.cs.washington.edu/~pedrod/papers/cacm12.pdf),但是从数据中提取故意义的特性并将数据的语义放入模型更为重要。这就像 LinkedIn 等大多数科技巨头正在通过大规模机器学习框架开发的社区特性定位一样,这多多少少是一种监督学习技能。工作流程如下:


    • 获取数据,提取特性,并设置目标
    • 特性和目标毗连
    • 从毗连数据创建一个快照
    • 将快照分成两部门:练习集和测试集
    • 从练习会合,通过采样技能预备样本数据
    • 使用采样数据练习模型
    • 评分
    • 从先前开发的持久模型以及步调 4 中预备的测试数据中评估模型。
    • 假如找到了最佳模型
    • 为目标受众部署模型
    那么接下来呢?你的模型也应该适应大规模动态数据,比如及时流式物联网数据,而且及时反馈也很重要,这样你的 ML 系统才能从错误中学习。下一小节将讨论这一点。
    将机器学习应用于动态数据

    原因是显而易见的,因为机器学习为物联网项目带来了具体和动态的方面。近来,机器学习在工业公司中的受接待水平有所提高,他们从中赢利。因此,险些每个 IT 供应商都在急速宣布物联网平台和咨询服务。但是通过物联网数据实现财政收益并不是一件容易的工作。此外,许多企业未能清楚地确定实行物联网战略将改变哪些范畴。
    综合考虑这些积极和消极的问题,你的 ML 模型应该适应大规模动态数据,因为大规模数据意味着数十亿条记载、大特性空间和来自稀疏问题的低正率。然而,数据是动态的,因此 ML 模型必须充足适应;否则你将面临糟糕的体验大概迷失在黑洞中。
    开发 ML 应用步伐后的最佳实践

    ML 模型/系统开发后的最佳实践步调包罗:可视化以明白预测值,模型验证,错误和准确性分析,模型调整,模型适应和扩展以便轻松处理大规模数据集。
    怎样实现及时 ML 可视化

    可视化提供了一个交互界面,以保持 ML 模型本身的关注。因此,假如不可视化预测结果,进一步改善 ML 应用步伐的性能将变得困难。最佳实践可能是这样的:


    • 为了可视化大规模图形相关数据,可以将一些第三方工具与 GraphX 结合起来(更多内容将在第九章中讨论,流式和图形数据的高级机器学习)
    • 对于非图形数据,Spark ML 算法可以通过集成其他工具如 Apache Kafka 来发送和吸收消息的回调接口:
    • 算法决定何时发送什么消息
    • 算法不关心消息是怎样传递的
    • 一个任务通道用于处理从 Spark 驱动步伐到 Spark 客户端或 Spark 集群节点的消息传递服务。任务通道将使用 Spark 核心在更低的抽象级别进行通信:
    • 它不关心消息的内容或消息的吸收者
    • 消息从 Spark 客户端传递到浏览器或可视化客户端:
    • 我们建议同时使用 HTML5 的服务器发送事件(SSE)和 HTTP 分块响应(PUSH)。将 Spark 与这种范例的技能结合起来将在第十章中讨论,配置和使用外部库
    • 拉取是可能的;然而,它须要一个消息队列
    • 使用 JavaScript 框架进行可视化,比如Plot.ly(请参考plot.ly/)和D3.js(请参考d3js.org/)
    进行一些错误分析

    随着算法变得更加普遍,我们须要更好的工具来构建复杂的、稳健的和稳定的机器学习系统。像 Apache Spark 这样的流行分布式框架将这些想法应用到了更广泛的大型数据会合。因此,假如我们可以或许绑定分层管道的近似毛病和收敛速度,那将更好。
    假设我们可以计算节点的毛病范围,下一步将是为这些管道提取毛病范围的机制。然而,在实践中,当 ML 模型部署到生产情况时,我们可能须要工具来确认管道将正常工作,不会出现故障或中途克制,而且可以提供一些预期的错误度量。
    保持你的 ML 应用步伐调优

    设计一个或两个在简单问题上表现精良的算法可以被以为是一个精良的开端。然而,偶然你可能渴望得到最佳的准确性,甚至会牺牲宝贵的时间和可用的计算资源。这将是一个更明智的方式,它不仅可以帮助你挤出额外的性能,还可以改善你之前设计的机器学习算法的准确性结果。为了做到这一点,当你调整模型和相关算法时,你必须对结果有很高的信心。
    显然,这些结果将在你指定测试和验证之后可用。这意味着你应该只使用那些减少性能丈量方差的技能,以便评估那些运行更顺利的算法。
    与大多数数据从业者一样,我们还建议您使用交织验证技能(也经常称为旋转估计),而且使用相称高数目的折叠(即 K 折交织验证,其中一个子样本用作验证数据集,用于测试模型本身,其余的 K-1 个子样本用于练习数据)。只管折叠的确切数目,或 K,取决于你的数据集,但是 10 折交织验证通常被使用,但是 K 的值通常是不固定的。我们将在这里提到三种策略,你须要调整你的机器学习模型:


    • 算法调优:使您的机器学习算法参数化。然后,调整这些参数的值(假如它们有多个参数)以影响整个学习过程的结果。
    • 集成:偶然间灵活是好的!因此,为了得到改进的结果,不断尝试将多个机器学习方法或算法的结果结合起来。
    • 极度特性工程:假如您的数据中嵌入了复杂和多维结构,ML 算法知道怎样找到并利用它来做出决议。
    使您的 ML 应用步伐适应和扩展

    如图 10 所示,自适应学习根据 Rob Munro 的说法,将基于规则的、简单的机器学习和深度学习方法融合到机器智能中。

    图 10:机器智能的四代(图由 Rob Munro 提供)。
    机器学习的第四代:自适应学习,(http://idibon.com/the-fourth-generation-of-machine-learning-adaptive-learning/#comment-175958)。
    研究还表明,自适应学习在预测人们购买汽车的意图方面准确率达到 95%(请参阅 Rob Munro,《机器学习的第四代:自适应学习》,http://idibon.com/the-fourth-generation-of-machine-learning-adaptive-learning/#comment-175958)。此外,假如您的 ML 应用步伐可以或许适应新情况和新数据,那么只要提供充足的底子设施,预计您的 ML 系统可以扩展以处理不断增加的数据负载。
    为您的应用步伐选择精确的算法

    我应该使用什么机器学习算法?对于灵活的机器学习从业者来说,这是一个非经常见的问题,但答案总是取决于。更详细地说:


    • 这取决于要测试/使用的数据的数目、质量、复杂性和性质
    • 这取决于外部情况和参数,例如您的计算系统配置或底子设施
    • 这取决于您想要用答案做什么
    • 这取决于算法的数学和统计公式怎样被转化为计算机的机器指令
    • 这取决于你有多少时间
    • 图 11提供了选择办理 ML 问题的精确算法的完整工作流程。但是,请注意,某些技巧可能会根据数据和问题范例而不起作用:

    图 11:选择精确算法的工作流程
    毕竟上,纵然是最有经验的数据科学家或数据工程师在尝试全部算法之前也无法给出哪种 ML 算法在性能上表现最佳的明确建议。大多数划一/差别等的陈述都以*取决于…嗯…*开始。习惯上,您可能会思考是否有机器学习算法的备忘单,假如有的话,怎样使用该备忘单。我们与几位数据科学家交谈时,他们表示找到最佳算法的唯一方法是尝试全部算法;因此,没有捷径!让我们明确一下,假设您有一组数据,而且想要进行一些聚类。因此,从技能上讲,这可能是分类或回归,假如您的数据是标记/未标记的或值或练习集数据。如今,您脑海中起首出现的问题是:


    • 在选择适当的算法之前,我应该考虑哪些因素?还是我应该随机选择一个算法?
    • 我怎样选择可以应用于我的数据的任何数据预处理算法或工具?
    • 我应该使用什么样的特性工程技能来提取有用的特性?
    • 哪些因素可以提高我的 ML 模型的性能?
    • 我怎样为新数据范例接纳我的 ML 应用步伐?
    • 我可以将我的 ML 应用步伐扩展到大规模数据集吗?等等。
    您总是盼望得到更合理的最佳答案,并解释应考虑的一切。在本节中,我们将尝试用我们的一点机器学习知识来回复这些问题。
    在选择算法时的考虑

    我们在这里提供的建议或建议是给初学者数据科学家和尝试选择 Spark ML API 的最佳算法的专家数据科学家。这意味着它做了一些概述和过度简化,但它会指引您朝着安全的方向,相信我们!假设您计划开发一个 ML 系统来回复以下问题基于规则:


    • IF特性 X 具有属性 ZTHEN实行 Y
    肯定地,应该有这样的规则:


    • 假如 XTHEN,尝试使用属性 Z 并避免 W 是明智的
    然而,什么是明智的,什么不是取决于:


    • 您的应用步伐和问题的预期复杂性。
    • 数据集的大小(即有多少行/列,有多少独备案例)。
    • 您的数据集是否有标签或无标签?
    • 数据范例和丈量范例,因为差别范例的数据暗示着差别的次序或结构,对吧?
    • 显然,在实践中,您在应用差别方法时的经验是高效和智能的。
    此外,假如您想对一般问题得到一般答案,我们建议初学者从《统计学习的要素》(Hastie Trevor,Tibshirani Robert,Friedman Jerome,统计学习的要素:数据挖掘、推断和预测,第二版,2009)开始。然而,我们还建议遵循以下算法属性:


    • 展示出色的准确性
    • 具有快速的练习时间
    • 以及线性的使用
    准确性

    从您的 ML 应用步伐中得到最准确的结果并非总是不可或缺的。根据您想要将其用于的情况,偶然近似也充足。假如情况是这样,您可以通过合并更好估计的方法来大幅减少处理时间。当您熟悉 Spark 机器学习 API 的工作流程时,您将享受到拥有更多近似方法的优势,因为这些近似方法将主动倾向于避免您的 ML 模型中的过度拟合问题。
    练习时间

    实行时间须要完成数据预处理或构建模型,而且在差别算法、继承复杂性和鲁棒性之间变革很大。练习时间通常与准确性密切相关。此外,您经常会发现,与其他算法相比,您将使用的一些算法对数据点的数目是难以捉摸的。然而,当您的时间充足充裕,特殊是当数据集较大时,为了完成全部的步伐,选择算法可能会变得轻松。因此,假如您特殊关注时间,尝试牺牲准确性或性能,并使用满足您最低要求的简单算法。
    线性

    近来开发了许多利用线性的机器学习算法(也可在 Spark MLlib 和 Spark ML 中使用)。例如,线性分类算法允许通过绘制区分直线或数据集的高维等价物来分离类别。另一方面,线性回归算法假设数据趋势遵循简单的直线。对于一些机器学习问题,这种假设并不灵活;然而,在其他一些情况下,准确性可能会降落。只管存在伤害,线性算法对于数据工程师或数据科学家来说是首选。此外,这些算法在整个练习过程中也倾向于算法简单且练习速度快。
    在选择算法时与您的数据交谈

    你可以在machinelearningmastery.com/tour-of-real-world-machine-learning-problems/或 UC Irvine 机器学习库(archive.ics.uci.edu/ml/)免费找到许多机器学习数据集。还应起首考虑以下数据属性:


    • 参数数目
    • 特性数目
    • 练习数据集的大小
    参数数目

    参数或数据属性是像你这样的数据科学家在设置算法时可以调整的本领。它们是影响算法性能的数字,例如毛病容限或迭代次数,大概是算法行为的变体之间的选项。算法的练习时间和准确性偶然对于找到合适的设置非常敏感。通常,具有大量参数的算法须要通过试错来找到最佳组合。
    只管这是跨越参数空间的好方法,但随着参数数目的增加,模型构建或练习时间呈指数增长。这既是一个窘境,也是一个时间性能的权衡。积极的一面是,拥有许多参数通常表示机器学习算法的更大灵活性。其次,你的机器学习应用可以得到更好的准确性。
    你的练习集有多大?

    假如你的练习集较小,毛病较高且方差较低的分类器(如质朴贝叶斯)比毛病较低且方差较高的分类器(如 kNN)具有优势。因此,后者会过拟合。但是,毛病较低且方差较高的分类器在你的练习集线性或指数增长时开始占优势,因为它们具有更低的渐近毛病。这是因为高毛病的分类器不足以提供准确的模型。你也可以将其视为生成模型与判别模型之间的权衡。
    特性数目

    对于某些范例的实验数据集,提取的特性数目可能与数据点数目本身相比非常大。这在基因组学、生物医学或文本数据中经常发生。大量特性可能会淹没一些学习算法,使练习时间变得非常长。支持向量机在这种情况下特殊实用,因为它具有高准确性、关于过拟合的精良理论保证以及适当的核函数。
    广泛使用的机器学习算法的特殊说明

    在这一部门,我们将为最常用的机器学习算法或技能提供一些特殊说明。我们将重点介绍的技能包罗逻辑回归、线性回归、推荐系统、支持向量机、决议树、随机丛林、贝叶斯方法和决议丛林、决议丛林以及变种。表 3 表现了一些广泛使用的算法的优缺点,包罗何时选择这些算法。
    算法长处缺点擅长线性回归(LR)非常快,通常在恒定时间内运行易于明白建模不太容易过拟合和欠拟合本质上简单速度非常快,因此建模时间较短不太容易过拟合和欠拟合方差较低通常无法进行复杂的数据建模无法概念化非线性关系,须要转换输入数据集不适合复杂建模仅实用于单一决议界限须要大样本量才能得到稳定的结果毛病较高具有大量特性的数值数据集广泛用于生物学、行为学和社会科学,以预测变量之间可能的关系对数值和分类变量都有效用于医学和社会科学等各个范畴决议树(DT)模型构建和预测时间较短,对噪声和缺失值具有鲁棒性,准确性高大型和复杂树的解释困难,同一子树内可能出现重复,对角决议界限可能存在问题针对高准确的分类、医学诊断和预后、信用风险分析神经网络(NN)非常强盛和稳健,可以或许建模非常复杂的关系,可以在不知道底子数据的情况下工作容易过拟合和欠拟合,练习和预测时间长,计算本钱高,模型不可读或可重复使用图像处理、视频处理、人工智能、机器人、深度学习随机丛林(RF)实用于装袋树,方差低,准确性高,可以处理过拟合问题不易直观解释,练习和预测时间长处理可能相关的多个特性、生物医学诊断和预后、可用于分类和回归支持向量机(SVM)准确性高容易过拟合和欠拟合,数值稳定性差,计算本钱高,须要大量计算资源图像分类、手写识别K 近来邻(K-NN)简单而强盛,须要懒惰练习,可用于多类分类和回归练习和预测时间长,须要准确的距离函数,高维数据集性能低低维数据集、异常检测、半导体故障检测、基因表达、蛋白质相互作用K-means线性实行时间表现优于分层聚类,对超球状聚类效果更好可重复但缺乏划一性,须要先验知识假如数据会合出现的自然聚类好坏球状的,则不是一个好选择,实用于大型数据集潜在狄利克雷分配(LDA)可应用于大规模文本数据集,可以克服 pLSA 的过拟合问题,可用于文档分类和通过主题建模进行聚类不能应用于高维和复杂的文本数据库,须要指定主题数目,无法找到最佳级别,层次狄利克雷过程(HDP)是更好的选择从大规模文本数据会合进行文档分类和通过主题建模进行聚类,可应用于自然语言处理和其他文本分析质朴贝叶斯(NB)计算速度快,实现简单,实用于高维数据,可以处理缺失值,适应性强,模型可以根据新的练习数据进行修改而无需重修依赖独立性假设,假如假设不成立则表现不佳,准确性相对较低当数据有大量缺失值、特性之间的依赖关系类似、垃圾邮件过滤和分类、对科技、政治或体育消息文章进行分类、文本挖掘奇异值分解(SVD)和主身分分析(PCA)反映了关于数据的真实直觉,可以在高维数据中估计概率,数据大小显著减少,两者都基于强盛的线性代数对于像 Twitter 和网络分析这样的许多应用来说太昂贵,对于细粒度类别的任务来说劫难性,须要精确明白线性性,复杂度通常是立方的,计算速度较慢SVD 用于低秩矩阵逼近、图像处理、生物信息学、信号处理、NLP,PCA 用于利率衍生品投资组合、神经科学等,两者都实用于具有高维和多变量数据的数据集 表 3:一些广泛使用算法的优缺点
    逻辑回归和线性回归

    逻辑回归是一种强盛的工具,因为它快速且简单,已在全球范围内用于两类和多类分类。毕竟上,它使用S形曲线而不是直线,使其自然适合将数据分成组。它提供线性类界限,因此在使用它时,请确保线性逼近是您可以接受的。与决议树或 SVM 差别,它还具有精良的概率解释,因此您将可以或许轻松更新模型以适应新数据集。
    因此,建议使用它,假如您盼望体验概率框架的味道,大概盼望将来得到更多的练习数据并将其纳入您的模型。如前所述,线性回归将一条直线、平面或超平面拟合到数据集。它是一个实用、简单且快速的工具,但对于某些问题可能过于简单。
    推荐系统

    我们已经讨论了大多数常用的机器学习算法和工具的准确性和性能问题。然而,除了准确性研究之外,对推荐系统的另一个关注点是寻找其他情况因素和/或参数多样性。因此,一个准确性高且列表内多样性高的推荐系统将是赢家。因此,您的产品将对目标客户非常宝贵。然而,让用户重新对物品进行评分,而不仅仅是表现新物品,可能会更有效。假如您的客户有一些须要满足的额外要求,比如隐私或安全性,您的系统必须可以或许处理与隐私相关的问题。
    这一点特殊重要,因为客户必须提供一些个人信息,因此建议不要公开这些敏感信息。
    然而,使用一些强盛的技能或算法(如协同过滤)来构建用户档案可能会从隐私角度带来问题。此外,该范畴的研究发现,用户生齿统计信息可能会影响其他用户对推荐的满意水平(另请参阅 Joeran Beel、Stefan Langer、Andreas Nürnberger、Marcel Genzmehr,《生齿统计信息(年事和性别)和其他用户特性对评估推荐系统的影响》,在 Trond Aalberg 和 Milena Dobreva 和 Christos Papatheodorou 和 Giannis Tsakonas 和 Charles Farrugia 的《第 17 届数字图书馆理论与实践国际会议论文集》,Springer,第 400-404 页,2013 年 11 月 1 日检索)。
    只管偶然性是权衡推荐有多么令人惊讶的关键指标,但终极创建信任还是须要通过推荐系统。这可以通过解释它是怎样生成推荐的,以及为什么会推荐一个物品,纵然用户的生齿统计信息很少,来实现。
    因此,假如用户根本不信任系统,他们将不会提供任何生齿统计信息,也不会重新对物品进行评分。根据Cowley 等人(G.C.Cawley 和 N.L.C.Talbot,《模型选择中的过拟合和性能评估中的后续选择毛病》,《机器学习研究杂志》,第 11 卷,第 2079-2107 页,2010 年 7 月),支持向量机有几个长处:


    • 您可以通过 SVM 提供的正则化参数来办理过拟合问题
    • SVM 使用核技巧来帮助轻松构建机器学习模型
    • SVM 算法是基于凸优化问题开发、设计和界说的,因此没有局部最小值的概念
    • 这是一个对测试错误率的界限的大抵估计,其中有一个重要且深入研究的理论可以发挥作用
    SVM 的这些有出息的特性确实会帮助您,建议经常使用。另一方面,缺点是:


    • 理论只能真正涵盖对给定的正则化和核参数值的参数确定。因此,你只能选择核。
    • 也可能存在更糟糕的情况,核模型本身在模型选择标准期间可能非常敏感于过拟合。
    决议树

    决议树很酷,因为它们易于解释和解释围绕机器学习问题。与此同时,它们可以很容易地处理与特性相关的交互。最重要的是,它们通常好坏参数的。因此,纵然你是一个工作能力有限的普通数据科学家,你也不须要担心异常值、参数设置和调整等问题。偶然,基本上,你可以依赖决议树,这样它们将减轻你处理数据线性问题的压力,大概更技能上说,你的数据是否是线性可分的,你不须要担心。相反,也有一些缺点。例如:


    • 在某些情况下,决议树可能不合适,偶然它们不支持及时数据集的在线学习。在这种情况下,当出现新的示例或数据集时,你必须重新构建你的树;更技能上说,得到模型的适应性是不可能的。
    • 其次,假如你没故意识到,它们很容易过拟合。
    随机丛林

    随机丛林非常受接待,对于数据科学家来说是一个赢家,因为它们对于大量分类问题来说好坏常好用的。它们通常在可用性方面略领先于支持向量机,而且对于大多数分类问题的操作速度更快。此外,它们在增加可用数据集时也是可扩展的。与此同时,你不须要担心调整一系列参数。相反,当处理数据时,你须要关注许多参数和调整。
    决议丛林、决议丛林和变体

    决议丛林、决议丛林和提升决议树都是基于决议树的,决议树是一个底子的机器学习概念,使用较少。决议树有许多变体;只管如此,它们都做同样的事情,即将特性空间细分为具有雷同标签的区域。为了避免过拟合问题,使用数学和统计公式构建了大量的树,这些树之间没有任何相关性。
    其平均值被称为决议丛林;这是一种避免过拟合问题的树,如前所述。然而,决议丛林可能会使用大量内存。另一方面,决议丛林是一种通过牺牲略长的练习时间来斲丧较少内存的变体。幸运的是,提升决议树通过限定分区的数目和每个区域允许的数据点数目来避免过拟合。
    贝叶斯方法

    当实验或样本数据集规模较大时,贝叶斯方法通常会为参数模型提供与其他经典统计方法产生的结果非常相似的结果。使用贝叶斯方法的一些潜在优势由 Elam 等人总结(W.T. Elam, B. Scruggs, F. Eggert, and J.A. Nicolosi,《获取 XRF NET 强度方法的优缺点》,版权全部©JCPDS-国际衍射数据中心 2011 ISSN 1097-0002)。例如,它提供了一种将先验信息与数据结合的自然方式。因此,作为一名数据科学家,你可以将过去关于参数的信息并入未来分析新数据集的先验分布。它还提供了在不须要算法渐近逼近的情况下,条件于数据的推断。
    它为各种模型提供了一些合适的设置,比如层次模型和缺失数据问题。使用贝叶斯分析也有一些缺点。例如,它不告诉你怎样选择先验世界模型,甚至没有精确选择先验的方法。因此,假如你不小心进行,你可能会产生许多伪阳性或伪阴性的结果,这每每伴随着高昂的计算本钱,假如模型中的参数数目很大的话。
    总结

    这竣事了我们对机器学习和须要遵循的最佳实践的相称快速的介绍。虽然我们试图涵盖一些最基本的要点,但合适的数据每每胜过更好的算法和更高的需求。最重要的是,从数据中设计出好的特性可能须要很长时间;然而,这将对你非常有帮助。然而,假如你有一个大规模的数据集要应用到你的机器学习算法或模型中,无论你使用哪种分类、聚类或回归算法,都可能不是关于机器学习类别及其相应的分类性能的毕竟。
    因此,选择一个可以或许满足速度、内存使用、吞吐量、可扩展性或可用性等要求的合适的机器学习算法将是一个明智的决定。除了我们在上面的部门中所说的内容之外,假如你真的关心准确性,你应该毫无疑问地尝试一组差别的分类器,使用交织验证技能找到最佳的一个,大概使用集成方法来一起选择它们。
    你也可以从 Netflix Prize PLUS 中得到开导并吸取教训。我们详细讨论了 Spark 机器学习 API、ML 应用开发中的一些最佳实践、机器学习任务和类别、一些广泛使用的最佳实践等等。然而,我们并没有深入分析机器学习技能。我们打算在第四章中更详细地讨论这个问题,通过特性工程提取知识
    在下一章中,我们将详细介绍 DataFrame、Dataset 和Resilient Distributed DatasetRDD)API,以处理结构化数据,旨在提供对可用数据进行机器学习问题的基本明白。因此,终极,你将可以或许轻松地应用从基本到复杂的数据操作。
    第三章:通过相识数据来相识问题

    本章将详细介绍 DataFrame、Datasets 和Resilient Distributed DatasetRDD)API,用于处理结构化数据,旨在提供对可用数据进行机器学习问题的基本明白。在本章竣事时,您将可以或许轻松应用从基本到复杂的数据操作。将提供一些比力,使用 RDD、DataFrame 和 Dataset 进行数据操作的基本抽象,以展示在编程和性能方面的收益。此外,我们将指导您走上精确的门路,以便您可以或许使用 Spark 将 RDD 或数据对象持久化在内存中,从而在后期的并行操作中高效地重复使用。简而言之,本章将涵盖以下主题:


    • 分析和预备您的数据
    • Resilient Distributed Dataset(RDD)底子知识
    • 数据集底子知识
    • 来自字符串和范例类的数据集
    • Spark 和数据科学家,工作流程
    • 深入 Spark
    分析和预备您的数据

    在实践中,有几个因素会影响给定任务上机器学习(ML)应用的成功。因此,实验数据集的表示和质量起首被视为一流实体。拥有更好的数据总是明智的。例如,不相关和冗余的数据,具有空值或嘈杂数据的数据特性会导致不可靠的信息泉源。数据会合的不良属性使得在机器学习模型练习阶段的知识发现过程更加繁琐和时间低效。
    因此,数据预处理将在总体 ML 工作流程步调中占据相称大的计算时间。正如我们在上一章中所述,除非您相识可用数据,否则很难明白问题本身。此外,相识数据将帮助您制定问题。同时,更重要的是,在尝试将 ML 算法应用于问题之前,起首您必须确定问题是否真的是一个机器学习问题,以及 ML 算法是否可以直策应用于办理问题。您须要接纳的下一步是相识机器学习类别。更具体地说,您须要知道已识别的问题是否属于分类、聚类、规则重构或回归类别。
    为了简单起见,我们假设您有一个机器学习问题。如今,您须要进行一些数据预处理,包罗一些步调,如数据清理、归一化、转换、特性提取和选择。数据预处理工作流程步调的产物通常用于构建/练习 ML 模型的终极练习集。
    在上一章中,我们还论证了机器学习算法是从数据和模型构建和反馈运动中学习的。关键是,您须要为您想要办理的问题为算法提供精确的数据。纵然您拥有精良的数据(大概更准确地说是结构精良的数据),您也须要确保数据处于适当的规模,而且具有编程语言可以解析的精良格式,最重要的是,是否还包罗最故意义的特性。
    在本节中,您将学习怎样预备数据,使您的机器学习算法对最佳性能变得自发。总体数据处理是一个庞大的主题;然而,我们将尝试覆盖一些基本技能,以便在第六章构建可扩展的机器学习管道中进行一些大规模的机器学习应用。
    数据预备过程

    假如您在数据处理和预备步调中更加专注和纪律,您很可能会在第一时间得到更划一和更好的结果。然而,数据预备是一个包含多个步调的繁琐过程。然而,为了让数据预备好用于机器学习算法,可以总结为三个步调:


    • 数据选择
    • 数据预处理
    • 数据转换
    数据选择

    这一步将专注于选择您将在机器学习应用步伐开发和部署中使用和处理的全部可用数据集的子集。在机器学习应用步伐开发中,总是有一种强烈的冲动,即包含全部可用数据,因为更多的数据将提供更多的特性。换句话说,按照众所周知的格言,越多越好。然而,实际上,在全部情况下,这可能并不精确。在实际回复问题之前,您须要考虑须要哪些数据。终极目标是提供特定假设的办理方案。在一开始,您可能对数据做出一些假设。虽然这很困难,但假如您是该问题的范畴专家,您可以在应用 ML 算法之前做出一些假设以至少相识一些见解。但是,要小心记载这些假设,以便在须要时在以后的阶段进行测试。我们将提出一些常见问题,以帮助您思考数据选择过程:


    • 第一个问题是,*您可用的数据范围是多少?*例如,范围可能是整个时间、数据库表、毗连的系统文件等。因此,最好的做法是确保您清楚地相识并低级结构化您可以使用的一切,大概非正式地持有可用资源(固然包罗可用的数据和计算资源)。
    • 第二个问题有点奇怪!*哪些数据尚未可用,但对办理问题很重要?*在这种情况下,您可能须要等待数据可用,大概您可以至少使用一些生成器或软件生成或模拟这些范例的数据。
    • 第三个问题可能是:*您不须要哪些数据来办理问题?*这意味着再次清除冗余数据,因此清除这些冗余或不须要的数据险些总是比全部包含它更容易。您可能会想知道是否须要记载清除的数据以及原因?我们以为应该是的,因为您可能在以后的阶段须要一些噜苏的数据。
    此外,在实践中,对于小问题或游戏,玩具比赛数据已经为您选择好了;因此,您无需担心!
    数据预处理

    在选择要处理的数据后,您须要考虑怎样使用数据和所需的适当利用。这个预处理步调将办理一些步调或技能,以便将所选数据转换为您可以在模型构建和验证步调中使用和应用的情势。最常用的三个数据预处理步调是格式化、清理和抽样数据:


    • 格式化:所选数据可能不够完善,因此可能不适合直接使用。您的数据很可能是原始数据格式(如文本格式或较少使用的专有格式的平面文件格式),假如您充足幸运,数据可能是在关系数据库中。假如是这种情况,最好应用一些转换步调(即,例如将关系数据库转换为其格式,因为使用 Spark 您无法进行任何转换)。正如已经说明的,Spark 的美好之处在于其对多种文件格式的支持。因此,我们将可以或许在接下来的部门中利用这一点。
    • 清洗:您将要使用的数据每每带有许多不须要的记载,偶然甚至有缺失的记载。这个清洗过程涉及到删除或修复缺失的数据。可能总会有一些微不足道或不完整的数据对象,处理它们应该是主要任务。因此,这些实例可能须要从数据会合删除、忽略或删除以摆脱这个问题。此外,假如由于某些属性中存在敏感信息的存在而导致隐私或安全成为问题,那么这些属性须要被匿名化或从数据中完全删除(假如实用)。
    • 抽样:第三步将是在格式化和清理的数据集上进行抽样。由于可用数据量可能很大或记载数目许多,因此通常须要抽样。然而,我们建议尽可能使用数据。另一个原因是更多的数据可能导致整个机器学习过程的实行时间更长。假如是这种情况,这也会增加算法的运行时间,并须要更强盛的计算底子设施。因此,您可以对所选数据进行较小的代表性样本,这样在考虑整个数据集之前,探索和原型化机器学习办理方案可能会更快。显然,无论您为机器学习应用开发和商业化应用的机器学习工具,数据都将影响您须要实行的预处理。
    数据转换

    在选择适当的数据源并对这些数据进行预处理后,末了一步是转换已处理的数据。您特定的机器学习算法和对问题范畴的相识将在这一步中受到影响。三种常见的数据转换技能是属性缩放、分解和属性聚合。这一步通常也被称为特性工程,在下一章中将更详细地讨论:


    • 缩放:预处理的数据可能包含具有各种数目和单元的混合比例的属性,例如美元、千克和贩卖量。然而,机器学习方法要求数据属性在雷同的比例内,例如对于给定特性的最小值和最大值之间的 0 到 1 之间。因此,考虑您可能须要实行适当的特性缩放来对已处理的数据进行适当的缩放。
    • 分解:数据可能具有一些代表复杂概念的特性,当您将数据集分解为基本部门时,可以使机器学习算法产生更强盛的响应。例如,考虑一天由 24 小时、1,440 分钟和 86,400 秒构成,这些时间又可以进一步分解。可能一些特定的小时或一天中的小时对于须要调查和办理的问题是相关的。因此,考虑适当的特性提取和选择来实行已处理数据的适当分解。
    • 聚合:通常,分散或零散的特性可能在其自身上是微不足道的。然而,这些特性可以被聚合成一个更故意义的特性,对您试图办理的问题更故意义。例如,一些数据实例可以在在线购物网站上呈现,每次客户登录网站时都会产生数据对象。这些数据对象可以通过丢弃额外的实例来聚合成登录次数的计数。因此,考虑适当的特性聚合来精确处理数据。
    Apache Spark 具有其分布式数据结构,包罗 RDD、DataFrame 和 Datasets,您可以使用这些数据结构高效地进行数据预处理。这些数据结构在处理数据时具有差别的优势和性能。在接下来的章节中,我们将分别描述这些数据结构,并展示怎样使用它们处理大型数据集的示例。
    弹性分布式数据集底子知识

    在第一章中,使用 Spark 进行数据分析简介,我们扼要描述了弹性分布式数据集,包罗数据转换和操作以及缓存机制。我们还指出 RDD 基本上是一个不可变的记载集合,只能通过 map、filter、group by 等操作来创建。在本章中,我们将使用 Spark 的这种本机数据结构进行数据操作和数据预处理,用于一个常被称为垃圾邮件过滤的实际机器学习应用。Spark 还提供了另外两个更高级别的 API,如 DataFrame 和 Datasets,用于数据操作。
    然而,我们将展示包罗 RDD 在内的全部 API,因为您可能须要这个 API 来处理更复杂的数据操作。我们已经从 Spark 编程指南中引用了一些关于 Spark 操作和操作的常用界说。
    正如我们已经讨论过使用操作和转换的 RDD 操作的一些底子知识。RDD 可以通过稳定的存储(如 Hadoop 分布式文件系统(HDFS))和对现有 RDD 的转换来创建。Spark 定期记载这些转换,而不是实际数据,因此从技能上讲,原始 RDD 和数据集不会发生变革。
    可以从现有数据集创建一个转换后的数据集;但是在 Spark 中不可能反过来。在数据集上完成计算后,操作将返回一个值给驱动步伐。例如,根据 Spark 编程指南,map 是一种通过函数传递每个数据集元素并返回一个全新的 RDD 来表示和保存结果的转换。相反,reduce 也是一种通过函数聚合 RDD 的全部元素并返回一个全新的 RDD 作为终极结果返回给驱动步伐的操作。
    更具体地说,假设我们有一个包含以逗号分隔的数字序列的文本文件(即 CSV 文件)。如今在读取完毕后,您将拥有一个 RDD,因此您可能盼望计算每个数字的频率。为此,您须要将 RDD 转换为键值对,其中键是数字,值将是每个数字的频率。
    另一方面,您可能须要通过一些操作在驱动步伐中收集结果。在接下来的几节中,我们将通过基于实际机器学习问题的一些示例,提供有关转换和操作等一些有用主题的更多细节。
    读取数据集

    为了从差别的数据源(如当地文件系统、HDFS、Cassandra、HBase 等)读取数据集,Spark 提供了易于使用的差别 API。它支持包罗文本文件、序列文件、Hadoop 输入格式、CSV、TSV、TXT、MD、JSON 和其他数据格式在内的差别数据表示。输入 API 或方法支持在压缩文件、目录和通配符上运行。例如,表 1表现了读取格式的列表。textFile()方法从目录/my/directory中读取差别的文件格式,如.txt和.gz。
    textFile(“/my/directory”),textFile(“/my/directory/.txt"),textFile("/my/directory/.gz”). 表 1:读取文件格式
    从文件中读取

    您可能须要从当地或 HDFS 读取数据集。以下代码展示了从存储在当地机器或 HDFS 上的给定数据集创建 RDD 的差别方法。
    然而,在使用 Spark 进行读取和写入之前,我们须要通过 Spark 会话创建 Spark 入口点,可以通过以下方式实例化:
    1. static SparkSession spark = SparkSession
    2.       .builder()
    3.       .appName("JavaLDAExample")
    4.       .master("local[*]")
    5.       .config("spark.sql.warehouse.dir", "E:/Exp/")
    6.       .getOrCreate();
    复制代码
    在这里,Spark SQL 仓库设置为E:/Exp/路径。您应该根据您地点的操作系统范例设置您的路径。好了,如今我们有了变量spark作为我们的 Spark 会话,让我们看看怎样轻松地使用它来从文本文件中读取。
    从文本文件中读取

    它使用SparkContext()的textFile()方法,并返回一个包含行集合的字符串的 RDD。在第一章中,我们解释了什么是 SparkContext。只管如此,Spark Context 是 Spark 应用步伐的入口点。假设我们有一个名为1.txt的数据集,其中包含一些推文数据作为非结构化文本。您可以从 Packt 材料中下载数据,并将其存储在project_path/input/test/目录下,界说如下:
    1. String csvFile = "input/test/1.txt";
    2. RDD<String> distFile = spark.sparkContext().textFile(csvFile, 2);
    复制代码
    在这里,我们已经创建了一个存储在变量distFile中的字符串的两个分区的 RDD。但是,要使用 Java,RDD 必须转换为 JavaRDD。通过调用toJavaRDD()方法来实现:
    1. JavaRDD<String> distFile2 = distFile.toJavaRDD();
    复制代码
    从目录中读取多个文本文件

    它将返回 RDD 作为(文件名和内容)对。假设我们有多个文件存储在csvFiles/目录中以供读取,界说如下:
    1. RDD<Tuple2<String, String>> distFile = spark.sparkContext().wholeTextFiles("csvFiles/*.txt", 2);
    2. JavaRDD<Tuple2<String, String>> distFile2 = distFile.toJavaRDD();
    复制代码
    请注意,当 RDD 中的数据对象不存储在主内存或 HDD 中时,我们须要对 RDD 实行分区以增加并行性。
    从现有集合中读取

    创建 RDD 的第二个泉源是从驱动步伐步伐的集合中,例如包含整数的列表。在深入讨论之前,让我们以另一种方式初始化 Spark,如下所示:
    1. SparkConf conf = new SparkConf().setAppName("SampleAppliation").setMaster("local[*]");
    2. JavaSparkContext sc = new JavaSparkContext(conf);
    复制代码
    这里 Java Spark 上下文可用作变量sc。这一次,我们已经创建了 Spark 上下文,因此我们将可以或许创建字符串的 Java RDD,而无需使用toJavaRDD()方法。
    如今,您可以使用 Spark Context 的并行化方法来实现:


    • 读取整数列表:它返回一个并行化的整数 RDD:
    1.       List<Integer> list = Arrays.asList(1,2,3,4,5);
    2.       JavaRDD<Integer> rdd = sc.parallelize(list);
    复制代码


    • 读取成对列表:它返回一个并行化的pairRDD,其中包含成对的整数和字符串:
    1.       List<Tuple2<Integer, String>> pairs = Arrays.asList(
    2.                 new Tuple2<>(1, "Hello"),
    3.                 new Tuple2<>(2, "World"),
    4.                 new Tuple2<>(3, "How are you?"));
    5.       JavaPairRDD<Integer, String> pairRDD = sc.parallelizePairs(pairs);
    复制代码
    RDD 的预处理

    为了继续讨论我们在上一节开始的数据预处理,我们将在本节中展示一个机器学习问题的示例,以及怎样使用 RDD 对数据集进行预处理。
    我们正在考虑的是垃圾邮件过滤器应用步伐,这是一个受接待的监督学习问题的典型示例。问题是从传入的电子邮件中预测和识别垃圾邮件消息(请参阅表 2)。通常,为了练习模型,您必须使用历史数据(您在几天、几小时或几个月甚至一年内收到的历史电子邮件)来练习模型。预处理任务的终极输出是制作特性向量或提取包罗其标签或类别的特性。通常,您可能会实行以下步调:


    • 停用词去除:文本文件可能包含一些对于特性向量无用或多余的单词,例如andtheof,因为这些单词在全部情势的英语句子中都非经常见。另一个原因是它们在决定垃圾邮件或正常邮件状态时没有太多意义,大概它们可能包含微不足道的意义。因此,在进行下一步之前,须要从电子邮件数据会合过滤掉这些单词。
    • 词形还原:一些具有雷同含义但差别末端的单词须要被调整,以使它们在整个数据会合保持划一,假如它们都具有雷同的情势,将更容易将它们转换为特性向量。例如,attachedattachmentattach都可以表示为电子邮件attachments。SMSSpamCollection数据集可以从 UCI ML 存储库archive.ics.uci.edu/ml/machine-learning-databases/00228/下载。
    请注意,在这个阶段,电子邮件正文中的全部单词通常都会被转换为小写。如今,让我们来看一下下表:
    ham: 你在干什么?你好吗?ham: 好的啦…只是和你开玩笑。ham: 不要这么早说…你已经看到了然后说。ham: 我的号码在卢顿 0125698789,假如你在附近给我打电话!H*spam: 免费信息:短信:拨打 86888 号码,领取您的 3 小时通话时间嘉奖,如今可以在您的手机上使用!订阅 6 英镑/月,包罗 3 小时 16 次克制?txtStop ham: 西瓦在宿舍哈哈。ham: 因为我刚才和达伦出去购物,我给他打电话问他想要什么礼物。然后他开始猜我和谁在一起,末了他猜到了是达伦。spam: 阳光测验!假如你能说出澳大利亚的首都,就赢得一个超级索尼 DVD 录像机!发送 MQUIZ 到 82277. B 表 2:包含正常邮件和垃圾邮件消息的练习集的测试文件


    • 去除非单词:数字和标点也必须被去除。然而,由于页面限定和简洁性,我们不会在这里展示全部可能的预处理数据的转换,但我们将尝试展示一些基本的预处理数据的转换和操作,其中包含一些标签数据,如表 2中所示。数据集或电子邮件被标记为正常邮件或垃圾邮件,后面跟着消息或电子邮件。正常邮件意味着非垃圾邮件,垃圾邮件被识别为垃圾邮件消息。
    使用 RDD 进行的整体预处理可以用以下步调描述。我们须要的第一步是使用 RDD 操作和转换预备特性向量。其余步调如下:


    • 读取数据集:以下代码用于读取数据集,从SMSSpamCollection数据集创建一个字符串的linesRDD。请从 Packt 材料中下载这个数据集,并将其存储在您的磁盘或 HDFS 中的Project+path/input/目录中。稍后将提供有关此数据集的详细描述:
    1.       String filePath = "input/SMSSpamCollection.txt";
    2.       JavaRDD<String> linesRDD = sc.textFile(filePath);
    复制代码
    然而,linesRDD包含了垃圾邮件和正常邮件消息。因此,我们须要从文件中分离垃圾邮件和正常邮件。


    • 过滤垃圾邮件:为了从现有的 RDD 中过滤数据,Spark 提供了一个名为filter()的方法,它返回一个只包含所选元素的新数据集。在下面的代码中,您可以看到我们已经将new Function()作为参数传递给了filter()方法,它接受两个范例为 String 和 Boolean 的参数。基本上,Spark API 在集群上运行时大量依赖于将函数传递给驱动步伐。有两种方法可以创建包含函数的函数,包罗:
    • 实现函数接口,无论是创建匿名内部类还是定名内部类,并将其实例传递给 Spark
    • 使用 lambda 表达式(只管您须要安装 Java 8 才能利用 lambda 表达式)
    • 以下代码片段说明了我们使用的匿名类概念作为包含call()方法的参数,假如行包含单词spam,则返回true:
    1.       JavaRDD<String> spamRDD = linesRDD.filter(new Function<String,   
    2.         Boolean>() {
    3.         @Override
    4.         public Boolean call(String line) throws Exception {
    5.           return line.split("\t")[0].equals("spam");}});
    复制代码


    • 过滤掉正常邮件:同样,我们可以过滤掉正常邮件,如下所示:
    1.       JavaRDD<String> hamRDD = linesRDD.filter(new Function<String,  
    2.        Boolean>() {
    3.        @Override
    4.        public Boolean call(String line) throws Exception {
    5.          return line.split("\t")[0].equals("ham");
    6.         }
    7.      });
    复制代码


    • 从行中分割单词:为了从每行中提取特性和标签,我们须要使用空格或制表符来分割它们。之后,我们可以得到不包含垃圾邮件或正常邮件单词的行。
    以下代码段表现了从行中分离垃圾邮件和正常邮件特性。我们使用了map转换,它返回一个新的 RDD,通过将现有 RDD 的每一行传递给call函数来形成。这里call方法总是返回一个单个项目。您将在后面的部门中发现与flatMap的区别:
    1.       JavaRDD<String> spam = spamRDD.map(new Function<String, String>() {
    2.         @Override
    3.         public String call(String line) throws Exception {      
    4.          return line.split("\t")[1];
    5.         }
    6.      });
    复制代码
    输出:ham.collect():

    图 1:垃圾邮件 RDD 的快照
    1.       JavaRDD<String> ham = hamRDD.map(new Function<String, String>() {
    2.         @Override
    3.         public String call(String line) throws Exception {     
    4.           return line.split("\t")[1];
    5.       }
    6.       });
    复制代码
    输出:ham.collect():

    图 2:正常邮件 RDD 的快照


    • 从垃圾邮件 RDD 的行中拆分单词:在我们分别得到垃圾邮件和正常邮件 RDD 的特性行之后,我们须要拆分单词以便在将来创建特性向量。以下代码通过使用空格进行拆分并返回单词列表 RDD。调用方法返回每行的单词列表:
    1.       JavaRDD<ArrayList<String>> spamWordList = spam.map(new  
    2.         Function<String, ArrayList<String>>() {
    3.           @Override
    4.       public ArrayList<String> call(String line) throws Exception{
    5.             ArrayList<String> words = new ArrayList<>();
    6.             words.addAll(Arrays.asList(line.split(" ")));
    7.             return words;
    8.           }});
    9.       JavaRDD<ArrayList<String>> hamWordList = ham.map(new Function<String,  
    10.         ArrayList<String>>() {
    11.           @Override
    12.       public ArrayList<String> call(String line) throws Exception{   
    13.             ArrayList<String> words = new ArrayList<>();
    14.             words.addAll(Arrays.asList(line.split(" ")));
    15.             return words;}
    16.       });
    复制代码


    • 创建标签和特性对 RDD:如今我们有了垃圾邮件和正常邮件的两个 RDD。我们想要用 1.0 或 0.0 来标记它们,分别表示垃圾邮件和正常邮件的单词或特性。为了方便使用,我们可以再次创建一个新的 RDD,每行包含一个标签和特性或单词列表的元组。在下面的代码中,我们使用了Tuple2来创建一对。您也可以使用JavaPairRDD来创建标签和特性的一对:
    1.       JavaRDD<Tuple2<Double, ArrayList<String>>> spamWordsLabelPair =  
    2.       spamWordList.map(new Function<ArrayList<String>, Tuple2<Double,  
    3.           ArrayList<String>>>() {
    4.           @Override
    5.             public Tuple2<Double, ArrayList<String>> call(
    6.             ArrayList<String> v1) throws Exception {     
    7.             return new Tuple2<Double, ArrayList<String>>(1.0, v1);
    8.           }});
    9.       JavaRDD<Tuple2<Double, ArrayList<String>>> hamWordsLabelPair =  
    10.       hamWordList.map(new Function<ArrayList<String>, Tuple2<Double,  
    11.           ArrayList<String>>>() {
    12.           @Override
    13.           public Tuple2<Double, ArrayList<String>> call(
    14.             ArrayList<String> v1) throws Exception {     
    15.             return new Tuple2<Double, ArrayList<String>>(0.0, v1);
    16.           }});
    17.       [Output: print spamWordsLabelPair2.collect() using for loop]
    18.       1.0: [FreeMsg:, Txt:, CALL, to, No:, 86888, &, claim, your, reward,
    19.       of, 3, hours, talk, time, to, use, from, your, phone, now!,
    20.       ubscribe6GBP/, mnth, inc, 3hrs, 16, stop?txtStop]
    21.       1.0: [Sunshine, Quiz!, Win, a, super, Sony, DVD, recorder,
    22.       if, you, canname, the, capital, of, Australia?, Text, MQUIZ,
    23.       to, 82277., B]
    复制代码


    • 两个 RDD 的并集:如今我们在表 2中有数据集的两个标签,即垃圾邮件和正常邮件的特性对 RDD。如今要创建练习数据集,我们可以将这两个 RDD 合并成一个。Spark 有一个union()方法可以做到这一点,它返回一个新的 RDD,包含数据集和参数或另一个数据集的并集:
    1.       JavaRDD<Tuple2<Double, ArrayList<String>>> train_set =  
    2.       spamWordsLabelPair.union(hamWordsLabelPair);
    复制代码


    • 对于前面的全部操作,称为转换。这在每种情况下都会从现有的工作节点中返回一个新的数据集。假如您想要将返回结果带回驱动步伐或打印结果,那将被称为动作操作。Spark 支持几种内置方法作为动作。count()方法用于计算数据会合的元素数目:
    1.       System.out.println(train_set.count());
    2.       The following output is 8
    复制代码


    • 打印 RDD:collect()和take()也是用于打印或收集数据集作为驱动步伐中的数组的动作方法,其中,take()接受一个参数,比如n,返回数据集的前 n 个元素。以下代码段打印出练习会合的前 10 个元素或元组:
    1.       for (Tuple2<Double, ArrayList<String>> tt : train_set.collect()) {
    2.           System.out.println(tt._1 + ": " + tt._2.toString()); }
    复制代码
    输出如下:
    1.       1.0: [FreeMsg:, Txt:, CALL, to, No:, 86888,
    2.        &, claim, your, reward, of, 3, hours, talk, time, to, use, from,
    3.        your, phone, now!, ubscribe6GBP/, mnth, inc, 3hrs, 16, stop?txtStop]
    4.       1.0: [Sunshine, Quiz!, Win, a, super, Sony, DVD, recorder, if,
    5.       you, canname, the, capital, of, Australia?, Text, MQUIZ,
    6.       to, 82277., B]
    7.       0.0: [What, you, doing?, how, are, you?]
    8.       0.0: [Ok, lar..., Joking, wif, u, oni...]
    9.       0.0: [dun, say, so, early, hor..., U, c, already, then, say...]
    10.       0.0: [MY, NO., IN, LUTON, 0125698789, RING, ME, IF, UR, AROUND!, H*]
    11.       0.0: [Siva, is, in, hostel, aha:-.]
    12.       0.0: [Cos, i, was, out, shopping, wif, darren, jus, now,
    13.        n, i, called,
    14.       him, 2, ask, wat, present, he, wan, lor., Then, he,
    15.       started, guessing,
    16.       who, i, was, wif, n, he, finally, guessed, darren, lor.]
    复制代码


    • 将结果保存在当地文件系统中:偶然您可能须要将 RDD 保存在文件系统中。您可以使用以下代码直接保存您的 RDD:
    1.       train_set.saveAsTextFile("output.txt");
    复制代码
    从 SMSSpamCollection 数据会合获取见解

    以下源代码表现了基本的正常邮件和垃圾邮件统计信息:
    1. String path = "input/SMSSpamCollection.txt";     
    2. RDD<String> lines = spark.sparkContext().textFile(path, 2);
    3. System.out.println(lines.take(10));
    4. JavaRDD<Row> rowRDD = lines.toJavaRDD().map( new Function<String, Row>() {
    5.     public Row call(String line) throws Exception {
    6.       return RowFactory.create(line);
    7.       }});
    8. System.out.println(rowRDD.collect());
    9. List<StructField> fields = new ArrayList<StructField>();
    10. fields.add(DataTypes.createStructField("line", DataTypes.StringType, true));
    11. org.apache.spark.sql.types.StructType schema = DataTypes.createStructType(fields);
    12. Dataset<Row> df = spark.sqlContext().createDataFrame(rowRDD, schema);
    13. df.select("line").show();
    14. Dataset<Row> spam = df.filter(df.col("line").like("%spam%"));
    15. Dataset<Row> ham = df.filter(df.col("line").like("%ham%"));
    16. System.out.println(spam.count());
    17. System.out.println(ham.count());
    18. spam.show();
    复制代码
    上述代码生成了以下垃圾邮件和正常邮件计数:
    1. 747
    2. 4831
    复制代码
    这意味着在 5578 封电子邮件中,有 747 封是垃圾邮件,4831 封被标记为正常邮件或非垃圾邮件。换句话说,垃圾邮件和正常邮件的比例分别为 13.40%和 86.6%。
    处理键值对

    本小节描述了在数据分析中经常须要的键值对,特殊是在文本处理中。
    mapToPair()

    这个方法将返回一个(K,V)对的数据集,其中 K 是键,V 是值。例如,假如您有一个包含整数列表的 RDD,然后想要计算列表中重复条目的数目,那么第一步是将每个数字映射为 1。之后您可以对其进行 reduce 操作。该代码产生了如下所示的输出和缓存:
    1. JavaRDD<Integer> rdd = sc.parallelize(Arrays.asList(1,2,1,3,4,5));
    2. JavaPairRDD<Integer, Integer> pairs = rdd.mapToPair(
    3.   new PairFunction<Integer, Integer, Integer>() {
    4.     @Override
    5.     public Tuple2<Integer, Integer> call(Integer x) {
    6.       return new Tuple2<>(x, 1);
    7.     }
    8. }).cache();
    9. [Output: pairs.collect()]
    10. [(1,1), (2,1), (1,1), (3,1), (4,1), (5,1)]
    复制代码
    更多关于转换的内容

    在本节中,您可以相识更多关于转换的内容,包罗一些类似方法之间的差异。重要将讨论map和flatMap,groupByKey,reduceByKey和aggregateByKey,sortByKey和sortBy。然而,有兴趣的读者可以参考[2]中的 Spark 编程指南相识 RDD 操作。
    map 和 flatMap

    flatMap类似于我们在前面的示例中展示的map,但是每个输入项或每次调用匿名类的call()方法都可以映射到零个或多个输出项。因此,call()函数返回的是一个序列,而不是像map那样返回单个项。例如,对于以下 RDD 的输入,输出应该如下所示:
    1. JavaRDD<String> rdd = sc.parallelize(Arrays.asList("Hello World!",
    2.   "How are you."));
    3. JavaRDD<String> words = rdd
    4.   .flatMap(new FlatMapFunction<String, String>() {
    5.     @Override
    6.     public Iterable<String> call(String t) throws Exception {
    7.       return Arrays.asList(t.split(" "));
    8.     }});
    9. [output: words.collect()]
    10. [Hello, World!, How, are, you.]
    复制代码
    对于前面的示例,您无法实行映射操作,因为map的call()方法只返回一个对象,而不是一系列对象。
    groupByKey,reduceByKey 和 aggregateByKey

    为了在预处理数据集时实行一些操作,您可能须要根据键值进行一些汇总,例如求和宁静均值。Spark 提供了一些方法来实行这些范例的操作。假设您有以下 RDD 对,而且您想根据键对值进行分组并进行一些汇总:
    1. JavaPairRDD<Integer, Integer> rdd_from_integer = sc
    2. .parallelizePairs(Arrays.asList( new Tuple2<>(1, 1),  
    3. new Tuple2<>(1, 1), new Tuple2<>(3, 2),
    4. new Tuple2<>(5, 1), new Tuple2<>(5, 3)), 2);  
    复制代码
    您想要实行的汇总可以通过 Spark 的三种方法来完成,包罗groupByKey,reduceByKey和aggregateByKey。但它们在性能、服从和灵活性方面有所差别,可以实行诸如计数、计算摘要统计信息、从数据会合找到唯一元素等操作。groupByKey方法返回一个(k,Iterable<v>)对的数据集,其中 k 是键,Iterable<v>是键 k 的值序列。使用此方法的先前数据集的输出如下所示,表现了每个键的集合值:
    1. [Output: pairs.groupByKey(2).collect() ]
    复制代码

    图 3:使用 groupBykey 的对
    为了对每个唯一键的值进行求和,groupByKey在性能上是低效的,因为它不实行组合的映射。您必须进行更多的转换来明确进行这种求和。因此,它会增加网络 I/O 和洗牌大小。通过reduceByKey或aggregateByKey可以得到更好的性能,因为它们实行映射端的组合。
    这些方法返回具有每个键聚合结果的数据集,例如每个键的值的总和。以下代码表现了这些方法的操作,它们返回由给定函数聚合键的值的(k,v)对的数据集。
    reduceByKey须要一个函数,用于减少每个键的值,而aggregateByKey须要两个函数,其中第一个函数用于指定如安在每个分区内进行聚合,第二个函数用于指定如安在分区之间进行聚合:


    • 代码:reduceByKey():
    1.       JavaPairRDD<Integer, Integer> counts = rdd
    2.         .reduceByKey(new Function2<Integer, Integer, Integer>() {
    3.           @Override
    4.           public Integer call(Integer a, Integer b) {
    5.             return a + b;}});
    复制代码


    • 代码:aggregateByKey():
    1.       JavaPairRDD<Integer, Integer> counts = pairs.aggregateByKey(0,
    2.           new Function2<Integer, Integer, Integer>() {
    3.             @Override
    4.             public Integer call(Integer v1, Integer v2) {
    5.               return v1 + v2;
    6.             }
    7.             }, new Function2<Integer, Integer, Integer>() {
    8.             @Override
    9.             public Integer call(Integer v1, Integer v2) {
    10.                   return v1 + v2;
    11.                 }
    12.               });
    复制代码
    对于这两种情况,输出将如下所示:
    counts.collect()的输出:

    图 4:使用计数的 RDD
    sortByKey 和 sortBy

    排序是数据预处理中的常见操作。Spark 提供了两种方法,可以将一个数据集转换为另一个排序的配对数据集,包罗sortByKey和sortBy。例如,我们有一个如下所示的数据集:
    1. List<Tuple2<Integer, Integer>> pairs = new ArrayList<>();
    2. pairs.add(new Tuple2<>(1, 5));
    3. pairs.add(new Tuple2<>(4, 2));
    4. pairs.add(new Tuple2<>(-1, 1));
    5. pairs.add(new Tuple2<>(1, 1));
    复制代码
    sortByKey()方法在(k,v)对上实行,并按键的升序或降序返回(k,v)对。您还可以通过提供比力器来自界说排序。以下代码表现了对前面数据集的键进行排序:


    • 代码:sortByKey():
    1.       JavaPairRDD<Integer, Integer> rdd = sc.parallelizePairs(pairs);
    2.       JavaPairRDD<Integer, Integer> sortedRDD=rdd.sortByKey(Collections.
    3.       <Integer> reverseOrder(), false);
    4.       [Output: sortedRDD.collect()]
    复制代码

    图 5:使用 sortByKey 的对
    sortBy()方法接受一个函数作为参数,您可以在其中指定排序方法,无论是按键还是按值。以下代码表现了对前面数据集的值进行排序:


    • 代码:sortBy():
    1.       JavaRDD<Tuple2<Integer, Integer>> rdd_new = sc.parallelize(pairs);
    2.       JavaRDD<Tuple2<Integer, Integer>> sortedRDD=rdd.sortBy(
    3.       new Function<Tuple2<Integer, Integer>, Integer>() {
    4.       @Override
    5.           public Integer call(Tuple2<Integer, Integer> t) {
    6.               return t._2();
    7.           }
    8.       ,} true, 2);
    复制代码
    sortedRDD.collect()的输出:

    图 6:使用 sortBy 的对
    数据集底子知识

    如在第一章中讨论的,使用 Spark 进行数据分析简介,在 Spark 2.0.0 发布中,DataFrame 仍旧是 Scala、Python 和 R 的重要计算抽象,但在使用 Java 时,将使用 Dataset 替换。因此,本书中将始终使用范例为 Row 的 Dataset。
    Dataset 是一个分布式的数据集合,结构化为行。这是与 Spark SQL 模块交互的更方便的方式之一。
    换句话说,它可以被视为类似于关系数据库(RDB)格式的等价实体。与 DataFrame 和 RDD 等其他数据抽象一样,Dataset 也可以从各种数据源创建,如结构化数据文件(TSV、CSV、JSON 和 TXT)、Hive 表、辅助存储、外部数据库或现有的 RDD 和 DataFrame。然而,在 Spark 2.0.0 发布后,基于 Java 的计算不支持 DataFrame,但假如您使用 Python、Scala 或 R 开发应用步伐,仍旧可以使用 DataFrame。
    在接下来的几节中,您将找到使用 Dataset 的操作和操作,以及怎样从差别的泉源创建 Dataset。
    读取数据集以创建 Dataset

    如上所述,Dataset 是从 Spark 1.5.0 版本开始引入的 Spark SQL 模块的一个组件。因此,全部功能的入口都始于初始化 Spark SQLContext。基本上,Spark SQL 用于实行 SQL 查询,可以使用基本的 SQL 语法或 HiveQL 编写。
    在另一种编程语言中运行 SQL 时,将返回一个 Dataset 对象。以下代码段将在 Spark 上下文中初始化SQLContext。另一方面,您可能须要初始化HiveContext以从 Hive 中读取数据集。您还可以创建一个差别的上下文,如HiveContext,它提供了SQLContext基本功能的超集:
    1. JavaSparkContext sc = new JavaSparkContext("local","DFDemo");
    2. SQLContext sqlContext = new org.apache.spark.sql.SQLContext(sc);
    复制代码
    从文件中读取

    例如,您有一个如下所示的 JSON 文件。如今您想要使用 SQL 上下文读取此文件,基本上返回一个 DataFrame,您可以实行全部基本的 SQL 操作和其他 Spark 的 DSL 操作:
    1. [Input File]
    2. {"name":"Michael"}
    3. {"name":"Andy", "age":30}
    4. {"name":"Justin", "age":19}
    5. [Code]   
    6. Dataset<Row> df = sqlContext.read().json("people.json");   
    7. [Output: df.show()]
    8. +----+-------+
    9. | age|   name|
    10. +----+-------+
    11. |null|Michael|
    12. |  30|   Andy|
    13. |  19| Justin|
    14. +----+-------+
    复制代码
    从 Hive 中读取

    以下代码毗连到 Hive 上下文,其中创建了一个表,并将 people JSON 文件加载到 Hive 中。DataFrame 的输出将与上述雷同:
    1. The code is as follows:]hiveContext.sql("CREATE TEMPORARY TABLE people USING  
    2. org.apache.spark.sql.json OPTIONS ( path "people.json" )");
    3. Dataset<Row> results = hiveContext.sql("SELECT * FROM people ");
    4. results.show();
    复制代码
    使用 Dataset 进行预处理

    在前一节中,我们已经描述了在实际机器学习应用步伐中使用 RDD 进行预处理。如今我们将使用 DataFrame(DF)API 进行雷同的示例。您会发现很容易操作SMSSpamCollection数据集(请参阅www.dt.fee.unicamp.br/~tiago/smsspamcollection/)。我们将展示雷同的示例,通过对垃圾邮件和正常消息进行标记化,以预备一个练习集:


    • 读取数据集:您可以使用初始化之前的 Spark 会话变量spark来读取该数据集。读取文件作为 Dataset 后,输出将是单列的表格格式。此列的默认名称是value:
    1.       Dataset<Row> df = spark.read().load("input/SMSSpamCollection.txt");
    2.       df.show();
    复制代码
    输出:

    图 7:SMS 垃圾邮件数据集的快照


    • 从现有数据集创建 Row RDD:从前面的输出中,您可以看到一个包含全部行在一起的列。为了使两列,如标签和特性,我们必须将其拆分。由于 Dataset 是不可变的,您无法修改现有的列或 Dataset。因此,您必须使用现有的 Dataset 创建新的 Dataset。这里的代码将 Dataset 转换为 Row 数据集的集合。Row 是一个接口,表示来自关系运算符的输出的一行。您可以使用 Spark 的RowFactory类创建一个新的 Row:
    1.          JavaRDD<Row> rowRDD = df.toJavaRDD();
    复制代码


    • 从现有的行 RDD 创建新的行 RDD:在拥有行 RDD 之后,您可以实行常规的 map 操作,其中包含全部包含两个值的行数据集。以下代码拆分每一行并返回一个新的行:
    1.       JavaRDD<Row> splitedRDD = rowRDD.map(new Function<Row, Row>() {
    2.            @Override
    3.           public Row call(Row r) throws Exception {
    4.             String[] split = r.getString(0).split("\t");
    5.             return RowFactory.create(split[0],split[1]);
    6.           }});
    复制代码


    • 从行 RDD 创建数据集:如今您有了包含每行两个值的行 RDD。要创建 DF,您必须界说列名或模式及其数据范例。有两种方法可以界说,包罗使用反射推断模式和以编程方式指定模式。方法如下:
    • 第一种方法基本上使用 POJO 类和字段名称将成为模式
    • 第二种方法通过界说数据范例并创建 structype 来创建 StruchFields 列表。在本例中,我们使用了第二种方法来从现有行 RDD 创建 DF,如下所示:
    1.       List<StructField> fields  = new ArrayList<>();
    2.       fields.add(DataTypes.createStructField("labelString",
    3.       DataTypes.StringType, true));
    4.       fields.add(DataTypes.createStructField("featureString",  
    5.       DataTypes.StringType, true));
    6.       org.apache.spark.sql.types.StructType schema = DataTypes
    7.       .createStructType(fields);
    8.       Dataset<Row> schemaSMSSpamCollection = sqlContext
    9.       .createDataFrame(splitedRDD, schema);
    10.       schemaSMSSpamCollection.printSchema();
    11.       [Output: schemaSMSSpamCollection.printSchema()]
    复制代码

    图 8:集合的模式


    • 添加新列:如今我们有了两列的 DF。但是我们想要添加新列,将labledSting转换为labedDouble,将featureString转换为featureTokens。您可以像从前的代码一样进行操作。在添加新字段后,创建新模式。然后在现有 DF 中进行常规 map 转换后创建新 DF。以下代码给出了具有四列的新 DF 的输出:
    1.       fields.add(DataTypes.createStructField("labelDouble",  
    2.       DataTypes.DoubleType, true));
    3.       fields.add(DataTypes.createStructField("featureTokens",  
    4.       DataTypes.StringType, true));
    5.       org.apache.spark.sql.types.StructType schemaUpdated =  
    6.       DataTypes.createStructType(fields);
    7.       Dataset Row> newColumnsaddedDF = sqlContext
    8.       .createDataFrame(schemaSMSSpamCollection.javaRDD().map(
    9.       new Function<Row, Row>() {
    10.           @Override
    11.           public Row call(Row row) throws Exception {
    12.             double label;
    13.             if(row.getString(0).equalsIgnoreCase("spam"))
    14.               label = 1.0;
    15.             else
    16.               label = 0.0;
    17.             String[] split = row.getString(1).split(" ");
    18.             ArrayList<String> tokens = new ArrayList<>();
    19.             for(String s:split)
    20.               tokens.add(s.trim());
    21.             return RowFactory.create(row.getString(0),
    22.        row.getString(1),label, tokens.toString());
    23.           }}), schemaUpdated);   
    24.       [Output: newColumnsaddedDF.show()]
    复制代码

    图 9:添加新列后的数据集


    • 一些数据集操作:对于数据操作,DF 提供了 Java、Scala 等范畴特定语言。您可以对 DF 进行选择、计数、过滤、groupBy等操作。以下代码展示了对上述 DF 的一些操作:
    1.       newColumnsaddedDF.select(newColumnsaddedDF.col("labelDouble"),
    2.       newColumnsaddedDF.col("featureTokens")).show();
    复制代码

    图 10:表现标签和特性的数据集
    1.       newColumnsaddedDF.filter(newColumnsaddedDF.col
    2.       ("labelDouble").gt(0.0)).show();
    复制代码

    图 11:数据集表现标签已转换为双值
    1.       newColumnsaddedDF.groupBy("labelDouble").count().show();
    复制代码

    图 12:表现操作后的数据集统计信息
    更多关于数据集操作

    本节将描述如安在 DF 上使用 SQL 查询以及在数据集之间创建差别方式的数据集。重要讨论在 DataFrame 上运行 SQL 查询以及从 JavaBean 创建 DataFrame。然而,有兴趣的读者可以参考 Spark 编程指南中有关 SQL 操作的内容[3]。
    在数据集上运行 SQL 查询

    Spark 的SQLContext具有sql方法,使应用步伐可以或许运行 SQL 查询。该方法返回一个 DataFrame 作为结果:


    • [FilternewColumnsAddedDF.createOrReplaceTempView(SMSSpamCollection)]:
    1.       Dataset<Row> spam = spark.sqlContext().sql("SELECT * FROM
    2.       SMSSpamCollection
    3.       WHERE labelDouble=1.0");
    4.       spam.show();  
    复制代码
    以下是上述代码的输出:

    图 13:使用 SQL 查询检索与图 11 雷同的结果


    • 计数:
    1.       Dataset<Row> counts = sqlContext.sql("SELECT labelDouble, COUNT(*)  
    2.       AS count FROM SMSSpamCollection GROUP BY labelDouble");
    3.       counts.show();
    复制代码
    输出:

    图 14:表现数据集统计信息
    从 Java Bean 创建数据集

    您可以从 Java Bean 创建数据集;在这种情况下,您不须要以编程方式界说模式。例如,您可以在以下代码中看到名为 Bean 的普通旧 Java 对象POJO):
    1. public class SMSSpamBean implements Serializable {
    2.   private String labelString;
    3.   private String featureString;
    4. public SMSSpamBean(String labelString, String featureString) {
    5.     super();
    6.     this.labelString = labelString;
    7.     this.featureString = featureString;
    8.   }
    9.   public String getLabelString() {
    10.     return labelString;
    11.   }
    12.   public void setLabelString(String labelString) {
    13.     this.labelString = labelString;
    14.   }
    15.   public String getFeatureString() {
    16.     return featureString;
    17.   }  public void setFeatureString(String featureString) {    this.featureString = featureString;
    18.   }}  
    复制代码
    创建 DF:
    1. JavaRDD<SMSSpamBean> smsSpamBeanRDD =  rowRDD.map(new Function<Row, SMSSpamBean>() {
    2.       @Override
    3.     public SMSSpamBean call(Row r) throws Exception {
    4.         String[] split = r.getString(0).split("\t");
    5.         return new SMSSpamBean(split[0],split[1]);
    6.       }});   
    7. Dataset<Row> SMSSpamDF = spark.sqlContext().createDataFrame(smsSpamBeanRDD, SMSSpamBean.class);
    8. SMSSpamDF.show();   
    复制代码
    以下输出如下:

    图 15:相应的特性和标签字符串
    从字符串和范例化类创建数据集

    如前所述,数据集是一组对象的范例化和不可变集合。数据集基本上映射到关系模式。使用数据集抽象,Spark 引入了一个新概念,称为编码器。编码器有助于实体转换,例如 JVM 对象与相应的表格表示之间的转换。您会发现这个 API 与 RDD 的转换非常相似,比如map、mapToPair、flatMap或filter。
    我们将在下一节中展示使用数据集 API 的垃圾邮件过滤示例。它使用文本文件读取并返回数据集作为表格格式。然后实行类似 RDD 的映射转换,以添加额外的编码器参数(标签、令牌列)。在这里,我们使用了SMSSpamTokenizedBean类的 bean 编码器。
    在本小节中,我们将展示怎样从字符串和范例类SMSSpamTokenizedBean创建数据集。起首让我们创建 Spark 会话,如下所示:
    1. static SparkSession spark = SparkSession.builder()
    2.       .appName("DatasetDemo")
    3.       .master("local[*]")
    4.       .config("spark.sql.warehouse.dir", "E:/Exp/")
    5.       .getOrCreate();
    复制代码
    如今从smm过滤数据集创建一个新的 String 范例的数据集,即Dataset<String>,并表现结果如下:
    1. Dataset<String> ds = spark.read().text("input/SMSSpamCollection.txt").as(org.apache.spark.sql.Encoders.STRING());
    2. ds.show();
    复制代码
    以下是前面代码的输出:

    图 16:表现使用数据集进行垃圾邮件过滤的快照
    如今让我们通过将我们之前创建的字符串数据集映射为SMSSpamTokenizedBean范例的第二个数据集,来创建第二个数据集,如下所示:
    1. Dataset<SMSSpamTokenizedBean> dsSMSSpam = ds.map(
    2. new MapFunction<String, SMSSpamTokenizedBean>() {
    3.           @Override
    4. public SMSSpamTokenizedBean call(String value) throws Exception {
    5.       String[] split = value.split("\t");
    6.       double label;
    7.       if(split[0].equalsIgnoreCase("spam"))
    8.           label = 1.0;
    9.       else
    10.           label=0.0;
    11. ArrayList<String> tokens = new ArrayList<>();
    12.   for(String s:split)
    13.     tokens.add(s.trim());           
    14.       return new SMSSpamTokenizedBean(label, tokens.toString());
    15.          }
    16. }, org.apache.spark.sql.Encoders.bean(SMSSpamTokenizedBean.class));
    复制代码
    如今让我们打印数据集及其模式,如下所示:
    1. dsSMSSpam.show();
    2. dsSMSSpam.printSchema();
    复制代码
    以下输出为:

    图 17:表现令牌和标签,下方是模式
    如今,假如您想将此范例的数据集转换为 Row 范例,那么您可以使用toDF()方法,而且可以轻松地使用createOrReplaceTempView()方法创建新的Dataset<Row>的暂时视图,如下所示:
    1. Dataset<Row> df = dsSMSSpam.toDF();
    2. df.createOrReplaceTempView("SMSSpamCollection");      
    复制代码
    同样,您可能盼望通过调用show()方法查看雷同的数据集,如下所示:
    1. df.show();
    复制代码
    输出:

    图 18:相应的标签和令牌。标签转换为双值
    如今让我们探索范例类SMSSpamTokenizedBean。该类作为用于标记文本的 Java 标记化 bean 类。更具体地说,该类接受输入,然后设置标签,然后获取标签。其次,它还设置和获取用于垃圾邮件过滤的令牌。包罗 setter 和方法,以下是该类:
    1. public class SMSSpamTokenizedBean implements Serializable {
    2. private Double labelDouble;
    3. private String tokens;     
    4. public SMSSpamTokenizedBean(Double labelDouble, String tokens) {
    5.   super();
    6.   this.labelDouble = labelDouble;
    7.   this.tokens = tokens;
    8.   }
    9.   public Double getLabelDouble() {
    10.     return labelDouble;
    11.   }
    12.   public void setLabelDouble(Double labelDouble) {
    13.     this.labelDouble = labelDouble;
    14.   }
    15.   public String getTokens() {
    16.     return tokens;
    17.   }
    18.   public void setTokens(String tokens) {
    19.     this.tokens = tokens;
    20.   }}
    复制代码
    RDD、DataFrame 和 Dataset 之间的比力

    将数据集作为 Spark 的新数据结构带来一些目标。虽然 RDD API 非常灵活,但偶然很难优化处理。另一方面,DataFrame API 很容易优化,但缺少 RDD 的一些好特性。因此,数据集的目标是允许用户轻松表达对象上的转换,并提供 Spark SQL 实行引擎的优势(性能和鲁棒性)。
    数据集可以实行许多操作,如排序或洗牌,而无需对对象进行反序列化。为此,它须要一个显式的编码器,用于将对象序列化为二进制格式。它可以或许将给定对象(Bean)的模式映射到 Spark SQL 范例系统。另一方面,RDD 基于运行时反射的序列化,而改变数据集对象范例的操作也须要新范例的编码器。
    Spark 和数据科学家的工作流程

    正如已经说明的,数据科学家的一个常见任务是选择数据、数据预处理(格式化、清理和抽样)和数据转换(缩放、分解和聚合)原始数据,以便将其传递到机器学习模型中构建模型。随着实验数据集的增加,传统的单节点数据库将无法处理这些范例的数据集,因此,您须要切换到像 Spark 这样的大数据处理计算。幸运的是,我们有 Spark 作为可扩展的分布式计算系统,可以处理您的数据集。

    图 19:数据科学家使用 Spark 的工作流程
    如今让我们来到确切的点,作为一名数据科学家,起首你将不得不阅读以各种格式提供的数据集。然后阅读数据集将为你提供我们已经描述的 RDDs、DataFrames 和 Datasets 的概念。你可以将数据集缓存到主内存中;你可以从 DataFrame、SQL 或 Datasets 转换读取的数据集。末了,你将实行一个操作,将数据转储到磁盘、计算节点或集群。我们在这里描述的步调基本上形成了一个工作流程,你将按照这个工作流程进利用用 Spark 进行基本数据处理,如图 1所示。
    深入相识 Spark

    在这一部门,我们将展示 Spark 的高级特性,包罗使用共享变量(广播变量和累加器),并讨论它们的基本概念。然而,我们将在后面的章节中讨论数据分区。
    共享变量

    在编程上下文中,共享变量的概念并不新鲜。须要许多函数和方法并利用用的变量称为共享变量。Spark 有一些机制来使用或实现共享变量。在 Spark 中,传递给 Spark 操作的函数(如 map 或 reduce)在远程集群节点上实行。代码或函数在节点上作为变量的独立副本工作,结果的更新不会流传回驱动步伐。然而,Spark 提供了两种常见用法模式的共享变量:广播变量和累加器。
    广播变量

    在 Spark API 中有许多范例和方法须要相识。然而,更多和更详细的讨论超出了本书的范围。
    1. Broadcast<int[]> broadcastVariable=sc.broadcast(new int[] {2,3,4});
    2. int[] values = broadcastVariable.value();
    3. for(int i:values){
    4.   System.out.println(i);}
    复制代码
    累加器

    累加器是另一种共享变量,可以用于实现计数器(如 MapReduce 中)或求和。Spark 只支持累加器为数值范例。然而,你也可以使用现有技能为新的数据范例添加支持[1]。通过调用以下初始值为val的方法创建:
    1. SparkContext. accumulator(val)
    复制代码
    以下代码表现了使用累加器将数组元素相加的用法:
    1. Accumulator<Integer> accumulator = sc.accumulator(0);
    2. sc.parallelize(Arrays.asList(1, 5, 3, 4))
    3. .foreach(x -> accumulator.add(x));   
    4. System.out.println(accumulator.value());
    复制代码
    Spark 编程指南:spark.apache.org/docs/latest/programming-guide.html。
    提示

    有兴趣的读者应该参考以下网页上关于 Spark 和相关材料的内容:
    在本章中,我们使用了 RDDs、Dataset 和 DataFrame API 进行了基本的数据操作。我们还学习了怎样通过这些 API 进行一些复杂的数据操作。我们试图专注于数据操作,以明白一个实际的机器学习问题——垃圾邮件过滤。除此之外,我们还展示了怎样从差别的泉源读取数据。分析和预备你的数据,以明白垃圾邮件过滤作为一个例子。
    Spark RDD 操作:spark.apache.org/docs/latest/programming-guide.html#rdd-operations。
    Spark SQL 操作:spark.apache.org/docs/latest/sql-programming-guide.html。
    总结

    广播变量提供了将只读变量持久化缓存在当地机器上的功能,而不是将副本发送到计算节点或驱动步伐。以一种高效的方式将大型输入数据集的副本提供给 Spark 中的每个节点。它还减少了通信本钱,因为 Spark 使用了高效的广播。广播变量可以通过调用SparkContext.broadcast(v)从变量v创建。以下代码表现了这一点:
    然而,我们并没有开发任何完整的机器学习应用步伐,因为我们的目标只是向您展示实验数据集上的基本数据操作。我们打算在第六章构建可扩展的机器学习管道中开发完整的 ML 应用步伐。
    创建预测模型应该使用哪些特性不仅是一个重要的问题,而且可能是一个须要深入相识问题范畴才能回复的困难问题。可以主动选择数据中对或人正在处理的问题最有用或最相关的特性。考虑到这些问题,下一章将详细介绍特性工程,解释为什么要应用它以及一些特性工程的最佳实践。一些仍不清楚的主题将在下一章中更清楚。

    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
  • 本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    回复

    使用道具 举报

    0 个回复

    倒序浏览

    快速回复

    您需要登录后才可以回帖 登录 or 立即注册

    本版积分规则

    何小豆儿在此

    金牌会员
    这个人很懒什么都没写!

    标签云

    快速回复 返回顶部 返回列表