在矩阵分解在协同过滤推荐算法中的应用中,我们总结了矩阵分解在推荐算法中的应用原理。这里我们从实用的角度使用Spark来学习矩阵。分解推荐算法。一、Spark推荐算法概述在SparkMLlib中,推荐算法只是实现了基于矩阵分解的协同过滤推荐算法。基于它的算法是FunkSVD算法,将m个用户和n个物品对应的评分矩阵M分解为两个低维矩阵:其中k为分解为低维的维数,一般远小于m和名词如果对FunkSVD算法不熟悉,可以复习一下相应的原理。2.Spark推荐算法类库介绍在SparkMLlib中,实现的FunkSVD算法支持Python、Java、Scala和R的接口,由于之前的实战文章都是基于Python的,本文的介绍和使用也将使用MLlib的Python接口。SparkMLlib推荐算法python对应的接口在pyspark.mllib.recommendation包中,有Rating、MatrixFactorizationModel和ALS三个类。虽然里面有3个类,但是算法就是FunkSVD算法。这三个类的用途如下所述。Rating类比较简单,只是封装了user、item、rating这三个值。也就是说,Rating类只有user、item、rating三元组,没有函数接口。ALS负责训练我们的FunkSVD模型。这里之所以使用交替最小二乘法ALS,是因为Spark在优化FunkSVD的矩阵分解的目标函数时使用了ALS。ALS函数有两个函数,一个是train,这个函数直接使用我们的评分矩阵来训练数据,另一个函数trainImplicit稍微复杂一点,它使用隐式反馈数据来训练模型,与train函数相比,它还有一个附加参数指定隐式反馈置信度阈值。例如,我们可以将评分矩阵转化为反馈数据矩阵,将对应的评分值按照一定的反馈原则转化为置信度权重值。由于隐式反馈的原理一般是根据具体的问题和数据来确定的,本文后面只讨论一般的评分矩阵分解。MatrixFactorizationModel类是我们使用ALS类训练的模型。这个模型可以帮助我们做出预测。常用的预测包括某个用户和某个物品对应的评分、某个用户最喜欢的N个物品、可能最喜欢某个物品的N个用户、所有用户最喜欢的N个物品、最喜欢的物品最受所有用户喜欢。喜欢N个用户。关于这些类的用法,我们后面会有例子来讲解。3.Spark推荐算法的重要参数这里我们总结一下ALS训练模型的重要参数。1)ratings:RDD对应的评分矩阵。需要我们的投入。如果是隐式反馈,则为评分矩阵对应的隐式反馈矩阵。2)rank:矩阵分解中对应的低维维度。即PTm×kQk×nPm×kTQk×n中的维度k。该值会影响矩阵分解的性能,算法越大,运行时间越长,可能占用的内存也越大。通常需要调整参数,一般取10-200之间的数即可。3)迭代次数:当用交替最小二乘法求解矩阵分解时,进行最大迭代次数。该值取决于评分矩阵的维数,以及评分矩阵的系数阶数。一般来说,不需要太大,比如5-20倍。默认值为5。4)lambda:在python接口中使用lambda_,因为lambda是Python的保留字。这个值就是FunkSVD分解对应的正则化系数。主要用于控制模型的拟合度,增强模型的泛化能力。值越大,正则化惩罚越强。大型推荐系统一般需要参数调优来获得合适的值。5)alpha:这个参数只有在使用隐式反馈trainImplicit时才有用。指定隐式反馈置信度阈值。值越大,用户与他未评价的项目越不相关。通常,需要调整参数以获得合适的值。从上面的描述可以看出使用ALS算法是相当简单的。需要注意参数调整的参数。主要参数是矩阵分解的维秩和正则化超参数lambda。如果是隐式反馈,还需要调整隐式反馈置信度阈值alpha。4.Spark推荐算法示例下面我们通过一个具体的例子来说明Spark矩阵分解推荐算法的使用。这里我们使用MovieLens100K数据,数据下载链接在这里。数据解压后,我们只使用u.data文件中的评分数据。该数据集每行有4列,分别对应用户ID、项目ID、评分和时间戳。由于我的机器比较破,所以在下面的例子中,我只使用了前100条数据。所以如果你使用所有的数据,接下来的预测就会和我的不一样。首先,你需要确保你已经安装了Hadoop和Spark(版本不低于1.6),并设置好环境变量。一般我们都是在ipythonnotebook(jupyternotebook)中学习,所以最好搭建一个基于notebook的Spark环境。当然如果使用没有notebook的Spark环境也无所谓,只是每次运行前都需要设置环境变量。如果您没有带有笔记本的Spark环境,则需要先运行以下代码。当然,如果你已经设置好了,下面的代码就不需要运行了。在运行算法之前,建议按如下方式输出SparkContext。如果可以正常打印内存地址,说明Spark运行环境搭建完成。比如我printsc的输出是:首先我们将u.data文件读入内存,尝试输出***行的数据,检查是否读取成功。注意复制代码的时候,data的目录要用自己的u。数据目录。代码如下:输出如下:u'196\t242\t3\t881250949'可以看到数据是用\t隔开的,我们需要把每一行的字符串分成一个数组,只取前三列没有时间单击该列。代码如下:输出结果如下:[u'196',u'242',u'3']此时,虽然我们已经获取到了评分矩阵数组对应的RDD,但是这些数据仍然是字符串,而Spark需要几个Ratings类对应的数组。所以我们现在转换RDD的数据类型,代码如下:输出如下:Rating(user=196,product=242,rating=3.0)可以看出我们的数据已经是一个基于评分类,现在终于可以整理出好的数据用于训练了,代码如下,我们设置矩阵分解的维度为20,最大迭代次数为5,正则化系数为0.02。在实际应用中,我们需要通过交叉验证来选择合适的矩阵分解维数和正则化系数。这里我们简化,因为它是一个例子。训练好模型后,我们终于可以对推荐系统进行预测了。先做最简单的预测,比如预测用户38对item20的评分。代码如下:printmodel.predict(38,20)输出如下:0.311633491603可以看出评分不高。现在预测用户38最喜欢的10件商品,代码如下:printmodel.recommendProducts(38,10)输出结果如下:[Rating(user=38,product=95,rating=4.995227969811873),Rating(user=38,产品=304,评分=2.5159673379104484),评分(用户=38,产品=1014,评分=2.165428673820349),评分(用户=38,产品=322,评分=1.7002266119079879),评分(用户=38,产品=111,评分=1.2057528774266673),评分(用户=38,产品=196,评分=1.0612630766055788),评分(用户=38,产品=23,评分=1.0590775012913558),评分(用户=38,产品=327,评分=1.033556517(user=38,product=98,rating=0.9677333686628911),Rating(user=38,product=181,rating=0.8536682271006641)]可以看出,用户38可能喜欢10个对应评分从高到低的item。那么我们来预测一下item20最可能被推荐的10个用户。代码如下:printmodel.recommendUsers(20,10)输出如下:[Rating(user=115,product=20,rating=2.9892138653406635),评分(用户=25,产品=20,评分=1.7558472892444517),评分(用户=7,产品=20,评分=1.523935609195585),评分(用户=286,产品=20,评分=1.3746309116764184),评分(用户=222,产品=20,评级=1.313891405211581),评级(用户=135,产品=20,评级=1.254412853860262),评级(用户=186,产品=20,评级=1.2194811581542384),评级(用户=72,产品=20,rating=1.154269935),Rating(user=241,product=20,rating=1.0863391992741023),Rating(user=160,product=20,rating=1.072353288848142)]现在让我们来看看每个用户最推荐的三个项目,代码如下:printmodel.recommendProductsForUsers(3).collect()由于输出很长,这里就不复制输出了。每个项目三个最推荐用户的代码如下:printmodel.recommendUsersForProducts(3).collect()也因为输出很长,这里就不复制输出了。希望以上例子对大家使用Spark矩阵分解推荐算法有所帮助。
