轉/寬客在線python
在矩陣分解在協同過濾推薦算法中的應用中,咱們對矩陣分解在推薦算法中的應用原理作了總結,這裏咱們就從實踐的角度來用Spark學習矩陣分解推薦算法。算法
在Spark MLlib中,推薦算法這塊只實現了基於矩陣分解的協同過濾推薦算法。而基於的算法是FunkSVD算法,即將m個用戶和n個物品對應的評分矩陣M分解爲兩個低維的矩陣:數組
其中k爲分解成低維的維數,通常遠比m和n小。若是你們對FunkSVD算法不熟悉,能夠複習對應的原理篇。app
在Spark MLlib中,實現的FunkSVD算法支持Python,Java,Scala和R的接口。因爲前面的實踐篇咱們都是基於Python,本文的後面的介紹和使用也會使用MLlib的Python接口。Spark MLlib推薦算法python對應的接口都在pyspark.mllib.recommendation包中,這個包有三個類,Rating,MatrixFactorizationModel和ALS。雖然裏面有三個類,可是算法只是FunkSVD算法。函數
下面介紹這三個類的用途。Rating類比較簡單,僅僅只是爲了封裝用戶,物品與評分這3個值。也就是說,Rating類裏面只有用戶,物品與評分三元組,並無什麼函數接口。ALS負責訓練咱們的FunkSVD模型。之因此這兒用交替最小二乘法ALS表示,是由於Spark在FunkSVD的矩陣分解的目標函數優化時,使用的是ALS。oop
ALS函數有兩個函數,一個是train,這個函數直接使用咱們的評分矩陣來訓練數據,而另外一個函數trainImplicit則稍微複雜一點,它使用隱式反饋數據來訓練模型,和train函數相比,它多了一個指定隱式反饋信心閾值的參數,好比咱們能夠將評分矩陣轉化爲反饋數據矩陣,將對應的評分值根據必定的反饋原則轉化爲信心權重值。因爲隱式反饋原則通常要根據具體的問題和數據來定,本文後面只討論普通的評分矩陣分解。性能
MatrixFactorizationModel類是咱們用ALS類訓練出來的模型,這個模型能夠幫助咱們作預測。經常使用的預測有某一用戶和某一物品對應的評分,某用戶最喜歡的N個物品,某物品可能會被最喜歡的N個用戶,全部用戶各自最喜歡的N物品,以及全部物品被最喜歡的N個用戶。對於這些類的用法咱們再後面會有例子講解。學習
這裏咱們再對ALS訓練模型時的重要參數作一個總結。 優化
1)ratings : 評分矩陣對應的RDD。須要咱們輸入。若是是隱式反饋,則是評分矩陣對應的隱式反饋矩陣。spa
2)rank : 矩陣分解時對應的低維的維數。即PTm×kQk×nPm×kTQk×n中的維度k。這個值會影響矩陣分解的性能,越大則算法運行的時間和佔用的內存可能會越多。一般須要進行調參,通常能夠取10-200之間的數。
3)iterations :在矩陣分解用交替最小二乘法求解時,進行迭代的最大次數。這個值取決於評分矩陣的維度,以及評分矩陣的係數程度。通常來講,不須要太***如5-20次便可。默認值是5。
4)lambda: 在 python接口中使用的是lambda_,緣由是lambda是Python的保留字。這個值即爲FunkSVD分解時對應的正則化係數。主要用於控制模型的擬合程度,加強模型泛化能力。取值越大,則正則化懲罰越強。大型推薦系統通常須要調參獲得合適的值。
5)alpha : 這個參數僅僅在使用隱式反饋trainImplicit時有用。指定了隱式反饋信心閾值,這個值越大則越認爲用戶和他沒有評分的物品之間沒有關聯。通常須要調參獲得合適值。
從上面的描述能夠看出,使用ALS算法仍是蠻簡單的,須要注意調參的參數主要的是矩陣分解的維數rank, 正則化超參數lambda。若是是隱式反饋,還須要調參隱式反饋信心閾值alpha 。
下面咱們用一個具體的例子來說述Spark矩陣分解推薦算法的使用。這裏咱們使用MovieLens 100K的數據。
將數據解壓後,咱們只使用其中的u.data文件中的評分數據。這個數據集每行有4列,分別對應用戶ID,物品ID,評分和時間戳。因爲個人機器比較破,在下面的例子中,我只使用了前100條數據。所以若是你使用了全部的數據,後面的預測結果會與個人不一樣。
首先須要要確保你安裝好了Hadoop和Spark(版本不小於1.6),並設置好了環境變量。通常咱們都是在ipython notebook(jupyternotebook)中學習,因此最好把基於notebook的Spark環境搭好。固然不搭notebook的Spark環境也沒有關係,只是每次須要在運行前設置環境變量。若是你沒有搭notebook的Spark環境,則須要先跑下面這段代碼。固然,若是你已經搭好了,則下面這段代碼不用跑了。
import os import sys #下面這些目錄都是你本身機器的Spark安裝目錄和Java安裝目錄 os.environ['SPARK_HOME'] = "C:/Tools/spark-1.6.1-bin-hadoop2.6/" sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/bin") sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python") sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/pyspark") sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib") sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib/pyspark.zip") sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib/py4j-0.9-src.zip") sys.path.append("C:/Program Files (x86)/Java/jdk1.8.0_102") from pyspark import SparkContext from pyspark import SparkConf sc = SparkContext("local", "testing") 複製代碼
在跑算法以前,建議輸出Spark Context以下,若是能夠正常打印內存地址,則說明Spark的運行環境搞定了。
print sc 複製代碼
好比個人輸出是:
<pyspark.context.SparkContext object at 0x07352950>
首先咱們將u.data文件讀入內存,並嘗試輸出第一行的數據來檢驗是否成功讀入,注意複製代碼的時候,數據的目錄要用你本身的u.data的目錄。代碼以下:
#下面目錄要用解壓後u.data所在的目錄 user_data = sc.textFile("C:/Temp/ml-100k/u.data") user_data.first() 複製代碼
輸出以下:
[u'196', u'242', u'3']
此時雖然咱們已經獲得了評分矩陣數組對應的RDD,可是這些數據都仍是字符串,Spark須要的是若干Rating類對應的數組。所以咱們如今將RDD的數據類型作轉化,代碼以下:
from pyspark.mllib.recommendation import Rating rates_data = rates.map(lambda x: Rating(int(x[0]),int(x[1]),int(x[2]))) print rates_data.first() 複製代碼
輸出以下:
Rating(user=196, product=242, rating=3.0)
可見咱們的數據已是基於Rating類的RDD了,如今咱們終於能夠把整理好的數據拿來訓練了,代碼以下, 咱們將矩陣分解的維度設置爲20,最大迭代次數設置爲5,而正則化係數設置爲0.02。在實際應用中,咱們須要經過交叉驗證來選擇合適的矩陣分解維度與正則化係數。這裏咱們因爲是實例,就簡化了。
from pyspark.mllib.recommendation import ALS from pyspark.mllib.recommendation import MatrixFactorizationModel sc.setCheckpointDir('checkpoint/') ALS.checkpointInterval = 2 model = ALS.train(ratings=rates_data, rank=20, iterations=5, lambda_=0.02) 複製代碼
將模型訓練完畢後,咱們終於能夠來作推薦系統的預測了。首先作一個最簡單的預測,好比預測用戶38對物品20的評分。代碼以下:
print model.predict(38,20) 複製代碼
輸出以下:
0.311633491603
可見評分並不高。如今咱們來預測了用戶38最喜歡的10個物品,代碼以下:
print model.recommendProducts(38,10) 複製代碼
輸出以下:
[Rating(user=38, product=95, rating=4.995227969811873), Rating(user=38, product=304, rating=2.5159673379104484), Rating(user=38, product=1014, rating=2.165428673820349), Rating(user=38, product=322, rating=1.7002266119079879), Rating(user=38, product=111, rating=1.2057528774266673), Rating(user=38, product=196, rating=1.0612630766055788), Rating(user=38, product=23, rating=1.0590775012913558), Rating(user=38, product=327, rating=1.0335651317559753), Rating(user=38, product=98, rating=0.9677333686628911), Rating(user=38, product=181, rating=0.8536682271006641)]
能夠看出用戶38可能喜歡的對應評分從高到低的10個物品。接着咱們來預測下物品20可能最值得推薦的10個用戶,代碼以下:
print model.recommendUsers(20,10) 複製代碼
輸出以下:
[Rating(user=115, product=20, rating=2.9892138653406635), Rating(user=25, product=20, rating=1.7558472892444517), Rating(user=7, product=20, rating=1.523935609195585), Rating(user=286, product=20, rating=1.3746309116764184), Rating(user=222, product=20, rating=1.313891405211581), Rating(user=135, product=20, rating=1.254412853860262), Rating(user=186, product=20, rating=1.2194811581542384), Rating(user=72, product=20, rating=1.1651855319930426), Rating(user=241, product=20, rating=1.0863391992741023), Rating(user=160, product=20, rating=1.072353288848142)]
如今咱們來看看每一個用戶最值得推薦的三個物品,代碼以下:
print model.recommendProductsForUsers(3).collect() 複製代碼
因爲輸出很是長,這裏就不將輸出copy過來了。而每一個物品最值得被推薦的三個用戶,代碼以下:
print model.recommendUsersForProducts(3).collect() 複製代碼
一樣因爲輸出很是長,這裏就不將輸出copy過來了。但願上面的例子對你們使用Spark矩陣分解推薦算法有幫助。