Spark-推荐引擎

推荐模型

推荐模型的种类分为:

1.基于内容的过滤:基于内容的过滤利用物品的内容或是属性信息以及某些相似度定义,来求出与该物品类似的物品。

2.协同过滤:协同过滤是一种借助众包智慧的途径。它利用大量已有的用户偏好来估计用户对其未接触过的物品的喜好程度。其内在思想是相似度的定义。

在基于用户的方法的中,如果两个用户表现出相似的偏好(即对相同物品的偏好大体相同),那就认为他们的兴趣类似。

同样也可以借助基于物品的方法来做推荐。这种方法通常根据现有用户对物品的偏好或是评级情况,来计算物品之间的某种相似度。

3.矩阵分解:

3.1. 显式矩阵分解

例如我们可以得到多个用户对多部电影的评级的数据,这样我们就可以得到一个用户—电影评级的矩阵

我们所得到的这个矩阵是稀疏的,假设得到的“用户—物品”矩阵的维度为U×I,我们需要对其进行降维,然后得到一个表示用户的U×k维矩阵和一个表示物品的k×I维矩阵

要计算给定用户对某个物品的预计评级 

只需要从用户因子矩阵和物品因子矩阵分别选取相应的行(用户因子向量)与列(物品因子向量),然后计算两者的点积即可

对于物品之间相似度的计算,可以用最近邻模型中用到的相似度衡量方法。不同的是,这里可以直接利用物品因子向量,将相似度计算转换为对两物品因子向量之间相似度的计算

 

1.使用的是Spark-shell和Scala语言,同样需要把文件放在Hadoop文件系统中

启动Spark-shell

(在此网站可以下载u.data数据,https://grouplens.org/datasets/movielens/

1

2

val rawData = sc.textFile("/user/common/ml-100k/u.data")

rawData.first()

1

2

#输出 res1: String = 196  242 3   881250949

#该数据由用户ID、影片ID、星级和时间戳等字段依次组成

 提取出前三个字段

1

val rawRatings = rawData.map(_.split("\t").take(3))

 使用ALS模型进行训练

1

2

import org.apache.spark.mllib.recommendation.ALS

val ratings = rawRatings.map { case Array(user, movie, rating) => Rating(user.toInt, movie.toInt, rating.toDouble) }

1

2

scala> ratings.first()

#输出 res24: org.apache.spark.mllib.recommendation.Rating = Rating(196,242,3.0)

 

1

val model = ALS.train(ratings, 50100.01)

 结果,每个用户和每部电影都会有对应的因子数组(分别含943个和1682个因子)

1

2

3

4

5

6

7

8

scala> model.userFeatures

res26: org.apache.spark.rdd.RDD[(Int, Array[Double])] = users MapPartitionsRDD[454] at mapValues at ALS.scala:269

 

scala> model.userFeatures.count

res27: Long = 943

 

scala> model.productFeatures.count

res28: Long = 1682

1. 从MovieLens 100k数据集生成电影推荐

 MLlib的推荐模型基于矩阵分解,因此可用模型所求得的因子矩阵来计算用户对物品的预计评级

1

2

scala> val predictedRating = model.predict(789123)

predictedRating: Double = 2.4585387904925593

predict 函数同样可以以 (user, item) ID对类型的RDD对象为输入,这时它将为每一对都生成相应的预测得分。我们可以借助这个函数来同时为多个用户和物品进行预测。 

为某个用户生成前K个推荐物品 , 可借助 MatrixFactorizationModel 所提供的recommendProducts 函数来实现。该函数需两个输入参数: user 和 num 。其中 user 是用户ID,而 num 是要推荐的物品个数。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

val userId = 789

val = 10

val topKRecs = model.recommendProducts(userId, K)

println(topKRecs.mkString("\n"))

 

scala> println(topKRecs.mkString("\n"))

Rating(789,179,5.5976762921826575)

Rating(789,1022,5.431324881530808)

Rating(789,182,5.4204134645044615)

Rating(789,942,5.340233945688523)

Rating(789,188,5.254370757962667)

Rating(789,183,5.208694711418427)

Rating(789,428,5.1758907376213825)

Rating(789,198,5.150276931639322)

Rating(789,59,5.123932678029936)

Rating(789,715,5.103514906503706)

 2. 检验推荐内容

读入电影数据,导入为Map[Int, String] 类型,即从电影ID到标题的映射

1

2

val movies = sc.textFile("/user/common/ml-100k/u.item")

val titles = movies.map(line => line.split("\\|").take(2)).map(array=> (array(0).toInt,array(1))).collectAsMap()

 查看123对应的电影的名称

1

2

scala> titles(123)

res30: String = Frighteners, The (1996)

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

val moviesForUser = ratings.keyBy(_.user).lookup(789)

println(moviesForUser.size)    #这个用户对33部电影做过评级

#获取评级最高的前10部电影

scala> moviesForUser.sortBy(-_.rating).take(10).map(rating => (titles(rating.product),rating.rating)).foreach(println)

(Godfather, The (1972),5.0)

(Trainspotting (1996),5.0)

(Dead Man Walking (1995),5.0)

(Star Wars (1977),5.0)

(Swingers (1996),5.0)

(Leaving Las Vegas (1995),5.0)

(Bound (1996),5.0)

(Fargo (1996),5.0)

(Last Supper, The (1995),5.0)

(Private Parts (1997),4.0)

 

scala> topKRecs.map(rating => (titles(rating.product), rating.rating)).foreach(println)

(Clockwork Orange, A (1971),5.5976762921826575)

(Fast, Cheap & Out of Control (1997),5.431324881530808)

(GoodFellas (1990),5.4204134645044615)

(What's Love Got to Do with It (1993),5.340233945688523)

(Full Metal Jacket (1987),5.254370757962667)

(Alien (1979),5.208694711418427)

(Harold and Maude (1971),5.1758907376213825)

(Nikita (La Femme Nikita) (1990),5.150276931639322)

(Three Colors: Red (1994),5.123932678029936)

(To Die For (1995),5.103514906503706)

 

附录:

 完整的idea项目代码,要引入maven依赖

<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-mllib_2.11</artifactId>
  <version>2.3.3</version>
</dependency>
package com.peigen

/**
  * Created by peigen on 2019/7/8.
  * 推荐引擎相关概念概述:
  *   场景:1.可选项众多 2.偏个人喜好
  *   1.基于内容的过滤: 利用物品的内容或是属性信息以及某些相似度定义,来求出与该物品类似的物品。
  *   2.基于用户的协同过滤: 利用大量已有的用户偏好来估计用户对其未接触过的物品的喜好程度。内在思想是相似度的定义。
  *   3.两者的得分取决于若干用户或是物品之间依据相似度所构成的集合,即最近邻模型。
  *
  *   1.计算给定用户对某个物品的预计评级: 从用户因子矩阵取相应的行和物品因子矩阵取列,然后计算点积即可。
  *   2.对于物品之间相似度的计算,可以利用最近邻模型中用到的相似度衡量方法。这里可直接将相似度计算转换成对两个物品因子之间相似度计算。
  *
  *   ALS实现原理:迭代求解一系列最小二乘回归问题,相互更新迭代到模型收敛,是一种求解矩阵分解问题的最优化方法。
  */
import org.apache.log4j._
import org.apache.spark._


object Recommend {
  def main(args: Array[String]) {

    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)



    val conf = new SparkConf()
        .setAppName("MovieLensALS").setMaster("local[5]")
    val sc = new SparkContext(conf)


    /**提取特征(影片 ID 星级 事件戳)*/
    val rawData = sc.textFile("D:/test_data/ml-100k/u.data")
    println(rawData.first())


    //    val ratingsList_Tuple = sc.textFile("file:///home/raini/data/ml-10M/ratings.dat").map { lines =>
    //      val fields = lines.split("::")
    //      (fields(0).toInt, fields(1).toInt, fields(2).toDouble, fields(3).toLong % 10)
    //    }
    //    ratingsList_Tuple.first
    //
    val rawRatings = rawData.map(_.split("\t").take(3))
    println(rawRatings.first())


    import org.apache.spark.mllib.recommendation.{ALS, Rating}


    val ratings = rawRatings.map { case Array(user, movie, rating) => Rating(user.toInt, movie.toInt, rating.toDouble)}

    println(ratings.first())

    /**训练推荐模型*/
    val rank = 50 //因子个数
    val iteratings = 10  //迭代
    val lambda = 0.01   //正则化参数
    val model = ALS.train(ratings, rank, iteratings, lambda)
    //    model.userFeatures
    //    model.userFeatures.count()
    //    model.productFeatures.count()


    /**使用推荐模型*/
    //用户推荐(给定用户对 给定物品预计得分-点积)
    // org.apache.spark.mllib.recommendation.MatrixFactorizationModel
    val predictedRating = model.predict(789,123)
    println("predictedRating : " + predictedRating)



    val userID = 789
    val K = 10
    val topKRecs = model.recommendProducts(userID,K)
    println("topKRecs : " + topKRecs.mkString("\n"))


    /**检验推荐内容*/
    val movies = sc.textFile("D:/test_data/ml-100k/u.item")
    val titles = movies.map(line => line.split("\\|").take(2)).map(array => (array(0).toInt, array(1))).collectAsMap()
    println(titles(123))


    //keyBy创建键值对RDD,lookup只返回给定键值
    val moviesForUser = ratings.keyBy(_.user).lookup(789)
    println(moviesForUser.size) //该用户评价过多少电影
    //查看789用户评价最高的10部电影
    moviesForUser.sortBy(-_.rating).take(10).map(rating => (titles(rating.product),rating.rating)).foreach(println)
    //查看给789用户推荐的前10部电影,sortBy 中的- 表示倒序
    topKRecs.map(rating => (titles(rating.product), rating.rating)).foreach(println)
  }
}



### 关于 Apache Spark 3.2.1 的版本特性 Apache Spark 是一种快速通用的大规模数据处理引擎。对于版本 3.2.1 而言,官方持续改进性能优化、稳定性增强以及错误修复等方面的工作[^1]。 - **SQL 和 DataFrame API 改善**:此版本增强了 SQL 查询解析器的功能,支持更多的 ANSI SQL 标准语法;同时,在 DataFrame API 上也进行了多项功能扩展与效率提升。 - **流处理能力加强**:针对 Structured Streaming 组件做了大量工作来提高其稳定性和易用性,特别是对 Kafka 连接的支持更加完善,并且可以将消费偏移量记录到 Zookeeper 中以确保系统的连续性和一致性[^4]。 - **资源管理调度灵活性增加**:允许更细粒度地控制作业执行过程中的资源配置选项,比如内存分配策略调整等。 ### 安装配置指南 #### 下载与准备环境 可以从官方网站获取所需软件包: - 访问 [Downloads | Apache Spark](https://spark.apache.org/downloads.html),选择适合的操作系统平台下载对应压缩包文件。 完成下载之后将其传输到目标服务器上进行解压操作: ```bash tar -zxvf spark-3.2.1.tgz ``` #### 修改默认设置 为了更好地适应特定应用场景下的需求,可能需要编辑 `conf/spark-defaults.conf` 文件来进行必要的参数定制化设定。例如指定 master URL 地址、启用事件日志记录等功能均可以通过这种方式实现[^3]: ```properties spark.master spark://hadoop0:7077 spark.eventLog.enabled true spark.eventLog.dir hdfs://hadoop0:9000/eventLog spark.serializer org.apache.spark.serializer.KryoSerializer spark.driver.memory 2g spark.executor.extraJavaOptions -XX:+PrintGCDetails -Dkey=value -Dnumbers="one two three" ``` #### 启动服务测试 最后一步就是验证整个集群是否能够正常运作了。这通常涉及到提交一个简单的应用程序给 Master Node 来检验各个节点之间的通信状况良好与否。下面是一个使用自带例子程序计算圆周率近似值的任务命令示例[^2]: ```bash spark-submit \ --class org.apache.spark.examples.SparkPi \ --master spark://lsyk01:7077 \ --num-executors 1 \ /opt/spark-3.2.1/examples/jars/spark-examples_2.13-3.2.1.jar ``` ### 使用文档推荐 除了上述提到的内容外,建议深入阅读官方提供的全面详细的用户手册和技术白皮书,这些资料不仅涵盖了基础概念介绍还包含了高级特性的讲解,有助于进一步掌握如何高效利用该工具解决实际问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值