[機器學習筆記]奇異值分解SVD簡介及其在推薦系統中的簡單應用

本文先從幾何意義上對奇異值分解SVD進行簡單介紹,而後分析了特徵值分解與奇異值分解的區別與聯繫,最後用python實現將SVD應用於推薦系統。python

1.SVD詳解

SVD(singular value decomposition),翻譯成中文就是奇異值分解。SVD的用處有不少,好比:LSA(隱性語義分析)、推薦系統、特徵壓縮(或稱數據降維)。SVD能夠理解爲:將一個比較複雜的矩陣用更小更簡單的3個子矩陣的相乘來表示,這3個小矩陣描述了大矩陣重要的特性。算法

 

1.1奇異值分解的幾何意義(因公式輸入比較麻煩因此採起截圖的方式)app

2.SVD應用於推薦系統機器學習

數據集中行表明用戶user,列表明物品item,其中的值表明用戶對物品的打分。基於SVD的優點在於:用戶的評分數據是稀疏矩陣,能夠用SVD將原始數據映射到低維空間中,而後計算物品item之間的類似度,能夠節省計算資源。函數

總體思路:先找到用戶沒有評分的物品,而後再通過SVD「壓縮」後的低維空間中,計算未評分物品與其餘物品的類似性,獲得一個預測打分,再對這些物品的評分從高到低進行排序,返回前N個物品推薦給用戶。學習

 

具體代碼以下,主要分爲5部分:測試

第1部分:加載測試數據集;spa

第2部分:定義三種計算類似度的方法;.net

第3部分:經過計算奇異值平方和的百分比來肯定將數據降到多少維才合適,返回須要降到的維度;翻譯

第4部分:在已經降維的數據中,基於SVD對用戶未打分的物品進行評分預測,返回未打分物品的預測評分值;

第5部分:產生前N個評分值高的物品,返回物品編號以及預測評分值。

 

優點在於:用戶的評分數據是稀疏矩陣,能夠用SVD將數據映射到低維空間,而後計算低維空間中的item之間的類似度,對用戶未評分的item進行評分預測,最後將預測評分高的item推薦給用戶。

#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]])

'''如下是三種計算類似度的算法,分別是歐式距離、皮爾遜相關係數和餘弦類似度,
注意三種計算方式的參數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之間

'''按照前k個奇異值的平方和佔總奇異值的平方和的百分比percentage來肯定k的值,
後續計算SVD時須要將原始矩陣轉換到k維空間'''
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

'''函數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的預測評分

'''函數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名,及其預測評分值
將文件命名爲svd2.py,在python提示符下輸入:
>>>import svd2
>>>testdata=svd2.loadExData()
>>>svd2.recommend(testdata,1,N=3,percentage=0.8)#對編號爲1的用戶推薦評分較高的3件商品

 

Reference:

1.Peter Harrington,《機器學習實戰》,人民郵電出版社,2013

2.http://www.ams.org/samplings/feature-column/fcarc-svd (講解SVD很是好的一篇文章,對於理解SVD很是有幫助,本文中SVD的幾何意義就是參考這篇)

3. http://blog.csdn.net/xiahouzuoxin/article/details/41118351 (講解SVD與特徵值分解區別的一篇文章)

相關文章
相關標籤/搜索