以下是我尝试创建一个以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
答案 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.matrix
或sparse
实施(并且实际上并不需要,因为它们总是为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)