构建基于Spark的推荐系统

一、推荐模型的分类

1,基于内容的过滤

  利用物品的内容或是属性信息以及某些相似度定义,来求出与该物品类似的物品。

2,协同过滤

  利用大量已有用户偏好来估计用户对其未接触过的物品的喜好程度。

3,矩阵分解

a,显式矩阵分解

  当要处理的数据是由用户所提供的自身的偏好数据,这些数据被称为显式偏好数据。这些数据包括如物品评级、赞、喜欢等用户对物品的评价。

b,隐式矩阵分解

  用户对物品的偏好不会直接给出,而是隐含在用户与物品的交互之中。二元数据(比如用户是否观看了某个电影或是是否购买了某个商品)和技术数据(比如用户观看某电影的次数)便是这类数据。

c,最小二乘法

  最小二乘法(Altermating Least Squares,ALS)是一种求解矩阵分解的最优化方法。
  ALS的实现原理是迭代求解一系列最小二乘回归问题。在每次迭代时,固定用用户因子矩阵或是物品因子矩阵中的一个,然后用固定的这个矩阵以及评级数据来更新另一个矩阵。之后,被更新的矩阵被固定住,再更新另外一个矩阵。如此迭代,直到模型收敛(或是迭代了预设计好的次数)。

二、提取有效特征

我们采用显式评级数据,而不是使用其他用户或物品的元数据以及“用户-物品”交互数据。

MacBook-Pro:bin xp$ spark-shell
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
17/12/11 17:28:24 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
17/12/11 17:28:29 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException
Spark context Web UI available at http://172.16.253.3:4040
Spark context available as 'sc' (master = local[*], app id = local-1512984505032).
Spark session available as 'spark'.
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 2.2.0
      /_/
         
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131)
Type in expressions to have them evaluated.
Type :help for more information.

先查看原始信息,该数据由用户ID、影片ID、星级和时间戳等字段依次组成,各字段间用制表符分隔。

scala> val rawData=sc.textFile("/Users/xp/mlpy/ml-100k/u.data")

输出如下:

rawData: org.apache.spark.rdd.RDD[String] = /Users/xp/mlpy/ml-100k/u.data MapPartitionsRDD[1] at textFile at <console>:24

scala> rawData.first()

输出如下:

res0: String = 196 242 3 881250949

由于时间戳是不需要的,那我们简单的提取前3个字段即可:

scala> val rawRatings=rawData.map(_.split("\t").take(3))

rawRatings: org.apache.spark.rdd.RDD[Array[String]] = MapPartitionsRDD[2] at map at <console>:26

上面先对各个记录用\t分割,这会返回一个Array[String]数组。之后调用Scala的take函数来仅保留数组的前三个元素,分别对应用户ID、影片ID、星级。
rawRatings.first()命令只会将新RDD的第一条记录返回到驱动程序。通过调用它,我们可以检查一下新RDD。

scala> rawRatings.first()

res1: Array[String] = Array(196, 242, 3)

scala> import org.apache.spark.mllib.recommendation.ALS

import org.apache.spark.mllib.recommendation.ALS

scala> ALS.train

<console>:25: error: ambiguous reference to overloaded definition,
both method train in object ALS of type (ratings: org.apache.spark.rdd.RDD[org.apache.spark.mllib.recommendation.Rating], rank: Int, iterations: Int)org.apache.spark.mllib.recommendation.MatrixFactorizationModel
and method train in object ALS of type (ratings: org.apache.spark.rdd.RDD[org.apache.spark.mllib.recommendation.Rating], rank: Int, iterations: Int, lambda: Double)org.apache.spark.mllib.recommendation.MatrixFactorizationModel
match expected type ?
ALS.train
^

这个错误提示,所需提供的输入参数至少有ratings、rank和iterations。第二个函数另外还需要一个lambda参数。导入上面提到的Rating类,再类似的输入Rating()后回车,便可看到Rating对象所需的参数:

scala> import org.apache.spark.mllib.recommendation.Rating

import org.apache.spark.mllib.recommendation.Rating

scala> Rating()

<console>:26: error: not enough arguments for method apply: (user: Int, product: Int, rating: Double)org.apache.spark.mllib.recommendation.Rating in object Rating.
Unspecified value parameters user, product, rating.
Rating()
^

上述输出表明ALS模型需要一个由Rating记录构成的RDD,而Rating类则是对用户ID、影片ID(这里是通称product)和实际星级这些参数封装。我们可以 调用map方法将原来的各ID和星级的数组转换为对应的Rating对象,从而创建所需的评级数据集。

scala> val ratings=rawRatings.map{case Array(user,movie,rating) => Rating(user.toInt,movie.toInt,rating.toDouble)}

ratings: org.apache.spark.rdd.RDD[org.apache.spark.mllib.recommendation.Rating] = MapPartitionsRDD[3] at map at <console>:30

scala> ratings.first()

res5: org.apache.spark.mllib.recommendation.Rating = Rating(196,242,3.0)

三、训练推荐模型

  从原始数据提取出这些简单特征后,便可训练模型。
训练模型所需的其他参数有以下几个:
rank:对应ALS模型中的因子个数。其合理值为10-200.
iterations:对应运行时的迭代次数。合理值10次左右。
lambda:该参数控制模型的正则化过程,从而控制模型的过拟合情况。

scala> val model=ALS.train(ratings,50,10,0.01)

17/12/11 17:36:04 WARN BLAS: Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS
17/12/11 17:36:04 WARN BLAS: Failed to load implementation from: com.github.fommil.netlib.NativeRefBLAS
17/12/11 17:36:04 WARN LAPACK: Failed to load implementation from: com.github.fommil.netlib.NativeSystemLAPACK
17/12/11 17:36:04 WARN LAPACK: Failed to load implementation from: com.github.fommil.netlib.NativeRefLAPACK
model: org.apache.spark.mllib.recommendation.MatrixFactorizationModel = org.apache.spark.mllib.recommendation.MatrixFactorizationModel@27ee8493

scala> model.userFeatures

res6: org.apache.spark.rdd.RDD[(Int, Array[Double])] = users MapPartitionsRDD[209] at mapValues at ALS.scala:271

scala> model.userFeatures.count

res7: Long = 943

scala> model.productFeatures.count

res8: Long = 1682

四、使用推荐模型

  用户推荐具体的实现方法取决于所采用的模型。比如若采用基于用户的模型,则会利用相似用户的评级来计算某个用户的推荐。而若采用基于物品的模型,则会依靠用户接触过的物品与候选物品之间的相似度来获得推荐。

  利用矩阵分解方法时,是直接对评级数据进行建模,所以预计得分可视作相应用户因子向量和物品向量的点积。

scala> val predictedRating=model.predict(789,123)

predictedRating: Double = 3.5709657849060057

可以看到,该模型预测用户789对电影123的评级3.57。

scala> val userId=789

userId: Int = 789

scala> val K=10

K: Int = 10

scala> val topKRecs=model.recommendProducts(userId,K)

topKRecs: Array[org.apache.spark.mllib.recommendation.Rating] = Array(Rating(789,156,5.575635336185863), Rating(789,42,5.529139597902855), Rating(789,179,5.516092734457448), Rating(789,39,5.400058460147818), Rating(789,180,5.3832945184540755), Rating(789,195,5.3781917200594105), Rating(789,671,5.375058224290015), Rating(789,663,5.2987123201627355), Rating(789,92,5.278211419850456), Rating(789,647,5.165706252282592))

scala> println(topKRecs.mkString("\n"))

Rating(789,156,5.575635336185863)
Rating(789,42,5.529139597902855)
Rating(789,179,5.516092734457448)
Rating(789,39,5.400058460147818)
Rating(789,180,5.3832945184540755)
Rating(789,195,5.3781917200594105)
Rating(789,671,5.375058224290015)
Rating(789,663,5.2987123201627355)
Rating(789,92,5.278211419850456)
Rating(789,647,5.165706252282592)

这就求得了为用户789所能推荐的物品以及对应的预计得分。

详细案例查看:《Spark机器学习》第4章

参考:
1,用户兴趣模型分类以及推荐系统技术调研

2,主流推荐算法的分类及介绍

    原文作者:Haraway
    原文地址: https://www.jianshu.com/p/721877f8638a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞