因为要进行大数据场景下利用Spark做音乐推荐,所以记录一下学习Spark的过程和实验过程。
一 对Spark整体上的认识
Spark是一个分布式计算引擎,将大量的计算任务分发到计算结点,实现分布式计算,和hadoop不同的是,Spark计算的中间结果存储在内存中,所以同等配置机器情况下,Spark的运算速度比hadoop块很多倍。Spark的基本概念包括:
Application:用户编写的Spark程序
RDD:弹性分布式数据集,可以看成是数据在分布式内存上的表示
Job(作业):一个Job包含多个RDD及应用于RDD上的各种操作
Executor(执行者):负责执行各种Task(任务)的进程
Task(任务): 运行在Executor上的工作单元
Worker(工作节点):集群中的具体执行计算任务的结点
Driver(任务控制节点):Driver负责提交Job,转换为Task,在Executor进程间协调Task调度。
SparkContext: 用户程序和集群管理器交互的接口
如下图,任务控制结点(Driver)创建SparkContext,由SparkContext向集群管理器(Cluster Manager)申请计算资源,创建执行者进程(Executor),然后将任务(Task)被分配到2个计算结点上(Worker Node),各个计算节点还需要和存储系统HDFS,HIVE进行交互,读取数据或者写入数据。
下图表明了Spark中各种概念之间的关系,一个任务控制节点可以创建多个作业,每个作业包含多个执行阶段,每个阶段包含多个任务。执行用户编写的Spark程序时,会创建一个任务控制节点,申请计算资源,分发程序代码和数据,各个计算节点的执行者开始分阶段执行不同的任务。
Spark的具体运行过程如下图,任务控制节点创建了SparkContext对象,其负责创建RDD,构建DAG图(有向无环图,反映了RDD之间的关系),然后向集群管理器申请资源,集群管理器分配计算节点 ,计算结点向SparkContext申请任务,SparkContext将DAG图分解成任务集合,在将任务集合分配到不同的计算结点上去 。计算节点上的执行者进程执行任务,任务完成后通知SparkContext,写入数据,释放资源。
二 spark mllib recommendation
Spark的推荐算法只有基于矩阵分解的协同过滤算法,即将m个用户和n个物品组成的评分矩阵M分解成低维矩阵A和B的內积。其矩阵分解算法是FunkSVD。
Spark MLlib推荐算法python对应的接口都在pyspark.mllib.recommendation包中,这个包有三个类,Rating, MatrixFactorizationModel和ALS。
Rating类如下所示,代表用户的评分记录,即用户id,物品id,评分
class Rating(namedtuple("Rating", ["user", "product", "rating"])):
"""
Represents a (user, product, rating) tuple.
>>> r = Rating(1, 2, 5.0)
>>> (r.user, r.product, r.rating)
(1, 2, 5.0)
>>> (r[0], r[1], r[2])
(1, 2, 5.0)
.. versionadded:: 1.2.0
"""
def __reduce__(self):
return Rating, (int(self.user), int(self.product), float(self.rating))
**ALS类中封装了使用交替最小二乘法,使用Rating类提供的元组进行模型训练的方法。**FunkSVD进行矩阵分解的目标优化函数使用的是ALS。ALS类中有train和trainImplicit两个方法,train方法是直接使用评分矩阵进行矩阵分解,而trainImplicit使用了隐式用户反馈数据来训练模型。本文只考虑使用评分矩阵进行矩阵分解。
train方法的参数有:
1) ratings : 输入评分矩阵对应的RDD。
2) rank : 矩阵分解时对应的低维的维数。维数越大,算法运行时间和空间需求越大,通常取10-200。
3) iterations :在矩阵分解用交替最小二乘法求解时,进行迭代的最大次数。这个值取决于评分矩阵的维度,以及评分矩阵的系数程度。一般来说,不需要太大,比如5-20次即可。默认值是5。
4) lambda: 在 python接口中使用的是lambda_,原因是lambda是Python的保留字。这个值即为FunkSVD分解时对应的正则化系数。主要用于控制模型的拟合程度,增强模型泛化能力。取值越大,则正则化惩罚越强。大型推荐系统一般需要调参得到合适的值。
class ALS(object):
"""Alternating Least Squares matrix factorization
.. versionadded:: 0.9.0
"""
....omitted...
@classmethod
@since("0.9.0")
def train(cls, ratings, rank, iterations=5, lambda_=0.01, blocks=-1, nonnegative=False,
seed=None):
"""
Train a matrix factorization model given an RDD of ratings by users
for a subset of products. The ratings matrix is approximated as the
product of two lower-rank matrices of a given rank (number of
features). To solve for these features, ALS is run iteratively with
a configurable level of parallelism.
:param ratings:
RDD of `Rating` or (userID, productID, rating) tuple.
:param rank:
Number of features to use (also referred to as the number of latent factors).
:param iterations:
Number of iterations of ALS.
(default: 5)
:param lambda_:
Regularization parameter.
(default: 0.01)
:param blocks:
Number of blocks used to parallelize the computation. A value
of -1 will use an auto-configured number of blocks.
(default: -1)
:param nonnegative:
A value of True will solve least-squares with nonnegativity
constraints.
(default: False)
:param seed:
Random seed for initial matrix factorization model. A value
of None will use system time as the seed.
(default: None)
"""
model = callMLlibFunc("trainALSModel", cls._prepare(ratings), rank, iterations,
lambda_, blocks, nonnegative, seed)
return MatrixFactorizationModel(model)
@classmethod
@since("0.9.0")
def trainImplicit(cls, ratings, rank, iterations=5, lambda_=0.01, blocks=-1, alpha=0.01,
nonnegative