scipy 稀疏矩阵包和 MATLAB 中的类似包基于从线性代数问题发展而来的思想,例如求解大型稀疏线性方程(例如有限差分和有限元实现)。因此,矩阵乘积(numpy 数组的dot 乘积)和方程求解器之类的东西都得到了很好的开发。
我的粗略经验是,稀疏csr 矩阵乘积必须具有 1% 的稀疏度才能比等效的密集dot 运算更快——换句话说,每 99 个零有一个非零值。 (但请参阅下面的测试)
但人们也尝试使用稀疏矩阵来节省内存。但请记住,这样的矩阵必须存储 3 个值数组(至少在 coo 格式中)。所以稀疏度必须小于 1/3 才能开始节省内存。显然,如果您首先构建密集数组并从中创建稀疏数组,则不会节省内存。
scipy 包实现了许多稀疏格式。 coo 格式最容易理解和构建。根据文档构建一个并查看其.data、.row 和.col 属性(3 个一维数组)。
csr 和 csc 通常是从 coo 格式构建的,并稍微压缩数据,使它们更难理解。但它们具有大部分数学功能。
也可以索引csr 格式,尽管通常这比等效的密集矩阵/数组情况要慢。改变值(尤其是从 0 到非零)、连接、增量增长等其他操作也较慢。
lil(列表列表)也很容易理解,最适合增量构建。 dok 实际上是一个字典子类。
关键点是稀疏矩阵仅限于 2d,并且在许多方面表现得像 np.matrix 类(尽管它不是子类)。
使用scikit-learn 和sparse 搜索其他问题可能是找出使用这些矩阵的优缺点的最佳方式。我已经回答了许多问题,但我比“学习”方面更了解“稀疏”方面。我认为它们很有用,但我觉得合身并不总是最好的。任何自定义都在learn 方面。到目前为止,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
这是一个尺寸问题;对于较小的矩阵,密集的dot 更快
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