一、協同過濾算法簡介
協同過濾算法是一種較為著名和常用的推薦算法,它基於對用戶歷史行為數據的挖掘發現用戶的喜好偏向,並預測用戶可能喜好的產品進行推薦。也就是常見的“猜你喜歡”,和“購買了該商品的人也喜歡”等功能。它的主要實現由:
●根據和你有共同喜好的人給你推薦
●根據你喜歡的物品給你推薦相似物品
●根據以上條件綜合推薦
因此可以得出常用的協同過濾算法分為兩種,基於用戶的協同過濾算法(user-based collaboratIve filtering),以及基於物品的協同過濾算法(item-based collaborative filtering)。特點可以概括為“人以類聚,物以群分”,並據此進行預測和推薦。
二、協同過濾算法的關鍵問題
實現協同過濾算法,可以概括為幾個關鍵步驟:
1:根據歷史數據收集用戶偏好
2:找到相似的用戶(基於用戶)或物品(基於物品)
三、基於用戶的協同過濾算法描述
基於用戶的協同過濾算法的實現主要需要解決兩個問題,一是如何找到和你有相似愛好的人,也就是要計算數據的相似度:
計算相似度需要根據數據特點的不同選擇不同的相似度計算方法,有幾個常用的計算方法:
(1)傑卡德相似系數(Jaccard similarity coefficient)
其實就是集合的交集除並集
(2)夾角余弦(Cosine)
在二維空間中向量A(x1,y1)與向量B(x2,y2)的夾角余弦公式:
兩個n維樣本點a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夾角余弦:
即
(3)其余方法,例如歐式距離、曼哈頓距離等相似性度量方法可以點此了解
找到與目標用戶最相鄰的K個用戶
我們在尋找有有相同愛好的人的時候,可能會找到許多個,例如幾百個人都喜歡A商品,但是這幾百個人里,可能還有幾十個人與你同時還喜歡B商品,他們的相似度就更高,我們通常設定一個數K,取計算相似度最高的K個人稱為最相鄰的K個用戶,作為推薦的來源群體。
這里存在一個小問題,就是當用戶數據量十分巨大的時候,在所有人之中找到K個基友花的時間可能會比較長,而且實際中大部分的用戶是和你沒有什么關系的,所以在這里需要用到反查表
所謂反查表,就是比如你喜歡的商品有A、B、C,那就分別以ABC為行名,列出喜歡這些商品的人都有哪些,其他的人就必定與你沒有什么相似度了,從這些人里計算相似度,找到K個人
通過這K個人推薦商品
我們假設找到的人的喜好程度如下
你 | A | B | C | D |
甲(相似度25%) | √ | √ | √ | |
乙(相似度80%) | √ | √ |
那么對於產品ABCD,推薦度可以計算為:
●A:1*0.25=0.25
●B:1*0.25=0.25
●C:1*0.8=0.8
●D:1*0.25+1*0.8=1.05
很明顯,我們首先會推薦D商品,其次是C商品,再后是其余商品
當然我們也可以采用其他的推薦度計算方法,但是我們一定會使用得到的相似度0.25和0.80,也即一定是進行加權的計算。
算法總結
這就是基於用戶的協同推薦算法,總結步驟為
1.計算其他用戶的相似度,可以使用反查表除掉一部分用戶
2.根據相似度找到與你嘴相似的K個用戶
3.在這些鄰居喜歡的物品中,根據與你的相似度算出每一件物品的推薦度
4.根據相似度推薦物品
算法存在的問題
例如一段時間內非常流行的某種商品,或者某種通用的商品,購買的人非常多,此時如果列入正常計算過程中就沒有太大意義了,並且會增加負擔。可以給此種商品價一個權值或者在數據預處理階段作為臟數據處理掉。
四、算法實現
先整理網上的資料,自己動手實踐后再進行編輯
我們使用的是集成在CDH集群上的spark-on-yarn方式,使用python寫算法,這是在集群上運行程序的方式以及一些問題解決
在集群上運行python編寫的spark應用程序時遇到的一些問題
測試1——我們自己測試的基於Python的協同過濾算法實踐
主要實現由讀取Hive中的數據並進行算法處理(python + spark + hive)
第一步:建立Hive的連接,並讀取Hive中的數據(sql方法)
第二步:划分訓練集和測試集(0.8,0.2)
第三步:利用ALS函數,設置參數,並通過訓練集訓練得到模型
第四步:利用測試集對訓練好的模型進行測試
第五步:最后將編好的.py文件上傳至服務器
第六步:使用./spark-submit –master yarn /program/wsh/readTpch1.py提交至spark進行處理。
注:通過訓練測試(幾千萬條數據),運行了40分鍾左右。由於時間較長,這此沒有等上截圖,具體看代碼。
代碼:
from pyspark.sql import HiveContext, SparkSession from pyspark.ml.evaluation import RegressionEvaluator from pyspark.ml.recommendation import ALS from pyspark.sql import Row ''' 基於spark的算法程序,在本地是不能直接運行的,將.py程序上傳至服務器,進而使用spark-submit 將程序提交給spark進行處理,並得到結果 ''' #初始化 spark = SparkSession.builder.master("local").appName("WordCount").getOrCreate() hive_context = HiveContext(spark) #切換數據庫至tpch hive_context.sql('use tpch') #SQL語言 sql = "select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt from partsupp, part where p_partkey = ps_partkey and p_brand <> '[BRAND]' and p_type not like '[TYPE]%' and ps_suppkey not in (select s_suppkey from supplier where s_comment like '%Customer%Complaints%') group by p_brand, p_type, p_size" #執行SQL語句,得到結果。該結果為DataFrame df = hive_context.sql(sql) #展示結果 df.show() rows = df.collect() #切分訓練集和測試集 training, test = df.randomSplit([0.8, 0.2]) #使用pyspark.ml.recommendation包下的ALS方法實現協同過濾算法,並設置參數 alsExplicit = ALS(maxIter=10, regParam=0.01, userCol="supplier_cnt", itemCol="p_brand", ratingCol="p_size") #訓練並得到模型 modelExplicit = alsExplicit.fit(training) #利用測試集對模型進行檢測 predictionsExplicit = modelExplicit.transform(test) #結果展示 predictionsExplicit.show() evaluator = RegressionEvaluator().setMetricName("rmse").setLabelCol("rating").setPredictionCol("prediction") rmse = evaluator.evaluate(predictionsExplicit) print("Explicit:Root-mean-square error = " + str(rmse)) print("Explicit:Root-mean-square error = " + str(rmse))
測試2——這是網上別人的代碼用來跑了一下
我們使用MovieLens數據集,其中每行包含一個用戶、一個電影、一個該用戶對該電影的評分以及時間戳。
使用默認的ALS.train() 方法,即顯性反饋(默認implicitPrefs 為false)來構建推薦模型並根據模型對評分預測的均方根誤差來對模型進行評估。
導入需要的包
from pyspark.ml.evaluation import RegressionEvaluator from pyspark.ml.recommendation import ALS from pyspark.sql import Row
根據數據結構創建讀取示范
創建一個函數,返回即[Int, Int, Float, Long]的對象
def f(x): rel = {} rel['userId'] = int(x[0]) rel['movieId'] = int(x[1]) rel['rating'] = float(x[2]) rel['timestamp'] = float(x[3]) return rel
讀取數據
ratings = sc.textFile("hdfs://10.77.20.23:8020/text/ml-1m/ml-1m/ratings.txt").map(lambda line: line.split('::')).map(lambda p: Row(**f(p))).toDF()
然后把數據打印出來:
構建模型
training, test = ratings.randomSplit([0.8,0.2])
使用ALS來建立推薦模型,這里我們構建了兩個模型,一個是顯性反饋,一個是隱性反饋
alsExplicit = ALS(maxIter=5, regParam=0.01, userCol="userId", itemCol="movieId", ratingCol="rating") alsImplicit = ALS(maxIter=5, regParam=0.01, implicitPrefs=True,userCol="userId", itemCol="movieId", ratingCol="rating")
接下來,把推薦模型放在訓練數據上訓練:
modelExplicit = alsExplicit.fit(training)
modelImplicit = alsImplicit.fit(training)
模型預測
使用訓練好的推薦模型對測試集中的用戶商品進行預測評分,得到預測評分的數據集
predictionsExplicit = modelExplicit.transform(test)
predictionsImplicit = modelImplicit.transform(test)
輸出結果
對比真實結果與預測結果
以上示例來自於 http://dblab.xmu.edu.cn/blog/1781-2/
python實現的電影推薦的協同過濾算法其他實例代碼