CF协同过滤算法
求解评分矩阵的一种典型方法是:ALS,在spark-mllib库中有实现好的api;
K可以视为:隐性偏好因子的维度数
K越大,隐含的偏好因子就越多,计算效果更好,但是运算量更大!
算法思想:
CF协同过滤算法推荐实战
数据加工
从各类数据中,计算出每个用户对它所接触过的物品的评分,整成如下格式:
用户id, 物品id, 评分
U001 p0001 8
U001 p0020 10
U001 p1010 6
U002 p0030 8
........
可以用一个case class描述上述数据
case class Rating(uid:String,itemid:String,rate:Float)
模型训练
调用spark-mllib中ALS算法
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]) { Logger.getLogger("org").setLevel(Level.WARN)val spark = SparkSession .builder .appName("ALSExample") .master("local[*]") .getOrCreate()import spark.implicits._
// 加载评分数据,并解析为Rating对象val ratings = spark.read.textFile("G:\\whale\\doit_recommend\\data\\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对test数据集的预测结果进行模型评估// 设置冷启动策略为drop,对于新注册用户避免产生空推荐矩阵 model.setColdStartStrategy("drop")// 针对测试数据集进行模型预测val predictions: DataFrame = model.transform(test)
predictions.printSchema() predictions.show(10,false)
// 构造一个评估模型,设置评估指标为RMSEval evaluator = new RegressionEvaluator() .setMetricName("rmse") // rmse 均方差 .setLabelCol("rating") .setPredictionCol("prediction")
// 评估预测结果val rmse = evaluator.evaluate(predictions) println(s"均方误差 = $rmse")
// 均方误差 = 1.827332995575392//sys.exit(1)
// 为每个用户推荐top10个物品val userRecs: DataFrame = model.recommendForAllUsers(10)
// 为每个物品推荐top10个用户val movieRecs = model.recommendForAllItems(10)
// 抽取用户数据子集val users = ratings.select(als.getUserCol).distinct().limit(3)// 为子集用户推荐top10部电影val userSubsetRecs = model.recommendForUserSubset(users, 10)
// 抽取电影子集val movies = ratings.select(als.getItemCol).distinct().limit(3)// 为子集电影推荐top10用户val movieSubSetRecs = model.recommendForItemSubset(movies, 10)
// 打印各项推荐结果/*userRecs.printSchema() userRecs.show(10,false)
movieRecs.printSchema() movieRecs.show(10,false)
userSubsetRecs.printSchema() userSubsetRecs.show(10,false)
movieSubSetRecs.printSchema() movieSubSetRecs.show(10,false)*/
// 保存推荐结果 userRecs.write.json("G:\\whale\\doit_recommend\\data\\rec_result") spark.stop() }}