scipy.sparse矩阵的布尔运算

11

我有一组填充有布尔值的稀疏矩阵,需要对其执行逻辑操作(主要是逐元素的OR运算)。

就像在numpy中一样,使用dtype='bool'对矩阵求和会得到逐元素的OR结果,但是会产生一个不好的副作用:

>>> from scipy import sparse
>>> [a,b] = [sparse.rand(5,5,density=0.1,format='lil').astype('bool')
...  for x in range(2)]
>>> b
<5x5 sparse matrix of type '<class 'numpy.bool_'>'
    with 2 stored elements in LInked List format>
>>> a+b
<5x5 sparse matrix of type '<class 'numpy.int8'>'
    with 4 stored elements in Compressed Sparse Row format>
数据类型被更改为'int8',这将对未来操作造成问题。可以通过以下方式解决:

数据类型被更改为 'int8',这会对将来的操作造成问题。 可以通过以下方式解决:

(a+b).astype('bool')

但我有一种印象,所有这些类型更改都会导致性能损失。

为什么结果的dtype与操作数不同?
在Python中对稀疏矩阵进行逻辑运算是否有更好的方法?

2个回答

6
稀疏矩阵不支持逻辑运算,但是将其转换为 'bool' 不会很费时。实际上,如果使用 LIL 格式的矩阵,由于性能波动,转换可能看起来需要负时间。
a = scipy.sparse.rand(10000, 10000, density=0.001, format='lil').astype('bool')
b = scipy.sparse.rand(10000, 10000, density=0.001, format='lil').astype('bool')

In [2]: %timeit a+b
10 loops, best of 3: 61.2 ms per loop

In [3]: %timeit (a+b).astype('bool')
10 loops, best of 3: 60.4 ms per loop

您可能已经注意到,在将LIL矩阵相加之前,它们被转换为CSR格式,请查看返回格式。如果您一开始就使用了CSR格式,那么转换开销会更加明显:

In [14]: %timeit a+b
100 loops, best of 3: 2.28 ms per loop

In [15]: %timeit (a+b).astype(bool)
100 loops, best of 3: 2.96 ms per loop

CSR(和CSC)矩阵具有一个名为“data”的属性,它是一个一维数组,保存稀疏矩阵的实际非零条目。因此,重新构造稀疏矩阵的成本取决于您的矩阵中非零条目的数量,而不是其大小:

a = scipy.sparse.rand(10000, 10000, density=0.0005, format='csr').astype('int8')
b = scipy.sparse.rand(1000, 1000, density=0.5, format='csr').astype('int8')

In [4]: %timeit a.astype('bool') # a is 10,000x10,000 with 50,000 non-zero entries
10000 loops, best of 3: 93.3 us per loop

In [5]: %timeit b.astype('bool') # b is 1,000x1,000 with 500,000 non-zero entries
1000 loops, best of 3: 1.7 ms per loop

5
你可以通过以下方式轻松表达布尔运算。然后它可以与稀疏矩阵一起使用。
a.multiply(b) #AND
a+b           #OR
(a>b)+(a<b)   #XOR
a>b           #NOT

所以布尔运算被支持的。


我一直在寻找表达异或的方法,谢谢!顺便说一句,这个方法可行是因为在Python中,False < True 被认为是真的,False < False 被认为是假的等等... - rodrigolece

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接