Spark學習筆記——構建基於Spark的推薦引擎


推薦模型

推薦模型的種類分為:

1.基於內容的過濾:基於內容的過濾利用物品的內容或是屬性信息以及某些相似度定義,來求出與該物品類似的物品。

2.協同過濾:協同過濾是一種借助眾包智慧的途徑。它利用大量已有的用戶偏好來估計用戶對其未接觸過的物品的喜好程度。其內在思想是相似度的定義。

在基於用戶的方法的中,如果兩個用戶表現出相似的偏好(即對相同物品的偏好大體相同),那就認為他們的興趣類似。

同樣也可以借助基於物品的方法來做推薦。這種方法通常根據現有用戶對物品的偏好或是評級情況,來計算物品之間的某種相似度。

3.矩陣分解:

3.1. 顯式矩陣分解

例如我們可以得到多個用戶對多部電影的評級的數據,這樣我們就可以得到一個用戶—電影評級的矩陣

我們所得到的這個矩陣是稀疏的,假設得到的“用戶—物品”矩陣的維度為U×I,我們需要對其進行降維,然后得到一個表示用戶的U×k維矩陣和一個表示物品的k×I維矩陣

要計算給定用戶對某個物品的預計評級

只需要從用戶因子矩陣和物品因子矩陣分別選取相應的行(用戶因子向量)與列(物品因子向量),然后計算兩者的點積即可

對於物品之間相似度的計算,可以用最近鄰模型中用到的相似度衡量方法。不同的是,這里可以直接利用物品因子向量,將相似度計算轉換為對兩物品因子向量之間相似度的計算

 

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

啟動Spark-shell

val rawData = sc.textFile("/user/common/ml-100k/u.data")
rawData.first()
#輸出 res1: String = 196	242	3	881250949
#該數據由用戶ID、影片ID、星級和時間戳等字段依次組成

 提取出前三個字段

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

 使用ALS模型進行訓練

import org.apache.spark.mllib.recommendation.ALS
val ratings = rawRatings.map { case Array(user, movie, rating) => Rating(user.toInt, movie.toInt, rating.toDouble) }
scala> ratings.first()
#輸出 res24: org.apache.spark.mllib.recommendation.Rating = Rating(196,242,3.0)

 

val model = ALS.train(ratings, 50, 10, 0.01)

 結果,每個用戶和每部電影都會有對應的因子數組(分別含943個和1682個因子)

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的推薦模型基於矩陣分解,因此可用模型所求得的因子矩陣來計算用戶對物品的預計評級

scala> val predictedRating = model.predict(789, 123)
predictedRating: Double = 2.4585387904925593

predict 函數同樣可以以 (user, item) ID對類型的RDD對象為輸入,這時它將為每一對都生成相應的預測得分。我們可以借助這個函數來同時為多個用戶和物品進行預測。 

為某個用戶生成前K個推薦物品 , 可借助 MatrixFactorizationModel 所提供的recommendProducts 函數來實現。該函數需兩個輸入參數: user 和 num 。其中 user 是用戶ID,而 num 是要推薦的物品個數。

val userId = 789
val K = 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到標題的映射

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對應的電影的名稱

scala> titles(123)
res30: String = Frighteners, The (1996)

 

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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM