前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >案例:Spark基于用户的协同过滤算法

案例:Spark基于用户的协同过滤算法

作者头像
Spark学习技巧
发布2018-01-31 12:15:12
2.2K0
发布2018-01-31 12:15:12
举报
文章被收录于专栏:Spark学习技巧Spark学习技巧

一 基于用户协同过滤简介

基于用户的协同过滤算法(user-based collaboratIve filtering)

基于用户的协同过滤算法是通过用户的历史行为数据发现用户对商品或内容的喜欢(如商品购买,收藏,内容评论或分享),并对这些喜好进行度量和打分。根据不同用户对相同商品或内容的态度和偏好程度计算用户之间的关系。在有相同喜好的用户间进行商品推荐。简单的说就是如果A,B两个用户都购买了x,y,z三本图书,并且给出了5星的好评。那么A和B就属于同一类用户。可以将A看过的图书w也推荐给用户B。

Spark MLlib的ALS

spark.ml目前支持基于模型的协作过滤,其中用户和产品由可用于预测缺失条目的一小组潜在因素来描述。spark.ml使用交替最小二乘(ALS) 算法来学习这些潜在因素。算法实现中spark.ml提供有以下参数:

  • numBlocks是为了并行化计算而将用户和项目分割成的块的数量(默认为10)。
  • rank是模型中潜在因子的数量(默认为10)。
  • maxIter是要运行的最大迭代次数(默认为10)。
  • regParam指定ALS中的正则化参数(默认为1.0)。
  • implicitPrefs 显示的反馈ALS(true,显示的表示偏好程度)或者隐式的反馈ALS(false隐式指定偏好)。默认是false,显示反馈ALS
  • alpha 偏好观察中置信度(可理解为一个系数),用于隐式反馈ALS。默认值是1.
  • nonnegative指定是否对最小二乘使用非负约束(默认为false)。

注意:ALS基于DataFrame的API目前仅支持用户和项目ID为整数。用户和项目ID列支持其他数字类型,但ID必须在整数值范围内。

显式与隐式反馈

基于矩阵分解的协作过滤的标准方法将用户条目矩阵中的条目视为用户对该项目的显式偏好,例如,用户给电影的评级。

在许多真实世界的使用情况中,通常只能访问隐式反馈(例如,观看,点击,购买,喜欢,分享等)。根本上讲,这种方法不是根据用户直接评分建模,而是根据用户的行为(点击次数,停留时间),将其视为数字,代表用户对电影的可能喜欢程度。然后,这些数字与观察到的用户偏好的置信度相关,而不是与物品的显式评分。然后该模型将尝试找出可以用来预测用户对于某一项目的预期偏好的潜在因子。

正则化参数

调整的正则化参数regParam,是根据用户在更新用户因子时产生的评分数或者物品在更新物品因子时收到的评分数来解决每个最小二乘问题。这种方法被命名为“ALS-WR”,并在“Large-Scale Parallel Collaborative Filtering for the Netflix Prize ”文章中进行了讨论。它对regParam数据集规模的依赖较小,因此我们可以将从采样子集学习到的最佳参数应用于整个数据集,并期望有相似的性能。

冷启动策略

使用ALSModel进行预测时,测试数据集中的用户和/或项目在训练模型期间不存在是很常见的。这通常发生在两种情况下:

  • 在生产中,对于没有评级历史记录且未进行模型训练的新用户或物品(这是“冷启动问题”)。
  • 在交叉验证过程中,数据分为训练集和评估集。当Spark中的使用简单随机拆分为CrossValidator或者TrainValidationSplit,它实际上是非常普遍遇到的评估集不是在训练集中的用户和/或项目。

默认情况,Spark在ALSModel.transform用户和/或项目因素不存在于模型中时分配NaN预测。这在生产系统中可能是有用的,因为它表名一个新的用户或项目,因此系统可以作为预测的一个后备决定。

然而,这在交叉验证期间是不希望的,因为任何NaN预测值都将影响NaN评估度量的结果(例如,在使用时RegressionEvaluator)。这使得模型选择变得不可能。Spark允许用户将coldStartStrategy参数设置为“drop”,以便删除DataFrame包含NaN值的预测中的任何行。

注意:目前支持的冷启动策略是“nan”(上面提到的默认行为)和“drop”。未来可能会支持进一步的策略。

MovieLens电影基于用户推荐

在以下示例中,我们将从MovieLens数据集(https://grouplens.org/datasets/movielens/)中加载评分数据 ,每行由用户,电影,评分和时间戳组成。然后,我们训练一个ALS模型,默认情况下,这个模型的评分是明确的(implicitPrefs是false)。我们通过测量评级预测的均方根误差来评估推荐模型。

代码语言:js
复制
import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.recommendation.ALS
import org.apache.spark.sql.SparkSession
object ALSExample {
 case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)
 def parseRating(str: String): Rating = {
 val fields = str.split("::")
 assert(fields.size == 4)
 Rating(fields(0).toInt, fields(1).toInt, fields(2).toFloat, fields(3).toLong)
  }
 def main(args: Array[String]) {
 val spark = SparkSession
      .builder
 .appName("ALSExample")
      .getOrCreate()
 import spark.implicits._

 // $example on$
 val ratings = spark.read.textFile("file:///opt/modules/spark-2.2.0/data/mllib/als/sample_movielens_ratings.txt").map(parseRating).toDF()
 //将数据集切分为训练集和测试集
 val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

 //使用ALS在训练集数据上构建推荐模型
 val als = new ALS().setMaxIter(5).setRegParam(0.01).setUserCol("userId").setItemCol("movieId").setRatingCol("rating")
 val model = als.fit(training)

 // 通过计算rmse(均方根误差)来评估模型
    //为确保不获取到NaN评估参数,我们将冷启动策略设置为drop。
 val predictions = model.transform(test)

 val evaluator = new RegressionEvaluator().setMetricName("rmse").setLabelCol("rating").setPredictionCol("prediction")
 val rmse = evaluator.evaluate(predictions)
 println(s"Root-mean-square error = $rmse")

 //每个用户推荐的前十个电影
 val userRecs = model.recommendForAllUsers(10)
 //每个电影推荐的十个用户
 val movieRecs = model.recommendForAllItems(10)
    userRecs.show()
    movieRecs.show()
    spark.stop()
  }
}

如果评级矩阵是从另一个信息源(即它是从其他因子推断)得出,可以设置implicitPrefs以true获得更好的效果:

代码语言:js
复制
val als = new ALS()
  .setMaxIter(5)
  .setRegParam(0.01)
  .setImplicitPrefs(true)
  .setUserCol("userId")
  .setItemCol("movieId")
  .setRatingCol("rating")
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浪尖聊大数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档