1.矩阵SVD分解
对于一个矩阵A mxn 进行矩阵分解:
其中U mxm V nxn Sigmoid mxn U,V都是酉矩阵 即UUT=I VVT=I
Sigmoid矩阵是一个mxn对角矩阵,对角元素为奇异值,即为矩阵A的奇异值,也是AAT特征值的平方根,代表了矩阵数据的重要特征,进行SVD分解可以看成是在有噪声的数据中提取相关特征。
矩阵的低维近似表示:
当对矩阵进行奇异值分解时,发现大部分奇异值为零,即说明矩阵的信息大部分集中在少量奇异值上,因此可以通过矩阵的近似低维表示来代替原先矩阵。
选取前K个奇异值来近似表示矩阵:
奇异值的个数选择,可以采用奇异值平方和的累加占比来决定,即选择前k个奇异值的平方和占全部奇异值的平方和的比值大于一定阈值。
利用奇异值进行矩阵压缩:
V为酉矩阵 VVT=I
两边同时右乘V
解得U矩阵为mxr,即实现了列的压缩,由Amxn----Umxr
两边同时左乘UT:
解得V为rxn 即实现了行的压缩,有Amxn----Vrxm
2.协同过滤推荐引擎
用户,物品以及用户-物品关系矩阵中存储了用户对于物品的分数评价,对用户进行物品推荐时,首先找出用户没有评价的物品列表,然后依次对于这些物品进行分数评估预测,返回评分最高的物品列表推荐给用户。
对于用户对一件新物品的评分估测:
可以计算待评分物品与其余物品已有分数评价的相似度,然后采用加权平均的方式来计算用户对于新物品的预测值。计算物品的相似度并不直接计算,而是通过转换为用户对于物品的评价意见来计算。
相似度的计算:两个向量的相似度的计算
1.欧式距离:
相似度=1/(1+距离) 相似度在0--1变化 norm函数计算向量的二范数
def ecludSim(inA,inB):
return 1.0/(1.0 + la.norm(inA - inB))
2.皮尔逊相关系数: corrcoef计算相关系数矩阵
def pearsSim(inA,inB):
if len(inA) < 3 : return 1.0
return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]
3.余弦相似度:
def cosSim(inA,inB):
num = float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom)
物品相似度以及用户相似度:
对于用户-物品关系矩阵来说,基于物品相似度即基于矩阵的列进行相似计算,基于用户相似度则基于矩阵的行进行相似度计算。
推荐新物品给用户
def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
unratedItems = nonzero(dataMat[user,:].A==0)[1]#find unrated items
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]
输入用户--物品矩阵,首先搜索用户没有评价分数的物品列表,然后计算用户对于新物品的预测分数值,将分数值排序,返回最大的N件物品。
计算用户对于一件新物品的分数预测值如下:
def standEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1]
simTotal = 0.0; ratSimTotal = 0.0
#遍历每一种物品
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 = 0
#计算两种物品的相似性
else: 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 0
else: return ratSimTotal/simTotal
遍历每一件物品,找出该物品与待评测物品之间的已有的其他人的分数评价来计算相似度,即通过用户的意见来计算物品的相似度,计算所有相似度的和,计算相似度的加权平均,即为用户对于待评测物品的分数预测。
利用SVD提升推荐效果:
用户-物品矩阵过于稀疏,可以进行SVD分解,选取奇异值最大的数据来进行矩阵低维的近似表示,以此来加速相似度的计算提升推荐效果。
加载用户-物品稀疏矩阵:
对其进行奇异值分解: 可以发现大部分信息集中在前几个奇异值
计算前K个奇异值所占全部奇异值的平方和比重:
def rate(n):
d = mat(loadExData2())
U,Sigma,VT = la.svd(d)
Sig2 = Sigma**2;
total = sum(Sig2)
totaln = sum(Sig2[:n])
print ('rate' , totaln / total)
可知当k=4时,比重已经超过96%,即前4个奇异值已经表示来矩阵大约96%的信息,因此可以对于原矩阵进行近似表示
利用SVD将原数据矩阵A映射到V矩阵:
A=U*S*VT,左乘UT
UTA=S*VT
V=AT*U*S逆
实现了原始数据矩阵行的压缩,由m---4,简化了相似度的计算。
def svdEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1]
simTotal = 0.0; ratSimTotal = 0.0
U,Sigma,VT = la.svd(dataMat)
Sig4 = mat(eye(4)*Sigma[:4]) #arrange Sig4 into a diagonal matrix
xformedItems = dataMat.T * U[:,:4] * Sig4.I #create transformed items
for j in range(n):
userRating = dataMat[user,j]
if userRating == 0 or j==item: continue
similarity = 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 0
else: return ratSimTotal/simTotal
3.基于SVD图像压缩
加载图像数据,进行奇异值分解,选取不同的奇异值数目,重构原来数据矩阵,观察数据的损失情况:
def printMat(inMat, thresh=0.8):
for i in range(32):
for k in range(32):
if float(inMat[i,k]) > thresh:
print ('1', end=''),
else: print ('0', end=''),
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 ("****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 vector
SigRecon[k,k] = Sigma[k]
reconMat = U[:,:numSV]*SigRecon*VT[:numSV,:]
print ("****reconstructed matrix using %d singular values******" % numSV)
printMat(reconMat, thresh)
return Sigma
观察奇异值情况:
分别取numSV=1,2,3: 两个奇异值便可以很好的重构原图像
SVD可以很好地实现数据矩阵降维,不断逼近矩阵来提取重要特征,通过保留矩阵大部分能量,可以得到重要特征并且去除噪声。可以用于推荐系统以及信息检索等方向。