spark机器学习笔记:(一)Spark Python初探

声明:版权所有,转载请联系作者并注明出处  http://blog.csdn.net/u013719780?viewmode=contents


博主简介:风雪夜归子(英文名:Allen),机器学习算法攻城狮,喜爱钻研Meachine Learning的黑科技,对Deep Learning和Artificial Intelligence充满兴趣,经常关注Kaggle数据挖掘竞赛平台,对数据、Machine Learning和Artificial Intelligence有兴趣的童鞋可以一起探讨哦,个人CSDN博客:http://blog.csdn.net/u013719780?viewmode=contents


        本系列的博文主要来源于《用spark机器学习》这本书的读书笔记,如果对scala熟悉,建议看原书,原书绝大多数代码都是采用scala书写的,如果对Python比较熟悉,也许本系列笔记对你有所帮助,为了各位童鞋看原书的方便,本系列的博文基本上保持了变量名与原书一致。


         Apache Spark是一个分布式计算框架,旨在简化运行于计算机集群上的并行程序的编写。该框架对资源调度,任务的提交、执行和跟踪,节点间的通信以及数据并行处理的内在底层操作都进行了抽象。它提供了一个更高级别的API用于处理分布式数据。从这方面说,它与Apache Hadoop等分布式处理框架类似。但在底层架构上,Spark与它们有所不同。

        Spark起源于加利福利亚大学伯克利分校的一个研究项目。学校当时关注分布式机器学习算法的应用情况。因此,Spark从一开始便为应对迭代式应用的高性能需求而设计。在这类应用中,相同的数据会被多次访问。该设计主要靠利用数据集内存缓存以及启动任务时的低延迟和低系统开销来实现高性能。再加上其容错性、灵活的分布式数据结构和强大的函数式编程接口,Spark在各类基于机器学习和迭代分析的大规模数据处理任务上有广泛的应用,这也表明了其实用性。

        本系列的spark笔记主要采用Python语言。

Spark支持四种运行模式。
 本地单机模式:所有Spark进程都运行在同一个Java虚拟机(Java Vitural Machine,JVM)中。
 集群单机模式:使用Spark自己内置的任务调度框架。
 基于Mesos:Mesos是一个流行的开源集群计算框架。
 基于YARN:即Hadoop 2,它是一个与Hadoop关联的集群计算和资源调度框架。


1. Spark 编程模型

       在对Spark的设计进行更全面的介绍前,我们先介绍SparkContext对象以及Spark shell。后面将通过它们来了解Spark编程模型的基础知识。


1.1 SparkContext类与SparkConf类

         任何Spark程序的编写都是从SparkContext(或用Java编写时的JavaSparkContext)开始的。SparkContext的初始化需要一个SparkConf对象,后者包含了Spark集群配置的各种参数(比如主节点的URL)。初始化后,我们便可用SparkContext对象所包含的各种方法来创建和操作分布式数据集和共享变量。Spark shell(在Scala和Python下可以,但不支持Java)能自动完成上述初始化。若要用Scala代码来实现的话,可参照下面的代码:

val conf = new SparkConf().setAppName("Test Spark App").setMaster("local[4]")
val sc = new SparkContext(conf)

这段代码会创建一个4线程的SparkContext对象,并将其相应的任务命名为Test SparkAPP。我们也可通过如下方式调SparkContext的简单构造函数,以默认的参数值来创建相应的对象。其效果和上述的完全相同:
val sc = new SparkContext("local[4]", "Test Spark App")


1.2 Spark shell

        Spark支持用Scala或Python REPL(Read-Eval-Print-Loop,即交互式shell)来进行交互式的程序编写。由于输入的代码会被立即计算,shell能在输入代码时给出实时反馈。在Scala shell里,命令执行结果的值与类型在代码执行完后也会显示出来。要想通过Scala来使用Spark shell,只需从Spark的主目录执行./bin/spark-shell。它会启动Scala shell并初始化一个SparkContext对象。我们可以通过sc这个Scala值来调用这个对象。

        要想在Python shell中使用Spark,直接运行./bin/pyspark命令即可,如果配置了pyspark的环境变量,则直接运行pyspark命令即可。与Scala shell类似, Python下的SparkContext对象可以通过Python变量sc来调用。上述命令的终端输出应该如下图所示:



1.3 弹性分布式数据集

        RDD(Resilient Distributed Dataset,弹性分布式数据集)是Spark的核心概念之一。一个RDD代表一系列的“记录”(严格来说,某种类型的对象)。这些记录被分配或分区到一个集群的多个节点上(在本地模式下,可以类似地理解为单个进程里的多个线程上)。Spark中的RDD具备容错性,即当某个节点或任务失败时(因非用户代码错误的原因而引起,如硬件故障、网络不通等),RDD会在余下的节点上自动重建,以便任务能最终完成。


1.3.1 创建RDD

        从现有集合创建

collection = list(["a", "b", "c", "d", "e"])
rddFromCollection = sc.parallelize(collection)


        RDD也可以基于Hadoop的输入源创建,比如本地文件系统、HDFS和Amazon S3。基于Hadoop的RDD可以使用任何实现了Hadoop InputFormat接口的输入格式,包括文本文件、其他Hadoop标准格式、HBase、Cassandra等。以下举例说明如何用一个本地文件系统里的文件创建RDD:

rddFromTextFile = sc.textFile("LICENSE")

上述代码中的textFile函数(方法)会返回一个RDD对象。该对象的每一条记录都是一个表示文本文件中某一行文字的String(字符串)对象。


1.3.2  spark操作

       创建RDD后,我们便有了一个可供操作的分布式记录集。在Spark编程模式下,所有的操作被分为转换(transformation)和执行(action)两种。一般来说,转换操作是对一个数据集里的所有记录执行某种函数,从而使记录发生改变;而执行通常是运行某些计算或聚合操作,并将结果返回运行SparkContext的那个驱动程序。Spark的操作通常采用函数式风格。对于那些熟悉用Scala或Python进行函数式编程的程序员来说,这不难掌握。但Spark API其实容易上手,所以那些没有函数式编程经验的程序员也不用担心。
       Spark程序中最常用的转换操作便是map操作。该操作对一个RDD里的每一条记录都执行某个函数,从而将输入映射成为新的输出。比如,下面这段代码便对一个从本地文本文件创建的RDD进行操作。它对该RDD中的每一条记录都执行size函数。之前我们曾创建过一个这样的由若干String构成的RDD对象。通过map函数,我们将每一个字符串都转换为一个整数,从而返回一个由若干Int构成的RDD对象。
intsFromStringsRDD = rddFromTextFile.map(lambda line: line.size)

        Spark的大多数操作都会返回一个新RDD,但多数的执行操作则是返回计算的结果(比如上面例子中,count返回一个Long,sum返回一个Double)。这就意味着多个操作可以很自然地前后连接,从而让代码更为简洁明了。举例来说,用下面的一行代码可以得到和上面例子相同的结果:
aveLengthOfRecordChained = rddFromTextFile.map(lambda line: line.size).sum() /rddFromTextFile.count()
       值得注意的一点是,Spark中的转换操作是延后的。也就是说,在RDD上调用一个转换操作并不会立即触发相应的计算。相反,这些转换操作会链接起来,并只在有执行操作被调用时才被高效地计算。这样,大部分操作可以在集群上并行执行,只有必要时才计算结果并将其返回给驱动程序,从而提高了Spark的效率。

       这就意味着,如果我们的Spark程序从未调用一个执行操作,就不会触发实际的计算,也不会得到任何结果。比如下面的代码就只是返回一个表示一系列转换操作的新RDD:
transformedRDD = rddFromTextFile.map(lambda line: line.size).filter(lambda size : size > 10).map(lambda size : size * 2)

注意,这里实际上没有触发任何计算,也没有结果被返回。如果我们现在在新的RDD上调用一个执行操作,比如sum,该计算将会被触发:
computation = transformedRDD.sum()


2. RDD缓存策略

       Spark最为强大的功能之一便是能够把数据缓存在集群的内存里。这通过调用RDD的cache函数来实现:
rddFromTextFile.cache
调用一个RDD的cache函数将会告诉Spark将这个RDD缓存在内存中。在RDD首次调用一个执行操作时,这个操作对应的计算会立即执行,数据会从数据源里读出并保存到内存。因此,首次调用cache函数所需要的时间会部分取决于Spark从输入源读取数据所需要的时间。但是,当下一次访问该数据集的时候,数据可以直接从内存中读出从而减少低效的I/O操作,加快计算。多数情况下,这会取得数倍的速度提升。

Spark的另一个核心功能是能创建两种特殊类型的变量:广播变量和累加器。广播变量(broadcast variable)为只读变量,它由运行SparkContext的驱动程序创建后发送给会参与计算的节点。对那些需要让各工作节点高效地访问相同数据的应用场景,比如机器学习,这非常有用。Spark下创建广播变量只需在SparkContext上调用一个方法即可:

>>> broadcastAList = sc.broadcast(list(["a", "b", "c", "d", "e"]))


16/06/26 21:04:50 INFO MemoryStore: Block broadcast_0 stored as values in memory (estimated size 296.0 B, free 296.0 B)
16/06/26 21:04:50 INFO MemoryStore: Block broadcast_0_piece0 stored as bytes in memory (estimated size 110.0 B, free 406.0 B)
16/06/26 21:04:50 INFO BlockManagerInfo: Added broadcast_0_piece0 in memory on localhost:36878 (size: 110.0 B, free: 517.4 MB)
16/06/26 21:04:50 INFO SparkContext: Created broadcast 0 from broadcast at PythonRDD.scala:430

终端的输出表明,广播变量存储在内存中,占用的空间大概是110字节,仍余下517MB可用空间。

       广播变量也可以被非驱动程序所在的节点(即工作节点)访问,访问的方法是调用该变量的value方法:

sc.parallelize(list(["1", "2", "3"])).map(lambda x: broadcastAList.value).collect()

       上述一行代码会从{"1", "2", "3"}这个集合(一个Scala List)里,新建一个带有三条记录的RDD。map函数里的代码会返回一个新的List对象。这个对象里的记录由之前创建的那个broadcastAList里的记录与新建的RDD里的三条记录分别拼接而成。

       注意,上述代码使用了collect函数。这个函数是一个Spark执行函数,它将整个RDD以Scala(Python或Java)集合的形式返回驱动程序。collect函数一般仅在的确需要将整个结果集返回驱动程序并进行后续处理时才有必要调用。如果在一个非常大的数据集上调用该函数,可能耗尽驱动程序的可用内存,进而导致程序崩溃。高负荷的处理应尽可能地在整个集群上进行,从而避免驱动程序成为系统瓶颈。然而在不少情况下,将结果收集到驱动程序的确是有必要的。很多机器学习算法的迭代过程便属于这类情况。

        累加器(accumulator)也是一种被广播到工作节点的变量。累加器与广播变量的关键不同,是后者只能读取而前者却可累加。但支持的累加操作有一定的限制。具体来说,这种累加必须是一种有关联的操作,即它得能保证在全局范围内累加起来的值能被正确地并行计算以及返回驱动程序。每一个工作节点只能访问和操作其自己本地的累加器,全局累加器则只允许驱动程序访问。累加器同样可以在Spark代码中通过value访问。


3. Spark Python编程入门

        Spark的Python API几乎覆盖了所有Scala API所能提供的功能,只有极少数的一些特性和个别的API方法,暂时还不支持。但通常不影响我们使用Spark Python进行编程。下面看一个简单的实例:


"""用Python编写的一个简单Spark应用"""

#filename pythonapp.py
from pyspark import SparkContext
sc = SparkContext("local[2]", "First Spark App")
# 将CSV格式的原始数据转化为(user,product,price)格式的记录集
data = sc.textFile("data/UserPurchaseHistory.csv").map(lambda line:line.split(",")).map(lambda record: (record[0], record[1], record[2]))
# 求总购买次数
numPurchases = data.count()
# 求有多少不同客户购买过商品
uniqueUsers = data.map(lambda record: record[0]).distinct().count()
# 求和得出总收入
totalRevenue = data.map(lambda record: float(record[2])).sum()
# 求最畅销的产品是什么
products = data.map(lambda record: (record[1], 1.0)).reduceByKey(lambda a, b: a + b).collect()
mostPopular = sorted(products, key=lambda x: x[1], reverse=True)[0]
print "Total purchases: %d" % numPurchases
print "Unique users: %d" % uniqueUsers
print "Total revenue: %2.2f" % totalRevenue
print "Most popular product: %s with %d purchases" % (mostPopular[0], mostPopular[1])


spark提交脚本命令如下:

tanyouwei@tanyouwei:~$  spark-submit pythonapp.py


  • 7
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
### 回答1: Spark SQL是Apache Spark中的一个模块,它提供了一种基于结构化数据的编程接口。Spark SQL可以让用户使用SQL语句来查询数据,也可以让用户使用DataFrame API来进行数据处理和分析。Spark SQL支持多种数据源,包括Hive、JSON、Parquet等。Spark SQL还提供了一些高级功能,如支持用户自定义函数、支持分布式机器学习算法等。Spark SQL的目标是让用户能够方便地使用Spark进行数据处理和分析,同时提供高性能和可扩展性。 ### 回答2: Spark SQL是一个基于Spark平台的关系型数据处理引擎,它支持使用SQL语句和数据框架操作数据,可以轻松处理结构化和半结构化的数据。它可以从多个数据源中读取数据,包括Hive、JSON、Parquet、ORC等。通过Spark SQL,用户可以方便地使用SQL查询语言来分析和处理数据,大大降低了开发和组织数据流的难度。 Spark SQL主要有两种执行模式:SQL查询和DataFrame操作。其中SQL查询基于Hive的SQL语法解析器,支持HiveQL中的大多数语言特性(如UDF、窗口函数等)。在执行计划生成时,Spark SQL采用了Spark的计算引擎,支持各种Spark算子的优化,以便最大程度地提高查询性能。 另一种操作模式是使用DataFrame API,它可以灵活地进行数据转换和处理,并提供了类似于SQL的语法。与SQL查询不同,DataFrame API通过静态检查和编译器优化来避免由SQL查询引起的语法错误和潜在性能问题。 除了这两种基本的操作模式外,Spark SQL还提供了一些高级特性,如嵌套查询、表和视图、共享变量等。这些特性扩展了Spark SQL的功能,使得它可以更加灵活地进行数据处理和查询。 Spark SQL是Spark的重要组成部分,它在数据存储和处理方面提供了很多便利。通过最大程度地利用Spark引擎的优势,Spark SQL能够处理海量数据,并将其转换为有用的信息。这使得Spark SQL成为实现数据分析、机器学习和人工智能的重要工具之一。 ### 回答3: Spark SQL是一种基于Spark平台的数据处理引擎,它提供了高度优化的查询引擎和优秀的支持SQL语句的API。它允许用户使用SQL语句查询来处理大规模数据集,同时仍然支持复杂数据类型和计算。Spark SQL支持数据源,包括Parquet,Avro,JSON等一系列结构化的和半结构化的数据源。 Spark SQL在历史上是一个单独的模块,在Spark 2.0之后,它已经成为Spark的核心组件之一,可以直接在Spark核心API中使用,包括作为一个RDD库或DataFrame/DataSet的API。 Spark SQL的优点如下: 1. 它可以向受过传统SQL培训的用户展示更高级别,更强大的API。 2. 它提供数据集和RDD的良好互操作性。Spark SQL可以通过未被优化的RDD/DataSet API访问同一数据。 3. 它支持Spark的执行引擎以加速查询处理。 使用Spark SQL的时候,可以根据需要选择编程语言,如Scala,Java,Python,SQL等。在Spark核心API中,Spark SQL提供了两种API来处理结构化数据: 1. DataFrame API:DataFrame是具有许多操纵数据的功能的分布式数据集,类似于数据库中的表。 2. Dataset API:Dataset是Scala和Java API,它是类型安全的,并且提供与RDD API相同的API,但比RDD具有更好的性能和可读性。 Spark SQL是Spark生态系统中重要的组成部分之一。在处理大规模数据时,使用Spark SQL可以方便地利用Spark的强大功能,提高处理效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值