机器学习实战第十四章-利用SVD简化数据

一,什么是SVD

SVD(Singular Value Decomposition):奇异值分解。
基本知识如下图所示:
SVD原理

SVD分解

其中U和V都可以作为高维转低维的转换矩阵将原始高维冗余数据转换到一个低维无冗余语义空间中,从而实现数据的降维。

SVD的应用

  • 优点:简化数据,去除噪声,提高算法的结果。
  • 缺点:数据的转换可能难以理解。
  • 适用数据类型:数值型数据。
  • 应用:LSA/LSI(隐性语义索引或隐性语义分析)、推荐系统、图像压缩等等

二,Numpy实现SVD

from numpy import *
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]]
Data = loadExData()
U,sigma,VT = linalg.svd(Data)
reconData = U[:,:3]*mat(diag(sigma[:3]))*VT[:3,:]
print(Data,'\n',reconData,'\n',sum(Data-reconData))

三,SVD在推荐系统中的应用

1,基于协同过滤的推荐系统

它和基于内容的内容系统有本质的不同。
本质:协同过滤是通过将用户与其他用户的数据进行对比,然后将相似度高的用户喜欢的东西推荐给该用户来实现推荐的。
分为两类:

  • 基于物品的协同过滤
  • 基于用户的协同过滤

用户数量一般都远远大于物品,所以一般情况下都是基于物品的协同过滤。

2,相似度计算

  • 欧式距离相似度:相似度=1/(1+距离)
  • 皮尔逊相关系数相似度:相似度=0.5+0.5*linalg.corrcoef()
  • 余弦相似度:相似度= 0.5+0.5cosθ=0.5+0.5A⃗ B⃗ |A⃗ ||B⃗ |
    这样可以把所有的相似度的取值归一化到0到1之间。
def euclidSim(inA,inB):
        return 1.0/(1+linalg.norm(inA-inB))
def pearsSim(inA,inB):
        if len(inA)<3:return 1.0
        return 0.5+0.5*linalg.corrcoef(inA,inB,rowvar=0)[0][1]
def cosSim(inA,inB):
        num = float(inA.T*inB)
        denom = linalg.norm(inA)*linalg.norm(inB)
        return 0.5+0.5*(num/denom)

3,推荐系统的评价

具体做法:将某些已知的评分去掉,然后对它们进行预测,最后计算预测值与真实值之间的差异。
最常用的评价指标为:最下均方根误差(Root Mean Squared Error,RMSE)

4,原始的推荐系统(推荐未用过的物品)

计算相似度时,维度很大导致计算量很大。

5,利用SVD提高推荐的效果

我们可以将用户物品评分矩阵进行SVD分解,将原始矩阵降维到一个低维语义矩阵(其中U矩阵可以将物品转换到低维空间,而V矩阵可以将用户转换到低维空间),从而减少计算相似度时的计算量,提高效率(当然也有可能提升推荐效果,因为它低维是从语义上计算相似度的,可能去除掉噪声)。

四,基于SVD的图像压缩

def printMat(inMat,thresh=0.8):
    for i in range(32):
        for j in range(32):
            if float(inMat[i,j])>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 = [int(i) for i in line.strip()]
        myl.append(newRow)
    myMat = mat(myl)
    print('******The original matrix******')
    printMat(myMat,thresh)
    U,sigma,VT = linalg.svd(myMat)
    reconMat = U[:,:numSV]*mat(diag(sigma[:numSV]))*VT[:numSV,:]
    print('******The reconstructed matrix using %d singular values******'%numSV)
    printMat(reconMat,thresh)

效果如下:

>>> svd.imgCompress(2)
******The original matrix******
00000000000000110000000000000000
00000000000011111100000000000000
00000000000111111110000000000000
00000000001111111111000000000000
00000000111111111111100000000000
00000001111111111111110000000000
00000000111111111111111000000000
00000000111111100001111100000000
00000001111111000001111100000000
00000011111100000000111100000000
00000011111100000000111110000000
00000011111100000000011110000000
00000011111100000000011110000000
00000001111110000000001111000000
00000011111110000000001111000000
00000011111100000000001111000000
00000001111100000000001111000000
00000011111100000000001111000000
00000001111100000000001111000000
00000001111100000000011111000000
00000000111110000000001111100000
00000000111110000000001111100000
00000000111110000000001111100000
00000000111110000000011111000000
00000000111110000000111111000000
00000000111111000001111110000000
00000000011111111111111110000000
00000000001111111111111110000000
00000000001111111111111110000000
00000000000111111111111000000000
00000000000011111111110000000000
00000000000000111111000000000000
******The reconstructed matrix using 2 singular values******
00000000000000000000000000000000
00000000000000000000000000000000
00000000000001111100000000000000
00000000000011111111000000000000
00000000000111111111100000000000
00000000001111111111110000000000
00000000001111111111110000000000
00000000011110000000001000000000
00000000111100000000001100000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001110000000
00000000111100000000001100000000
00000000001111111111111000000000
00000000001111111111110000000000
00000000001111111111110000000000
00000000000011111111100000000000
00000000000011111111000000000000

使用SVD压缩后的图像只需要存储 UVT 和两个奇异值,共32*2*2+2=130个数,比原始数目32*32=1024少得多了!

五,总结

SVD是一种强大的降维工具,我们可以利用SVD来逼近矩阵并从中提取重要特征。通过保留矩阵80%~90%的能量,就可以得到重要的特征并去掉噪声。SVD已有很多应用,其中一个成功的应用案例就是推荐引擎。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值