1、What ?
SVD:奇异值分解(Singular Value Decomposition,SVD),在线性几何中,SVD是实数和复数矩阵的因式分解。在信号处理和统计学应用较多。
(from wiki)
2、Why ?
简化数据,去除噪声和冗余信息。
3、SVD原理:参考文献:A Singularly Valuable Decomposition,http://www-users.math.umn.edu/~lerman/math5467/svd.pdf
??
4、机器学习实战:利用python实现SVD
奇异值分解:
- 优点:简化数据,去除噪声,提高算法的结果
- 缺点:数据的转换可能难以理解
- 使用数据类型:数值型数据
5、机器学习实战:基于协同过滤推荐引擎
协同过滤方法(collaborative filtering):通过讲用户的和其他用户的数据进行对比来实现推荐的。
- 相似度计算:
(1)欧式距离计算:,“相似度 = 1/(1+距离)”
(2) 皮尔逊相关系数(Pearson correlation):对用户的评级的量级比较敏感,好于欧式距离。可以通过0.5 + 0.5 * corrcoef()可以规划到(0,1)之间
(3)余弦相似度(cosine similarity):,
分别表示A、B的2范数,计算工具linalg.norm()
eg1、示例:餐馆菜肴推荐引擎
推荐系统的工作过程:给定一个用户,系统会为此用户返回N个最好的推荐菜肴。为了实现这一点,则需要我们做到:
a,寻找用户没有评级的菜肴,即在用户-物品矩阵中的0值;
b,在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。
c,对这些物品的评分从高到低进行排序,返回前N个物品
代码如下:
#实现SVD
def loadExData():
return [[1, 1, 1, 0, 0],
[2, 2, 2, 0, 0],
[1, 1, 1, 0, 0],
[5, 5, 5, 0, 0],
[1, 1, 0, 2, 2],
[0, 0, 0, 3, 3],
[0, 0, 0, 1, 1]]
#相似度计算
#利用欧式距离
def euclidSim(inA, inB):
return 1.0/(1.0 + la.norm(inA - inB))
#利用皮尔逊相关系数
def pearsSim(inA, inB):
if len(inA) < 3: return 1.0
return 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):
"""
arg:
dataMat 数据集
user 用户编号
simMeans 相似度计算方法
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 * userRating
#根据评分计算比例
ratSimTotal += similarity * userRating
if simTotal == 0:
return 0
else:
return ratSimTotal/simTotal
#推荐实现:recommeng()产生了最高的N个推荐结果
def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
#寻找用户未评价的产品
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.0; ratSimTotal = 0.0
U, Sigma, VT = la.svd(dataMat)
Sig4 = mat(eye(4) * Sigma[: 4])
xformedItems = dataMat.T * U[:, : 4] * Sig4.I#这里xformedItems 这个等式不是很理解???
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
#图像压缩函数
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)
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(myMat)
print("****original matrix******")
printMat(myMat, thresh)
U, Sigma, VT = la.svd(myMat)
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)
print(reconMat, thresh)