四、Collaborative filtering
协作过滤通常用于推荐系统。这些技术旨在填充用户项关联矩阵的缺失条目。 spark.mllib当前支持基于模型的协作过滤,其中通过一小部分潜在因素来描述用户和产品,这些潜在因素可用于预测丢失的条目。 spark.mllib使用交替最小二乘(ALS)算法来学习这些潜在因素。 spark.mllib中的实现具有以下参数:
- numBlocks是用于并行化计算的块数(设置为-1以进行自动配置)。
- rank是要使用的功能数(也称为潜在因子数)。
- iterations是要运行的ALS的迭代次数。 ALS通常会在20次或更短的迭代中收敛到一个合理的解决方案。
- lambda在ALS中指定正则化参数。
- implicitPrefs指定是使用显式反馈ALS变体还是适用于隐式反馈数据的变体。
- alpha是适用于ALS的隐式反馈变量的参数,该变量控制偏好观察中的基线置信度。
alternating least squares(ALS,交替最小二乘法)
显式反馈与隐式反馈
基于矩阵分解的协作过滤的标准方法将用户项矩阵中的条目视为用户对项目(例如,给电影评分的用户)赋予的明确偏好。
在许多实际用例中,通常只能访问隐式反馈(例如,视图,点击,购买,喜欢,分享等)。 spark.mllib中用于处理此类数据的方法来自隐式反馈数据集的协作过滤。从本质上讲,该方法不是尝试直接对评分矩阵建模,而是将数据视为代表用户操作观察力的数字(例如,点击次数或某人观看电影的累积时间)。然后,这些数字与观察到的用户偏好的置信度有关,而不是与对商品的明确评分有关。然后,该模型尝试查找可用于预测用户对某项商品的期望偏好的潜在因素。
正则化参数的缩放
从v1.1开始,我们通过解决用户在更新用户因子时生成的评分数量或产品在更新产品因子时获得的评分数量来缩放解决每个最小二乘问题的正则化参数lambda。这种方法称为“ ALS-WR”,并在论文“为Netflix奖进行大规模并行协作过滤”中进行了讨论。它使lambda较少依赖于数据集的规模,因此我们可以将从采样子集中学习的最佳参数应用于整个数据集,并期望获得类似的性能。
示例代码
在以下示例中,我们加载评级数据。每行包含一个用户,一个产品和一个评分。我们使用默认的ALS.train()方法,该方法假定等级是明确的。我们通过测量评分预测的均方误差来评估推荐模型。
有关API的更多详细信息,请参阅ALS Scala文档。
import org.apache.spark.mllib.recommendation.ALS
import org.apache.spark.mllib.recommendation.MatrixFactorizationModel
import org.apache.spark.mllib.recommendation.Rating
// Load and parse the data
val data = sc.textFile("data/mllib/als/test.data")
val ratings = data.map(_.split(',') match { case Array(user, item, rate) =>
Rating(user.toInt, item.toInt, rate.toDouble)
})
// Build the recommendation model using ALS
val rank = 10
val numIterations = 10
val model = ALS.train(ratings, rank, numIterations, 0.01)
// Evaluate the model on rating data
val usersProducts = ratings.map { case Rating(user, product, rate) =>
(user, product)
}
val predictions =
model.predict(usersProducts).map { case Rating(user, product, rate) =>
((user, product), rate)
}
val ratesAndPreds = ratings.map { case Rating(user, product, rate) =>
((user, product), rate)
}.join(predictions)
val MSE = ratesAndPreds.map { case ((user, product), (r1, r2)) =>
val err = (r1 - r2)
err * err
}.mean()
println(s"Mean Squared Error = $MSE")
// Save and load model
model.save(sc, "target/tmp/myCollaborativeFilter")
val sameModel = MatrixFactorizationModel.load(sc, "target/tmp/myCollaborativeFilter")
如果评分矩阵是从其他信息源得出的(即是从其他信号推断得出的),则可以使用trainImplicit方法获得更好的结果。
val alpha = 0.01
val lambda = 0.01
val model = ALS.trainImplicit(ratings, rank, numIterations, lambda, alpha)