繁体   English   中英

如何在 Python Scipy 稀疏 COO(坐标格式)矩阵中保留显式零值?

[英]How to Retain Expicit Zero Values in a Python Scipy Sparse COO (Coordinate Format) Matrix?

我创建了一个 COO 矩阵,数据数组中的值为零。 当我查询新的 COO 矩阵数据数组时,我可以在数组中看到那些零值。 但是,我无法获得那些零值的索引。 我使用 nonzero() 方法来检索索引,并且缺少那些零值的索引。 有谁知道如何获得这些零值的索引? 如果不是,这是 COO 代码中的错误吗?

下面是重现问题的示例代码。 最后的断言是假的,因为值的数量是七个,但只有六个非零索引。 我知道非零显然不包括我的零值,但有没有办法使用另一种类似的方法来获得明确的零值?

sparse_simple = sp.coo_matrix(
    [
        [1.1, 0, 1.1],
        [0, 1.1, 4.1],
        [1.1, 4.1, 1.1]
    ]
)

sparse_simple_data = sparse_simple.data
sparse_simple_nz = sparse_simple.nonzero()
sparse_simple_data[1] = 0
(n_rows, n_cols) = sparse_simple.shape
sparse_simple_with_explicit_close_to_zero = sp.coo_matrix(
    (sparse_simple_data, (sparse_simple_nz[0], sparse_simple_nz[1])),
    shape=(n_rows, n_cols)
)
num_explicit_vals = len(sparse_simple_with_explicit_close_to_zero.data)
nz_idcs = sparse_simple_with_explicit_close_to_zero.nonzero()
num_nzs = len(nz_idcs[0])

assert num_explicit_vals == num_nzs

我试图在 Scipy sparse arrays 的文档中找到另一种方法来提取值的索引,包括非零值,但没有找到任何东西。

我有一个修复程序,但这有点麻烦。 我只是将一个小数字添加到数据数组中的所有 nvalues,然后这个“工作”。

通过将其添加到上面创建 COO 矩阵的行中,这将识别“零”值,该值现在是一个非常小的值。 我用这个修复了我的代码,但我不喜欢它。

sparse_simple.data += 0.1e-09
In [1]: import numpy as np
In [2]: from scipy import sparse

您的样本矩阵:

In [3]: sparse_simple = sparse.coo_matrix(
   ...:     [
   ...:         [1.1, 0, 1.1],
   ...:         [0, 1.1, 4.1],
   ...:         [1.1, 4.1, 1.1]
   ...:     ]
   ...: )

In [4]: sparse_simple
Out[4]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in COOrdinate format>

您已经摆弄了data属性; 这是其他的:

In [5]: sparse_simple.data, sparse_simple.row, sparse_simple.col
Out[5]: 
(array([1.1, 1.1, 1.1, 4.1, 1.1, 4.1, 1.1]),
 array([0, 0, 1, 1, 2, 2, 2], dtype=int32),
 array([0, 2, 1, 2, 0, 1, 2], dtype=int32))

添加你的“显式”0; 不改变矩阵的“稀疏性”:

In [6]: sparse_simple.data[1] = 0; sparse_simple
Out[6]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in COOrdinate format>

In [7]: sparse_simple.A
Out[7]: 
array([[1.1, 0. , 0. ],
       [0. , 1.1, 4.1],
       [1.1, 4.1, 1.1]])

但是nonzero ,顾名思义,不包括这个明确的 0:

In [8]: sparse_simple.nonzero()
Out[8]: 
(array([0, 1, 1, 2, 2, 2], dtype=int32),
 array([0, 1, 2, 0, 1, 2], dtype=int32))

如果我们查看代码,我们就会明白为什么:

In [9]: sparse_simple.nonzero??
Signature: sparse_simple.nonzero()
Source:   
    def nonzero(self):
        """nonzero indices

        Returns a tuple of arrays (row,col) containing the indices
        of the non-zero elements of the matrix.
        """

        # convert to COOrdinate format
        A = self.tocoo()
        nz_mask = A.data != 0
        return (A.row[nz_mask], A.col[nz_mask])

它以“原始”coo 属性开始,但删除了所有“显式”0——所以我们只得到非零值,而不是非零值加上“显式”0。

稀疏矩阵也有一个就地方法来“清除”显式 0:

In [24]: sparse_simple.eliminate_zeros??
Signature: sparse_simple.eliminate_zeros()
Source:   
    def eliminate_zeros(self):
        """Remove zero entries from the matrix

        This is an *in place* operation
        """
        mask = self.data != 0
        self.data = self.data[mask]
        self.row = self.row[mask]
        self.col = self.col[mask]

我已经看到它更多地用于csr格式。 改变这种格式的稀疏性相对昂贵,所以创建显式 0 的操作不会在它们自己之后“清理”; 我们可以之后再做。

请注意coo格式不能被索引,例如sparse_simple[0,1]返回错误。 csr格式可以。

因此,虽然可以创建带有显式 0 的矩阵,但这些矩阵以其他方式被视为异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM