我正在尝试使用 scipy 以 dok(键字典(格式执行稀疏线性代数计算。 当我将两个矩阵相乘时,格式从 dok 类型更改为 csr 格式,这对于数据和后续操作来说是一种低效的格式。
如何保留 dok 格式?
我看过文档:
-
西比稀疏矩阵
-
dok_matrix
但看不到任何信息自动类型转换或是否以及如何避免。
请参阅此示例:
from scipy.sparse import dok_matrix
my_mat = dok_matrix([[1,2], [3,4]])
print(type(my_mat.dot(my_mat)))
print(type(my_mat @ my_mat))
显示格式已更改:
<class 'scipy.sparse.csr.csr_matrix'>
<class 'scipy.sparse.csr.csr_matrix'>
只需转换回来:
result = result.todok()
CSR 对于后续操作来说可能是一种低效的格式(或者可能不是,我们无法判断(,但它非常适合矩阵乘法。尝试使矩阵乘法代码对 DOK 结果本机操作将比仅转换结果慢。
正如@user2357112csr
所指出的,它对线性代数有好处。然而,转换的成本是巨大的。由于dok
不是唯一支持可接受的时间编辑的格式,因此值得查看lil
的其他选项。根据您的用例,您可以节省相当多的时间:
from scipy import sparse
from timeit import timeit
a = random(100,100,0.1,format='lil')
b = random(100,100,0.1,format='dok')
a
# <100x100 sparse matrix of type '<class 'numpy.float64'>'
# with 1000 stored elements in LInked List format>
b
# <100x100 sparse matrix of type '<class 'numpy.float64'>'
# with 1000 stored elements in Dictionary Of Keys format>
timeit(lambda:(a@a).tolil(),number=100)*10
# 1.491789099527523
timeit(lambda:(b@b).todok(),number=100)*10
# 4.220661079743877
请注意,在这个例子中a@a
/b@b
相当密集,如果我们选择更稀疏的情况,差异就不那么明显了:
a = random(100,100,0.01,format='lil')
b = random(100,100,0.01,format='dok')
timeit(lambda:(a@a).tolil(),number=100)*10
# 0.6880075298249722
timeit(lambda:(b@b).todok(),number=100)*10
# 0.7450748200062662