Scipy Sparse:意外的身份行为

时间:2015-03-17 15:44:40

标签: python scipy

以下是我尝试创建一个以c为对角线的稀疏矩阵。我知道还有替代方法,但我很好奇为什么以下代码没有按预期工作:

import numpy as np
import scipy.sparse as sparse

c = np.arange(0,5)
>>> np.identity(5)*c
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  2.,  0.,  0.],
       [ 0.,  0.,  0.,  3.,  0.],
       [ 0.,  0.,  0.,  0.,  4.]])
>>> sparse.identity(5)*c
array([ 0.,  1.,  2.,  3.,  4.])
#expected output:
<5x5 sparse matrix of type '<type 'numpy.float64'>'
with 5 stored elements (1 diagonals) in DIAgonal format>
# and (sparse.identity(5)*c).todense() == np.identity(5)*c

2 个答案:

答案 0 :(得分:1)

在表达式sparse.identity(5)*c中,使用稀疏矩阵的乘法运算符,即代数矩阵乘法(即矩阵乘以向量给出向量)。

您可以使用scipy.sparse.diags创建具有给定对角线的稀疏对角矩阵:

In [18]: from scipy import sparse

In [19]: c = np.arange(5)

In [20]: d = sparse.diags(c, 0)

In [21]: d
Out[21]: 
<5x5 sparse matrix of type '<type 'numpy.float64'>'
    with 5 stored elements (1 diagonals) in DIAgonal format>

In [22]: d.A
Out[22]: 
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  2.,  0.,  0.],
       [ 0.,  0.,  0.,  3.,  0.],
       [ 0.,  0.,  0.,  0.,  4.]])

答案 1 :(得分:1)

有两种常见的数组乘法类型,逐元素和矩阵。

在MATLAB中,*是矩阵版本,.*是元素1的元素。

在numpy中,*是逐个元素(有广播),&#39; np.dot&#39;是矩阵乘法的基本形式。 Python开发人员已批准@作为可用于矩阵乘法(最终)的运算符。

对于numpy matrix子类,*是矩阵乘法,np.multiply用于逐个元素。 (np.multiply也适用于ndarray。)

scipy遵循np.matrix约定。 *是矩阵乘法。 sparse.identity(5).multiply(c)按元素乘法进行元素处理(尽管它返回np.matrix,而不是稀疏元素。)

至于为什么,它归结为开发人员习惯的惯例。对于线性代数问题,矩阵乘法很常见,因此它在sparse中使用。 np.matrix复制MATLAB约定。创建MATLAB是为了访问FORTRAN矩阵库。

在物理学中还有另一种惯例,即爱因斯坦符号。这是一个广义矩阵乘法,扩展到更多维度。 np.einsum这样做。它可以逐元素地实现,虽然它的核心是它使用了一个“产品和”的总和。方法。但它尚未针对np.matrixsparse实施(并且实际上并不需要,因为它们总是为2d)。

请注意您的示例的规范有多相似

np.einsum('ij,j->ij',np.identity(5),c) # element by element
np.einsum('ij,j->i',np.identity(5),c)  # matrix (sum on j)
相关问题