SVD簡化數據

一,引言python

  咱們知道,在實際生活中,採集到的數據大部分信息都是無用的噪聲和冗餘信息,那麼,咱們如何才能剔除掉這些噪聲和無用的信息,只保留包含絕大部分重要信息的數據特徵呢?算法

  除了上次降到的PCA方法,本次介紹另一種方法,即SVD。SVD能夠用於簡化數據,提取出數據的重要特徵,而剔除掉數據中的噪聲和冗餘信息。SVD在現實中能夠應用於推薦系統用於提高性能,也能夠用於圖像壓縮,節省內存。數組

二,利用python事先SVD網絡

1 svd原理--矩陣分解app

    在不少狀況下,數據中的一小段攜帶了數據集的大部分信息,其餘信息則要麼是噪聲,要麼是絕不相關的信息。而矩陣分解技術能夠將原始矩陣表示成新的易於理解的形式,即將數據矩陣表示成兩個或者多個矩陣相乘的形式。而咱們這裏要講的SVD,就是最經常使用的一種矩陣分解技術,SVD將原始的數據矩陣D分解成三個矩陣U,Σ和VT。若是原始矩陣是m行n列,那麼U,Σ和VT就分別是m行m列,m行n列,以及n行n列,即:機器學習

                             Dm×n=Um×m Σm×n和VTn×n                             (1)函數

其中,矩陣Σ是一個只含對角元素的矩陣,其他元素都爲0;此外,Σ的對角元素值是按照由大到小排列的。這就給了咱們一個啓示,若是某一數據矩陣進過奇異值分解後獲得的Σ,從某一對角元素值日後元素值小於某一很小的閾值,那麼咱們就能夠將這些小於閾值的特徵值忽略掉,只保留前面的包含絕大部分信息的特徵值(通常狀況下,這裏的絕大部分指的是至少包含數據信息的90%的信息量)。這樣,咱們就能剔除掉數據中的噪聲和冗餘信息,使數據變得更加簡潔和高效。工具

2 python實現SVD性能

  在python中的Numpy中有一個線性工具箱叫作linalg,它能夠幫助咱們實現矩陣的奇異值分解,即調用語句:學習

from numpy import*
from numpy import linalg
U,Sigma,VT=linalg.svd(dataMat)

須要說明的是,在python中,由上述方法獲得的Sigma,是Numpy的數組,因此,在實際的應用中,咱們須要根據Sigma數組構建出相對應的方陣。好比,咱們利用以下的矩陣來進行SVD,獲得的Sigma以下所示:

  由上圖能夠看到,Sigma是以數組的形式呈現的,此外,前三個數值比其餘值大不少個數量級。因而,咱們能夠將最後兩個值去掉,只保留下前三個值,這樣,SVD公式就變成這樣:Dm×n=Um×3 Σ3×3和VT3×n。也是咱們只用矩陣U的前三列和VT的前三行,進行計算,從而將原始數據轉化到低維度的空間。

  固然,這裏的3僅表明此狀況下只保留Sigma的前三個特徵奇異值。而在實際中,一個典型的作法是,保留矩陣中90%的能量信息。計算方法是,先求出全部奇異值的平方和,而後從第一個特徵奇異值開始進行平方和累加,當達到總能量的90%以上時,這些特徵奇異值就是要保留下來的奇異值,其他的奇異值所有捨棄。

三,基於協同過濾的推薦引擎

1 類似度的計算

 推薦引擎是機器學習的一個重要應用,好比,Amazon會根據顧客的購買歷史向他們推薦物品,Netflix會像其用戶推薦電影,新聞網站會對用戶推薦新聞報道等等。固然,有不少方法能夠實現推薦功能,好比基於內容的推薦,基於協同過濾的推薦,或者多個推薦相組合的推薦等等。基於內容的推薦,是經過機器學習的方法,好比決策樹,神經網絡等從用戶對於物品的評價的內容特徵描述中獲得用戶感興趣的資料,而不須要其餘用戶的數據。而基於協同過濾的推薦方法則是經過將用戶與其餘用戶的數據進行比對,依據類似度的大小實現推薦。

  首先,在進行協同過濾以前,咱們須要將數據轉化爲合理的形式,即將數據轉化爲矩陣的形式,這樣,便於咱們處理和計算類似度。當咱們計算出了用戶或者物品之間的類似度,咱們就能夠利用已有的數據來預測未知的用戶喜愛。好比,咱們試圖對某個用戶喜歡的電影進行預測,推薦引擎會發現有一部電影該用戶沒有看過。而後,就會計算該電影和用戶看過電影之間的類似度,若是類似度很高,推薦算法就會認爲用戶喜歡這部電影。

  這裏,協同過濾的類似度計算,並非計算兩個物品的屬性信息的類似程度,而是基於用戶對這些物品的評價信息來計算類似度。這也是協同過濾所使用的方法,即不關心物品的描述屬性,而只關心用戶對於物品的評價觀點來進行類似度計算。

  類似度的計算方法有不少,好比歐氏距離,相關係數,餘弦距離等。相關係數和餘弦距離,是對兩個向量之間的比較。這兩種方法相對於歐氏距離的一個優點在於,它們對於用戶的評級的量級並不敏感。爲了將類似度歸一化,咱們須要對着三種方法計算獲得的結果,進行歸一化處理,使其最終的結果位於(0,1)內,即:

  歐式距離類似度=1/(1+歐式距離)

  相關係數類似度=0.5+0.5*corrcoef()

  餘弦距離類似度=0.5+0.5*(cosine距離)

下面是具體的類似度計算方法代碼:

from numpy import *
from numpy import linalg

#歐式距離類似度計算
def eulidSim(inA,inB):
    return 1.0/(1.0+linalg.norm(inA,inB))

#相關係數類似度計算
def corrSim(inA,inB):
    if len(inA)<3:return 1.0
    return 0.5+0.5*corrcoef(inA,inB,rowvar=0)[0][1]

#餘弦距離類似度計算
def cosineSim(inA,inB):
    num=float(inA.T*inB)
    denom=linalg.norm(inA)*linalg.norm(inB)
    return 0.5+0.5*corrcoef(num/denom)

  上面有了,類似度的計算方法,那麼接下來要考慮的問題就是,是計算用戶的類似度仍是計算物品的類似度呢?顯然,數據的行表明的是基於用戶,而列表明的則是基於物品。具體使用哪種類似度計算,須要根據用戶或者物品的數目。由於,不論是基於物品的類似度仍是基於用戶的類似度都會隨着各自的數目的增長,計算的時間也相應增長。因此,爲了節省計算時間,咱們按照數目相對較少的那一個量去計算類似度。顯然,對於一家固定的餐館,其菜品的數目基本是固定的,變化不大,但其用戶數目卻可能會發生很大的變化,因此,通常狀況下,協同過濾的推薦方法會偏向於計算基於物品的類似度。

2 推薦引擎的評價

       那麼如何對推薦引擎進行評價呢?此時,咱們既沒有預測的目標值,也沒有用戶來調查他們對於預測的滿意程度。這麼咱們採用前面屢次使用的交叉測試的方法。即,將某些已知的物品評分刪掉,而後對這些物品的評分進行預測,而後比較預測值和真實值的差別。

  一般用於推薦系統的評價的指標是最小均方根偏差。即,首先計算平方偏差的均值,而後再對平均值開根號。

 3 餐館菜菜餚引擎

  首先咱們構建一個基本的推薦引擎,它可以尋找用戶沒有嘗過的菜餚。而後,經過SVD來減小特徵空間並提升推薦效果。

  基本的推薦系統基本流程以下:

(1)尋找用戶沒有評級的菜餚,即在用戶-物品矩陣中的0值

(2)在用戶沒有評級的全部物品中,對每個物品預測一個可能的評級分數。

(3)對這些物品的評分從高到低排序,返回前N個物品。

具體的代碼以下:

#未評級物品的評分預測函數
#@dataMat:數據矩陣
#@user:目標用戶編號(矩陣索引,從0開始)
#@simMeans:類似度計算方法 默認餘弦距離
#@item:未評分物品編號(索引,從0開始)
def standEst(dataMat,user,simMeans,item):
    #獲取數據矩陣的列數
    n=shape[dataMat][1]
    #須要更新的兩個類似度計算相關的值
    simTotal=0.0;ratSimTotal=0.0
    #遍歷矩陣的每一列(遍歷目標用戶評價的物品列)
    for j in range(m):
        #若是目標用戶對該物品爲評分,跳出本次循環
        userRating=dataMat[user,j]
        if userRating==0:continue
        #用'logical_and'函數,統計目標列與當前列中在當前行均有評分的數據
        overLap=nonzero(logical_and(dataMat[:,item].A>0,\
                                     dataMat[:,j].A>0))[0]
       #若是不存在,則當前列於目標列類似性爲0返回
        if len(overLap)==0:simiarity=0
        不然,計算這兩列中均有評分的行之間的類似度
        else:similarity=simMean(dataMat[overLap,item],\
                                               dataMat[overLap,j])
        #更新兩個變量的值
        simTotal+=similarity
        ratSimTotal+=similarity+userRating
    if simTotal==0:return 0
    else:return ratSimTotal/simTotal

#推薦系統主體函數
#@dataMat:數據矩陣
#@user:目標用戶編號(矩陣索引,從0開始)
#@N=3:保留的類似度最高的前N個菜餚,默認爲3個
#@simMeas=cosSim:類似度計算方法 默認餘弦距離
#@estMethod=standEst:評分方法,默認是standEst函數
def recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):
    #從數據矩陣中找出目標用戶user所用的未評分的菜餚的列
    unratedItems=nonzero(dataMat[user,:].A==0)[1]
    #若是沒有,代表全部菜餚均有評分
    if len(unratedItems)==0:renturn 'you rated everything'
    itemScores=[]
   #遍歷每個未評分的矩陣列(未評分的菜餚)
    for item in unratedItems:
       #預估的評分採用默認的評分方法
        estimatedScore=esMethod(dataMat,user,simMeans,item)
       #將該菜餚及其預估評分加入數組列表
        itemScores.append((item,estimatedScore))
    #利用sorted函數對列表中的預估評分由高到低排序,返回前N個菜餚
    return sorted(itemsScores,key=lambda jj=jj[1],reverse=True)[:N]             

  由上面的函數,咱們知道,推薦系統對於用戶沒有評分的菜餚,經過計算該用戶與其餘用戶評分的菜餚的類似度,來預估出該用戶對於該未評分菜餚的評分,從而選擇出評分最高的前N個菜餚推薦給用戶。

  有了基本的協同過濾的推薦系統,咱們接下來在推薦系統中引入SVD,將高維的數據矩陣映射到低維的矩陣中去,而後,在低緯空間中,利用前面的類似度計算方法來進行推薦。具體的代碼以下:

#引入SVD的推薦引擎
#@dataMat:數據矩陣
#@user:目標用戶索引
#@simMeans:類似度計算方法
#@item:目標菜餚索引
def svdEst(dataMat,user,simMeans,item):
    #獲取數據矩陣列
    n=shape(dataMat)[1]
    simTotal=0.0;ratSimTotal=0.0
    #svd進行奇異值分解
    U,Sigma,VT=linalg.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=simMeans(xformedItems[item,:].T,\
                                     xformedItems[j,:].T)
        simTotal+=similarity
        ratSimTotal+=similarity*userRating
        if simTotal==0:return 0
        else:return ratSimTotal/simTotal

  由上面的函數可知,相比於普通的推薦系統,增長了SVD的計算,即對數據矩陣進行奇異值分值,保留包含數據信息90%能量的m奇異值,組成m*m的方陣。而後,利用矩陣U的前m列和m*m的奇異值方陣,將數據矩陣映射到低緯的空間。

4 推薦系統面臨的挑戰

(1)當數據集規模很大時,SVD分解會下降程序的速度,因此,在大型系統中,SVD運行的頻率很低,而且須要離線運行。

(2)實際的數據矩陣中0的數目不少,顯然會形成空間資源的浪費,若是有效的存儲這些數據,能夠幫助咱們節省內存和計算開銷。

(3)在程序中,每次須要計算一個得分時,都要計算多個物品的類似度得分。咱們知道,這些得分記錄的是物品的類似度。因此,咱們能夠離線計算類似度得分並保存,當須要的時候調用便可。

(4)冷啓動問題,即如何在缺少數據時給出好的推薦。這時,咱們能夠將推薦當作是搜索問題,這就要用到須要推薦物品的屬性。在餐館菜餚的推薦系統中,咱們能夠經過各類標籤來標記菜餚,好比素食,美式BBQ,價格高低等。同時,咱們也能夠將這些屬性做爲類似度計算所須要的數據,即基內容的推薦。

四,基於SVD的圖像壓縮

  SVD除了應用在推薦系統中,還能夠用來進行數據壓縮,好比圖像壓縮。好比,對一個32*32=1024像素的圖像,首先,咱們採用矩陣的形式存儲該圖像;而後,對於圖像中每一個像素值,咱們採用閾值函數,將像素值大於0.8像素設置爲1,不然設置爲0;接下來,咱們對該圖像進行奇異值分解,獲得矩陣U,Sigma和VT,咱們保留包含圖像信息90%的m(m<32)奇異值;最後,咱們只保留矩陣U的前m列,矩陣VT的前m行,以及m個奇異值,就能夠完成原始矩陣的重構。假設,m=4,那麼須要保存的數值個數爲32*4+4*32+4=258,相比於原始矩陣的1024,得到了接近4倍的壓縮比。

五,小結

  SVD是一種相似於PCA的降維工具,咱們能夠利用SVD來提取矩陣的重要特徵,選擇保留數據90%的能量的狀況下,剔除數據中的噪聲和冗餘信息。SVD的一個強大的應用是提升推薦系統的性能,經過將數據矩陣映射到低緯的空間進行計算類似度,從而提高推薦引擎的效果。SVD還能夠用於數據的壓縮等,從而達到節省內存的目的。

相關文章
相關標籤/搜索