scipy稀疏诊断矩阵构造中的错误

use*_*584 6 python scipy sparse-matrix

当使用scipy.sparse.spdiags或scipy.sparse.diags时,我注意到我希望我认为这是例程中的错误,例如

scipy.sparse.spdiags([1.1,1.2,1.3],1,4,4).toarray()
Run Code Online (Sandbox Code Playgroud)

回报

array([[ 0. ,  1.2,  0. ,  0. ],
       [ 0. ,  0. ,  1.3,  0. ],
       [ 0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

对于正对角线,它会丢弃第一个k数据.有人可能会说,这有一些宏大的编程原因,我只需要用零填充.好吧很烦人,可以使用scipy.sparse.diags来提供正确的结果.但是这个例程有一个无法解决的bug

scipy.sparse.diags([1.1,1.2],0,(4,2)).toarray()
Run Code Online (Sandbox Code Playgroud)

array([[ 1.1,  0. ],
       [ 0. ,  1.2],
       [ 0. ,  0. ],
       [ 0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

好和

scipy.sparse.diags([1.1,1.2],-2,(4,2)).toarray()
Run Code Online (Sandbox Code Playgroud)

array([[ 0. ,  0. ],
       [ 0. ,  0. ],
       [ 1.1,  0. ],
       [ 0. ,  1.2]])
Run Code Online (Sandbox Code Playgroud)

scipy.sparse.diags([1.1,1.2],-1,(4,2)).toarray()
Run Code Online (Sandbox Code Playgroud)

给出一个错误,说ValueError:对角线长度(偏移-1处的索引0:2)与矩阵大小(4,2)不一致.显然答案是

array([[ 0. ,  0. ],
       [ 1.1,  0. ],
       [ 0. ,  1.2],
       [ 0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

以及我们的额外随机行为

scipy.sparse.diags([1.1],-1,(4,2)).toarray()
Run Code Online (Sandbox Code Playgroud)

array([[ 0. ,  0. ],
       [ 1.1,  0. ],
       [ 0. ,  1.1],
       [ 0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

任何人都知道是否有一个函数来构造实际有效的对角稀疏矩阵?

hpa*_*ulj 2

执行摘要: spdiags即使矩阵输入不是最直观的,也能正常工作。 diags有一个错误会影响矩形矩阵中的某些偏移量。scipy github 上有一个错误修复。


的例子spdiags是:

>>> data = array([[1,2,3,4],[1,2,3,4],[1,2,3,4]])
>>> diags = array([0,-1,2])
>>> spdiags(data, diags, 4, 4).todense()
matrix([[1, 0, 3, 0],
        [1, 2, 0, 4],
        [0, 2, 3, 0],
        [0, 0, 3, 4]])
Run Code Online (Sandbox Code Playgroud)

请注意, 的第三列data始终出现在稀疏的第三列中。其他的柱子也排成一排。但它们在“脱离边缘”的地方被忽略了。

该函数的输入是一个矩阵,而输入diags是一个参差不齐的列表。稀疏矩阵的对角线都有不同数量的值。因此,规范必须以一种或另一种方式适应这一点。 spdiags通过忽略某些值并diags采用列表输入来实现此目的。

这个sparse.diags([1.1,1.2],-1,(4,2))错误令人费解。

等效spdiags的确实有效:

In [421]: sparse.spdiags([[1.1,1.2]],-1,4,2).A
Out[421]: 
array([[ 0. ,  0. ],
       [ 1.1,  0. ],
       [ 0. ,  1.2],
       [ 0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

此代码块中引发了错误:

for j, diagonal in enumerate(diagonals):
    offset = offsets[j]
    k = max(0, offset)
    length = min(m + offset, n - offset)
    if length <= 0:
        raise ValueError("Offset %d (index %d) out of bounds" % (offset, j))
    try:
        data_arr[j, k:k+length] = diagonal
    except ValueError:
        if len(diagonal) != length and len(diagonal) != 1:
            raise ValueError(
                "Diagonal length (index %d: %d at offset %d) does not "
                "agree with matrix size (%d, %d)." % (
                j, len(diagonal), offset, m, n))
        raise
Run Code Online (Sandbox Code Playgroud)

中实际的矩阵构造函数diags是:

dia_matrix((data_arr, offsets), shape=(m, n))
Run Code Online (Sandbox Code Playgroud)

这是使用相同的构造函数spdiags,但没有任何操作。

In [434]: sparse.dia_matrix(([[1.1,1.2]],-1),shape=(4,2)).A
Out[434]: 
array([[ 0. ,  0. ],
       [ 1.1,  0. ],
       [ 0. ,  1.2],
       [ 0. ,  0. ]])
Run Code Online (Sandbox Code Playgroud)

dia格式上,输入完全按照给定的方式存储spdiags(包含带有额外值的矩阵):

In [436]: M.data
Out[436]: array([[ 1.1,  1.2]])
In [437]: M.offsets
Out[437]: array([-1], dtype=int32)
Run Code Online (Sandbox Code Playgroud)

正如所@user2357112指出的,在测试用例中length = min(m + offset, n - offset生成是错误的。3将其更改为length = min(m + k, n - k)使该 (4,2) 矩阵的所有情况都有效。但转置失败:diags([1.1,1.2], 1, (2, 4))

截至 10 月 5 日,该问题的更正如下:

https://github.com/pv/scipy-work/commit/529cbde47121c8ed87f74fa6445c05d71353eb6c

length = min(m + offset, n - offset, min(m,n))
Run Code Online (Sandbox Code Playgroud)

通过此修复,diags([1.1,1.2], 1, (2, 4))可以工作。