spark 2.3 ml 协同过滤推荐算法ALS

一.spark ml 协同过滤推荐算法
相似度算法
在Spark MLlib中提供了余弦相似度的分布式实现,org.apache.spark.mllib.linalg.distributed包中的IndexedRowMatrix是一个分布式矩阵类,其中提供了一个columnSimilarities方法用于计算该矩阵各列之间的余弦相似度。

预测值计算:采用加权求和的方法计算预测值.
Step 1:读取用户评分数据,设用户数为U,物品数目为I,将数据转换为以用户为行,物品为列的二维矩阵R,R维度为(U×I)。矩阵的每一个数据表示某个用户对特定物品的评分。
Step 2:计算R每列之间的相似度,可以得到维度(I×I)的矩阵S。S(i,j)表示物品i和物品j之间的相似度。
Step 3:使用预测值计算公式计算用户对未评分物品的预测评分。得到预测评分矩阵P,P维度为(U×I),P(i,j) 表示用户i对物品j的预测评分。
Step 4:对用户i进行推荐。找出P的第i行中评分最高的前K个物品推荐给用户。K是需要推荐的物品数量。
二.
关于官方例子:
官方例子是用户-电影数据
很多人想把例子copy过来试试,却不知道源数据是什么样子的。方法:spark-2.3.1-bin-hadoop2.7.tar 这个包大家很熟悉,解压后里面有很多目录,data\mllib目录下就有所有的源数据。官方的例子包括数据都是最优的,随便训练效果都很好,实际数据很糟糕。
三.
下边例子,我训练的是用户-主题,做的是某款软件上的主题推荐。
最终代码没有放上,这只是最开始的demo。

import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.recommendation.ALS
import org.apache.spark.sql.SparkSession
import org.apache.spark.storage.StorageLevel


object user_theme_model {
  case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)
  def parseRating(str: String): Rating = {
    val fields = str.split("\001")
    assert(fields.size == 6)
    Rating(fields(1).toInt, fields(3).toInt, fields(4).toFloat, fields(5).toLong)
  }
  def main(args: Array[String]) {
    val spark = SparkSession
      .builder
      .appName("user_theme_model")
      //.master("local[4]")
      .getOrCreate()
    import spark.implicits._

    val inputdata = args(0).toString
    val outputdata = args(1).toString
    val MaxIter = args(2).toInt
    val RegParam = args(3).toFloat

    // $example on$
    val ratings = spark.read.textFile(inputdata).map(parseRating).toDF()
    // 筛选出安装主题数大于N的用户,有大部分用户只安装了一个主题,特征太少,干掉了。
    ratings.createOrReplaceTempView("input_data")
    val result_valuse = spark.sql("SELECT uts.userId,uts.movieId,uts.rating,uts.timestamp from(SELECT userId from input_data GROUP BY userId HAVING count(userId)>4) TABLE1 join input_data uts on (uts.userId = TABLE1.userId)")
    val ratings2 = result_valuse.toDF()
    ratings2.show()

    //将数据集切分为训练集和测试集
    val Array(training, test) = ratings2.randomSplit(Array(0.9, 0.1))

    //使用ALS在训练集数据上构建推荐模型
    val als = new ALS()
      .setMaxIter(MaxIter)
      .setRegParam(RegParam)
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")
    val model = als.fit(training)
    //为确保不获取到NaN评估参数,我们将冷启动策略设置为drop。
    model.setColdStartStrategy("drop")

    val predictions = model.transform(test)

    // 通过计算rmse(均方根误差)来评估模型
    val evaluator = new RegressionEvaluator()
      .setMetricName("rmse")
      .setLabelCol("rating")
      .setPredictionCol("prediction")
    val rmse = evaluator.evaluate(predictions)
    println(s"Root-mean-square error = $rmse")

    //推荐前100个主题
    val userRecs = model.recommendForAllUsers(100)
    val dataout = userRecs.rdd.map(x => x.get(0) + "\001" +  x.get(1))
    dataout.saveAsTextFile(outputdata)
    //userRecs.show()
    spark.stop()
  }
}
四.结果,我入hive了

 有兴趣可以加我的大数据、数据分析、爬虫群:
《453908562》

猜你喜欢

转载自blog.csdn.net/qq_31032181/article/details/84347174