天天看點

機器學習-python利用SVD編寫推薦引擎

代碼及資料集下載下傳:SVD

SVD(Singular Value Decomposition)主要用來進行資料降維、特征提取、消除資料噪聲、消去資料中的備援資訊、資料壓縮等。用于提高機器學習算法的效果,或壓縮資料存儲空間。利用SVD能夠用小的多的資料集表示原始資料,其實質是去除了噪聲以及備援項。SVD常用于隐形語義檢索的搜尋系統(LSI)、隐性語義分析(LSA)、推薦引擎、圖像壓縮。這裡主要通過推薦引擎的編寫,講述SVD的作用。

—推薦引擎

推薦系統是通過計算項與項之間的相似度而實作。利用SVD可以建構出一個主題空間,在該空間下電腦相似度将更加準确。

SVD的理論在博文機器學習中特征值分解與奇異值分解的差別及應用中檢視。

假定資料行為不同的人,列為菜品,元素為對應人對該菜品的打分,0表示沒打分。

機器學習-python利用SVD編寫推薦引擎

numpy的庫函數 U,sigma,VT=numpy.linalg.svd() 可以友善的實作奇異值分解。

sigma中奇異值的數量選取方法有以下幾種:

  • 保留90%的能量資訊。
  • 使用者自定義

協同過濾:協同過濾是通過将使用者和其他使用者或物品與其他物品的資料進行對比來實作推薦的。若兩個物品的相似度非常高,則可以将其推薦給使用者。

相似度計算:

  • 歐氏距離

    A = [a1,a2,a3],B=[b1,b2,b3]

    相似度 =11+norm(A−B)

  • 皮爾遜相關系數

    可以直接通過

    numpy.corrcoef()

    函數計算得到。其直接得到的值在 [−1,1] ,通過

    0.5+0.5*numpy.corrcoef()

    将其化為 [0,1]
  • 餘弦相似度

    計算兩個向量的餘弦值,如果夾角為90°則相似度為0,若同方向,則相似度為1。

    cosθ=A∗B||A||∗||B|| ,也可歸一化 0.5+0.5∗cosθ 得到。

    代碼如下:

def eulidSim(inA,inB):
    return /(+np.linalg.norm(inA-inB))
def pearsSim(inA,inB):
    if len(inA) < :
        return 
    return  +  * np.corrcoef(inA,inB,rowvar = )[][]
def cosSim(inA,inB):
    num = float(inA.T*inB)
    demon = np.linalg.norm(inA)*np.linalg.norm(inB)
    return  +  * (num/demon)
           

選擇基于使用者相似度還是基于物品相似度:

基于物品:計算兩個物品之間的相似度,來确定推薦物品。計算量随着物品的增加而增加。

基于使用者:計算使用者的相似度,确定推薦物品。計算量随着使用者增加而增加。

對于推薦系統,使用者數量遠大于物品數量,是以一般選擇基于物品的推薦算法。

評價名額:

推薦引擎的評價名額采用最小均方根誤差(RMSE),對均方誤差的平均值取其平方根。如果評級在1~5星之間,若RMSE=1,則可認為預測值與實際值相差1個等級。

基于SVD的推薦引擎。其思路為

尋找沒評價過得菜品
計算菜品的預測分數
推薦前N個
           

預測分數的思路為

SVD分解
SVD分解後矩陣= data.T * U[:,:N] * sigma(N)
for 每個菜品
    如果沒被使用者評價過
        continue
    如果評價過
        使用SVD分解後的矩陣計算相似度
        評分累加 = 相似度*評分
評分 = 評分累加/相似度累加
           

完整代碼為:

import numpy as np
def loadExData2():
    return[[, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ],
           [, , , , , , , , , , ]]

def eulidSim(inA,inB):#歐式相似度
    return /(+np.linalg.norm(inA-inB))
def pearsSim(inA,inB):#皮爾遜相關系數
    if len(inA) < :
        return 
    return  +  * np.corrcoef(inA,inB,rowvar = )[][]
def cosSim(inA,inB):#餘弦相似度
    num = float(inA.T*inB)
    demon = np.linalg.norm(inA)*np.linalg.norm(inB)
    return  +  * (num/demon)
def svdEst(dataSet,user,simMeans,item):#基于SVD的評價預測
    n = np.shape(dataSet)[]
    U,sigma,VT = np.linalg.svd(dataSet)
    sig4 = np.mat(np.eye()*sigma[:])
    xformedItems = dataSet.T * U[:,:] * sig4
#    xformedItems = VT[:4,:].T
    simTotal = 
    ratSimTotal = 
    for i in range(n):
        userRating = dataSet[user,i]
        if userRating ==  or i == item:
            continue
        similarity = simMeans(xformedItems[i,:].T,xformedItems[item,:].T)
        simTotal += similarity
        ratSimTotal += similarity * userRating
    if simTotal == :
        return 
    else:
        return ratSimTotal/simTotal



def recommend(dataSet,user,N=,simMeans = cosSim,estMethod = svdEst):#推薦引擎
    unratedItems = np.nonzero(dataSet[user,:]==)[]
    if len(unratedItems) == :
        return 'every dish have been rate'
    itemScores = [] 
    for item in unratedItems:
        estimatedScore = estMethod(dataSet,user,simMeans,item)
        itemScores.append((item,estimatedScore))
    return sorted(itemScores,key = lambda pp: pp[],reverse = True)[:N]



data = np.mat(loadExData2())
u,sigma,vt = np.linalg.svd(data)
sig4 = np.mat(np.eye()*sigma[:])

xform = data.T*u[:,:]*sig4
xform2 = sig4 * vt[:,:]    
estimatedScore = recommend(data,)