2015-08-09 154 views
0

在Python 3中,我试图运行下面的代码行来获取特定的稀疏矩阵。来自sparse.spdiags()的意外错误

sparse.spdiags(np.concatenate((-np.ones((9,1)), np.ones((9,1))), axis=1), [0, 1], 9, 10)

这提供了以下错误信息:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3/dist-packages/scipy/sparse/construct.py", line 61, in spdiags 
    return dia_matrix((data, diags), shape=(m,n)).asformat(format) 
    File "/usr/lib/python3/dist-packages/scipy/sparse/dia.py", line 138, in __init__ 
    % (self.data.shape[0], len(self.offsets))) 
ValueError: number of diagonals (9) does not match the number of offsets (2) 

运行我的理解是在八度等价代码似乎让我稀疏矩阵。

spdiags([-ones(9,1) ones(9,1)],[0 1],9,10) 

Compressed Column Sparse (rows = 9, cols = 10, nnz = 18 [20%]) 

(1, 1) -> -1 
(1, 2) -> 1 
(2, 2) -> -1 
(2, 3) -> 1 
(3, 3) -> -1 
(3, 4) -> 1 
(4, 4) -> -1 
(4, 5) -> 1 
(5, 5) -> -1 
(5, 6) -> 1 
(6, 6) -> -1 
(6, 7) -> 1 
(7, 7) -> -1 
(7, 8) -> 1 
(8, 8) -> -1 
(8, 9) -> 1 
(9, 9) -> -1 
(9, 10) -> 1 

为什么他们都表现不同,以及如何解决它的任何想法?

我在与Scipy.sparse的输出VS八度的另外一个问题的补充。

PYTHON

>>> sparse.spdiags(np.concatenate((-np.ones((9,1)),np.ones((9,1))), axis=1).T, [0,1],9,10).A 
array([[-1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., -1., 1., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., -1., 1., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., -1., 1., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., -1., 1., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., -1., 1., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., -1., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., -1., 1., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., -1., 0.]]) 

>>> sparse.spdiags(np.concatenate((-np.ones((9,1)),np.ones((9,1))), axis=1).T, [0,1],9,10).A.shape              
(9, 10) 

>>> sparse.spdiags(np.vstack([-np.ones(9),np.ones(9)]), [0,1],9,10).A       
array([[-1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., -1., 1., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., -1., 1., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., -1., 1., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., -1., 1., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., -1., 1., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., -1., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., -1., 1., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., -1., 0.]]) 

>>> sparse.spdiags(np.vstack([-np.ones(9),np.ones(9)]), [0,1],9,10).A.shape 
(9, 10) 

>>> sparse.spdiags(np.ones(9)*[[-1],[1]], [0,1],9,10).A 
array([[-1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., -1., 1., 0., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., -1., 1., 0., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., -1., 1., 0., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., -1., 1., 0., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., -1., 1., 0., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., -1., 1., 0., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., -1., 1., 0.], 
    [ 0., 0., 0., 0., 0., 0., 0., 0., -1., 0.]]) 

>>> sparse.spdiags(np.ones(9)*[[-1],[1]], [0,1],9,10).A.shape 
(9, 10) 

OCTAVE

>full(spdiags([-ones(9,1) ones(9,1)],[0 1],9,10)) 
ans = 

    -1 1 0 0 0 0 0 0 0 0 
    0 -1 1 0 0 0 0 0 0 0 
    0 0 -1 1 0 0 0 0 0 0 
    0 0 0 -1 1 0 0 0 0 0 
    0 0 0 0 -1 1 0 0 0 0 
    0 0 0 0 0 -1 1 0 0 0 
    0 0 0 0 0 0 -1 1 0 0 
    0 0 0 0 0 0 0 -1 1 0 
    0 0 0 0 0 0 0 0 -1 1 

>size(full(spdiags([-ones(9,1) ones(9,1)],[0 1],9,10))) 
ans = 

9 10 

为什么SciPy的和倍频不是在最后一排的最后一列给出相同的价值呢?

回答

1

concatenate你产生(9,2)矩阵:

In [310]: np.concatenate((-np.ones((9,1)), np.ones((9,1))), axis=1) 
Out[310]: 
array([[-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.], 
     [-1., 1.]]) 

In [311]: _.shape 
Out[311]: (9, 2) 

spdiags文档描述此data参数作为matrix diagonals stored row-wise。也就是说,矩阵的每一行对应于对角线。 9行,但在[0,1]中只有2个值。

这是一个重要的区别,我在前面的回答中提到过,但也许我没有足够强调它。

如果你想2条对角线,你需要给它一个(2,9)阵列,比如这个矩阵的转置:

In [317]: sparse.spdiags(np.concatenate((-np.ones((9,1)), 
    np.ones((9,1))), axis=1).T, [0,1],9,10) 
Out[317]: 
<9x10 sparse matrix of type '<class 'numpy.float64'>' 
    with 18 stored elements (2 diagonals) in DIAgonal format> 

你也可以构建对角线用:

In [321]: np.concatenate([-np.ones((1,9)), np.ones((1,9))],axis=0) 
Out[321]: 
array([[-1., -1., -1., -1., -1., -1., -1., -1., -1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1., 1.]]) 

或者np.vstack([-np.ones(9),np.ones(9)])np.ones(9)*[[-1],[1]]


看看我以前的答案,但改变的最终形状,使比行更多的列):

octave:17> reshape (1:12, 4, 3) 
ans = 
    1 5 9 
    2 6 10 
    3 7 11 
    4 8 12 

octave:18> full(spdiags (reshape (1:12, 4, 3), [-1 0 1], 4,5)) 
ans = 
    5 9 0 0 0 
    1 6 10 0 0 
    0 2 7 11 0 
    0 0 3 8 12 

In [327]: np.arange(1,13).reshape(3,4) 
Out[327]: 
array([[ 1, 2, 3, 4], 
     [ 5, 6, 7, 8], 
     [ 9, 10, 11, 12]]) 

In [328]: sparse.spdiags(np.arange(1,13).reshape(3,4), [-1, 0, 1], 4,5).A 
Out[328]: 
array([[ 5, 10, 0, 0, 0], 
     [ 1, 6, 11, 0, 0], 
     [ 0, 2, 7, 12, 0], 
     [ 0, 0, 3, 8, 0]]) 

在八度(大概MATLAB)+1对角线开始与9,两端12,输入矩阵的最后一列。看看[2,6,10] - 以直角排列。

scipy对角线从10开始,以加上0结束。9在上面不存在的行中不可见。看看[2,6,10] - 在一列中。

他们都是一致的 - 以他们自己的方式。因此,至少当列数多于行数时,创建输入矩阵时需要考虑差异。

另一个scipy函数采用模糊了,待加入每个对角线元素的正确数目(名单列表):

In [337]: sparse.diags([[1,2,3],[5,6,7,8],[9,10,11,12]],[-1,0,1],(4,5),dtype=int).A 
Out[337]: 
array([[ 5, 9, 0, 0, 0], 
     [ 1, 6, 10, 0, 0], 
     [ 0, 2, 7, 11, 0], 
     [ 0, 0, 3, 8, 12]]) 

注意,我不得不省略4

看在scipy/sparse/dia.pytocoo方法,进一步了解如何dia_matrix对角线数据映射到稀疏的坐标(coo格式)。