前言
在生活中,我們經常給朋友推薦一些自己喜歡的東西,也時常接受別人的推薦。怎麼能保證推薦的電影或者美食就是朋友喜歡的呢?一般來說,你們兩個人經常對同一個電影或者美食感興趣,那麼你喜歡的東西就很大程度上朋友也會比較感興趣。在大資料的背景下,演算法會幫我尋找興趣相似的那些人,並關注他們喜歡的東西,以此來給我們推薦可能喜歡的事物。
場景描述
某外賣店鋪收集了一些使用者對本店鋪美食的評價和推薦分,並計劃為一些新老客戶推薦他們未曾嘗試的美食。
資料分析
A B C D E F G H I J K
0[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
1[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
2[0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
3[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
4[0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
5[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
6[0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
7[0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],
8[0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],
9[1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]
複製程式碼
橫軸為美食品種,分為A--K 11中,豎軸為使用者序號,有0-9 10個人。表內值為某個使用者對某種美食的推薦分,0表示其未曾吃過,5分為最高的推薦分。以上資料為實驗虛構資料。
場景抽象化
給定一個使用者i,我們根據上面的資料為其推薦N個推薦分最高的美食。
模型選擇
協同過濾簡單來說是利用某興趣相投、擁有共同經驗之群體的喜好來推薦使用者感興趣的資訊,個人通過合作的機制給予資訊相當程度的迴應(如評分)並記錄下來以達到過濾的目的進而幫助別人篩選資訊,迴應不一定侷限於特別感興趣的,特別不感興趣資訊的紀錄也相當重要。
我們也將採用協同過濾來實現商品推薦,並在下面的章節一步步實現基於協同過濾的商品推薦系統。
資料處理
以上資料,不存在缺失和無意義推薦分,即不超出範圍,格式正確。
搭建環境
- 首先進入noteBook建模,連結
然後建立新例項
之後開啟例項
現在基礎環境以及搞定了,我們可以用terminal安裝自己需要的包環境。同時可以選擇python2或者python3的開發環境。而且左側的檔案系統,支援本地檔案的上傳下載等。
相似度計算
在推薦系統中,我們需要計算兩個人或商品的相似度,我們可以採用餘弦相似度,皮爾遜相關係數等。
餘弦相似性通過測量兩個向量的夾角的餘弦值來度量它們之間的相似性。0度角的餘弦值是1,表示完全一樣,而其他任何角度的餘弦值都不大於1;並且其最小值是-1,相似度為0。
皮爾遜相關係數( Pearson correlation coefficient),是用於度量兩個變數X和Y之間的相關(線性相關),其值介於-1與1之間。
新建檔案recom.py,實現相似度計算函式
def cosSim(inA,inB):
num = float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom)
複製程式碼
推薦分計算
在檔案recom.py,實現推薦分計算
#dataMat 使用者與美食的矩陣
#user 使用者序號
#simMeas 相似度演算法
#item 美食商品
def standEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1]#商品數
simTotal = 0.0; ratSimTotal = 0.0
for j in range(n):#所有商品,遍歷
userRating = dataMat[user,j]#user對該商品的推薦分
if userRating == 0: continue#如果user 未推薦該商品則過濾
#logical_and邏輯與,nonzero非零判斷,overLap為均為商品item,j推薦的使用者
overLap = nonzero(logical_and(dataMat[:,item].A>0, \
dataMat[:,j].A>0))[0]
if len(overLap) == 0: similarity = 0
#以此overLap,計算兩商品的相似度。
else: similarity = simMeas(dataMat[overLap,item], \
dataMat[overLap,j])
print('the %d and %d similarity is: %f' % (item, j, similarity))
simTotal += similarity
ratSimTotal += similarity * userRating
if simTotal == 0: return 0
else: return ratSimTotal/simTotal
複製程式碼
對於特徵向量非常稀疏,或者特徵之間關聯關係明顯,協方差較大則需要對原有維度的特徵進行降維。這樣既可以節省資源加快運算,也可以避免冗餘特徵帶來的干擾。
def svdEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1]
simTotal = 0.0; ratSimTotal = 0.0
U,Sigma,VT = la.svd(dataMat) #奇異值分解
Sig4 = mat(eye(4)*Sigma[:4]) #構建對角矩陣
xformedItems = dataMat.T * U[:,:4] * Sig4.I #資料維度轉換
for j in range(n):
userRating = dataMat[user,j]
if userRating == 0 or j==item: continue
similarity = simMeas(xformedItems[item,:].T,\
xformedItems[j,:].T)
print('the %d and %d similarity is: %f' % (item, j, similarity))
simTotal += similarity
ratSimTotal += similarity * userRating
if simTotal == 0: return 0
else: return ratSimTotal/simTotal
複製程式碼
通過計算待推薦商品與已推薦商品的相似度,並乘以該使用者對已推薦商品的推薦分,來計算待推薦商品的推薦分。
在檔案recom.py,加入recommend函式
#dataMat 使用者與美食的矩陣
#user 使用者序號
#N 推薦前N個商品
#simMeas 相似度計算演算法
#estMethod 推薦分計算演算法
def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
#找出user未評分的商品
unratedItems = nonzero(dataMat[user,:].A==0)[1]#find unrated items
if len(unratedItems) == 0: return 'you rated everything'
itemScores = []
#依次計算這些商品的推薦分
for item in unratedItems:
estimatedScore = estMethod(dataMat, user, simMeas, item)
itemScores.append((item, estimatedScore))
#返回前N個較好分的結果
return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N]
複製程式碼
演算法演示
如果是本地編輯的檔案,可以通過檔案上傳方式上傳到伺服器。
新建noteBook演示
載入演算法模板
資料展示
為序號為2的使用者推薦商品
總結
通常在計算相似度之前,我們需要確定是計算基於商品的相似度(上面的方式),還是計算基於使用者的相似度。在現實情況下,我們要根據使用者和商品的資料決定選擇哪種計算方式。同時,在資料量變大時,我們通常需要先降維,在做商品推薦。部分程式碼參考《機器學習實戰》,本篇文章主要介紹如何使用PAI-DSW實現演算法實驗。
本文為雲棲社群原創內容,未經允許不得轉載。