当前位置: 首页 > 工具软件 > examples > 使用案例 >

从examples中学spark(三):ALSExample.scala

席嘉祯
2023-12-01

基于矩阵分解的推荐算法(评分数据集中,并不是每个用户都对每个产品进行过评分,所以这个矩阵往往是很稀疏的【所以更应该多注意过拟合的问题】,也就是说用户i对产品j的评分很多地方是空的,ALS所做的事情就是将这个稀疏矩阵通过一定的规律填满,这样就可以从矩阵中得到任意一个user对任意一个product的评分,然后以此为据做推荐。所以说,ALS算法的核心就是:打分矩阵是近似低秩的。换句话说,打分矩阵A(m∗n)”可以由“用户喜好特征矩阵U(m∗k)”和“产品特征矩阵V(n∗k)”的乘积。

显示反馈与隐式反馈(显式数据的数值代表偏好,隐式数据【无正面的直接表达用户喜好情况的数据】的数值代表了置信等级(confidence level))
##学习中(领悟)

// scalastyle:off println
package org.apache.spark.examples.ml

// $example on$
import org.apache.log4j.{Level, Logger}
import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.recommendation.ALS
// $example off$
import org.apache.spark.sql.SparkSession

object ALSExample {

  // $example on$
/**  当你声明了一个 case class(样例类)时,scala会帮助我们做下面几件事情:
  1 构造器中的参数如果不被声明为var的话,它默认的话是val类型的,但一般不推荐将构造器中的参数声明为var
  2 自动创建伴生对象,同时在里面给我们实现子apply方法,使得我们在使用的时候可以不直接显示地new对象
  3 伴生对象中同样会帮我们实现unapply方法,从而可以将case class应用于模式匹配
  4 实现自己的toString、hashCode、copy、equals方法
  */
  case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)
  // 数据示例:0::2::3::1424380312
  def parseRating(str: String): Rating = {
    val fields = str.split("::")
  //    assert() 或 assume() 方法在对中间结果或私有方法的参数进行检验,不成功则抛出 AssertionError 异常
    assert(fields.size == 4)
  //      返回分割好的Rating对象,注意用户Id列以及产品id列,必须是整数(如果是其他数值类型,只要在整形范围内,都会转为integers)
    Rating(fields(0).toInt, fields(1).toInt, fields(2).toFloat, fields(3).toLong)
  }

  // $example off$

  def main(args: Array[String]) {
    Logger.getLogger("org.apache.hadoop").setLevel(Level.ERROR)
    Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
    val spark = SparkSession
      .builder
      .master("local")
      .appName("ALSExample")
      .getOrCreate()
    import spark.implicits._

    // $example on$
    val ratings = spark.read.textFile("data/mllib/als/sample_movielens_ratings.txt")
      .map(parseRating)
      .toDF()
    ratings.printSchema()
    ratings.show(5)
//    切分训练集和测试集
    val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

    // Build the recommendation model using ALS on the training data
    val als = new ALS()
      .setRank(8) //  对应ALS模型中的因子个数,即矩阵分解出的两个矩阵的新的行/列数,即A≈UVT,k<<m,n中的k。
      .setMaxIter(20) // 默认10
      .setRegParam(0.01) // 正则化参数
      .setImplicitPrefs(true) // 使用隐式反馈
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")
    val model = als.fit(training)

    // 通过计算测试集上的均方根误差来评估模型
    // transform操作会增加一个prediction列
    val predictions = model.transform(test)
    println("=================predictions")
    predictions.printSchema()
    predictions.show(7)

    val evaluator = new RegressionEvaluator()
      .setMetricName("rmse")
      .setLabelCol("rating")
      .setPredictionCol("prediction")
    val rmse = evaluator.evaluate(predictions)
    println(s"Root-mean-square error = $rmse")
    // $example off$
    spark.stop()
  }
}
// scalastyle:on println

##学习后(实操)
TODO

##总结
TODO

##参考

  1. 知乎——如何解释spark mllib中ALS算法的原理?
 类似资料: