日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

机器学习实战(十四)利用SVD简化数据

發布時間:2023/12/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习实战(十四)利用SVD简化数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

    • 第十四章 利用SVD簡化數據
      • 14.1 SVD的應用
      • 14.1.1 隱形語義索引
        • 14.1.2 推薦系統
      • 14.2 矩陣分解(SVD矩陣分解)
      • 14.3 利用python實現SVD
      • 14.4 基于協同過濾(collaborative filtering)的推薦引擎
        • 14.4.1 相似度計算
        • 14.4.2 基于物品的相似度還是基于用戶的相似度?
        • 14.4.3 推薦引擎的評價
      • 14.5 示例:餐館菜肴推薦系統
        • 14.5.1 推薦未嘗過的菜肴
        • 14.5.2 利用SVD提高推薦效果
        • 14.5.3 構建推薦引擎面臨的挑戰
      • 14.6 基于SVD的圖像壓縮
      • 14.7 總結

第十四章 利用SVD簡化數據

14.1 SVD的應用

餐館可以劃分為很多類別,比如中式、美式、快餐、素食等等,但是人們可以喜歡某些混合的類別,比如中式素食的子類別,我們可以對記錄用戶關于餐館觀點的數據進行處理,并且從中提取背后的因素,這些因素可能與類別、配料或其他任意對象一致。

提取這些信息的方法稱為奇異值分解(Singular Value Decomposition,SVD)。

作用:能夠用小得多的數據集來表示原始數據集

原理:去除了噪聲和冗余信息,也就是從噪聲數據中抽取信息。

14.1.1 隱形語義索引

SVD最早的應用之一就是信息檢索,稱為隱形語義索引(Latent Semantic Indexing,LSI)或隱形語義分析(Latent Semantic Analysis,LSA)。

LSI中,一個矩陣是由文檔和詞語組成的,當在該矩陣上應用SVD時,就會構建多個奇異值,這些奇異值代表了文檔中的概念或者主題,這一特點可以用于更高效的文檔搜索。

14.1.2 推薦系統

SVD的另一個應用就是推薦系統。 先利用SVD從數據中構建一個主題空間, 然后在該主題空間下計算相似度。


上述矩陣由餐館的菜和品菜師對這些菜的意見構成的。品菜師采用1到5之間的任意一個整數來對菜評級,如果品菜師沒有嘗過某道菜,則評級為0。對上述矩陣進行SVD分解,會得到兩個奇異值(注意其特征值位2),也即仿佛有兩個概念或主題與此數據集相關聯。

SVD是矩陣分解的一種類型,而矩陣分解時將數據矩陣分解為多個獨立部分的過程,下面首先介紹矩陣分解。

14.2 矩陣分解(SVD矩陣分解)

在很多情況下,數據中的一小段攜帶了數據集中的大部分信息,其他信息則要么是噪聲,要么就是毫不相關的信息。在線性代數中還有很多矩陣分解技術。 矩陣分解可以將原始矩陣表示成新的易于處理的形式。

SVD將原始數據集矩陣Data?m?n??Datam?n分解為三個矩陣:

Data?m?n?=U?m?m?Σ?m?n?V?T?n?n??Datam?n=Um?mΣm?nVn?nT

矩陣Σ?Σ

1)只有對角元素(也稱奇異值),其他元素均為0
2)對角元素是從大到小排列的
3)奇異值就是矩陣Data?Data?T??Data?DataT特征值的平方根

在某個奇異值(r個)之后, 其它的奇異值由于值太小,被忽略置為0, 這就意味著數據集中僅有r個重要特征,而其余特征都是噪聲或冗余特征。如下圖所示:

如何選擇數值r?

解答: 確定要保留的奇異值數目有很多啟發式的策略,其中一個典型的做法就是保留矩陣中90%的能量信息.為了計算能量信息,將所有的奇異值求其平方和,從大到小疊加奇異值,直到奇異值之和達到總值的90%為止;另一種方法是,當矩陣有上萬個奇異值時, 直接保留前2000或3000個.,但是后一種方法不能保證前3000個奇異值能夠包含錢90%的能量信息,但是操作簡單.

SVD分解很耗時,通過離線方式計算SVD分解和相似度計算,是一種減少冗余計算和推薦所需時間的辦法.

14.3 利用python實現SVD

Numpy的linalg的線性代數工具箱來實現,其有包括處理求范式、逆、行列式、偽逆、秩、qr分解、svd分解等等函數。

from numpy import * from numpy import linalg as ladef loadExData():return [[1,1,1,0,0],[2,2,2,0,0],[5,5,5,0,0],[1,1,0,2,2],[0,0,0,3,3],[0,0,0,1,1]]Data=loadExData() U,Sigma,VT=la.svd(Data)#由于Sigma是以向量的形式存儲,故需要將其轉為矩陣, sig3=mat([[Sigma[0],0,0],[0,Sigma[1],0],[0,0,Sigma[2]]]) # 也可以用下面的方法,將行向量轉化為矩陣,并且將值放在對角線上,取前面三行三列 # Sig3=diag(Sigma)[:3,:3] print(Sigma) #重構原始矩陣 print(U[:,:3]*sig3*VT[:3,:])

結果:

U: [[ -1.80802750e-01 -1.71990790e-02 1.86518261e-02 9.66314851e-011.32410225e-01 -1.23975026e-01][ -3.61605500e-01 -3.43981580e-02 3.73036522e-02 -2.19496756e-018.71711981e-01 -2.42086892e-01][ -9.04013750e-01 -8.59953949e-02 9.32591306e-02 -1.05464268e-01-3.75166837e-01 1.21629762e-01][ -1.36839850e-01 5.33014079e-01 -8.34967572e-01 -7.16304166e-16-3.46093235e-16 2.46957870e-16][ -2.29617316e-02 7.97696413e-01 5.12984591e-01 -2.63326233e-02-9.04630306e-02 -3.01865919e-01][ -7.65391052e-03 2.65898804e-01 1.70994864e-01 7.89978699e-022.71389092e-01 9.05597757e-01]]Sigma: [ 9.56627891e+00 5.29323150e+00 6.84111192e-01 3.10730143e-164.98171926e-32]VT: [[ -5.81304643e-01 -5.81304643e-01 -5.67000247e-01 -3.66097214e-02-3.66097214e-02][ 3.21952849e-03 3.21952849e-03 -9.74777636e-02 7.03731964e-017.03731964e-01][ -4.02584831e-01 -4.02584831e-01 8.17929585e-01 5.84897501e-025.84897501e-02][ 7.07106781e-01 -7.07106781e-01 5.19776737e-17 1.98940359e-171.98940359e-17][ -0.00000000e+00 1.80770896e-17 -1.42706714e-17 7.07106781e-01-7.07106781e-01]]sig3 : [[ 9.56627891 0. 0. ][ 0. 5.2932315 0. ][ 0. 0. 0.68411119]]重構矩陣(和原始矩陣非常接近):[[ 1.00000000e+00 1.00000000e+00 1.00000000e+00 -9.14152286e-16-9.14152286e-16][ 2.00000000e+00 2.00000000e+00 2.00000000e+00 -3.49477979e-16-3.49477979e-16][ 5.00000000e+00 5.00000000e+00 5.00000000e+00 6.09916192e-166.09916192e-16][ 1.00000000e+00 1.00000000e+00 2.79971461e-16 2.00000000e+002.00000000e+00][ -6.37559172e-17 5.31300838e-17 2.94979631e-16 3.00000000e+003.00000000e+00][ -4.45609774e-17 -5.59897708e-18 1.68959598e-16 1.00000000e+001.00000000e+00]]

重構矩陣和原始矩陣非常接近,類似于壓縮圖像,只保留圖像分解后的兩個方陣和一個對角陣的對角元素,就可以恢復原始圖像。

觀察上述結果中的Sigma,可以發現前三個數值比后面兩個大了很多,于是可以將后面兩個值去掉。

原始數據集就和下面結果近似:

Data?m?n?=U?m?3?Σ?3?3?V?T?3?n??Datam?n=Um?3Σ3?3V3?nT

14.4 基于協同過濾(collaborative filtering)的推薦引擎

近些年來,推薦引擎對因特網用戶而言已經不是什么新鮮事物了,Amazon會根據顧客的購買歷史向他們推薦物品,新聞網站會對用戶推薦新聞報道等。

接下來我們介紹被稱為“協同過濾”的方法,來實現推薦功能。協同過濾是通過將用戶和其他用戶的數據進行對比來實現推薦的。

數據組織成了類似圖14-2所給出的矩陣的形式,當數據采用這種方式進行組織時,我們就可以比較用戶或物品之間的相似度了,當知道相似度后,就可以利用已有的數據來預測未知用戶喜好。

例如: 試圖對某個用戶喜歡的電影進行預測,搜索引擎會發現有一部電影該用戶還沒看過,然后它會計算該電影和用戶看過的電影之間的相似度, 如果相似度很高, 推薦算法就會認為用戶喜歡這部電影.

缺點: 在協同過濾情況下, 由于新物品到來時由于缺乏所有用戶對其的喜好信息,因此無法判斷每個用戶對其的喜好.而無法判斷某個用戶對其的喜好,也就無法利用該商品.

14.4.1 相似度計算

不利用專家給出的重要屬性來描述物品從而計算其相似度,而是利用用戶對他們的意見來計算相似度,這就是協同過濾使用的方法。并不關心物品的描述屬性,而是嚴格按照許多用戶的觀點來計算相似度。

一、歐氏距離

手撕豬肉和烤牛肉間的歐氏距離:

(4?4)?2?+(3?3)?2?+(2?1)?2?=1????????????????????????????????????????????????????????(4?4)2+(3?3)2+(2?1)2=1

手撕豬肉和鰻魚飯的歐氏距離:

(4?2)?2?+(3?5)?2?+(2?2)?2?=2.83??????????????????????????????????????????????????????????????(4?2)2+(3?5)2+(2?2)2=2.83

因此手撕豬肉和烤牛肉更為相似

相似性度量方式: 0~1之間的變化,可以使用=11+??相似度=11+距離來度量,距離為0時,相似度為1,距離很大時,相似度趨于0。

二、皮爾遜相關系數(person correlation)

度量兩個向量之間的相似度,相對于歐式距離的優勢在于對用戶評級的量級并不敏感。

Numpy中實現:corrcoef()

取值范圍:[-1,1],通過0.5+0.5?corrcoef()?0.5+0.5?corrcoef()函數來計算,將其取值范圍歸一化到[0,1]。

三、余弦相似度(cosine similarity)

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

取值范圍:[-1,+1],因此也需要將其歸一化到(0,1)之間。

定義:cosθ=A?B||A||||B||??cosθ=A?B||A||||B||

其中,||A||?||A||||B||?||B||表示向量的2范數,例如向量[4,2,2]?[4,2,2]的2范數為4?2?+2?2?+2?2?????????????????????????42+22+22

Numpy中,范數的計算方法:linalg.norm()

2范數=x到0點的歐氏距離

其他距離:


代碼實現:

#!/usr/bin/env python # coding=utf-8 from numpy import * from numpy import linalg as la def loadExData():return [[1,1,1,0,0],[2,2,2,0,0],[5,5,5,0,0],[1,1,0,2,2],[0,0,0,3,3],[0,0,0,1,1]]# 利用不同的方法計算相似度 def eulidSim(inA, inB):return 1.0/(1.0+la.norm(inA - inB))#根據歐式距離計算相似度def pearsSim(inA, inB):if len(inA)<3:return 1.0else:return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]def cosSim(inA, inB):num = float(inA.T*inB) #向量inA和向量inB點乘,得cos分子denom = la.norm(inA)*la.norm(inB) #向量inA,inB各自范式相乘,得cos分母return 0.5+0.5*(num/denom) #從-1到+1歸一化到[0,1]myMat = mat(loadExData()) print(eulidSim(myMat[:,0], myMat[:,4])) #第一行和第五行利用歐式距離計算相似度 print(eulidSim(myMat[:,0], myMat[:,0])) #第一行和第一行歐式距離計算相似度 print(cosSim(myMat[:,0], myMat[:,4])) #第一行和第五行利用cos距離計算相似度 print(cosSim(myMat[:,0], myMat[:,0])) #第一行和第一行利用cos距離計算相似度 print(pearsSim(myMat[:,0], myMat[:,4])) #第一行和第五行利用皮爾遜距離計算相似度 print(pearsSim(myMat[:,0], myMat[:,0])) #第一行和第一行利用皮爾遜距離計算相似度

結果(相似度):

0.135078105936 1.0 0.548001536074 1.0 0.204196010845 1.0

14.4.2 基于物品的相似度還是基于用戶的相似度?

菜肴之間的距離:基于物品(item-based)的相似度

用戶之間的距離:基于用戶(user-based)的相似度

行與行之間比較的是基于用戶的相似度,列與列之間比較的則是基于物品的相似度。

基于物品相似度計算的時間會隨物品數量的增加而增加,基于用戶的相似度計算的時間則會隨用戶數量的增加而增加。如果用戶的數目很多,那么我們可能傾向于使用基于物品相似度的計算方法。對于大部分產品導向的推薦系統而言,用戶的數量往往大于物品的數量,即購買商品的用戶數會多于出售的商品種類。

14.4.3 推薦引擎的評價

使用交叉測試的方法,具體做法就是我們將某些已知的評分值去掉,然后對它們進行預測,最后計算預測值與真實值之間的差異。通常使用的指標為最小均方根誤差(Root Mean Squared Error, RMSE)。

14.5 示例:餐館菜肴推薦系統

假設他不知道去哪里吃飯,該點什么菜,則我們的系統可以推薦給他。

步驟:

1)構建一個基本引擎,能夠尋找用戶沒有品嘗過的菜肴

2)通過SVD來減少特征空間,并提高推薦效果

3)將程序打包并通過用戶可讀的人機界面提供給人們使用

14.5.1 推薦未嘗過的菜肴

過程:

給定一個用戶,系統會為此用戶返回N個最好的推薦菜。需要:

  • 尋找用戶沒有評級的菜肴,即在用戶-物品矩陣中的0值。
  • 在用戶沒有評級的所有物品中,對每個物品預計一個可能的評級分數。
  • 對這些物品的評分從高到低進行排序,返回前N個物品。
  • from numpy import * from numpy import linalg as la def loadExData():return [[1,1,1,0,0],[2,2,2,0,0],[5,5,5,0,0],[1,1,0,2,2],[0,0,0,3,3],[0,0,0,1,1]]# 利用不同的方法計算相似度 def eulidSim(inA, inB):return 1.0/(1.0+la.norm(inA - inB))#根據歐式距離計算相似度def pearsSim(inA, inB):if len(inA)<3:return 1.0else:return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]def cosSim(inA, inB):num = float(inA.T*inB) #向量inA和向量inB點乘,得cos分子denom = la.norm(inA)*la.norm(inB) #向量inA,inB各自范式相乘,得cos分母return 0.5+0.5*(num/denom) #從-1到+1歸一化到[0,1]def standEst(dataMat,user,simMeas,item):"""計算在給定相似度計算方法的前提下,用戶對物品的估計評分值:param dataMat: 數據矩陣:param user: 用戶編號:param simMeas: 相似性度量方法:param item: 物品編號:return:"""#數據中行為用于,列為物品,n即為物品數目n=shape(dataMat)[1]simTotal=0.0ratSimTotal=0.0#用戶的第j個物品for j in range(n):userRating=dataMat[user,j]if userRating==0:continue#尋找兩個用戶都評級的物品overLap=nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]if len(overLap)==0:similarity=0else:similarity=simMeas(dataMat[overLap,item],dataMat[overLap,j])simTotal+=similarityratSimTotal+=simTotal*userRatingif simTotal==0:return 0else:return ratSimTotal/simTotaldef recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):"""推薦引擎,會調用standEst()函數:param dataMat: 數據矩陣:param user: 用戶編號:param N:前N個未評級物品預測評分值:param simMeas::param estMethod::return:"""#尋找未評級的物品,nonzeros()[1]返回參數的某些為0的列的編號,dataMat中用戶對某個商品的評價為0的列#矩陣名.A:將矩陣轉化為array數組類型#nonzeros(a):返回數組a中不為0的元素的下標unratedItems=nonzero(dataMat[user,:].A==0)[1]if 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]myMat = mat(loadExData()) myMat[0,3] = myMat[0,4] = myMat[1,4] = myMat[2,3] = 4 myMat[4,1] = 2 print(myMat) print(recommend(myMat, 4)) print(recommend(myMat, 4,simMeas = eulidSim)) print(recommend(myMat, 4,simMeas = pearsSim))

    結果:

    [[1 1 1 4 4][2 2 2 0 4][5 5 5 4 0][1 1 0 2 2][0 2 0 3 3][0 0 0 1 1]] [(2, 5.6806547361770336), (0, 5.6789547243533818)] [(0, 6.9478362016501283), (2, 6.9253660746962069)] [(0, 5.9000000000000004), (2, 5.666666666666667)]

    我們可知:

    用戶4對物品2的預測評分值為5.6806547361770336;

    用戶4對物品0的預測評分值為5.6789547243533818;

    14.5.2 利用SVD提高推薦效果

    下面展示一個更加真實的矩陣的例子:

    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]]U, Sigma, VT = la.svd(mat(loadExData2())) print('Sigma:\n',Sigma) #查看到底多少個奇異值能夠達到總能量的90% #對Sigma求平方 Sig2 = Sigma ** 2 print('Sig2:\n',Sig2)#計算總能量(542.0) print('sum(Sig2):',sum(Sig2)) #計算總能量的90%(487.8) print('sum(Sig2) * 0.9:',sum(Sig2) * 0.9) #計算前兩個元素包含的能量(378.829559511) print('前兩個元素包含的能量:',sum(Sig2[:2])) #由于前兩個的和未達到總和的90%,所以計算前三個的和 print('前三個元素包含的能量:',sum(Sig2[:3]))

    結果:

    Sigma:[ 15.77075346 11.40670395 11.03044558 4.84639758 3.092920552.58097379 1.00413543 0.72817072 0.43800353 0.220821130.07367823] Sig2:[ 2.48716665e+02 1.30112895e+02 1.21670730e+02 2.34875695e+019.56615756e+00 6.66142570e+00 1.00828796e+00 5.30232598e-011.91847092e-01 4.87619735e-02 5.42848136e-03] sum(Sig2): 542.0 sum(Sig2) * 0.9: 487.8 前兩個元素包含的能量: 378.829559511 前三個元素包含的能量: 500.500289128

    前三個元素包含的能量超過了總能量的90%,故可以將這11維矩陣轉化為3維矩陣,對轉化后的三維空間構造一個相似度計算函數,利用SVD將所有的菜肴映射到一個低維空間。

    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 eulidSim(inA, inB):return 1.0/(1.0+la.norm(inA - inB))#根據歐式距離計算相似度def pearsSim(inA, inB):if len(inA)<3:return 1.0else:return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]def cosSim(inA, inB):num = float(inA.T*inB) #向量inA和向量inB點乘,得cos分子denom = la.norm(inA)*la.norm(inB) #向量inA,inB各自范式相乘,得cos分母return 0.5+0.5*(num/denom) #從-1到+1歸一化到[0,1]def standEst(dataMat,user,simMeas,item):"""計算在給定相似度計算方法的前提下,用戶對物品的估計評分值:param dataMat: 數據矩陣:param user: 用戶編號:param simMeas: 相似性度量方法:param item: 物品編號:return:"""#數據中行為用于,列為物品,n即為物品數目n=shape(dataMat)[1]simTotal=0.0ratSimTotal=0.0#用戶的第j個物品for j in range(n):userRating=dataMat[user,j]if userRating==0:continue#尋找兩個用戶都評級的物品overLap=nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]if len(overLap)==0:similarity=0else:similarity=simMeas(dataMat[overLap,item],dataMat[overLap,j])simTotal+=similarityratSimTotal+=simTotal*userRatingif simTotal==0:return 0else:return ratSimTotal/simTotaldef recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):"""推薦引擎,會調用standEst()函數:param dataMat: 數據矩陣:param user: 用戶編號:param N:前N個未評級物品預測評分值:param simMeas::param estMethod::return:"""#尋找未評級的物品,nonzeros()[1]返回參數的某些為0的列的編號,dataMat中用戶對某個商品的評價為0的列#矩陣名.A:將矩陣轉化為array數組類型#nonzeros(a):返回數組a中不為0的元素的下標unratedItems=nonzero(dataMat[user,:].A==0)[1]if 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]#======================基于SVD的評分估計========================== def SVDEst(dataMat, user, simMeas, item):n = shape(dataMat)[1]simTotal = 0.0ratSimTotal = 0.0U, Sigma, VT = la.svd(dataMat)Sig4 = mat(eye(4)*Sigma[:4]) #化為對角陣,或者用linalg.diag()函數可破xformedItems = dataMat.T*U[:,:4]*Sig4.I#構造轉換后的物品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 += similarityratSimTotal += similarity*userRatingif simTotal ==0 :return 0else:return ratSimTotal/simTotalmyMat = mat(loadExData2()) print(recommend(myMat, 1, estMethod = SVDEst)) print(recommend(myMat, 1, estMethod = SVDEst, simMeas = pearsSim))

    結果:

    the 0 and 3 similarity is: 0.490950 the 0 and 5 similarity is: 0.484274 the 0 and 10 similarity is: 0.512755 the 1 and 3 similarity is: 0.491294 the 1 and 5 similarity is: 0.481516 the 1 and 10 similarity is: 0.509709 the 2 and 3 similarity is: 0.491573 the 2 and 5 similarity is: 0.482346 the 2 and 10 similarity is: 0.510584 the 4 and 3 similarity is: 0.450495 the 4 and 5 similarity is: 0.506795 the 4 and 10 similarity is: 0.512896 the 6 and 3 similarity is: 0.743699 the 6 and 5 similarity is: 0.468366 the 6 and 10 similarity is: 0.439465 the 7 and 3 similarity is: 0.482175 the 7 and 5 similarity is: 0.494716 the 7 and 10 similarity is: 0.524970 the 8 and 3 similarity is: 0.491307 the 8 and 5 similarity is: 0.491228 the 8 and 10 similarity is: 0.520290 the 9 and 3 similarity is: 0.522379 the 9 and 5 similarity is: 0.496130 the 9 and 10 similarity is: 0.493617 [(4, 3.3447149384692283), (7, 3.3294020724526971), (9, 3.328100876390069)] the 0 and 3 similarity is: 0.341942 the 0 and 5 similarity is: 0.124132 the 0 and 10 similarity is: 0.116698 the 1 and 3 similarity is: 0.345560 the 1 and 5 similarity is: 0.126456 the 1 and 10 similarity is: 0.118892 the 2 and 3 similarity is: 0.345149 the 2 and 5 similarity is: 0.126190 the 2 and 10 similarity is: 0.118640 the 4 and 3 similarity is: 0.450126 the 4 and 5 similarity is: 0.528504 the 4 and 10 similarity is: 0.544647 the 6 and 3 similarity is: 0.923822 the 6 and 5 similarity is: 0.724840 the 6 and 10 similarity is: 0.710896 the 7 and 3 similarity is: 0.319482 the 7 and 5 similarity is: 0.118324 the 7 and 10 similarity is: 0.113370 the 8 and 3 similarity is: 0.334910 the 8 and 5 similarity is: 0.119673 the 8 and 10 similarity is: 0.112497 the 9 and 3 similarity is: 0.566918 the 9 and 5 similarity is: 0.590049 the 9 and 10 similarity is: 0.602380 [(4, 3.3469521867021736), (9, 3.3353796573274703), (6, 3.307193027813037)]

    14.5.3 構建推薦引擎面臨的挑戰

    14.6 基于SVD的圖像壓縮

    本節使用手寫體“0”來展開SVD對圖像的壓縮,原始圖像大小為32*32=1024,進行圖像壓縮以后,就可以節省空間或帶寬開銷了。

    代碼:

    from numpy import * from numpy import linalg as ladef printMat(inMat,thresh=0.8):"""打印矩陣:param inMat:輸入數據集:param thresh:閾值:return:"""#由于矩陣包含了浮點數,因此必須定義深色和淺色,通過閾值來界定#元素大于閾值,打印1,小于閾值,打印0for 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):"""實現圖像的壓縮,允許基于任意給定的奇異值數目來重構圖像:param numSV::param thresh::return:"""#構建列表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("******original matrix**********")#使用SVD對圖像進行SVD分解和重構printMat(myMat,thresh)U,Sigma,VT=la.svd(myMat)#建立一個全0矩陣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***" %numSV)printMat(reconMat,thresh)if __name__=='__main__':imgCompress(2)

    只需要兩個奇異值就能相當精確地對圖像實現重構,U和VT都是32×2的矩陣,有兩個奇異值,也即只需要32×2+2+32×2=130個0、1進行存儲。原來需要1024個0、1,幾乎獲得10倍的壓縮比。

    14.7 總結

    SVD是一種強大的降維工具,可以利用SVD來逼近矩陣并從中提取重要特征,保留矩陣80%-90%的能量,得到重要的特征去掉噪音。推薦系統為SVD的一個成功的應用,協同過濾則是一種基于用戶喜好或行為數據的推薦的實現方法。協同過濾的核心是相似度計算方法。

    大規模數據集上,SVD的計算和推薦可能是一個很困難的工程問題,通過離線的方式來進行SVD分解和相似度計算,是一種減少冗余計算和推薦所需時間的辦法。

    總結

    以上是生活随笔為你收集整理的机器学习实战(十四)利用SVD简化数据的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。