机器学习实战—利用SVD简化数据

一、SVD的应用
奇异值分解:
优点:简化数据,去除噪声。提高算法的结果。
缺点:数据转换难以理解。

利用SVD能够实现用小得多的数据集来表示原始数据集,这样做,实际上是去除了噪声和冗余信息。当我们视图节省空间时,去除噪声和冗余信息是目标,但是我们这里则是从数据中抽取信息,基于这个视角,我们可以把SVD看成是从有噪声的数据中抽取相关特征。

1、隐性语义索引(LSI)

利用SVD的方法为隐性语义索引(Latent Semantic Indexing, LSI)或隐性语义分析(Latent Semantic Analysis, LSA)。在LSI中,一个矩阵是由文档和词语组成的,应用SVD时,会构建出多个奇异值,其代表了文档中的概念或主题。

2、推荐系统
这里写图片描述
上述矩阵由餐馆的菜和品菜师对这些菜的意见构成的。品菜师采用1到5之间的任意一个整数来对菜评级,如果品菜师没有尝过某道菜,则评级为0。对上述矩阵进行SVD分解,会得到两个奇异值(注意其特征值位2),也即仿佛有两个概念或主题与此数据集相关联。

3.特征分解

在很多情况下,数据中的一小段携带了数据集中的大部分信息,其他信息则要么是噪声,要么就是毫不相关的信息。在线性代数中还有很多矩阵分解技术。 矩阵分解可以将原始矩阵表示成新的易于处理的形式。

SVD将原始数据集矩阵Data分解成三个矩阵U,sigma,V.T。
这里写图片描述
分解出来的sigma矩阵为对角阵,对角元素从大到小排列,称之为奇异值(Singular Value),这些奇异值为Data*Data.T特征值的平方根。且若是Data的秩为r,则奇异值的个数为r个,也即数据集中仅有r个重要特征。

4.奇异值:

下面谈谈奇异值分解。特征值分解是一个提取矩阵特征很不错的方法,但是它只是对方阵而言的,在现实的世界中,我们看到的大部分矩阵都不是方阵,比如说有N个学生,每个学生有M科成绩,这样形成的一个N * M的矩阵就不可能是方阵,我们怎样才能描述这样普通的矩阵呢的重要特征呢?奇异值分解可以用来干这个事情,奇异值分解是一个能适用于任意的矩阵的一种分解的方法:
这里写图片描述

假设A是一个N * M的矩阵,那么得到的U是一个N * N的方阵(里面的向量是正交的,U里面的向量称为左奇异向量),Σ是一个N * M的矩阵(除了对角线的元素都是0,对角线上的元素称为奇异值),V’(V的转置)是一个N * N的矩阵,里面的向量也是正交的,V里面的向量称为右奇异向量),从图片来反映几个相乘的矩阵的大小可得下面的图片
这里写图片描述

那么奇异值和特征值是怎么对应起来的呢?首先,我们将一个矩阵A的转置 * A,将会得到一个方阵,我们用这个方阵求特征值可以得到:
这里写图片描述

这里得到的v,就是我们上面的右奇异向量。此外我们还可以得到:
这里写图片描述

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

r是一个远小于m、n的数,这样矩阵的乘法看起来像是下面的样子:
这里写图片描述

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

5.奇异值的计算:
奇异值的计算是一个难题,是一个O(N^3)的算法。在单机的情况下当然是没问题的,matlab在一秒钟内就可以算出1000 * 1000的矩阵的所有奇异值,但是当矩阵的规模增长的时候,计算的复杂度呈3次方增长,就需要并行计算参与了。Google的吴军老师在数学之美系列谈到SVD的时候,说起Google实现了SVD的并行化算法,说这是对人类的一个贡献,但是也没有给出具体的计算规模,也没有给出太多有价值的信息。

其实SVD还是可以用并行的方式去实现的,在解大规模的矩阵的时候,一般使用迭代的方法,当矩阵的规模很大(比如说上亿)的时候,迭代的次数也可能会上亿次,如果使用Map-Reduce框架去解,则每次Map-Reduce完成的时候,都会涉及到写文件、读文件的操作。个人猜测Google云计算体系中除了Map-Reduce以外应该还有类似于MPI的计算模型,也就是节点之间是保持通信,数据是常驻在内存中的,这种计算模型比Map-Reduce在解决迭代次数非常多的时候,要快了很多倍。

Lanczos迭代就是一种解对称方阵部分特征值的方法(之前谈到了,解A’* A得到的对称方阵的特征值就是解A的右奇异向量),是将一个对称的方程化为一个三对角矩阵再进行求解。按网上的一些文献来看,Google应该是用这种方法去做的奇异值分解的。请见Wikipedia上面的一些引用的论文,如果理解了那些论文,也“几乎”可以做出一个SVD了。

由于奇异值的计算是一个很枯燥,纯数学的过程,而且前人的研究成果(论文中)几乎已经把整个程序的流程图给出来了。更多的关于奇异值计算的部分,将在后面的参考文献中给出,这里不再深入,我还是focus在奇异值的应用中去。

二、利用Python实现SVD

#SVD算法是对原数据矩阵的分解,分解为左奇异矩阵*奇异值矩阵*右奇异矩阵的乘积
from numpy import *
import numpy as np
def loadDataSet1():
    dataSet = [[1,1],
               [7,7]]
    return mat(dataSet)

def loadDataSet2():
    dataSet = [[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]]
    return mat(dataSet)
def loadDataSet3():
    dataSet = [[4,4,0,2,2],
               [4,0,0,3,3],
               [4,0,0,1,1],
               [1,1,1,2,0],
               [2,2,2,0,0],
               [1,1,1,0,0],
               [5,5,5,0,0]]
    return mat(dataSet)

if __name__ == "__main__":
    #利用numpy模块中的函数进行SVD三个矩阵的求解
    # U,sigma,VT = np.linalg.svd(loadDataSet1())
    # sigmaMat = mat([[sigma[0],0],[0,sigma[1]]])
    # print("sigmaMat:",sigmaMat)
    # print("U:",U)
    # print("sigma:",sigma)
    # print("type(sigma):",type(sigma))
    # print("VT",VT)
    # dataSet2 = loadDataSet2()
    # print("dataSet2:",dataSet2)
    # U, sigma, VT = np.linalg.svd(dataSet2)
    # # print("sigma:",sigma)
    # #组合sigma矩阵
    # sigmaMat = mat([[sigma[0],0,0],[0,sigma[1],0],[0,0,sigma[2]]])
    # dataSetRec = U[:,:3]*sigmaMat*VT[:3,:]
    # print()
    # print("dataSetRec:",dataSetRec)

三、基于协同过滤的推荐引擎

协同过滤是通过将用户和其他用户的数据进行对比来实现推荐的。
当知道了两个用户或两个物品之间的相似度,我们就可以利用已有的数据来预测未知的用户喜好。

1.相似度计算利用用户对物品的意见来计算相似度,模糊了用物品属性来衡量相似度的不确定性,协同过滤不关心物品的描述属性,而是按照多用户的观点来计算相似度。

计算相似度有很多方法:
a.欧氏距离 b.皮尔逊相关系数 c.余弦相似度
这里写图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值