当前位置: 代码迷 >> 综合 >> Machine Learning---11--svd
  详细解决方案

Machine Learning---11--svd

热度:1   发布时间:2023-12-05 21:53:34.0

奇异值分解,singular value decomposition(SVD)是线性代数中一种重要的矩阵分解

特征值

对于一个方阵,其特征值和特征向量满足:

Aν=λνAν=λν

求出所有的特征值和特征向量后,就得出了方阵A的特征值分解:

A=QΣQ?1

奇异值

现实世界里,为了实现类似特征值分解的计算,我们使用奇异值分解。奇异值分解适用于任何矩阵,如下所示,其中A是一个m*n的矩阵:

A=Um?mΣm?nVTn?nA=Um?mΣm?nVn?nT

其中

  • UU 是一个m*m的正交矩阵,其向量被称为左奇异向量
  • VV 也是一个n*n的正交矩阵,其向量被成为右奇异向量
  • ΣΣ 是一个m*n的矩阵,其对角线上的元素为奇异值,其余元素皆为0

当选取top k个奇异值时,可以将矩阵降维成为:

Am?nUm?kΣk?kVTk?nAm?n≈Um?kΣk?kVk?nT

基于SVD的机器学习之Python代码如下:

import numpy as np from numpy import linalg as ladef loadExData():data=np.array([[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]])return datadef loadExData2():data2=np.array([[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]])return data2#计算相似度 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*np.corrcoef(inA, inB, rowvar = 0)[0][1]''' def cosSim(inA,inB): #利用余弦相似度计算num=float(np.multiply(inA.T,inB)) #错误不知道为啥#num = float(inA.T*inB)denom = la.norm(inA)*la.norm(inB)return 0.5+0.5*(num/denom) '''#基于物品相似度的推荐引擎 #1、 def standEst(dataMat, user, simMeas, item):#输入:数据集、用户、相似性度量、物品编号#输出:用户对物品的估计评分值n = np.shape(dataMat)[1] #得到物品数simTotal = 0.0; ratSimTotal = 0.0for j in range(n):userRating = dataMat[user,j]if userRating == 0: continueoverLap =np. nonzero(np.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/simTotal#2、推荐引擎 def recommend(dataMat, user, N=3, simMeas=ecludSim, estMethod=standEst):#输入:数据集、用户、返回个数(默认为3)、相似性度量、评估方法#输出:返回相似度最高的N个推荐结果unratedItems = np.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) #调用standEst对物品进行评分itemScores.append((item, estimatedScore)) #将物品编号与评分值放入列表中return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N] #从大到小进行排序,返回前N个值#3、基于SVD的评分估计 def svdEst(dataMat, user, simMeas, item):n = np.shape(dataMat)[1]simTotal = 0.0; ratSimTotal = 0.0U,Sigma,VT = la.svd(dataMat)Sig4 = np.mat(np.eye(4)*Sigma[:4]) #使用总能量达90%(使用前三个元素)的奇异值构建对角矩阵xformedItems = dataMat.T * U[:,:4] * Sig4.I #利用矩阵U将数据转化到低维空间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/simTotalif __name__ == "__main__":#SVD分解Data=loadExData()U,Sigma,VT=np.linalg.svd(Data)print(Sigma) #只返回对角线的值#数据重构--只取前两个奇异值Sig2=([Sigma[0],0],[0,Sigma[1]])print(Sig2)#reconData=U[:,:2]*Sig2*VT[:2,:]#print(reconData)#计算相似度p1=ecludSim(Data[:,0],Data[:,4])p11=ecludSim(Data[:,0],Data[:,0])print(p1,p11)print('-----------------------------')p2=pearsSim(Data[:,0],Data[:,4])p22=pearsSim(Data[:,0],Data[:,0])print(p2,p22)print('-----------------------------')''' p3=cosSim(Data[:,0],Data[:,4])p33=cosSim(Data[:,0],Data[:,0])print(p3,p33)print('-----------------------------')'''#查看推荐引擎的效果print(Data)print('-----------------------------')Data[0,0]=Data[0,1]=Data[1,0]=Data[2,0]=4print(Data)Data1=np.mat(Data) #数组转为矩阵,因为矩阵才可使用.A属性,即dataMat[user,:].Aprint('-----------------------------')pre=recommend(Data1,2) #用户2,即矩阵的第三行print(pre)print('-----------------------------')#利用SVD提高推荐效果Data2=loadExData2()Data2=np.mat(Data2)pre2=recommend(Data1,1,simMeas=pearsSim, estMethod=svdEst)print(pre2)'''计算奇异值的能量Sig2=Sigma**2sum(Sig2) 总能量sum(Sig2)*0.9 90%的能量sum(Sig2[:2]) 前两个值能获得的能量sum(Sig2[:3]) 前三个值能获得的能量'''


  相关解决方案