sklearn与机器学习系列专题之降维(四)一文弄懂SVD特征筛选&降维

10 篇文章 1 订阅
9 篇文章 1 订阅

1.SVD算法简介

SVD降维算法(Singular Value Decompositionm,SVD),即在矩阵论中常见的奇异值分解降维。通俗地讲,就是将一个线性变换分解为两个线性变换,一个线性变换代表旋转,一个线性变换代表拉伸。奇异值分解是在机器学习领域应用较为广泛的算法之一,也是学习机器学习算法绕不开的基石,可应用在特征分解、推荐系统、自然语言处理和计算机视觉等各个方面

2.枯燥又简洁的理论推导

SVD降维算法的理论推导让小编觉得很尴尬——学过《矩阵论》这门课的读者,可以直接把这一块儿的内容跳过,进入下一章节;没有学过《矩阵论》的读者,小编也很难像老师在课堂上那样把每一步的原理细细推导讲清楚。此处,还是再一次点亮标题——只作“简洁的理论推导”。

SVD的核心思想是将一个大矩阵转化为几个小矩阵的乘积,如下图所示。
在这里插入图片描述
其中,U、S和V分别为分解后的小矩阵,通常更关注S矩阵,S矩阵的每一个值都代表该位置的重要性指标,它与降维算法中的特征值和特征向量的关系类似。

在这里插入图片描述
其中n和m都是比较大的数值,代表原始数据;r是较小的数值,表示矩阵分解后的结果用较小的矩阵组合来近似代替。对于奇异值,与特征分解中的特征值类似,在奇异值矩阵中是按照从大到小排序,且奇异值减小得非常快,在大多数情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。

由于r比n和m小很多,因此原本三个大矩阵(n×n)(n×m)(m×m)可以近似由三个较小的矩阵(n×r)(r×r)(r×m)表示,且原矩阵会在较大程度上保留信息。

由于这个重要的性质,SVD可以用于降维,来做数据压缩和去噪;也可以用于推荐算法,将用户和喜好对应的矩阵做特征分解,进而得到隐含的用户需求来做推荐。同时也可以用于NLP中的算法,比如潜在语义索引(LSI)。

3.SVD算法优缺点

优点:
1.原理和实现步骤都很简单;
2.可实现并行化。

缺点:

1.分解出的矩阵解释性不强,有“黑匣子”的味道;
2.每个基含有不同的鉴别信息和重构信息,且受原始数据的干扰较大。

4.python实战SVD(一)——用SVD算法降维

第一个实战项目,还是以降维开题——创建一个较小的矩阵,模拟用户对商品的评分降维。

import numpy as np 
class CSVD(object):
    '''
    实现svd分解降维应用示例的Python代码
    '''    
    def __init__(self, data):
        self.data = data       #用户数据
        self.S = []  #用户数据矩阵的奇异值序列 singular values
        self.U = []  #svd后的单位正交向量
        self.VT = []  #svd后的单位正交向量
        self.k = 0   #满足self.p的最小k值(k表示奇异值的个数)
        self.SD = [] #对角矩阵,对角线上元素是奇异值 singular values diagonal matrix        
    def _svd(self):
        '''
        用户数据矩阵的svd奇异值分解
        '''
        self.U, self.S, self.VT = np.linalg.svd(self.data)
        return self.U, self.S, self.VT        
    def _calc_k(self, percentge):
        '''确定k值:前k个奇异值的平方和占比 >=percentage, 求满足此条件的最小k值
        :param percentage, 奇异值平方和的占比的阈值
        :return 满足阈值percentage的最小k值
        '''
        self.k = 0
        #用户数据矩阵的奇异值序列的平方和
        total = sum(np.square(self.S))
        svss = 0 #奇异值平方和 singular values square sum
        for i in range(np.shape(self.S)[0]):
            svss += np.square(self.S[i])
            if (svss/total) >= percentge:
                self.k = i+1
                break
        return self.k

    def _buildSD(self, k):
        '''构建由奇异值组成的对角矩阵
        :param k,根据奇异值开放和的占比阈值计算出来的k值
        :return 由k个前奇异值组成的对角矩阵
        '''
        #方法1:用数组乘方法
        self.SD = np.eye(self.k) * self.S[:self.k] 
        #方法2:用自定义方法
        e = np.eye(self.k)
        for i in range(self.k):
            e[i,i] = self.S[i] 
        return self.SD

    def DimReduce(self, percentage):
        '''
        SVD降维
        :param percentage, 奇异值开方和的占比阈值
        :return 降维后的用户数据矩阵
        '''
        #Step1:svd奇异值分解
        self._svd()
        #Step2:计算k值
        self._calc_k(percentage)
        print('\n按照奇异值开方和占比阈值percentage=%d, 求得降维的k=%d'%(percentage, self.k))
        #Step3:构建由奇异值组成的对角矩阵singular values diagonal
        self._buildSD(self.k)
        k,U,SD,VT = self.k,self.U, self.SD, self.VT
        #Step4:按照svd分解公式对用户数据矩阵进行降维,得到降维压缩后的数据矩阵        
        a = U[:len(U), :k]
        b = np.dot(SD, VT[:k, :len(VT)])
        newData = np.dot(a,b)
        return newData
def CSVD_manual():
    ##训练数据集,用户对商品的评分矩阵,行为多个用户对单个商品的评分,列为用户对每个商品的评分
    data = np.array([[5, 5, 0, 5],
                     [5, 0, 3, 4],
                     [3, 4, 0, 3],
                     [0, 0, 5, 3],
                     [5, 4, 4, 5],
                     [5, 4, 5, 5]])
    percentage = 0.9
    svdor = CSVD(data)
    ret = svdor.DimReduce(percentage)
    print('====================================================')
    print('原始用户数据矩阵:\n', data)
    print('降维后的数据矩阵:\n', ret)
    print('====================================================')    
if __name__=='__main__':
    CSVD_manual()

运行程序,输出如下:
在这里插入图片描述

5.python实战SVD(二)——用SVD算法进行音乐推荐

近几年,随着各种短视频和音乐软件日渐火爆,以及各大厂之间的竞争日渐激烈。如何在短时间内让消费者对产品更加感兴趣,如何精准地分析用户心理和用户喜好度,一直是各个大厂孜孜不倦讨论和研究的热门话题。因此,在大厂算法工程师岗位中,日渐独立出一个新的岗位——推荐算法工程师。

借此机会,在这个降维的专题系列里,拓展降维算法的应用实例——应用SVD算法进行音乐推荐(选自《跟着迪哥学python》)。在程序中,首先构建评分矩阵,对其进行SVD分解,再选择待推荐用户,还原得到其对所有歌曲的估测评分值,最后排序,返回结果即可。

由于数据集比较大,且源代码较长,楼主双手奉上源程序和数据集的网盘,关注公众号“码点联盟”(文末有二维码),在后台回复“音乐推荐”即可自动获取网盘资源。

在SVD中所需的数据是用户对商品的打分,但在现在的数据集中,只有用户播放歌曲的情况,并没有实际的打分值,所以,在数据准备阶段,需要定义用户对每首歌曲的评分值。如果一个用户喜欢某首歌曲,他应该经常播放这首歌曲;相反,如果不喜欢某首歌曲,播放次数肯定比较少。

SVD的主体程序如下:

def compute_svd(urm, K):
    U, s, Vt = svds(urm, K)

    dim = (len(s), len(s))
    S = np.zeros(dim, dtype=np.float32)
    for i in range(0, len(s)):
        S[i,i] = mt.sqrt(s[i])

    U = csc_matrix(U, dtype=np.float32)
    S = csc_matrix(S, dtype=np.float32)
    Vt = csc_matrix(Vt, dtype=np.float32)

    return U, S, Vt

def compute_estimated_matrix(urm, U, S, Vt, uTest, K, test):
    rightTerm = S*Vt 
    max_recommendation = 250
    estimatedRatings = np.zeros(shape=(MAX_UID, MAX_PID), dtype=np.float16)
    recomendRatings = np.zeros(shape=(MAX_UID,max_recommendation ), dtype=np.float16)
    for userTest in uTest:
        prod = U[userTest, :]*rightTerm
        estimatedRatings[userTest, :] = prod.todense()
        recomendRatings[userTest, :] = (-estimatedRatings[userTest, :]).argsort()[:max_recommendation]
    return recomendRatings

最终得到的结果如下:

在这里插入图片描述

6.下篇预告

下一篇,额,小编还没想好,不过,还是以降维为专题。

敬请期待!

欢迎关注公众号“码点联盟”,不定期分享机器学习、深度学习干货,及各种资料大礼包!
另外,这是一个由一线互联网大厂算法工程师及双985研究生创建的公众号,后续会经常分享各类实用机器学习算法技术文章,欢迎交流讨论!在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值