【问题标题】:How to test if two sparse arrays are (almost) equal?如何测试两个稀疏数组是否(几乎)相等?
【发布时间】:2018-05-26 00:53:48
【问题描述】:

我想检查两个稀疏数组是否(几乎)相等。而对于 numpy 数组,您可以这样做:

import numpy as np

a = np.ones(200)
np.testing.assert_array_almost_equal(a, a)

这不适用于稀疏数组,我可以理解(对于较小的矩阵或与数组大小相关的错误返回错误AttributeError: ravel not found)。是否有等效于测试稀疏矩阵的 scipy?我可以将稀疏矩阵转换为密集矩阵并使用 numpy 测试功能,但有时由于(内存/大小)限制,这是不可能的。例如:

from scipy import sparse

b = sparse.rand(80000,8000,density=0.01)
type(b)  # <class 'scipy.sparse.coo.coo_matrix'>
c = b.toarray()  # ValueError: array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size.

是否可以测试这些较大的 scipy 数组是否相等,还是应该测试较小的样本?

【问题讨论】:

    标签: python numpy scipy sparse-matrix


    【解决方案1】:

    假设我们不关心可能在容差值内的数组中的非零值,我们可以简单地获取行、列索引和相应的值,并查找索引之间的精确匹配,而allclose() 匹配值。

    因此,实现将是 -

    from scipy.sparse import find
    
    def allclose(A, B, atol = 1e-8):
    
        # If you want to check matrix shapes as well
        if np.array_equal(A.shape, B.shape)==0:
            return False
    
        r1,c1,v1 = find(A)
        r2,c2,v2 = find(B)
        index_match = np.array_equal(r1,r2) & np.array_equal(c1,c2)
    
        if index_match==0:
            return False
        else:  
            return np.allclose(v1,v2, atol=atol)
    

    这是另一个用 nonzerodata 方法替换 find 函数的方法 -

    def allclose_v2(A, B, atol = 1e-8):
        # If you want to check matrix shapes as well
        if np.array_equal(A.shape, B.shape)==0:
            return False
    
        r1,c1 = A.nonzero()
        r2,c2 = B.nonzero()
    
        lidx1 = np.ravel_multi_index((r1,c1), A.shape)
        lidx2 = np.ravel_multi_index((r2,c2), B.shape)
    
        sidx1 = lidx1.argsort()
        sidx2 = lidx2.argsort()
    
        index_match = np.array_equal(lidx1[sidx1], lidx2[sidx2])
        if index_match==0:
            return False
        else:  
            v1 = A.data
            v2 = B.data        
            V1 = v1[sidx1]
            V2 = v2[sidx2]        
            return np.allclose(V1,V2, atol=atol)
    

    我们可以在几个地方短路以进一步加快速度。在性能方面,我更关注只有值不同的情况。

    【讨论】:

    • 可能想把 np.allclose 放在 if index_match: 后面。如果v1v2 的长度不同,则会抛出错误。
    • 如果我理解正确,您建议比较行和列索引是否相同以及值是否接近。我喜欢这个想法,但是如果努力查看 find() 在您的示例中的工作方式(如果我尝试使用它会引发错误)。与直接在比较语句中使用A.rowA.colA.data 相同吗?
    • @BartDur 猜测它首先需要一个 IF 来比较长度是否相等。已编辑。
    • @DanielF 谢谢。那里需要改进。
    • 等等...您使用的find()scipy.sparse.find()?起初我并不清楚,但现在一切都说得通了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多