協同過濾算法介紹及算法實現

一、協同過濾算法簡介

  協同過濾算法是一種較爲著名和常用的推薦算法,它基於對用戶歷史行爲數據的挖掘發現用戶的喜好偏向,並預測用戶可能喜好的產品進行推薦。也就是常見的“猜你喜歡”,和“購買了該商品的人也喜歡”等功能。它的主要實現由:

  ●根據和你有共同喜好的人給你推薦

  ●根據你喜歡的物品給你推薦相似物品

  ●根據以上條件綜合推薦

  因此可以得出常用的協同過濾算法分爲兩種,基於用戶的協同過濾算法(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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章