SVD简化数据
基礎知識可以參考:
http://blog.csdn.net/lilong117194/article/details/78579062
1. 奇異值分解 SVD(singular value decomposition)
1.1 基本概念:
(1)定義:提取信息的方法:奇異值分解Singular Value Decomposition(SVD)
(2)優點:簡化數據, 去除噪聲,提高算法的結果
(3)缺點:數據轉換難以想象,耗時,損失特征
(4)適用于:數值型數據
1.2 SVD應用
(1) 隱性語義索引(latent semantic indexing, LSI)/隱性語義分析(latent semantic analysis, LSA):
在LSI中, 一個矩陣由文檔和詞語組成的.在該矩陣上應用SVD可以構建多個奇異值, 這些奇異值代表文檔中的概念或主題, 可以用于更高效的文檔搜索.
(2) 推薦系統
先利用SVD從數據中構建一個主題空間, 然后在該主題空間下計算相似度.
1.3 SVD分解
SVD奇異值分解的定義:
M=U∑VT
假設M是一個m×n的矩陣,如果存在一個分解:
其中U為m×m的酉矩陣,∑為m×n的半正定對角矩陣,VT為V的共軛轉置矩陣,且為n×n的酉矩陣。這樣的分解稱為M的奇異值分解,∑對角線上的元素稱為奇異值,U稱為左奇異矩陣,VT稱為右奇異矩陣。SVD奇異值分解與特征值分解的關系:
特征值分解與SVD奇異值分解的目的都是提取一個矩陣最重要的特征。然而,特征值分解只適用于方陣,而SVD奇異值分解適用于任意的矩陣,不一定是方陣。
這里,MTM和MMT是方陣,UTU和VTV為單位矩陣,VT為MTM的特征向量,U為MMT的特征向量。MTM和MMT的特征值為M的奇異值的平方。
- SVD是一種矩陣分解技術,其將原始的數據集矩陣Am?n分解為三個矩陣, ,A=U∑VT分解得到的三個矩陣的維度分別為m?m,m?n,n?n.其中∑除了對角元素不為0,其它元素均為0,其對角元素稱為奇異值,且按從大到小的順序排列, 這些奇異值對應原始數據集矩陣A的奇異值。即A?AT的特征值的平方根。在某個奇異值(r個)之后, 其它的奇異值由于值太小,被忽略置為0, 這就意味著數據集中僅有r個重要特征,而其余特征都是噪聲或冗余特征.如下圖所示:
如何選擇數值r?
確定要保留的奇異值數目有很多啟發式的策略,其中一個典型的做法就是保留矩陣中90%的能量信息.為了計算能量信息,將所有的奇異值求其平方和,從大到小疊加奇異值,直到奇異值之和達到總值的90%為止;另一種方法是,當矩陣有上萬個奇異值時, 直接保留前2000或3000個.,但是后一種方法不能保證前3000個奇異值能夠包含錢90%的能量信息,但是操作簡單。
SVD分解很耗時,通過離線方式計算SVD分解和相似度計算,是一種減少冗余計算和推薦所需時間的辦法.
2. 基于協同過濾的推薦引擎
協同過濾是通過將用戶和其他用戶的數據進行對比來實現推薦的。
這里不利用專家所給出的重要屬性來描述物品從而計算它們之間的相似度,而是利用用戶對它們的意見來計算相似度。這就是協同過濾中所使用的方法。它并不關心物品的描述屬性,而是嚴格地按照許多用戶的觀點來計算相似度。
歐式距離
dist(X,Y)=[∑ni=1|xi?yi|2]12
我們希望,相似度值在0到1之間變化,并且物品對越相似,它們的
相似度值也就越大。我們可以用“相似度=1/(1+距離)”這樣的算式來計算相似度。當距離為0時,相似度為1.0。如果距離真的非常大時,相似度也就趨近于0。皮爾遜相關系數
第二種計算距離的方法是皮爾遜相關系數(Pearson correlation),它度量的是兩個向量之間的相似度。該方法相對于歐氏距離的一個
優勢在于,它對用戶評級的量級并不敏感。比如某個狂躁者對所有物品的評分都是5分,而另一個憂郁者對所有物品的評分都是1分,皮爾遜相關系數會認為這兩個向量是相等的。在Numpy中,皮爾遜相關系數的計算是由函數corrcoef()進行的。皮爾遜相關系數的取值范圍從-1到+1,我們通過$0.5+0.5*corrcoef()這個函數計算,并且把其取值范
圍歸一化到0到1之間。余弦相似度
cosθ=A?B||A||?||B||
另一個常用的距離計算方法就是余弦相似度(cosine similarity),其計算的是兩個向量夾角的余弦值。如果夾角為90度,則相似度為0;如果兩個向量的方向相同,則相似度為1.0。同皮爾遜相關系數一樣,余弦相似度的取值范圍也在-1到+1之間,因此我們也將它歸一化到0到1之間。計算余弦相似度值,我們采用的兩個向量A和B夾角的余弦相似度的定義如下:
基于物品的相似度還是基于用戶的相似度?
我們計算了兩個餐館菜肴之間的距離,這稱為基于物品(item-based)的相似度。另一種計算用戶距離的方法則稱為基于用戶的相似度到底使用哪一種相似度呢?這取決于用戶或物品的數目。基于物品相似度計算的時間會隨物品數量的增加而增加,基于用戶的相似度計算的時間則會隨用戶數量的增加而增加。
對于大部分產品導向的推薦引擎而言,用戶的數量往往大于物品的數量,即購買商品的用戶數會多于出售的商品種類。推薦引擎的評價:
如何對推薦引擎進行評價呢?此時,我們既沒有預測的目標值,也沒有用戶來調査他們對預測的滿意程度。這里我們就可以采用前面多次使用的交叉測試的方法。具體的做法就是,我們將某些已知的評分值去掉,然后對它們進行預測,最后計算預測值和真實值之間的差異。通常用于推薦引擎評價的指標是稱為最小均方根誤差的指標,它首先計算均方誤差的平均值然后取其平方根。3. 餐館菜肴推薦引擎
推薦系統的工作過程是:給定一個用戶,系統會為此用戶返回N個最好的推薦菜。為了實現這一點,則需要我們做到:
(1)尋找用戶沒有評級的菜肴,即在用戶-物品矩陣中的0值;
(2)在用戶沒有評級的所有物品中,對每個物品預計一個可能的評級分數。這就是說,我們認為用戶可能會對物品的打分(這就是相似度計算的初衷);
⑶對這些物品的評分從高到低進行排序,返回前N個物品。代碼實現:
# -*- coding: utf-8 -*- """ Spyder Editor""" from numpy import * from numpy import linalg as ladef loadExData():return[[0, 0, 0, 2, 2],[0, 0, 0, 3, 3],[0, 0, 0, 1, 1],[1, 1, 1, 0, 0],[2, 2, 2, 0, 0],[5, 5, 5, 0, 0],[1, 1, 1, 0, 0]]def ecludSim(inA,inB): # 計算兩向量的相似度return 1.0/(1.0 + la.norm(inA - inB)) # 這里距離采用的是歐式距離def pearsSim(inA,inB):if len(inA) < 3 : return 1.0return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[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)# 用戶對物品的估計評分值 def standEst(dataMat, user, simMeas, item): # 參數:數據矩陣,用戶編號,物品編號,相似度計算方法n = shape(dataMat)[1] # 數據的物品數(列對應物品,行對應用戶)simTotal = 0.0; ratSimTotal = 0.0for j in range(n): # 遍歷每個物品userRating = dataMat[user,j] # 該用戶對所有物品的評分if userRating == 0: continue # 跳過這個物品# 得到第2列和其他列物品的同時被評分的元素overLap = nonzero(logical_and(dataMat[:,item].A>0, dataMat[:,j].A>0))[0]print 'overLap :',overLap if len(overLap) == 0: # 如果兩者沒有任何重復的元素print 'here...'similarity = 0 # 則相似度為0else: # 基于重合物品計算相似度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 0else: return ratSimTotal/simTotal # 除以相似度的總和得到對相似度評分的歸一化,使得最后的評分在0到5之間# 推薦引擎(用的是余弦相似度) def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):unratedItems = nonzero(dataMat[user,:].A==0)[1] # 得到dataMat中用戶2對沒有評價過物品的索引if len(unratedItems) == 0: # 如果都評價了則返回顯示已評價過所有的物品return 'you rated everything'itemScores = []print 'unratedItems:',unratedItems # 索引值for item in unratedItems: # 遍歷沒有評價過的物品estimatedScore = estMethod(dataMat, user, simMeas, item) # 得到預測評分itemScores.append((item, estimatedScore)) # 物品編號和估計值分值放在一個元素列表中return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N] # 從大到小的逆序排列# 主函數 myData=mat(loadExData())sim_dis_1=ecludSim(myData[:,0],myData[:,4]) # 歐式距離計算相似度 print 'sim_dis_1:',sim_dis_1 sim_dis_2=cosSim(myData[:,0],myData[:,4]) # 余弦相似度 print 'sim_dis_2:',sim_dis_2 sim_dis_3=pearsSim(myData[:,0],myData[:,4]) # 余弦相似度 print 'sim_dis_3:',sim_dis_3# 推薦引擎 myData[0,1]=myData[0,0]=myData[1,0]=myData[2,0]=4 myData[3,3]=2 re_1=recommend(myData,2) re_2=recommend(myData,2,simMeas=ecludSim) re_3=recommend(myData,2,simMeas=pearsSim) print 're_1:',re_1 print 're_2:',re_2 print 're_3:',re_3運行結果:
sim_dis_1: 0.129731907557 sim_dis_2: 0.5 sim_dis_3: 0.205965381738 unratedItems: [1 2] overLap : [0 3 4 5 6] the 1 and 0 similarity is: 1.000000 overLap : [0 3] the 1 and 3 similarity is: 0.928746 overLap : [0] the 1 and 4 similarity is: 1.000000 overLap : [3 4 5 6] the 2 and 0 similarity is: 1.000000 overLap : [3] the 2 and 3 similarity is: 1.000000 overLap : [] here... the 2 and 4 similarity is: 0.000000 unratedItems: [1 2] overLap : [0 3 4 5 6] the 1 and 0 similarity is: 1.000000 overLap : [0 3] the 1 and 3 similarity is: 0.309017 overLap : [0] the 1 and 4 similarity is: 0.333333 overLap : [3 4 5 6] the 2 and 0 similarity is: 1.000000 overLap : [3] the 2 and 3 similarity is: 0.500000 overLap : [] here... the 2 and 4 similarity is: 0.000000 unratedItems: [1 2] overLap : [0 3 4 5 6] the 1 and 0 similarity is: 1.000000 overLap : [0 3] the 1 and 3 similarity is: 1.000000 overLap : [0] the 1 and 4 similarity is: 1.000000 overLap : [3 4 5 6] the 2 and 0 similarity is: 1.000000 overLap : [3] the 2 and 3 similarity is: 1.000000 overLap : [] here... the 2 and 4 similarity is: 0.000000 re_1: [(2, 2.5), (1, 2.0243290220056256)] re_2: [(2, 3.0), (1, 2.8266504712098603)] re_3: [(2, 2.5), (1, 2.0)]這個例子給出了如何利用基于物品相似度和多個相似度計算方法來進行推薦的過程,下面我們介紹如何將SVD應用于推薦。
4. 利用SVD提高推薦效果
實際的數據集得到的矩陣相當稀疏,因此可以先利用SVD將原始矩陣映射到低維空間中,; 然后再在低維空間中, 計算物品間的相似度,大大減少計算量。
代碼實現:
# -*- coding: utf-8 -*-from numpy import * from numpy import linalg as ladef loadExData2():return[[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]]def cosSim(inA,inB): # 余弦相似度num = float(inA.T*inB)denom = la.norm(inA)*la.norm(inB)return 0.5+0.5*(num/denom)def ecludSim(inA,inB): # 計算兩向量的相似度return 1.0/(1.0 + la.norm(inA - inB)) # 這里距離采用的是歐式距離def pearsSim(inA,inB):if len(inA) < 3 : return 1.0return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]# 基于SVD的評分估計 def svdEst(dataMat, user, simMeas, item):n = shape(dataMat)[1]simTotal = 0.0; ratSimTotal = 0.0U,Sigma,VT = la.svd(dataMat) # 對數據集進行了SVD分解Sig4 = mat(eye(4)*Sigma[:4]) # 構造對角矩陣(Sigma[:4]是以數組的形式保存,因此需要進行矩陣運算)xformedItems = dataMat.T * U[:,:4] * Sig4.I # 利用U矩陣將物品轉換到低維空間中去#print 'xformedItems:','\n',xformedItemsprint shape(xformedItems)for j in range(n): # 對給定用戶上循環所有的元素userRating = dataMat[user,j]if userRating == 0 or j==item: continuesimilarity = 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 0else: return ratSimTotal/simTotal# 推薦引擎(用的是余弦相似度) def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=svdEst):unratedItems = nonzero(dataMat[user,:].A==0)[1] # 得到dataMat中用戶對沒有評價過物品的索引print 'unratedItems:',unratedItemsif len(unratedItems) == 0: # 如果都評價了則返回顯示已評價過所有的物品return 'you rated everything'itemScores = []for item in unratedItems: # 遍歷沒有評價過的物品estimatedScore = estMethod(dataMat, user, simMeas, item) # 得到預測評分itemScores.append((item, estimatedScore)) # 物品編號和估計值分值放在一個元素列表中return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N] # 從大到小的逆序排列,輸出前三 # 主函數 U,Sigma,VT=la.svd(loadExData2()) print 'Sigma:',Sigma # 計算要多少個奇異值才能到總能量的90% Sig2=Sigma**2 sum_1=sum(Sig2) print 'sum_1:',sum_1 sum_2=sum(Sig2)*0.9 print 'sum_2',sum_2 print sum(Sig2[:2]) print sum(Sig2[:3])myMat=mat(loadExData2()) re=recommend(myMat,1,estMethod=svdEst) print 're:',re運行結果:
Sigma: [ 15.77075346 11.40670395 11.03044558 ..., 0.43800353 0.220821130.07367823] sum_1: 542.0 sum_2 487.8 378.829559511 500.500289128 unratedItems: [0 1 2 4 6 7 8 9] (11L, 4L) the 0 and 3 similarity is: 0.490950 the 0 and 5 similarity is: 0.484274 the 0 and 10 similarity is: 0.512755 (11L, 4L) the 1 and 3 similarity is: 0.491294 the 1 and 5 similarity is: 0.481516 the 1 and 10 similarity is: 0.509709 (11L, 4L) the 2 and 3 similarity is: 0.491573 the 2 and 5 similarity is: 0.482346 the 2 and 10 similarity is: 0.510584 (11L, 4L) the 4 and 3 similarity is: 0.450495 the 4 and 5 similarity is: 0.506795 the 4 and 10 similarity is: 0.512896 (11L, 4L) the 6 and 3 similarity is: 0.743699 the 6 and 5 similarity is: 0.468366 the 6 and 10 similarity is: 0.439465 (11L, 4L) the 7 and 3 similarity is: 0.482175 the 7 and 5 similarity is: 0.494716 the 7 and 10 similarity is: 0.524970 (11L, 4L) the 8 and 3 similarity is: 0.491307 the 8 and 5 similarity is: 0.491228 the 8 and 10 similarity is: 0.520290 (11L, 4L) the 9 and 3 similarity is: 0.522379 the 9 and 5 similarity is: 0.496130 the 9 and 10 similarity is: 0.493617 re: [(4, 3.3447149384692283), (7, 3.3294020724526963), (9, 3.328100876390069)]5. 冷啟動問題
推薦引擎面臨的另一個問題就是如何在缺乏數據時給出好的推薦。這稱為冷啟動問題,處理起來十分困難。這個問題的另一個說法是,用戶不會喜歡一個無效的物品,而用戶不喜歡的物品又無效。
(也就是說,在協同過濾楊景下,由于新物品到來時由于缺乏所有用戶對其的喜好信息,因此無法判斷每個用戶對其的喜好。而無法判斷某個用戶對其的喜好,也就無法利用該商品)冷啟動問題的解決方案,就是將推薦看成是搜索問題。在內部表現上,不同的解決辦法雖然有所不同,但是對用戶而言卻都是透明的。為了將推薦看成是搜索問題,我們可能要使用所需要推薦物品的屬性。在餐館菜肴的例子中,我們可以通過各種標簽來標記菜肴,比如素食、美式88、價格很貴等。同時,我們也可以將這些屬性作為相似度計算所需要的數據,這被稱為基于內容(content-based)的推薦。可能,基于內容的推薦并不如我們前面介紹的基于協同過濾的推薦效果好 ,但我們擁有它,這就是個良好的開始。
6. 基于圖像的壓縮
這里是關于如何將SVD應用于圖像壓縮的例子。通過可視化的方式,該例子使得我們很容易就能看到SVD對數據近似的效果。在代碼庫中,我們包含了一張手寫的數字圖像,原始的圖像大小是32×32=1024像素,我們能否使用更少的像素來表示這張圖呢?如果能對圖像進行壓縮,那么就可以節省空間或帶寬開銷了。
代碼:
# -*- coding: utf-8 -*-# 打印矩陣 def printMat(inMat, thresh=0.8): for i in range(32):for k in range(32):if float(inMat[i,k]) > thresh: # 通過閾值來界定深色和淺色print 1,else: print 0,print ''# 實現圖像的壓縮 def imgCompress(numSV=3, thresh=0.8):myl = []for line in open('0_5.txt').readlines():newRow = []for i in range(32):newRow.append(int(line[i]))myl.append(newRow)myMat = mat(myl)print ' shape myMat:',shape(myMat)print "****original matrix******"printMat(myMat, thresh)U,Sigma,VT = la.svd(myMat) #SVD分解SigRecon = mat(zeros((numSV, numSV)))for k in range(numSV): # 把奇異值填充到對角線SigRecon[k,k] = Sigma[k]reconMat = U[:,:numSV]*SigRecon*VT[:numSV,:] # 得到重構的矩陣print "****reconstructed matrix using %d singular values******" % numSVprint 'reconMat',shape(reconMat)printMat(reconMat, thresh) # 打印出來# 主函數 imgCompress(2)運行結果:
shape myMat: (32L, 32L) ****original matrix****** 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 ****reconstructed matrix using 2 singular values****** reconMat (32L, 32L) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0可以看到,只需要兩個奇異值就能相當精確地對圖像實現重構。那么,我們到底需要多少個0-1的數字來重構圖像呢?U和VT都是32×2的矩陣,有兩個奇異值。因此總數字數目是64+64+2=130。和原數目1024相比,我們獲得了幾乎10倍的壓縮比。
6. 筆記
(1)overLap = nonzero(logical_and(dataMat[:,item].A>0, dataMat[:,j].A>0))[0]
>>> import numpy as np >>> np.logical_or(True, False) True >>> np.logical_or([True, False], [False, False]) array([ True, False], dtype=bool) >>> x = np.arange(5) >>> x array([0, 1, 2, 3, 4]) >>> np.logical_or(x < 1, x > 3) array([ True, False, False, False, True], dtype=bool) >>> x<1 array([ True, False, False, False, False], dtype=bool) >>> x>3 array([False, False, False, False, True], dtype=bool) >>> np.logical_or(x < 1, x > 3) array([ True, False, False, False, True], dtype=bool) >>>(2)unratedItems = nonzero(dataMat[user,:].A==0)[1]
In [16]: myData[2,:] Out[16]: matrix([[4, 0, 0, 1, 1]])In [17]: nonzero(myData[2,:].A==0) Out[17]: (array([0, 0], dtype=int64), array([1, 2], dtype=int64))In [18]: nonzero(myData[2,:].A==0)[1] Out[18]: array([1, 2], dtype=int64)(3)verLap = nonzero(logical_and(dataMat[:,item].A>0, dataMat[:,j].A>0))[0]
In [24]: myData Out[24]: matrix([[4, 4, 0, 2, 2],[4, 0, 0, 3, 3],[4, 0, 0, 1, 1],..., [2, 2, 2, 0, 0],[5, 5, 5, 0, 0],[1, 1, 1, 0, 0]])In [25]: logical_and(myData[:,1].A>0, myData[:,0].A>0) Out[25]: array([[ True],[False],[False],[ True],[ True],[ True],[ True]], dtype=bool)In [26]: nonzero(logical_and(myData[:,1].A>0, myData[:,0].A>0)) Out[26]: (array([0, 3, 4, 5, 6], dtype=int64), array([0, 0, 0, 0, 0], dtype=int64))In [27]: nonzero(logical_and(myData[:,1].A>0, myData[:,0].A>0))[0] Out[27]: array([0, 3, 4, 5, 6], dtype=int64)(4)similarity = simMeas(dataMat[overLap,item], dataMat[overLap,j])
In [33]: overlap=[0,3,4,5,6]In [35]: myData[overlap,0] # 得到第一列的坐標為overlap的元素 Out[35]: matrix([[4],[1],[2],[5],[1]])(5)Sig4 = mat(eye(4)*Sigma[:4])
In [11]: Sigma[:4] Out[11]: array([ 15.77075346, 11.40670395, 11.03044558, 4.84639758])In [12]: type(Sigma) Out[12]: numpy.ndarrayIn [13]: mat(eye(4)*Sigma[:4]) Out[13]: matrix([[ 15.77075346, 0. , 0. , 0. ],[ 0. , 11.40670395, 0. , 0. ],[ 0. , 0. , 11.03044558, 0. ],[ 0. , 0. , 0. , 4.84639758]])總結
- 上一篇: 奇异值分解SVD与PCA
- 下一篇: 良/恶性乳腺癌肿瘤预测