如何测试两个稀疏数组是否(几乎)相等?
How to test if two sparse arrays are (almost) equal?
我想检查两个稀疏数组是否(几乎)相等。而对于 numpy 数组,你可以这样做:
import numpy as np
a = np.ones(200)
np.testing.assert_array_almost_equal(a, a)
这不适用于我能理解的稀疏数组(较小矩阵的 returns 错误 AttributeError: ravel not found
或与数组大小相关的错误)。是否有 scipy 等同于测试稀疏矩阵?我可以将我的稀疏矩阵转换为密集矩阵并使用 numpy 测试函数,但有时由于 (memory/size) 限制,这是不可能的。例如:
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 数组是否相等,或者我应该测试较小的样本?
假设我们不关心数组中可能在容差值范围内的非零值,我们可以简单地获取行、列索引和相应的值,并寻找索引之间的精确匹配, 而 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)
这是另一个用 nonzero
和 data
方法替换 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)
我们可以在少数地方短路以进一步加快速度。关于性能,我更关注只有值不同的情况。
我想检查两个稀疏数组是否(几乎)相等。而对于 numpy 数组,你可以这样做:
import numpy as np
a = np.ones(200)
np.testing.assert_array_almost_equal(a, a)
这不适用于我能理解的稀疏数组(较小矩阵的 returns 错误 AttributeError: ravel not found
或与数组大小相关的错误)。是否有 scipy 等同于测试稀疏矩阵?我可以将我的稀疏矩阵转换为密集矩阵并使用 numpy 测试函数,但有时由于 (memory/size) 限制,这是不可能的。例如:
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 数组是否相等,或者我应该测试较小的样本?
假设我们不关心数组中可能在容差值范围内的非零值,我们可以简单地获取行、列索引和相应的值,并寻找索引之间的精确匹配, 而 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)
这是另一个用 nonzero
和 data
方法替换 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)
我们可以在少数地方短路以进一步加快速度。关于性能,我更关注只有值不同的情况。