Python Scipy稀疏矩阵-A[i,j]在做什么?

Python Scipy稀疏矩阵-A[i,j]在做什么?,python,matrix,scipy,sparse-matrix,Python,Matrix,Scipy,Sparse Matrix,根据我前面的问题()稀疏矩阵的直接索引是不可能的(至少如果您不想使用定义sparse.csr矩阵的三个数组,数据,索引,indptr)。 但是我刚刚发现,给定一个csr稀疏矩阵a,这个操作可以很好地工作并产生正确的结果:a[I,j]。 我还注意到:它非常慢,甚至比处理密集矩阵还要慢 我找不到关于这个索引方法的任何信息,所以我想知道:A[I,j]到底在做什么 如果你想让我猜一猜,我会说它正在生成一个稠密矩阵,然后像你通常会做的那样索引它 In [211]: M = sparse.csr_matri

根据我前面的问题()稀疏矩阵的直接索引是不可能的(至少如果您不想使用定义
sparse.csr
矩阵的三个数组,
数据
索引
indptr
)。 但是我刚刚发现,给定一个csr稀疏矩阵
a
,这个操作可以很好地工作并产生正确的结果:
a[I,j]
。 我还注意到:它非常慢,甚至比处理密集矩阵还要慢

我找不到关于这个索引方法的任何信息,所以我想知道:
A[I,j]
到底在做什么

如果你想让我猜一猜,我会说它正在生成一个稠密矩阵,然后像你通常会做的那样索引它

In [211]: M = sparse.csr_matrix(np.eye(3))                                   
In [212]: M                                                                  
Out[212]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in Compressed Sparse Row format>
A[0][1]
确实与
np.ndarray
一起工作,但这是因为第一个
[0]
生成的数组的维数小于1。但是
np.matrix
,和
sparse
返回一个2d矩阵,而不是1d矩阵。这是我们不推荐
np.matrix
的一个原因。使用
sparse
时,矩阵的性质会更深,因此我们不能简单地对其进行去润滑

通过触发错误,我们可以了解从稀疏矩阵中选择元素所涉及的代码:

In [216]: M[0,4]                                                             
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-216-4919ae565782> in <module>
----> 1 M[0,4]

/usr/local/lib/python3.6/dist-packages/scipy/sparse/csr.py in __getitem__(self, key)
    287             # [i, j]
    288             if isintlike(col):
--> 289                 return self._get_single_element(row, col)
    290             # [i, 1:2]
    291             elif isinstance(col, slice):

/usr/local/lib/python3.6/dist-packages/scipy/sparse/compressed.py in _get_single_element(self, row, col)
    868         if not (0 <= row < M) or not (0 <= col < N):
    869             raise IndexError("index out of bounds: 0<=%d<%d, 0<=%d<%d" %
--> 870                              (row, M, col, N))
    871 
    872         major_index, minor_index = self._swap((row, col))

IndexError: index out of bounds: 0<=0<3, 0<=4<3
要选择第0行,我们必须使用
indptr
从其他行中选择一个切片:

In [225]: slc = slice(M.indptr[0],M.indptr[1])                               
In [226]: M.data[slc], M.indices[slc]                                        
Out[226]: (array([1.]), array([0], dtype=int32))
然后要选择列1,我们必须检查该值是否在
索引[slc]
中。如果是,则返回
data[slc]
中的相应元素。如果不是,则返回0

对于更复杂的索引,稀疏实际上使用矩阵乘法,从索引中创建了一个
提取器
矩阵。它还使用乘法来执行行和或列和

矩阵乘法是一种稀疏矩阵强度-只要矩阵足够稀疏。稀疏格式的数学根,特别是csr,在稀疏线性方程问题中,如有限差分和有限元偏微分方程

===

以下是
lil
矩阵的基本属性

In [227]: ml=M.tolil()                                                       
In [228]: ml.data                                                            
Out[228]: array([list([1.0]), list([1.0]), list([1.0])], dtype=object)
In [229]: ml.rows                                                            
Out[229]: array([list([0]), list([1]), list([2])], dtype=object)
In [230]: ml.data[0],ml.rows[0]                                              
Out[230]: ([1.0], [0])          # cf Out[226]

是什么让你想到不能索引稀疏矩阵的?这样做通常是个坏主意,但这是很有可能的。@user2357112因为典型的
a[i][j]
给了我一个错误。但是
A[i,j]
有效-你知道它在做什么吗?
A[i][j]
不应该被认为是索引任何NumPy或SciPy数据结构的“典型”方法。它甚至不适用于规则矩阵,更不用说稀疏矩阵了。给定一个二维numpy数组
a
a[i][j]
(至少在我的系统上)确实是可能的。你介意告诉我为什么
A[i,j]
这么慢吗?至于
A[i,j]
,它给出行
i
和列
j
的值,就像常规矩阵或数组索引一样。它如何做到这一点因SciPy版本和稀疏矩阵格式而异,但它并没有具体化整个矩阵。那将是一种荒谬的浪费。您可以从中的相关
\uuuu getitem\uuuu
方法跟踪代码路径,但由于涉及到所有继承,您需要在文件之间跳转很多次。
In [216]: M[0,4]                                                             
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-216-4919ae565782> in <module>
----> 1 M[0,4]

/usr/local/lib/python3.6/dist-packages/scipy/sparse/csr.py in __getitem__(self, key)
    287             # [i, j]
    288             if isintlike(col):
--> 289                 return self._get_single_element(row, col)
    290             # [i, 1:2]
    291             elif isinstance(col, slice):

/usr/local/lib/python3.6/dist-packages/scipy/sparse/compressed.py in _get_single_element(self, row, col)
    868         if not (0 <= row < M) or not (0 <= col < N):
    869             raise IndexError("index out of bounds: 0<=%d<%d, 0<=%d<%d" %
--> 870                              (row, M, col, N))
    871 
    872         major_index, minor_index = self._swap((row, col))

IndexError: index out of bounds: 0<=0<3, 0<=4<3
In [224]: M.data,M.indices,M.indptr                                          
Out[224]: 
(array([1., 1., 1.]),
 array([0, 1, 2], dtype=int32),
 array([0, 1, 2, 3], dtype=int32))
In [225]: slc = slice(M.indptr[0],M.indptr[1])                               
In [226]: M.data[slc], M.indices[slc]                                        
Out[226]: (array([1.]), array([0], dtype=int32))
In [227]: ml=M.tolil()                                                       
In [228]: ml.data                                                            
Out[228]: array([list([1.0]), list([1.0]), list([1.0])], dtype=object)
In [229]: ml.rows                                                            
Out[229]: array([list([0]), list([1]), list([2])], dtype=object)
In [230]: ml.data[0],ml.rows[0]                                              
Out[230]: ([1.0], [0])          # cf Out[226]