Spark基於用戶的協同過濾算法

Spark基於用戶的協同過濾算法

一 基於用戶協同過濾簡介

基於用戶的協同過濾算法(user-based collaboratIve filtering)

基於用戶的協同過濾算法是通過用戶的歷史行為數據發現用戶對商品或內容的喜歡(如商品購買,收藏,內容評論或分享),並對這些喜好進行度量和打分。根據不同用戶對相同商品或內容的態度和偏好程度計算用戶之間的關係。在有相同喜好的用戶間進行商品推薦。簡單的說就是如果A,B兩個用戶都購買了x,y,z三本圖書,並且給出了5星的好評。那麼A和B就屬於同一類用戶。可以將A看過的圖書w也推薦給用戶B。

Spark基於用戶的協同過濾算法

Spark MLlib的ALS

spark.ml目前支持基於模型的協作過濾,其中用戶和產品由可用於預測缺失條目的一小組潛在因素來描述。spark.ml使用交替最小二乘(ALS) 算法來學習這些潛在因素。算法實現中spark.ml提供有以下參數:

·

  • numBlocks是為了並行化計算而將用戶和項目分割成的塊的數量(默認為10)。

  • rank是模型中潛在因子的數量(默認為10)。

  • maxIter是要運行的最大迭代次數(默認為10)。

  • regParam指定ALS中的正則化參數(默認為1.0)。

  • implicitPrefs 顯示的反饋ALS(true,顯示的表示偏好程度)或者隱式的反饋ALS(false隱式指定偏好)。默認是false,顯示反饋ALS

  • alpha 偏好觀察中置信度(可理解為一個係數),用於隱式反饋ALS。默認值是1.

  • nonnegative指定是否對最小二乘使用非負約束(默認為false)。

注意:ALS基於DataFrame的API目前僅支持用戶和項目ID為整數。用戶和項目ID列支持其他數字類型,但ID必須在整數值範圍內。

顯式與隱式反饋

基於矩陣分解的協作過濾的標準方法將用戶條目矩陣中的條目視為用戶對該項目的顯式偏好,例如,用戶給電影的評級。

在許多真實世界的使用情況中,通常只能訪問隱式反饋(例如,觀看,點擊,購買,喜歡,分享等)。根本上講,這種方法不是根據用戶直接評分建模,而是根據用戶的行為(點擊次數,停留時間),將其視為數字,代表用戶對電影的可能喜歡程度。然後,這些數字與觀察到的用戶偏好的置信度相關,而不是與物品的顯式評分。然後該模型將嘗試找出可以用來預測用戶對於某一項目的預期偏好的潛在因子。

正則化參數

調整的正則化參數regParam,是根據用戶在更新用戶因子時產生的評分數或者物品在更新物品因子時收到的評分數來解決每個最小二乘問題。這種方法被命名為“ALS-WR”,並在“Large-Scale Parallel Collaborative Filtering for the Netflix Prize ”文章中進行了討論。它對regParam數據集規模的依賴較小,因此我們可以將從採樣子集學習到的最佳參數應用於整個數據集,並期望有相似的性能。

冷啟動策略

使用ALSModel進行預測時,測試數據集中的用戶和/或項目在訓練模型期間不存在是很常見的。這通常發生在兩種情況下:

  • 在生產中,對於沒有評級歷史記錄且未進行模型訓練的新用戶或物品(這是“冷啟動問題”)。

  • 在交叉驗證過程中,數據分為訓練集和評估集。當Spark中的使用簡單隨機拆分為CrossValidator或者TrainValidationSplit,它實際上是非常普遍遇到的評估集不是在訓練集中的用戶和/或項目。

默認情況,Spark在ALSModel.transform用戶和/或項目因素不存在於模型中時分配NaN預測。這在生產系統中可能是有用的,因為它表名一個新的用戶或項目,因此係統可以作為預測的一個後備決定。

然而,這在交叉驗證期間是不希望的,因為任何NaN預測值都將影響NaN評估度量的結果(例如,在使用時RegressionEvaluator)。這使得模型選擇變得不可能。Spark允許用戶將coldStartStrategy參數設置為“drop”,以便刪除DataFrame包含NaN值的預測中的任何行。

注意:目前支持的冷啟動策略是“nan”(上面提到的默認行為)和“drop”。未來可能會支持進一步的策略。

案例:MovieLens電影基於用戶推薦

在以下示例中,我們將從MovieLens數據集(https://grouplens.org/datasets/movielens/)中加載評分數據 ,每行由用戶,電影,評分和時間戳組成。然後,我們訓練一個ALS模型,默認情況下,這個模型的評分是明確的(implicitPrefs是false)。我們通過測量評級預測的均方根誤差來評估推薦模型。

import org.apache.spark.ml.evaluation.RegressionEvaluator

import org.apache.spark.ml.recommendation.ALS

import org.apache.spark.sql.SparkSession

object ALSExample {

case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)

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]) {

val spark = SparkSession

.builder

.appName("ALSExample")

.getOrCreate()

import spark.implicits._

// $example on$

val ratings = spark.read.textFile("file:///opt/modules/spark-2.2.0/data/mllib/als/sample_movielens_ratings.txt").map(parseRating).toDF()

//將數據集切分為訓練集和測試集

val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

//使用ALS在訓練集數據上構建推薦模型

val als = newALS().setMaxIter(5).setRegParam(0.01).setUserCol("userId").setItemCol("movieId").setRatingCol("rating")

val model = als.fit(training)

// 通過計算rmse(均方根誤差)來評估模型

//為確保不獲取到NaN評估參數,我們將冷啟動策略設置為drop。

val predictions = model.transform(test)

val evaluator = newRegressionEvaluator().setMetricName("rmse").setLabelCol("rating").setPredictionCol("prediction")

val rmse = evaluator.evaluate(predictions)

println(s"Root-mean-square error = $rmse")

//每個用戶推薦的前十個電影

val userRecs = model.recommendForAllUsers(10)

//每個電影推薦的十個用戶

val movieRecs = model.recommendForAllItems(10)

userRecs.show()

movieRecs.show()

spark.stop()

}

}

如果評級矩陣是從另一個信息源(即它是從其他因子推斷)得出,可以設置implicitPrefs以true獲得更好的效果:

valals = new ALS()

.setMaxIter(5)

.setRegParam(0.01)

.setImplicitPrefs(true)

.setUserCol("userId")

.setItemCol("movieId")

.setRatingCol("rating")

為了方便大家相互交流學習,創建了一個公眾號同名微信群:《大數據和雲計算技術交流群》,人數已經2000+,歡迎大家加我微信。


分享到:


相關文章: