郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(三)SVD...

  4.5.1 SVD算法回顾

  A = U∑VT

  其中:A是N*M的矩阵,U是M*M的方阵(里面向量正交,称为左奇异向量),∑是一个M*N的矩阵,VT是一个N*N的矩阵(里面向量正交,右奇异向量)

  那么奇异值是怎么对应起来的呢?首先,将矩阵A转置AT,将会得到一个方阵,这个方阵求特征值可以得到:

  (AAT)v = λv

  这里得到的v,就是我们上面的右奇异值,此外我们还可以得到:

  δ = λ1/2=>u=Av/δ

  δ就是奇异值,u就是上面说的左奇异向量。奇异值δ跟特征值类似,在矩阵∑中也是按从大到小排列。而且δ的减少特别快,在很多情况下,前10%甚至1%的奇异值的和就占了全部奇异值之和的99%以上,也就是,我们也可以用前r个奇异值来近似描述矩阵。这里定义一下部分奇异值分解:

  Am×n≈ Am×r = Um×rr×rVTr×n

  右边的三个矩阵相乘的结果将会是一个接近于A的矩阵,在这里,r越接近于n,则相乘的结果越接近于A。而这三个矩阵的面积之和(对于存储观点来说,矩阵面积越小,存储量就越小)要远远小于原始的矩阵A。我们如果想要压缩空间来表示矩

阵,只要记录U、∑、V三个矩阵即可。

  例子:

  

#coding:utf-8
from numpy import *

A        = mat([[5,5,3,0,5,5],
                [5,0,4,0,4,4],
                [0,3,0,5,4,5],
                [5,4,3,3,5,5]])
U         = A*A.T   #手工分解求矩阵的svd
lamda,hU = linalg.eig(U) #hU:U特征向量
VT        = A.T*A
ev,hVT    = linalg.eig(VT)#hVT:VT特征向量
hV        = hVT.T
print "hU:",hU           #U矩阵
print "hV:",hV           #V矩阵
sigma     = sqrt(lamda)   #奇异值
print"sigma:",sigma

  使用NumPy的Linalg中的svd函数计算如下。

sigma     = np.zeros([shape(A)[0],shape(A)[1]])
U,S,VT    = linalg.svd(A)
print S

  4.5.2 常用的距离函数

  (1)欧式距离

#欧式距离
eps = 1.0e-6
def distEclud(vecA,vecB):
    return linalg.norm(vecA-vecB) + eps

  (2)相关系数

  

def distCorrcoef(vecA,vecB):
    return corrcoef(vecA,vecB,rowvar = 0)[0][1]

  (3)Jaccard距离

import scipy.spatial.distance as dist
def distJaccard(vecA,vecB):
    temp = mat([array(vecA.tolist()[0]),array(vecB.tolist()[0])])
    return dist.pdist(temp,'jaccard')

  (4)余弦定理

def cosSim(vecA,vecB):
    return dot(vecA,vecB)/((linalg.norm(vecA)*(linalg.norm(vecB))+eps)

  4.5.3 SVD数据集

  SVD数据集用于计算奇异值分解测试。

  

#加载修正后的数据
trainset = mat([[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],])
test = mat([[1,0,0,0,0,0,0,1,2,0,0]])

4.5.4 SVD算法主函数

  根据SVD的原理,我们实现了最简单的SVD算法的主函数。

  

#coding:utf-8
__author__ = 'wuchuanying'

#dataSet 训练集
#testVect 测试集
#r = 3 取前r个近似值
#rank =1 ,结果排序
#distCalc 相似度计算函数

from numpy import *

def recommand(dataSet,testVect,r = 3,rank = 1,distCalc = cosim):
    m,n = shape(dataSet)
    limit = min(m,n)
    if r > limit:
        r = limit
    U,S,VT = linalg.svd(dataSet.T)   #svd分解
    V      = VT.T
    Ur     = U[:,:r]
    Sr     = diag(S)[:r,:r]         #If v is a 1-D array, return a 2-D array with v on the k-th diagonal.
    Vr     = V[:,:r]
    testresult = testVect*Ur*linalg.inv(Sr)  #计算User E的坐标值
    #计算测试集与训练集每个记录的相似度
    resultarray = array([distCalc(testresult,vi) for vi in vr])
    descindx    = argsort(-resultarray)[:rank]  #排序结果---降序
    return descindx,resultarray[descindx]      #排序后的索引和值

  4.5.5 评估结果

  执行Recommend_lib中的推荐方法,获取执行结果

  

trainset = mat([[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],])
test = mat([[1,0,0,0,0,0,0,1,2,0,0]])

indx,resultarray = recommand(A,test,r = 2,rank = 2,distCalc = cosSim)

  执行结果如下:

  [4,3]

  [0.99995847,0.99987554]

  返回最相似的两个向量,第一个相似度是99.996%,第二个相似度99.998%,可以将这两个向量的物品推荐给测试集中的用户。

 

 

  资料来源及版权所有:郑捷《机器学习算法原理与编程实践》 仅供学习研究

  

  

转载于:https://www.cnblogs.com/wuchuanying/p/6265699.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值