python - 为什么 .nnz 表示稀疏矩阵中存在更多非零元素?
问题描述
在 SciPy 中,我有一个 CSR 矩阵。我通过从该矩阵中选择每列的某些行来创建一个 LiL 矩阵。然后将结果矩阵转换为 CSR 矩阵。
我有一个特殊情况,每列的所有行都被选中。在执行此操作时,我注意到值的轻微扰动。这是一个MWE。可以使用此处给出的 CSR 矩阵进行尝试。
from scipy import sparse
import numpy as np
ip_mat = sparse.load_npz('a_di_mat.npz')
# this is not useful for me in practice
# this is being done for comparison
lil_mat_direct = ip_mat.tolil()
csr_mat_direct = lil_mat_direct.tocsr()
# I need to copy column-by-column.
# this a MWE representing the special case where the entire column is copied
lil_mat_steps = sparse.lil_matrix((ip_mat.shape), dtype=np.float64)
for i_col in range(ip_mat.shape[1]):
lil_mat_steps[:, i_col] = ip_mat[:, i_col]
csr_mat_steps = lil_mat_steps.tocsr()
diff_mat = csr_mat_direct - csr_mat_steps
print('nnz: direct copy: {} columnwise copy: {} diff: {}'.format(
csr_mat_direct.nnz, csr_mat_steps.nnz, diff_mat.nnz))
# a colleague suggested the following
ind_x, ind_y = ip_mat.nonzero()
print('ip_mat: nonzero indices {} nnz {}'.format(len(ind_x), ip_mat.nnz))
在第一个打印语句中,人们期望:
nnz: direct copy: 2886100 columnwise copy: 2886100 diff: 0
然而,一个人获得:
nnz: direct copy: 2886100 columnwise copy: 2879757 diff: 0
差分矩阵全为零表明矩阵非常接近,如果不完全相同的话。如何解释非零数量的减少?这意味着非零值受到干扰。在原始矩阵中非常接近零的值的情况下,它们会受到干扰并在输出矩阵中变为零。恐怕这种扰动会发生在所有非零元素上,并可能影响更一般的情况,即每列只选择行的一个子集。
对于第二个打印语句,可以获得:
ip_mat: nonzero indices 2879757 nnz 2886100
那么,错误是否会妨碍.nnz
实施?按列复制是否删除了一些本来应该为零的值?
解决方案
我没有尝试遵循您的操作,但可以提出一些差异来源。一些操作(在 csr 上)只是将数据元素设置为 0,而不会将它们从稀疏结构中删除。稀疏矩阵将“非零”元素存储在几个数组中。 nnz
本质上报告这些数组的大小。
看代码nonzero
A = self.tocoo()
nz_mask = A.data != 0
return (A.row[nz_mask], A.col[nz_mask])
它进行了额外的data!=0
测试,因此可以不同于nnz
.
csr
还具有eliminate_zeros
就地清理稀疏性。此操作非常昂贵,csr
不会在您对矩阵执行任何操作时执行它。
所以是的,有可能有一个nnz
大于nonzero
计数的。对于csr
从“从头开始”创建的(即从密集数组或coo
样式输入),nnz
应该匹配nonzero
. 但是是从带有属性数组的文件ip_mat
中加载的。如果保存的 csr 不是“干净的”,则加载的 csr 也不是。npz
csr
插图
In [103]: from scipy import sparse
In [104]: M = sparse.csr_matrix([[1,0,0,2],[0,3,4,0]])
In [105]: M
Out[105]:
<2x4 sparse matrix of type '<class 'numpy.longlong'>'
with 4 stored elements in Compressed Sparse Row format>
In [106]: M.A
Out[106]:
array([[1, 0, 0, 2],
[0, 3, 4, 0]], dtype=int64)
In [107]: M.data
Out[107]: array([1, 2, 3, 4], dtype=int64)
修改元素:
In [108]: M[0,1] = 12
/usr/local/lib/python3.6/dist-packages/scipy/sparse/_index.py:84: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
self._set_intXint(row, col, x.flat[0])
In [109]: M.data
Out[109]: array([ 1, 12, 2, 3, 4], dtype=int64)
In [110]: M
Out[110]:
<2x4 sparse matrix of type '<class 'numpy.longlong'>'
with 5 stored elements in Compressed Sparse Row format>
In [111]: M.nnz
Out[111]: 5
In [112]: M[0,1] = 0 # data is set to 0, but indices does not change
In [113]: M
Out[113]:
<2x4 sparse matrix of type '<class 'numpy.longlong'>'
with 5 stored elements in Compressed Sparse Row format>
In [114]: M.data
Out[114]: array([1, 0, 2, 3, 4], dtype=int64)
打扫干净:
In [115]: M.eliminate_zeros()
In [116]: M
Out[116]:
<2x4 sparse matrix of type '<class 'numpy.longlong'>'
with 4 stored elements in Compressed Sparse Row format>
csr
从样式输入创建一个数组(数据为 0):
In [120]: M1 = sparse.csr_matrix(([1,0,2,3,4],[0,1,3,1,2],[0,3,5]))
In [121]: M1
Out[121]:
<2x4 sparse matrix of type '<class 'numpy.int64'>'
with 5 stored elements in Compressed Sparse Row format>
In [122]: M1.data
Out[122]: array([1, 0, 2, 3, 4])
In [123]: M1.nonzero()
Out[123]: (array([0, 0, 1, 1], dtype=int32), array([0, 3, 1, 2], dtype=int32))
In [124]: M1.eliminate_zeros()
In [125]: M1
Out[125]:
<2x4 sparse matrix of type '<class 'numpy.int64'>'
with 4 stored elements in Compressed Sparse Row format>
推荐阅读
- css - CSS背景重复多个图像
- python - 带有浮动索引的熊猫系列没有隐式索引?
- javascript - 如何将来自 HTML 页面的输入数据包含到 URL 中的参数中?
- html - 使用网格布局在列之间留出空间
- angular - Angular - pass variable to HTML
- java - Converting tree representing math expression to a string without redundant parentheses
- css - 如何将特定样式应用到此输入框
- jquery - 使用 jQuery + Ajax 加载表单结果
- video - WMF EVR stops sending MEStreamSinkRequestSample event ~7 seconds into the live stream
- python - SQLAlchemy "AttributeError: 'str' object has no attribute 'c'"