基本信息
from numpy import *from numpy import linalg as la
SVD能够对矩阵做到降维简化的效果
U,Sigma,VT = la.svd(dataMat)
分解之后可以得到三个矩阵
第二个是一个对角矩阵(在numpy里为了节约空间就直接是一个数组)。可以通过其他办法重新复原为一个对角
Sig4 = mat(eye(4)*Sigma[:4])#或者SigRecon = mat(zeros((numSV, numSV)))for k in range(numSV):#construct diagonal matrix from vectorSigRecon[k,k] = Sigma[k]
这个对角矩阵决定了信息的量
比如说想要保留90%的信息,可以选择[0:m]的sigma使得平方和是总的90%
或者是通过观察等等
则原先为n的sigma就削减为m
原先的是U[m,n]Sigma[m,n]VT[n,n]=Data[m,n]
这个时候化简为U[m,x]Sigma[x,x]VT[x,n]=Data[m,n]
于是就起到了简化数据和减噪的功能
例子
推荐系统
推荐系统就是基于一些数据向量推荐相似的产品
在书中的例子就是多个用户对多个产品进行了打分(每个用户不一定对所有的产品打分,推荐的目标就是推荐打分最高的产品,其中需要对没有打分的产品进行推理)
这里的应用就是在推理得分上
对推荐的时候找到这个用户的某个未打分产品,遍历已打分的产品,对任意的已打分产品搜集得到其他用户(同时打分了这个已打分产品和未打分产品)对这个的打分情况,假设为向量X(维数未知),同时未打分产品也有一个打分向量,计算两个向量的相似度。把此用户对这个已打分产品的打分乘上相似度后累加。
基本原理就是相似的产品,大家的打分情况相似,那么此用户对这个产品的打分可以推理到未打分产品上
若两产品的打分情况相似(其他人给出了相似的分数),则打分可以较大幅度的借鉴,反之则较小
相似度计算
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)
SVD应用
对于一数据集MN,M为用户数,N为对应打分
使用矩阵分解保留维数X的sigma
DataT[N,M]U[M,X]Sigma[X,X]
操作之后得到NX维度的矩阵用以推理打分(可以近似的看作神经网络里加上了全连接层,原先N个向量(M长度)经过全链接层得到N个长度为X的向量),然后向量之间做所谓的相似度用以推理分数。
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: continueoverLap = 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])print ('the %d and %d similarity is: %f' % (item, j, similarity))simTotal += similarityratSimTotal += similarity * userRatingif simTotal == 0: return 0else: return ratSimTotal/simTotaldef svdEst(dataMat, user, simMeas, item):n = shape(dataMat)[1]simTotal = 0.0; ratSimTotal = 0.0U,Sigma,VT = la.svd(dataMat)#print(Sigma)Sig4 = mat(eye(4)*Sigma[:4]) #arrange Sig4 into a diagonal matrix#print(Sig4)xformedItems = dataMat.T * U[:,:4] * Sig4.I #create transformed itemsprint(dataMat.shape)print(xformedItems.shape)for j in range(n):userRating = dataMat[user,j]if userRating == 0 or j==item: continueprint(xformedItems[item,:].shape)similarity = 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/simTotal
图片压缩
和上述的同理,对Sigma进行裁剪,得到了更小的三个矩阵,拼接最后的结果却能够较好的还原原矩阵
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 ("****original matrix******")printMat(myMat, thresh)U,Sigma,VT = la.svd(myMat)SigRecon = mat(zeros((numSV, numSV)))for k in range(numSV):#construct diagonal matrix from vectorSigRecon[k,k] = Sigma[k]reconMat = U[:,:numSV]*SigRecon*VT[:numSV,:]print ("****reconstructed matrix using %d singular values******" % numSV)printMat(reconMat, thresh)
