基于linalg.svd的推薦算法的實現

數據集中行代表用戶user,列代表物品item,其中的值代表用戶對物品的打分。基于SVD的優勢在于:用戶的評分數據是稀疏矩陣,可以用SVD將原始數據映射到低維空間中,然后計算物品item之間的相似度,可以節省計算資源。
整體思路:先找到用戶沒有評分的物品,然后再經過SVD“壓縮”后的低維空間中,計算未評分物品與其他物品的相似性,得到一個預測打分,再對這些物品的評分從高到低進行排序,返回前N個物品推薦給用戶。

1.加載測試數據集
#coding=utf-8
from numpy import *
from numpy import linalg as la
# 加載測試數據集
def loadExData():
    return mat([[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
           [0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
           [0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
           [3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
           [5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
           [0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
           [4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
           [0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
           [0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],
           [0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],
           [1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]])

2.定義三種計算相似度的方法

分別是歐式距離、皮爾遜相關系數和余弦相似度,
注意三種計算方式的參數inA和inB都是列向量

def ecludSim(inA,inB):
    return 1.0/(1.0+la.norm(inA-inB))  #范數的計算方法linalg.norm(),這里的1/(1+距離)表示將相似度的范圍放在0與1之間

def pearsSim(inA,inB):
    if len(inA)<3: return 1.0
    return 0.5+0.5*corrcoef(inA,inB,rowvar=0)[0][1]  #皮爾遜相關系數的計算方法corrcoef(),參數rowvar=0表示對列求相似度,這里的0.5+0.5*corrcoef()是為了將范圍歸一化放到0和1之間

def cosSim(inA,inB):
    num=float(inA.T*inB)
    denom=la.norm(inA)*la.norm(inB)
    return 0.5+0.5*(num/denom) #將相似度歸一到0與1之間
3.通過計算奇異值平方和的百分比來確定將數據降到多少維才合適,返回需要降到的維度
def sigmaPct(sigma,percentage):
    sigma2=sigma**2 #對sigma求平方
    sumsgm2=sum(sigma2) #求所有奇異值sigma的平方和
    sumsgm3=0 #sumsgm3是前k個奇異值的平方和
    k=0
    for i in sigma:
        sumsgm3+=i**2
        k+=1
        if sumsgm3>=sumsgm2*percentage:
            return k
4.在已經降維的數據中,基于SVD對用戶未打分的物品進行評分預測,返回未打分物品的預測評分值

函數svdEst()的參數包含:數據矩陣、用戶編號、物品編號和奇異值占比的閾值,
數據矩陣的行對應用戶,列對應物品,函數的作用是基于item的相似性對用戶未評過分的物品進行預測評分

def svdEst(dataMat,user,simMeas,item,percentage):
    n=shape(dataMat)[1]
    simTotal=0.0;ratSimTotal=0.0
    u,sigma,vt=la.svd(dataMat)
    k=sigmaPct(sigma,percentage) #確定了k的值
    sigmaK=mat(eye(k)*sigma[:k])  #構建對角矩陣
    xformedItems=dataMat.T*u[:,:k]*sigmaK.I  #根據k的值將原始數據轉換到k維空間(低維),xformedItems表示物品(item)在k維空間轉換后的值
    for j in range(n):
        userRating=dataMat[user,j]
        if userRating==0 or j==item:continue
        similarity=simMeas(xformedItems[item,:].T,xformedItems[j,:].T) #計算物品item與物品j之間的相似度
        simTotal+=similarity #對所有相似度求和
        ratSimTotal+=similarity*userRating #用"物品item和物品j的相似度"乘以"用戶對物品j的評分",并求和
    if simTotal==0:return 0
    else:return ratSimTotal/simTotal #得到對物品item的預測評分
5.產生前N個評分值高的物品,返回物品編號以及預測評分值。

函數recommend()產生預測評分最高的N個推薦結果,默認返回5個;
參數包括:數據矩陣、用戶編號、相似度衡量的方法、預測評分的方法、以及奇異值占比的閾值;
數據矩陣的行對應用戶,列對應物品,函數的作用是基于item的相似性對用戶未評過分的物品進行預測評分;
相似度衡量的方法默認用余弦相似度

def recommend(dataMat,user,N=5,simMeas=cosSim,estMethod=svdEst,percentage=0.9):
    unratedItems=nonzero(dataMat[user,:].A==0)[1]  #建立一個用戶未評分item的列表
    if len(unratedItems)==0:return 'you rated everything' #如果都已經評過分,則退出
    itemScores=[]
    for item in unratedItems:  #對于每個未評分的item,都計算其預測評分
        estimatedScore=estMethod(dataMat,user,simMeas,item,percentage)
        itemScores.append((item,estimatedScore))
    itemScores=sorted(itemScores,key=lambda x:x[1],reverse=True)#按照item的得分進行從大到小排序
    return itemScores[:N]  #返回前N大評分值的item名,及其預測評分值
6.測試:對編號為1的用戶推薦評分較高的3件商品
testdata=loadExData()
recommend(testdata,1,N=3,percentage=0.8)

輸出結果:
[(4, 2.388669784821897), (8, 2.386959260544295), (7, 2.3859254004913772)]

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容

  • 推薦系統的主要方法 一、基于內容的推薦算法 網絡基于內容的推薦系統,也稱CB(Content-based Reco...
    Arya鑫閱讀 3,594評論 1 6
  • SVD解析以及用其實現推薦算法 標簽:推薦算法 [TOC] 首先介紹一下SVD,是對一個$mn$規模矩陣進行奇異值...
    PerfectDemoT閱讀 7,054評論 0 1
  • SVD解析以及用其實現推薦算法 標簽:推薦算法 [TOC] 首先介紹一下SVD,是對一個$mn$規模矩陣進行奇異值...
    PerfectDemoT閱讀 955評論 0 3
  • 在推薦系統中,我們經常會拿到一種數據是user—item的表格,然后對應的是每位user對每個item的評分,如下...
    Colleen_oh閱讀 7,117評論 0 15
  • 今天突發奇想,趁著陽光明媚,上街轉轉,不是逛商店的轉街。特意換上運動鞋,從家出發,沿八一路走,路兩邊停滿了車,人行...
    隨意路過閱讀 261評論 0 0