Scipy csr_matrix与自定义SparseMatrix比较返回False的问题求助
问题:两种稀疏矩阵实例的比较问题
我用两种方式构建了稀疏矩阵:
a = csr_matrix(M) # scipy库函数 b = SparseMatrix(M) # 自定义类
打印a和b时,输出的矩阵内容完全一致:
[[10. 20. 0. 0. 0. 0.] [ 0. 30. 99. 40. 0. 0.] [ 0. 0. 50. 60. 70. 0.] [ 0. 0. 0. 0. 0. 80.]] [[10. 20. 0. 0. 0. 0.] [ 0. 30. 99. 40. 0. 0.] [ 0. 0. 50. 60. 70. 0.] [ 0. 0. 0. 0. 0. 80.]]
但执行print(a == b)返回False。检查属性发现:
print(a.dtype) # 输出 float64 print(b.dtype) # 报错 'SparseMatrix' object has no attribute 'dtype'
推测是类型差异导致比较失败,希望找到无需修改SparseMatrix类的平滑解决办法。
以下是自定义SparseMatrix类的代码:
import numpy as np from scipy.sparse import csr_matrix class SparseMatrix: def __init__(self, A, tol = 1e-8): """ 参数 ---------- A : Numpy.Array 输入矩阵。 tol : float, 可选 判断元素是否为0的容差,默认值1e-8。 返回 ------- None. """ self.n_rows = A.shape[0] self.n_cols = A.shape[1] self.intern_represent = 'CSR' self.tol = tol self.V = [] self.col_index = [] self.row_index = np.zeros(self.n_rows + 1, dtype = int) self.number_of_nonzero = 0 for row in range(self.n_rows): self.row_index[row] = self.number_of_nonzero for column in range(self.n_cols): if abs(A[row, column]) >= tol: self.number_of_nonzero += 1 self.V.append(A[row, column]) self.col_index.append(column) self.row_index[-1] = self.number_of_nonzero
解决方案
因为csr_matrix和自定义SparseMatrix是不同类型的对象,直接用==比较会因类型不匹配返回False,可以通过以下两种方式实现内容比较:
方法1:转为稠密矩阵后比较
把两个矩阵都转换成numpy稠密数组,再进行元素级比较,考虑浮点数精度问题用容差匹配:
# 转换scipy矩阵为稠密格式 a_dense = a.toarray() # 转换自定义矩阵为稠密格式 b_dense = np.zeros((b.n_rows, b.n_cols)) for row in range(b.n_rows): start = b.row_index[row] end = b.row_index[row+1] for idx in range(start, end): b_dense[row, b.col_index[idx]] = b.V[idx] # 用容差判断所有元素是否相等 is_equal = np.allclose(a_dense, b_dense, atol=b.tol) print(is_equal) # 返回True则内容一致
方法2:直接对比CSR核心数据
两种矩阵都采用CSR存储格式,直接对比核心存储数据(值、列索引、行指针),效率更高:
# 提取scipy csr_matrix的核心数据 a_vals = a.data a_col_idx = a.indices a_row_ptr = a.indptr # 提取自定义SparseMatrix的核心数据 b_vals = np.array(b.V) b_col_idx = np.array(b.col_index) b_row_ptr = b.row_index # 分别验证各部分是否一致 vals_match = np.allclose(a_vals, b_vals, atol=b.tol) col_idx_match = np.array_equal(a_col_idx, b_col_idx) row_ptr_match = np.array_equal(a_row_ptr, b_row_ptr) # 所有部分匹配则矩阵内容一致 is_equal = vals_match and col_idx_match and row_ptr_match print(is_equal)
内容的提问来源于stack exchange,提问作者Bronze
相关产品推荐
相关产品推荐

