【问题标题】:Accessing non-zero elements in specific row of matrix in python在python中访问特定行矩阵中的非零元素
【发布时间】:2015-11-05 12:26:01
【问题描述】:

我在 python 中的稀疏矩阵中具有非零元素位置的索引,格式为

(array([0, 1, 2], dtype=int32), array([2, 0, 0], dtype=int32), array([2, 1, 3]))

或矩阵形式

[[0 2]
 [1 0]
 [2 0]]

我想使用这个(或其他方法,如果有的话)只使用其他矩阵的相应非零元素执行逐行操作,如下所示:

for r in range(rows):
    A[r,:] = np.dot(B[r,:],C.T)

基本上我需要一种方法来指定行,并且只从该行中选择与矩阵 B 中的非零元素相对应的元素。

我无法理解的部分是因为每行/列可能有不同数量的条目。

【问题讨论】:

  • 只使用非零元素如何改变最终答案?
  • 您已经设置了scipysparse-matrix 标签。这是否意味着您打算使用scipy.sparse 矩阵?他们可以进行矩阵乘法(在编译代码中)。
  • 问题是矩阵 B 稀疏而巨大,随后 A 和 C 会很大,因此为了提高效率,我只想完成与非零元素的乘法。零元素比非零元素多得多。我认为解决方案可能涉及 scipy.sparse 但不确定并且愿意接受想法!
  • np.nonzero 为您提供非零元素的索引。但即使您知道这些元素的索引,在 AB 中对它们进行索引也会比将零元素相乘更损害效率。
  • 这种索引是否真的提高了 MATLAB 的速度?如果密度为 0.01 或更小,则可能。但几年前,我使用 MATLAB 稀疏矩阵进行有限元计算。但 sparse 与其说是速度工具,不如说是一种节省内存的工具。

标签: python numpy matrix scipy sparse-matrix


【解决方案1】:

我对第一个元组代表什么感到有些困惑。它是稀疏数组的索引和值吗?例如

In [4]: arrays=(np.array([0, 1, 2], dtype=int), np.array([2, 0, 0], dtype=int), np.array([2, 1, 3], dtype=float))
...
In [6]: from scipy import sparse
In [7]: M=sparse.csr_matrix((arrays[2],(arrays[0],arrays[1])))
In [8]: M
Out[8]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in Compressed Sparse Row format>
In [9]: M.A
Out[9]: 
array([[ 0.,  0.,  2.],
       [ 1.,  0.,  0.],
       [ 3.,  0.,  0.]])

In [10]: print(M)
  (0, 2)    2.0
  (1, 0)    1.0
  (2, 0)    3.0

为这样的数组定义了矩阵乘法:

In [12]: M*M.T
Out[12]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements in Compressed Sparse Row format>
In [13]: (M*M.T).A
Out[13]: 
array([[ 4.,  0.,  0.],
       [ 0.,  1.,  3.],
       [ 0.,  3.,  9.]])
In [14]: M.A.dot(M.A.T)  # dense equivalent
Out[14]: 
array([[ 4.,  0.,  0.],
       [ 0.,  1.,  3.],
       [ 0.,  3.,  9.]])

我可以用这个数组实现逐行乘法:

In [21]: A=M.A      # dense array
In [22]: for r in range(3):
    print(np.dot(A[r,:],A[r,:]))
4.0
1.0
9.0
# actually this is just the diagonal

In [23]: for r in range(3):   # or with the nonzero elements
    I=np.nonzero(A[r,:])
    dot = np.dot(A[r,I[0]],A[r,I[0]])
    print(dot)
4.0
1.0
9.0

对于它的价值,nonzero 返回我在开始时从您的帖子中复制的数组:

In [24]: np.nonzero(A)
Out[24]: (array([0, 1, 2], dtype=int32), array([2, 0, 0], dtype=int32))
In [25]: A[np.nonzero(A)]
Out[25]: array([ 2.,  1.,  3.])

稀疏矩阵还有一个nonzero方法:

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

我觉得我在挣扎,试图理解这个问题和例子。

【讨论】:

    【解决方案2】:

    我发现你可以在 python 中使用布尔数组索引,所以以下是我想要实现的:

    for r in range(rows):
        A[r,B[r,:]!=0] = np.dot(B[r , B[r,:]!=0], C[: , B[r,:]!=0].T)
    

    看起来有点复杂,但它得到了正确的计算元素。唯一的问题是当 B 的维度大于它的索引时,会引发索引越界错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多