机器学习处理稀疏向量(机器学习-稀疏矩阵的处理)
机器学习处理稀疏向量(机器学习-稀疏矩阵的处理)存储稀疏矩阵必须为矩阵中的每个32位乃至64位零值分配存储器,这明显是浪费内存资源的,因为这些零值不包含任何信息。我们可以利用压缩技术使我们需要存储的数据量最小化。这并非唯一好处。几乎所有的自然机器学习算法都要求数据矩阵事先存在于内存中,也就是说,当数据矩阵不能完全存入内存中时,机器学习过程就会中断。将稠密矩阵转换成稀疏矩阵的好处之一就是在多数情况下,稀疏矩阵可以被压缩到能适应内存容量。2. 加速多数机器学习程序为什么使用稀疏矩阵?由于稀疏矩阵含有许多数值为零的元素,我们可以运用特定算法做以下两件重要的事:1. 压缩矩阵对象的内存台面空间
什么是稀疏矩阵?
我们知道矩阵是一个由m行和n列组成的二维数据对象,因此一共有m x n个数值。当这个矩阵的绝大部分数值为零,且非零元素呈不规律分布时,则称该矩阵为稀疏矩阵(Sparse Matrix)。下图所示的是一个8 x 8的稀疏矩阵。
稀疏矩阵在机器学习方面是很常见的。尽管它们自然而然地出现在一些数据收集过程中,更多时候,它们是在使用特定的数据转化技术时得到的。例如我们用一个算法来提取词性标签作为补充标签,来训练序列分类器;如果在文档全集中进行提取,其结果可以被向量化成一个非常巨大的稀疏矩阵,从而作为参数传递给分类器;又例如从TalkingData的移动数据中,把移动设备的品牌以及使用的app这两个变量变为虚拟变量时,我们会得到一个数万列的稀疏矩阵。
说了这么多稀疏矩阵,我们不禁会问,是不是也存在稠密矩阵?答案是显而易见的,那些非零数值占大多数元素的矩阵即是稠密矩阵(Dense Matrix)。那么两者之间除了直观上的不同,还有其他深层次的区别吗?或者说,相对于稠密矩阵,稀疏矩阵有哪些优点?
为什么使用稀疏矩阵?
由于稀疏矩阵含有许多数值为零的元素,我们可以运用特定算法做以下两件重要的事:
1. 压缩矩阵对象的内存台面空间
2. 加速多数机器学习程序
存储稀疏矩阵必须为矩阵中的每个32位乃至64位零值分配存储器,这明显是浪费内存资源的,因为这些零值不包含任何信息。我们可以利用压缩技术使我们需要存储的数据量最小化。这并非唯一好处。几乎所有的自然机器学习算法都要求数据矩阵事先存在于内存中,也就是说,当数据矩阵不能完全存入内存中时,机器学习过程就会中断。将稠密矩阵转换成稀疏矩阵的好处之一就是在多数情况下,稀疏矩阵可以被压缩到能适应内存容量。
再者,考虑一个稀疏矩阵和一个稠密矩阵相乘。尽管稀疏矩阵中有很多零值,我们也知道零乘以任何数还是零,然而常规途径会不可避免地进行此无意义的运算。这就大大拖延了处理时间。显然,只操作那些返回非零数值的元素是更加有效率的。因此,任何用到基本数学运算(比如乘法)的算法都能从稀疏矩阵实施中获益。
我们可以通过下面这个简单的例子验证以上结论。假设我们有一个2000×10000的数据集,该矩阵的元素只有1和0两个数值。为了直观表现出这个矩阵的稀疏度,我们建立一个象限,用点来表示数值为1的元素,数值为0的元素则留白,如下图所示。
可以看到,图像化的数据集大部分都是空白的。作为比较,下图所示的是一个元素数量相同的稠密矩阵。
现在我们尝试将稠密矩阵转换成稀疏矩阵。这里,我们通过Python SciPy模块中的压缩稀疏行(CSR)算法来完成这一操作。压缩结果如下图所示。可以看到,稠密矩阵的大小是160 MB,而稀疏矩阵的大小则是24 MB,这相当于85%的压缩率!
接着让我们来看一下计算时间方面的比较。我们运行三种不同的分类算法:伯努利朴素贝叶斯(Bernoulli Naive Bayes)、逻辑回归(Logistic Regression)、以及支持向量机(Support Vector Machines),然后分别检查各个算法的处理时间。
试验结果总结如下:
可以看出,朴素贝叶斯分类器在稀疏矩阵下运行速度提升了8倍;对于逻辑回归,我们看到处理时间减少了大约33%,尽管性能不如朴素贝叶斯,提速还是很明显的;最后来看支持向量机,相对于稠密矩阵,稀疏矩阵仅仅用了一半的处理时间!总的来说,将稠密矩阵转换为稀疏矩阵形式几乎总是可以提升处理时间上的效率。
稀疏矩阵稀疏性处理
通常,为了处理稀疏性矩阵,我们会构造更为有效的数据结构,压缩稀疏行和列,或者通过PCA、SVD等方法来进行降维。
1构造更为有效的数据结构
因为零值没有太多的意义,所以我们可以忽略零值,并且仅需要存储或操作稀疏矩阵中数据或非零值。有多种数据结构可用于有效地构造稀疏矩阵,下面列出了三个常见的例子。
● Dictionary of Keys:使用字典,其中行和列索引映射到值。
● List of Lists:矩阵的每一行都存储为一个列表,每个子列表包含列索引和值。
● Coordinate List :每个元组都存储一个元组列表,其中包含行索引、列索引和值。
2压缩稀疏行或者列
可以通过对数据的理解来合并或者删除部分列。例如上文提到app数据,我们可以将app根据其所属的类型分为金融、娱乐、音乐或者电影等,之后将其进行合并,即可大大提高运算效率。而对于一些使用频率远低于平均值的列可以酌情删掉。
3降维
除了传统的PCA、k-SVD、LDA、NNMF等方法外,今天分享一个PCA方法的延展:构筑-核心集算法。
将维基百科的文本作为案例,一个369万(份文件)×796万(个英文词汇)的稀疏矩阵,其空间复杂度可想而知。目前还没有一种降维算法能够计算这个矩阵的特征值。基于这点,即便是用最先进的GenSim库来对维基的“文件-词汇”稀疏矩阵运行SVD算法,计算机也会很快地在最初的几千份文件的随机投影过程中宕机。这里介绍一种新的构筑-核心集算法,从而有效的解决上述问题。
● (k ε)-核心集((k ε)-Coreset):
基础概念:
对于一个n维空间的点集
和一个n维空间内的向量
,我们定义向量
到点集S中的最小欧式距离为:
对于一个(m×n)维的矩阵A,其行向量是
,我们定义A到S的距离平方和为:
对于核心集:
所谓核心集,指的是对于一个(m×n)的矩阵A,其行向量
可以理解为m个在n维空间的点。而核心集是由这些行向量
加权之后的集合C,即
(这里的所有权重均大于等于0)。这时我们说,核心集C是矩阵A的行向量集合的一个加权子集。但所有权重均等于1时,这是集合C就是A的行向量的集合。此外,核心集还需满足,对于所有的k阶子空间S,其到A的距离可以近似的表示成其到A的核心集C的距离。用数学表达式表示则是:
简单地说,就是S到A的距离可以用S到C的距离近似表示。
可以这样理解,当绝大多数的权重都等于0的时候,原先的440万份文件,就可以用最后的几千份文件乘以各自权重代表,并且保持足够程度的信息量,这时的数据量就从原先的369万(份文件)×796万(个英文单词)降低到几千(份文件)×796万(英文单词)的程度。
从这个角度来讲核心集并未对矩阵A中的维度进行处理,而仅仅是对行数进行了压缩。因此,将构建核心集结合已有的PCA、SVD或者LSA降维,可以将原有的稀疏矩阵压缩至一个新的(p×q)的矩阵
(这里,p≪m q≪n)。
至此,关于稀疏矩阵的降维处理,我们可以应用SVD-Coreset,或者PCA-Coreset方法进行多步降维。
● 核心集算例:
在抽样的过程中,利用核心集算法和利用均匀随机抽样,以及加权随机抽样所构筑的样本集合,对于不同的迭代次数k,在利用(3)式计算出来的相对误差对比图,显示在下图(a)-(c)中。
可以看到利用核心集构造的方法抽样,其相对误差对比另外两种方法总体上更为稳定。换言之,通过构造核心集的方法进行抽样,其样本在代表全体的表现上更有优势,尤其是当样本数量超过一定阈值的时候。
图(e)显示的是,应用不同的降维方法在整个(369万×796万)维基百科的数据上进行LSA分析的实验。红色的线是利用MATLAB的svds工具箱在16GB内存笔记本电脑上运行的结果,蓝色的线是利用MATLAB的svds工具箱在集群上运行的结果,绿色的线是利用核心集-SVD方法在集群上运行的结果。
可以看到,随着维度的增加,每个方法的运行时间都在增加,但是最先崩溃的是用笔记本运行MATLAB的svds方法的LSA分析,原因是内存溢出。在分别利用MATLAB的svds和核心集-SVD的方法比较中,无论是运行时间,还是空间复杂度上,核心集-SVD方法相比较之下具有优势,并且优势明显,且表现稳定。
因此,在大规模稀疏矩阵的降维处理过程中,核心集配合其他的降维方法(包括PCA、SVD等),可以有效的提高模型对数据降维处理的性能。