稀疏矩阵

转自https://juejin.im/entry/5ab9e64f6fb9a028d1411d79

稀疏矩阵

稀疏矩阵是由大部分为 零 的矩阵组成的矩阵,这是和稠密矩阵有所区别的主要特点。

如果它的许多元素为,则矩阵是稀疏的。对稀疏性感兴趣的原因是利用好这一特性能够大幅降低计算量,并且在实践中发现很多大型矩阵问题也是稀疏的。

矩阵的稀疏性可以用一个分数来量化,即矩阵中 零 元素的个数除以矩阵中元素的总数。

 

sparsity = count zero elements / total elements

 

 

 

 

下面是一个小的 3x6 的稀疏矩阵例子

 

     1, 0, 0, 1, 0, 0
A = (0, 0, 2, 0, 0, 1)
     0, 0, 0, 2, 0, 0

 

 

 

 

上面这个矩 阵中总共有18个元素,其中有13个元素为0,则 该矩阵的稀疏分数为 0.722 或 72% 左右。

稀疏存在的问题

稀疏矩阵会导致空间和时间复杂度方面的问题。

空间复杂度

大 型 矩阵需要大量的内存 来 存储,我们希望使用的一些大型矩阵是稀疏的。

实际上,大多数大型矩阵都是稀疏的,几乎所有的条目都是

一个例子是大型矩阵太大以至于不能存储在内存中,这个矩阵就是链接矩阵,它表示的从一个网站到另一个网站的链接。一个较小的稀疏矩阵例子可能是一本书中针对所有已知单词或术语出现矩阵。这两种情况所包含的矩阵都是稀疏的,其 零 值比非 零 数据值多,将这些矩阵表示为稠密矩阵的问题是需要内存,并且在矩阵中必须分配32 位或 64 位 零 值。这显然是对内存资源的一种浪费,因为这些 零 值不包含任何信息。

时间复杂度

假设一个非常大型的稀疏矩阵可以存储在内存中,之后将在这个矩阵上执行一些操作。简单来说,若矩阵主要包含的是 零 值,即没有多少数据,那么对这个矩阵执行操作可能需要 花费 很长 的 时间,其中执行的大部分计算将涉及 零 值相加或相乘。

在这样的问题上使用线性代数的方法是浪费的,因为大多数O(N^3) 的算术运算致力于求解方程组或矩阵求逆涉及的零操作数。

矩阵运算的时间复杂度随着矩阵大小增加而增加。对于机器学习而言,即使是最简单的方法也可能需要对每一行、每一列甚至整个矩阵进行许多操作运算, 这会 导致执行时间会变得很长,上述问题会 变得 更加复杂。

机器学习中的稀疏矩阵

稀疏矩阵在机器学习应用中经常出现。本节将讨论一些常见的示例,以便读者对其有个直观的了解,并深入的理解稀疏性问题。

数据

稀疏矩阵一般出现在一些特定类型的数据中,比如常见的记录活动发生的次数等。

这里有三个例子:

1.用户是否在电影目录中观看过电影;

2.用户是否购买产品目录中的产品;

3.歌曲目录中收听歌曲的次数;

数据准备

稀疏矩阵出现在用于编写数据的编码方案中。三个常见的例子如下:

1.独热编码,用于将分类数据表示为稀疏二元向量;

2.计数编码,用于表示文档词汇表中单词的频率;

3.TF-IDF编码,用于表示词汇表中词频逆文档频数;

研究领域

机器学习中一些研究领域必须开发专门的方法来直接解决稀疏性问题,这是因为输入数据几乎总是稀疏的。以下是三个例子:

1. 处理文本文档的自然语言处理 ;

2. 用于处理目录中的产品使用的推荐系统 ;

3. 处理包含大量黑色像素图像时的计算机视觉问题 ;

若语言模型中有100000个单词,那么特征向量的长度为100000,但对于简短的电子邮件消息而言,几乎所有的特征计数为

使用稀疏矩阵

表示和使用稀疏矩阵的解决方案是使用替代的数据结构来表示稀疏矩阵。 零元素 值可以被忽略,只有稀疏矩阵中的非零元素值需要被存储或使用。有多种数据结构能有效地构造稀疏矩阵,下面列出三个常见示例:

1.字典:一个字典使用行和列索引映射出一个值;

2.列表的列表:矩阵的每一行都以列表形式存储,每个子列表包含列的索引和其值;

3.坐标列表:元组列表存储在包含行索引、列索引和其值的每个元组中;

还有一些更适合执行有效操作的数据结构,比如以下两个常见示例:

1.CSR(Compressed Sparse Row):稀疏矩阵用非零值的三个一维数组、行的范围和列索引表示;

2.CSC(Compressed Sparse Column):与CSR方法相同,只是列索引在行索引之前被压缩并首先被读取;

Python中的稀疏矩阵

SciPy使用多个数据结构为创建稀疏矩阵提供了工具,以及将稠密矩阵转化为稀疏矩阵的工具。许多在Numpy数组上运行的线性代数Numpy和SciPy函数可以在SciPy稀疏数组上操作。此外,使用Numpy数据结构的机器学习库也可以在Scipy稀疏数组上操作,例如,用于机器学习的scikit-learning和用于深度学习的Keras。

通过调用scr_matrix()函数,可以使用CSR表示将存储在Numpy数组中的稠密矩阵转换为稀疏矩阵。在下面的例子中,定义一个3x6稀疏矩阵作为一个密集数组,并将其转换为CSR稀疏表示,然后通过调用todense()函数将其转换回密集数组。

 

# dense to sparse
from numpy import array
from scipy.sparse import csr_matrix
# create dense matrix
A = array([[1, 0, 0, 1, 0, 0], [0, 0, 2, 0, 0, 1], [0, 0, 0, 2, 0, 0]])
print(A)
# convert to sparse matrix (CSR method)
S = csr_matrix(A)
print(S)
# reconstruct dense matrix
B = S.todense()
print(B)

 

 

 

运行该示例后,首先打印出定义的密集数组,然后打印出CSR表示,最后打印出重建的密集矩阵。

 

[[1 0 0 1 0 0]
 [0 0 2 0 0 1]
 [0 0 0 2 0 0]]

  (0, 0)	1
  (0, 3)	1
  (1, 2)	2
  (1, 5)	1
  (2, 3)	2

[[1 0 0 1 0 0]
 [0 0 2 0 0 1]
 [0 0 0 2 0 0]]

 

 

 

Numpy不提供函数来计算矩阵的稀疏性。不过,可以通过首先找到矩阵的密度并从中减去相关值来轻松地计算出来。Numpy数组中的非零元素的数量可以由count_nonzero()函数给出,数组中的元素总个数可以由数组的size属性给出。因此,可以将数组稀疏度计算为:

 

sparsity = 1.0 - count_nonzero(A) / A.size

 

 

 

下面的示例演示如何计算数组的稀疏度:

 

# calculate sparsity
from numpy import array
from numpy import count_nonzero
# create dense matrix
A = array([[1, 0, 0, 1, 0, 0], [0, 0, 2, 0, 0, 1], [0, 0, 0, 2, 0, 0]])
print(A)
# calculate sparsity
sparsity = 1.0 - count_nonzero(A) / A.size
print(sparsity)

 

 

 

运行示例后,首先打印定义的稀疏矩阵,然后是矩阵的稀疏度。

 

[[1 0 0 1 0 0]
 [0 0 2 0 0 1]
 [0 0 0 2 0 0]]

0.7222222222222222

 

 

 

 

 

相关资源

如果您希望深入的了解稀疏矩阵,本节提供了有关该主题的一些资源:

书籍

线性代数简介,第五版,2016.

科学计算的艺术,第三版,2007.

人工智能:现代方法,第三版,2009.

直接稀疏矩阵的方法,第二版,2017.

API

Sparse matrices(scipy.sparse)API

Scipy.sparse.csr_matrix()API

Numpy.count_nonzero()API

Numpy.ndarray.size API

文章

稀疏矩阵(维基百科)

 

作者信息

Jason Brownlee , 机器学习专家 ,专注于 机器学习的推广教育 。

Linkedin: http://www.linkedin.com/in/jasonbrownlee/

本文由阿里云云栖社区 组织翻译 , 文章原标题《A Gentle Introduction to Sparse Matrices for Machine Learning 》,作者: Jason Brownlee ,译者:海棠。

文章为简译,更为详细的内容,请查看原文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值