spark 机器学习 笔记(一)——matrix factorization and ALS

Apache Spark是最近兴起的分布式框架,是一个分布式计算框架,旨在简化运行于计算机集群上的并行程序的编写。该框架对资源调度,任务的提交、执行和跟踪,节点间的通信以及数据并行处理的内在底层操作都

进行了抽象,同时提供了一些高级封装的Api接口来方便用户使用。
相比较于基于hdfs文件系统的hadoop,基于内存存储数据的spark采用数据集内存缓存和数据操作的延迟性处理等机制以及通过低延迟低系统开销的任务启动,十七更加适用于会不断迭代求解、不同的过程中传递变量的机器学习法,spark本身的运行速度也比hadoop要快。同时spark里面有一些现成的工具包比如MLIB。
以为上述优点,本着工欲善其事必先利其器的指导精神,正式开学,记笔记作为总结和督促,一边学习机器学习算法,一遍学习spark实现,写到哪算哪。spark支持scala和python,这两个语言都是语法简单友好的面向对象的语言,但本文不涉及具体的环境设置和安装。我使用的是ipython和spark notebook,主要的语言是scala,部分图表是使用的python的matplotlib绘制,顺便说一句,各种图形可以直观的展现数据的分布,比如数据是平均分布,还是聚集到几个中心,发现噪声和离群点数据,从而帮助我们对数据进行除去异常点等数据处理,选择合适的模型来揭示数据规律,因此学会使用各种图表,也是一种善其事的利器。

一. 矩阵分解
目前有很多基于矩阵分解的算法,基于矩阵分解的算法的好处是有较高的推荐准确率和很好的扩展性适应性。
矩阵分解顾名思义是把原有矩阵分解掉。在推荐中一般会存在两个角A和B,寻找A和B之间的关系,为A推荐 B或者反过来,在推荐系统中A和B一般为用户U和商品I。那么就会存在一个二维的关系矩阵,如图(图来源于《spark机器学习》):
spark 机器学习 笔记(一)——matrix factorization and ALS_第1张图片
图中的深色方格代表u和I存在交互。这样的矩阵一般是稀疏的,特别是对于目前的电商系统来说,I代表的商品集合和U代表的商品集合一般都很大,而用户能有交互的商品一般很少,用传统的协同过滤比较难处理这种高维稀疏数据,而且如果新增了一个商品,又要重新计算,成本较高。
现在用矩阵分解,就比较合适了,他会对原有矩阵做变换,变成2个低维矩阵UxK和KxI,其中k远小于I or U,相当于对高维稀疏数据做降维处理
,从而减少稀疏性。如图所示(图来源于《spark机器学习》):
spark 机器学习 笔记(一)——matrix factorization and ALS_第2张图片
一个用户(Ui)对一个商品Ii的得分为(1):S_i=U_i x I_i. 这样,当新增一个商品I_n+1的商品时候,只需要计算着这一个商品的隐因子,然后用上面公式(1)计算即可,很方便扩展。
那大家肯定很奇怪,这么做靠谱么?要怎么做呢?这里简单说一下数学原理,有时间的建议看看线性代数这个课麻省理工Gilbert Strang的公开课
基本的原来在于U\approx UxK * IxK。式子两边基本相当,代表着携带的信息也是相等的,基本没有流失,但矩阵的维数和稀疏性降下来了。

二. ALS(Alternative Least Sqares)
ALS交替最小二乘法,是一种求解矩阵分解的最优化算法,具体做法是在每一次迭代中,固定U和I的其中一方,然后用U对I的交互评分信息来更新另一方,这样交替进行,直到规定的迭代次数或者模型收敛。
Spark的Mlib包里面实现了相关的接口,可以方便的调用。从MLlib引入ALS模型相关包如下:
import org.apache.spark.mllib.recommendation.ALS。
三. 实现
一个推荐系统中的数据分为显示反馈数据(explicit feedback data)和隐式反馈数据(implicit feedback data)。显示反馈数据顾名思义是用户明确表示出的对商品的喜好,包括用户的打分、评价等,里面包含了用户对物品的正面反馈和负面反馈;隐式反馈数据是指不会直接给出用户的爱好倾向,而是隐藏在用户与物品的交互中,比如用户经常浏览某些图书,一定程度反映用户对这些书的喜爱。隐式反馈数据通常数据量比显式数据要大很多,而且数据存在不平衡性,只存在正面反馈,没有负向反馈,里面蕴含了很多的用户信息,但处理起来比较麻烦,难以发现内部规律。我们首先用显式反馈数据来学习。
首先读入训练样本。spark使用的数据集合类型叫做RDD(Resilient Distributed Datasets),弹性分布式数据集,是spark的核心,对读入的数据在内存进行管理,并且定义了各种数据接口给使用者操作。
val rawdata=sc.textFile(“/spark/moviedata/u.data”)
我们使用的数据集是《spark 机器学习》里面的电影评分数据集,可以在movie rating data
sc(SparkContext)是spark的上下文对象.SparkContext是Spark的入口,负责连接Spark集群,创建RDD,累积量和广播量等。Spark提供了各种方法来读取不同媒介上的数据,这个地方的sc.textFile(“/spark/moviedata/u.data”)为读取HDFS上的文本文件的方法。
我们现在读取数据到了内存里面,如果有必要(比如数据量较大),可以把数据使用广播变量的方法,广播到各个工作节点上,让各个节点可以高效的读取数据,省却数据从驱动节点传送到工作节点的过程。
scala
val rawdata_bcast = sc.broadcast(rawdata)

我们使用ALS的的train方法来处理数据,得到模型。ALS的train方法需要把数据首先转化为Rating类型数据才能处理
scala
val rawRating=rawdata.map(x => x.split("\t").take(3))//对每一行数据做split操作,得到一个数组的集合
rawRating.first() //查看拿到的数据
import org.apache.spark.mllib.recommendation.ALS
import org.apache.spark.mllib.recommendation.Rating
val ratings=rawRating.map{case Array(user,moive,rating) => Rating(user.toInt,moive.toInt,rating.toDouble)}//对RDD的每一行做转化,包装成Rating对象
val model=ALS.train(ratings,50,10,0.1)//训练数据

经过上面过程,既可以得到矩阵分解后的因子矩阵模型model。
train方法有四个参数
- rating.训练样本
- rank.(代码中的50):隐特征个数,一般隐藏特征越多效果越好(特征越多,用来描绘规律的信息越多,表达能力越强,),但也也不能一味追求多,会影响模型的性能以及可能过拟合。
- iterations(代码中的10):代表预期迭代次数,迭代到制定的次数,程序会停止,避免无限迭代下去。
- lamda(代码中的0.1): 正则化选项,用于控制模型复杂度,避免过拟合,提高模型的泛化能力。
其中,rank、iterations、和iterations都没有固定值,需要经过交叉检验来确定。
Spark中ALS模型矩阵分解后的两个因子矩阵有自己的固定命名:userFeatures和productFeatures。model.userFeatures.count 和
model.productFeatures.count可以产看矩阵对应的因子组数。
模型训练好了,接下来就可以通过计算用户因子矩阵和物品因子矩阵对应的因子向量V_ui和V_Ii来计算用户U_i对物品I_i的得分了。具体代码下回再续。

你可能感兴趣的:(spark 机器学习 笔记(一)——matrix factorization and ALS)