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

利用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)
  }
}

 

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
项目完整可用,配合压缩包内数据库可直接运行使用。 eclipse+mysql5.7+jdk1.8 功能:推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜好程度。参考特征的选取可能是从项目本身的信息中提取的,或是基于用户所在的社会或社团环境。 根据如何抽取参考特征,我们可以将推荐引擎分为以下四大类: • 基于内容的推荐引擎:它将计得到并推荐给用户一些与该用户已选择过的项目相似的内容。例如,当你在网上购书时,你总是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。 • 基于协同过滤推荐引擎:它将推荐给用户一些与该用户品味相似的其他用户喜欢的内容。例如,当你在网上买衣服时,基于协同过滤推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣品位,并找到与你品味相似的一些用户,将他们浏览和购买的衣服推荐给你。 • 基于关联规则的推荐引擎:它将推荐给用户一些采用关联规则发现算法出的内容。关联规则的发现算法有很多,如 Apriori、AprioriTid、DHP、FP-tree 等。 • 混合推荐引擎:结合以上各种,得到一个更加全面的推荐效果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值