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]