1.ItemCF: 協(xié)同過(guò)濾是什么? ItemCF:Item Collaboration Filter,基于物品的協(xié)同過(guò)濾。 |N(i)|是喜歡物品i的用戶數(shù),|N(j)|是喜歡物品j的用戶數(shù)。 3.給用戶推薦物品。
舉個(gè)例子: ItemCF流程: CalSim為計(jì)算poi相似度的模塊,基于論文Scalable Similarity-Based Neighborhood Methods with MapReduce實(shí)現(xiàn)。 CalSim模塊: 理論部分已經(jīng)介紹完畢,下面是代碼部分: #-*-coding:utf-8-*-'''Created on 2016-5-30@author: thinkgamer'''import mathclass ItemBasedCF:def __init__(self,train_file):self.train_file = train_fileself.readData()def readData(self):#讀取文件,并生成用戶-物品的評(píng)分表和測(cè)試集self.train = dict() #用戶-物品的評(píng)分表for line in open(self.train_file):# user,item,score = line.strip().split(",")user,score,item = line.strip().split(",")self.train.setdefault(user,{})self.train[user][item] = int(float(score))def ItemSimilarity(self):#建立物品-物品的共現(xiàn)矩陣C = dict() #物品-物品的共現(xiàn)矩陣N = dict() #物品被多少個(gè)不同用戶購(gòu)買(mǎi)for user,items in self.train.items():for i in items.keys():N.setdefault(i,0)N[i] += 1C.setdefault(i,{})for j in items.keys():if i == j : continueC[i].setdefault(j,0)C[i][j] += 1#計(jì)算相似度矩陣self.W = dict()for i,related_items in C.items():self.W.setdefault(i,{})for j,cij in related_items.items():self.W[i][j] = cij / (math.sqrt(N[i] * N[j]))return self.W#給用戶user推薦,前K個(gè)相關(guān)用戶def Recommend(self,user,K=3,N=10):rank = dict()action_item = self.train[user] #用戶user產(chǎn)生過(guò)行為的item和評(píng)分for item,score in action_item.items():for j,wj in sorted(self.W[item].items(),key=lambda x:x[1],reverse=True)[0:K]:if j in action_item.keys():continuerank.setdefault(j,0)rank[j] += score * wjreturn dict(sorted(rank.items(),key=lambda x:x[1],reverse=True)[0:N])#聲明一個(gè)ItemBased推薦的對(duì)象Item = ItemBasedCF("uid_score_bid")Item.ItemSimilarity()recommedDic = Item.Recommend("xiyuweilan")for k,v in recommedDic.iteritems():print k,"\t",v 2.MF(ALS)矩陣分解原理和代碼可以參考https://blog.csdn.net/pearl8899/article/details/80336938,這是18年夏天使用該算法的時(shí)候,做的筆記,寫(xiě)的略微繁瑣,這里精簡(jiǎn)一下。論文名字:matrix factorization techniques for recommender systems 先放一張圖留著: MF(matrix factorization):矩陣分解,分解的是什么矩陣,元素如何獲?。?/h2>這個(gè)矩陣是上圖的“Rating”,是user對(duì)deal,也就是item的行為,在論文中,Rating是電影評(píng)分的意思,在工業(yè)界中,這個(gè)Rating,可以是user對(duì)deal的點(diǎn)擊、下單、瀏覽的匯總,至于匯總的方式是什么,根據(jù)你對(duì)業(yè)務(wù)的理解,自己定義。比如user對(duì)deal1點(diǎn)擊1次算1分,下單算5分,也即是給不同行為加權(quán)累積。這里要注意,在使用spark ML中ALS的時(shí)候,要注意迭代分解的時(shí)候是顯示還是隱式,像上述給出的Rating,那便是顯示行為,人為的給這個(gè)user-deal之間強(qiáng)加了一個(gè)rating. 基于矩陣分解的推薦算法的核心假設(shè)是用隱語(yǔ)義(隱變量)來(lái)表達(dá)用戶和物品,他們的乘積關(guān)系就成為了原始的元素。這種假設(shè)之所以成立,是因?yàn)槲覀冋J(rèn)為實(shí)際的交互數(shù)據(jù)是由一系列的隱變量的影響下產(chǎn)生的(通常隱變量帶有統(tǒng)計(jì)分布的假設(shè),就是隱變量之間,或者隱變量和顯式變量之間的關(guān)系,我們往往認(rèn)為是由某種分布產(chǎn)生的。),這些隱變量代表了用戶和物品一部分共有的特征,在物品身上表現(xiàn)為屬性特征,在用戶身上表現(xiàn)為偏好特征,只不過(guò)這些因子并不具有實(shí)際意義,也不一定具有非常好的可解釋性,每一個(gè)維度也沒(méi)有確定的標(biāo)簽名字,所以才會(huì)叫做 “隱變量”。而矩陣分解后得到的兩個(gè)包含隱變量的小矩陣,一個(gè)代表用戶的隱含特征,一個(gè)代表物品的隱含特征,矩陣的元素值代表著相應(yīng)用戶或物品對(duì)各項(xiàng)隱因子的符合程度,有正面的也有負(fù)面的。 ALS 是什么?----同SGD一樣,求解參數(shù)的一種方法ALS 是交替最小二乘 (alternating least squares)的簡(jiǎn)稱(chēng)。在機(jī)器學(xué)習(xí)的上下文中,ALS 特指使用交替最小二乘求解的一個(gè)協(xié)同推薦算法。 ALS 的核心就是下面這個(gè)假設(shè):打分矩陣是近似低秩的。換句話說(shuō),一個(gè)m*n的大矩陣 A 可以用兩個(gè)小矩陣U(m*k)和V(n*k)的乘積來(lái)近似: ALS 的名字里給出——交替最小二乘。ALS 的目標(biāo)函數(shù)不是凸的,而且變量互相耦合在一起,所以它并不算好解。但如果我們把用戶特征矩陣U和產(chǎn)品特征矩陣V固定其一,這個(gè)問(wèn)題立刻變成了一個(gè)凸的而且可拆分的問(wèn)題。比如我們固定U,那么目標(biāo)函數(shù)就可以寫(xiě)成。其中關(guān)于每個(gè)產(chǎn)品特征vj的部分是獨(dú)立的,也就是說(shuō)固定U求vj我們只需要最小化就好了,這個(gè)問(wèn)題就是經(jīng)典的最小二乘問(wèn)題。所謂“交替”,就是指我們先隨機(jī)生成U0然后固定它求解V0,在固定V0求解U1,這樣交替進(jìn)行下去。因?yàn)槊坎降紩?huì)降低重構(gòu)誤差,并且誤差是有下界的,所以 ALS 一定會(huì)收斂。但由于問(wèn)題是非凸的,ALS 并不保證會(huì)收斂到全局最優(yōu)解。但在實(shí)際應(yīng)用中,ALS 對(duì)初始點(diǎn)不是很敏感,是不是全局最優(yōu)解造成的影響并不大。 匯總: 對(duì)于一個(gè)users-products-rating的評(píng)分?jǐn)?shù)據(jù)集,ALS會(huì)建立一個(gè)user*product的m*n的矩陣。其中,m為users的數(shù)量,n為products的數(shù)量。但是在這個(gè)數(shù)據(jù)集中,并不是每個(gè)用戶都對(duì)每個(gè)產(chǎn)品進(jìn)行過(guò)評(píng)分,所以這個(gè)矩陣往往是稀疏的,用戶i對(duì)產(chǎn)品j的評(píng)分往往是空的。 ALS所做的事情就是將這個(gè)稀疏矩陣通過(guò)一定的規(guī)律填滿,這樣就可以從矩陣中得到任意一個(gè)user對(duì)任意一個(gè)product的評(píng)分,ALS填充的評(píng)分項(xiàng)也稱(chēng)為用戶i對(duì)產(chǎn)品j的預(yù)測(cè)得分。所以說(shuō),ALS算法的核心就是通過(guò)什么樣子的規(guī)律來(lái)填滿(預(yù)測(cè))這個(gè)稀疏矩陣 它是這么做的:假設(shè)m*n的評(píng)分矩陣R,可以被近似分解成U*(V)T,U為m*d的用戶特征向量矩陣,V為n*d的產(chǎn)品特征向量矩陣((V)T代表V的轉(zhuǎn)置),d為user/product的特征值的數(shù)量。ALS算法的核心就是將稀疏評(píng)分矩陣分解為用戶特征向量矩陣和產(chǎn)品特征向量矩陣的乘積交替使用最小二乘法逐步計(jì)算用戶/產(chǎn)品特征向量,使得差平方和最小通過(guò)用戶/產(chǎn)品特征向量的矩陣來(lái)預(yù)測(cè)某個(gè)用戶對(duì)某個(gè)產(chǎn)品的評(píng)分。 spark ALS代碼解釋常被應(yīng)用于推薦系統(tǒng)。這些技術(shù)旨在補(bǔ)充用戶-商品關(guān)聯(lián)矩陣中所缺失的部分。MLlib當(dāng)前支持基于模型的協(xié)同過(guò)濾,其中用戶和商品通過(guò)一小組隱語(yǔ)義因子進(jìn)行表達(dá),并且這些因子也用于預(yù)測(cè)缺失的元素。為此,我們實(shí)現(xiàn)了ALS來(lái)學(xué)習(xí)這些隱性語(yǔ)義因子。在 MLlib 中的實(shí)現(xiàn)有如下的參數(shù): numBlocks 是用于并行化計(jì)算的分塊個(gè)數(shù) (設(shè)置為-1為自動(dòng)配置)。 rank 是模型中隱語(yǔ)義因子的個(gè)數(shù)。就是平時(shí)的特征向量的長(zhǎng)度。 maxIter:iterations 是迭代的次數(shù)。 lambda 是ALS的正則化參數(shù)。 implicitPrefs 決定了是用顯性反饋ALS的版本還是用適用隱性反饋數(shù)據(jù)集的版本,如果是隱性反饋則需要將其參數(shù)設(shè)置為true。 alpha 是一個(gè)針對(duì)于隱性反饋 ALS 版本的參數(shù),這個(gè)參數(shù)決定了偏好行為強(qiáng)度的基準(zhǔn)。 itemCol:deal的字段名字,需要跟表中的字段名字是一樣的。 nonnegative:是否使用非負(fù)約束,默認(rèn)不使用 false。 predictionCol:預(yù)測(cè)列的名字 ratingCol:評(píng)論字段的列名字,要跟表中的數(shù)據(jù)字段一致。 userCol:用戶字段的名字,同樣要保持一致。 實(shí)踐小技巧: 包括三步: println("end als and begin paramGrid ----------")val paramGrid = new ParamGridBuilder().addGrid(als.maxIter,Array(50,100,150)).addGrid(als.rank,Array(32,64,128,256)).build()val evaluator = new RegressionEvaluator().setMetricName("rmse").setLabelCol("rating").setPredictionCol("prediction")println("end evaluator and begin TV ")val trainValidationSplit = new TrainValidationSplit().setEstimator(als).setEvaluator(evaluator).setTrainRatio(0.8).setEstimatorParamMaps(paramGrid).setSeed(567812)println("begin tv model__________")val tvModel: TrainValidationSplitModel = trainValidationSplit.fit(training) 第一步:確定paramGrid。這里加入對(duì)迭代次數(shù)和分裂維度進(jìn)行網(wǎng)格搜索。其實(shí)就是貪婪搜索,遍歷每一種可能。 第二步:確定評(píng)估方法evaluator。這里用rmse進(jìn)行評(píng)估。 第三步:TV方法進(jìn)行訓(xùn)練。 第四步:可能需要模型之間的轉(zhuǎn)換。 2. ALS中還有一個(gè)加速分解的參數(shù): .setNumBlocks(200) 這個(gè)參數(shù)官網(wǎng)文檔說(shuō)這個(gè)參數(shù)可以設(shè)置為-1,加速分解,但是我將其設(shè)置為-1的時(shí)候,出bug,說(shuō)是該參數(shù)設(shè)置無(wú)效。因此只能盡量的將這些參數(shù)設(shè)置的大一些,加速矩陣分解。我采用了rating矩陣中有5億數(shù)據(jù)進(jìn)行分解,分200塊,速度確實(shí)提高了不少,具體沒(méi)有衡量。 3. 寫(xiě)在最后,感謝孟祥瑞大佬、銘霏大佬以及各位大佬在als在sparkML中的實(shí)現(xiàn)。 參考博客: 1.https://blog.csdn.net/u012102306/article/details/51097502 補(bǔ)充知識(shí): |
|
來(lái)自: Clay*more > 《機(jī)器學(xué)習(xí)》