Python 使用稀疏矩阵与numpy数组
我正在Python中创建一些具有单词计数的numpy数组:行是文档,列是word X的计数。如果我有很多零计数,人们建议在进一步处理这些时使用稀疏矩阵,例如在分类器中。然而,在向Scikit中输入numpy数组和稀疏矩阵时,这似乎没有多大区别。所以我想知道三件事:Python 使用稀疏矩阵与numpy数组,python,numpy,matrix,scipy,scikit-learn,Python,Numpy,Matrix,Scipy,Scikit Learn,我正在Python中创建一些具有单词计数的numpy数组:行是文档,列是word X的计数。如果我有很多零计数,人们建议在进一步处理这些时使用稀疏矩阵,例如在分类器中。然而,在向Scikit中输入numpy数组和稀疏矩阵时,这似乎没有多大区别。所以我想知道三件事: 说 稀疏矩阵是大多数元素为零的矩阵 这是确定何时使用稀疏矩阵的适当方法吗 格式-只要>50%的值为零?还是说它让你 使用以防万一有意义吗 在像我这样的任务中,稀疏矩阵对性能有多大帮助, 尤其是与numpy数组或标准列表相比 到目前为
- 说 稀疏矩阵是大多数元素为零的矩阵 这是确定何时使用稀疏矩阵的适当方法吗 格式-只要>50%的值为零?还是说它让你 使用以防万一有意义吗
- 在像我这样的任务中,稀疏矩阵对性能有多大帮助, 尤其是与numpy数组或标准列表相比
- 到目前为止,我将数据收集到一个numpy数组中,然后转换为 csr_矩阵。这样做对吗?我不能 找出如何从头开始构建稀疏矩阵,然后 可能是不可能的
X' W
其中X是数据矩阵nxd,W是一些权重矩阵dxk。因此,“密集”乘法需要NdK
时间,而稀疏,假设平均每行稀疏度为p isNpdK
。因此,如果你的稀疏度为50%,你可以期望运行速度快近2倍。较难的部分是估计稀疏访问的开销,而不是高度优化的密集访问
在像我这样的任务中,稀疏矩阵对性能有多大帮助,特别是与numpy数组或标准列表相比
对于LR的特定情况,这可能比密集格式快几倍,但为了观察差异,需要大量高维(>100)数据(>1000)
到目前为止,我将数据收集到一个numpy数组中,然后转换成Scipy中的csr_矩阵。这样做对吗?我不知道如何从头开始构建稀疏矩阵,这可能是不可能的
不,这不是一个好办法。您可以“从头开始”构建它,例如首先构建一个字典,然后对其进行转换等。有很多方法可以构建稀疏矩阵,而不是首先构建密集矩阵 scipysparse matrix软件包以及MATLAB中的类似软件包基于线性代数问题的思想,如求解大型稀疏线性方程组(如有限差分和有限元实现)。因此,矩阵积(numpy数组的点积)和方程求解器都得到了很好的发展 我的粗略经验是,稀疏
csr
矩阵积必须具有1%的稀疏性,才能比等效的密集dot
运算快——换句话说,每99个零有一个非零值。(但请参见下面的测试)
但人们也尝试使用稀疏矩阵来节省内存。但请记住,这样的矩阵必须存储3个值数组(至少是coo
格式)。因此稀疏度必须小于1/3才能开始节省内存。显然,如果首先构建密集数组,然后从中创建稀疏数组,就不会节省内存
scipy
包实现了许多稀疏格式。coo
格式最容易理解和构建。根据文档构建一个,并查看其.data
、.row
和.col
属性(3 1d数组)
csr
和csc
通常是从coo
格式构建的,并对数据进行了一些压缩,使其更难理解。但它们拥有大部分的数学功能
也可以索引csr
格式,尽管通常这比等效的密集矩阵/数组情况慢。其他操作,如更改值(特别是从0更改为非零)、串联、增量增长,也会变慢
lil
(列表列表列表)也很容易理解,最适合增量构建dok
实际上是一个字典子类
一个关键点是稀疏矩阵仅限于2d,并且在许多方面的行为类似于np.matrix
类(尽管它不是一个子类)
使用scikit learn
和sparse
搜索其他问题可能是找到使用这些矩阵的优缺点的最佳方法。我已经回答了很多问题,但我知道“稀疏”的一面比“学习”的一面好。我认为它们很有用,但我感觉合身并不总是最好的。任何定制都在学习
端。到目前为止,sparse
软件包尚未针对此应用程序进行优化
我刚刚尝试了一些矩阵积测试,使用
sparse.random
方法创建具有指定稀疏度的稀疏矩阵。稀疏矩阵乘法的性能比我预期的要好
In [251]: M=sparse.random(1000,1000,.5)
In [252]: timeit M1=M*M
1 loops, best of 3: 2.78 s per loop
In [253]: timeit Ma=M.toarray(); M2=Ma.dot(Ma)
1 loops, best of 3: 4.28 s per loop
这是一个规模问题;对于较小的矩阵,密集的点
更快
In [255]: M=sparse.random(100,100,.5)
In [256]: timeit M1=M*M
100 loops, best of 3: 3.24 ms per loop
In [257]: timeit Ma=M.toarray(); M2=Ma.dot(Ma)
1000 loops, best of 3: 1.44 ms per loop
但是比较一下索引
In [268]: timeit M.tocsr()[500,500]
10 loops, best of 3: 86.4 ms per loop
In [269]: timeit Ma[500,500]
1000000 loops, best of 3: 318 ns per loop
In [270]: timeit Ma=M.toarray();Ma[500,500]
10 loops, best of 3: 23.6 ms per loop
@hpaulj您的时间这是错误的,由于将稀疏.random映射到numpy数组(它的慢目标),您得到的结果很慢,请记住:
M=sparse.random(10001000.5)
Ma=M.toarray()
%timeit-n 25 M1=M*M
每个回路352 ms±1.18 ms(7次运行的平均值±标准偏差,25 l