利用协同过滤算法进行电影推荐

利用Spark MLlib中的协同过滤算法完成针对特定用户的电影推荐功能,并将推荐结果保存到MySQL数据库中。

数据集

https://grouplens.org/datasets/movielens/

1.数据处理

创建一个rating类和parseRating函数。parseRating把读取的ratings数据集中的每一行,并转化成Rating类的对象。

主要代码:

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]): Unit = {
    val sc=SparkSession.builder()
      .master("local")
      .appName("movie")
      .getOrCreate()
    val ratingRDD=sc.sparkContext.textFile("/usr/cx/ratings.dat")

    //将RDD数据转化成DataFrame数据
    val ratings=sc.createDataFrame(ratingRDD.map(parseRating))
//    ratings.show()

2.划分数据集

把ratings数据集划分训练集和测试集,其中训练集占80%,测试集占20%。

主要代码:

//将样本8-2分成训练样本和测试样本
    val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

3.使用ALS构建模型

使用ALS来建立模型。这里构建两个模型,一个是显性反馈,另一个是隐性反馈。

主要代码:

//协同过滤,训练模型
    val alsExplicit = new ALS()
      .setMaxIter(5)             //迭代次数,用于最小二乘交替迭代的次数
      .setRegParam(0.01)         //惩罚系数
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")    //显示评分得到的矩阵形式
    val alsImplicit = new ALS()
      .setMaxIter(5)             //迭代次数,用于最小二乘交替迭代的次数
      .setRegParam(0.01)        //惩罚系数
      .setImplicitPrefs(true)
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")    //显示评分得到的矩阵形式

4.训练模型 

把推荐模型放在训练数据上训练。

主要代码:

val modelExplicit = alsExplicit.fit(training)
    val modelImplicit = alsImplicit.fit(training)

5.计算误差

对训练集中的用户电影进行预测,得到预测评分的数据集。计算模型的均方根误差。

主要代码:

//得到预测评分的测试集
    val predictionsExplicit = modelExplicit.transform(test).na.drop()
    val predictionsImplicit = modelImplicit.transform(test).na.drop()
//    predictionsExplicit.show()
//    predictionsImplicit.show()

    //计算模型均方根误差
    val evaluator = new RegressionEvaluator()
      .setMetricName("rmse")
      .setLabelCol("rating")
      .setPredictionCol("prediction")
    val rmseExplicit = evaluator.evaluate(predictionsExplicit)
    val rmseImplicit = evaluator.evaluate(predictionsImplicit)
    println(s"Explicit:模型均方根误差 : $rmseExplicit")
    println(s"Implicit:模型均方根误差 : $rmseImplicit")

6.进行预测 

对输入的用户进行预测,并将结果存入数据库。

主要代码:

println("请输入用户id:")
    val userId:Int=StdIn.readInt()
    val movieDF=ratings.where(s"userId= $userId")
    println(s"为id为 $userId 的用户推荐如下10部电影:")
    movieDF.limit(10).show()
    val df=movieDF.limit(10)
    //将数据存到数据库中
    val prop=new Properties()
    prop.put("user","root")
    prop.put("password","XXXXX")
    prop.put("driver","com.mysql.jdbc.Driver")
    df.write.mode("Overwrite").jdbc("jdbc:mysql://localhost:3306/movies","movies.ratings",prop)

 源码

import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.recommendation.ALS
import org.apache.spark.sql.SparkSession
import java.util.Properties
import scala.io.StdIn
object movie {
  case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)
  //将ratings数据集中的每一行转化为Rating对象
  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]): Unit = {
    val sc=SparkSession.builder()
      .master("local")
      .appName("movie")
      .getOrCreate()
    val ratingRDD=sc.sparkContext.textFile("/usr/cx/ratings.dat")

    //将RDD数据转化成DataFrame数据
    val ratings=sc.createDataFrame(ratingRDD.map(parseRating))
//    ratings.show()
    //将样本8-2分成训练样本和测试样本
    val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

    //协同过滤,训练模型
    val alsExplicit = new ALS()
      .setMaxIter(5)             //迭代次数,用于最小二乘交替迭代的次数
      .setRegParam(0.01)         //惩罚系数
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")    //显示评分得到的矩阵形式
    val alsImplicit = new ALS()
      .setMaxIter(5)             //迭代次数,用于最小二乘交替迭代的次数
      .setRegParam(0.01)        //惩罚系数
      .setImplicitPrefs(true)
      .setUserCol("userId")
      .setItemCol("movieId")
      .setRatingCol("rating")    //显示评分得到的矩阵形式
    val modelExplicit = alsExplicit.fit(training)
    val modelImplicit = alsImplicit.fit(training)

    //得到预测评分的测试集
    val predictionsExplicit = modelExplicit.transform(test).na.drop()
    val predictionsImplicit = modelImplicit.transform(test).na.drop()
//    predictionsExplicit.show()
//    predictionsImplicit.show()

    //计算模型均方根误差
    val evaluator = new RegressionEvaluator()
      .setMetricName("rmse")
      .setLabelCol("rating")
      .setPredictionCol("prediction")
    val rmseExplicit = evaluator.evaluate(predictionsExplicit)
    val rmseImplicit = evaluator.evaluate(predictionsImplicit)
    println(s"Explicit:模型均方根误差 : $rmseExplicit")
    println(s"Implicit:模型均方根误差 : $rmseImplicit")

    println("请输入用户id:")
    val userId:Int=StdIn.readInt()
    val movieDF=ratings.where(s"userId= $userId")
    println(s"为id为 $userId 的用户推荐如下10部电影:")
    movieDF.limit(10).show()
    val df=movieDF.limit(10)
    //将数据存到数据库中
    val prop=new Properties()
    prop.put("user","root")
    prop.put("password","XXXXX")
    prop.put("driver","com.mysql.jdbc.Driver")
    df.write.mode("Overwrite").jdbc("jdbc:mysql://localhost:3306/movies","movies.ratings",prop)
  }
}

 

你可能感兴趣的:(scala)