首页 文章

NumPy矩阵到SciPy稀疏矩阵:添加标量最安全的方法是什么?

提问于
浏览
2

首先,我不是数学家 . 我承认 . 然而,我仍然需要理解ScyPy的稀疏矩阵是如何算术运算的,以便在我必须处理的应用程序中从密集的NumPy矩阵切换到SciPy稀疏矩阵 . 问题是内存使用情况 . 大密集矩阵将消耗大量内存 .

有争议的公式部分是将矩阵添加到标量的位置 .

A = V + x

其中V是一个方阵(它的大,比如60,000 x 60,000)并且人口稀少 . x是一个浮点数 .

使用NumPy的操作(如果我没有记错的话)将v添加到V中的每个字段 . 如果我完全偏离基数,请告诉我,并且x将仅添加到V中的非零值 .

使用SciPy,并非所有稀疏矩阵都支持相同的功能,如标量添加 . dok_matrix(Keys of Keys)支持标量添加,但看起来(实际上)它正在分配每个矩阵条目,有效地将我的稀疏dok_matrix渲染为具有更多开销的密集矩阵 . (不好)

其他矩阵类型(CSR,CSC,LIL)不支持标量添加 .

我可以尝试构建一个标量值为x的完整矩阵,然后将其添加到V.我对矩阵类型没有任何问题,因为它们似乎都支持矩阵加法 . 但是我不得不耗费大量的内存来构造x作为矩阵,并且添加的结果也可能最终成为完全填充的矩阵 .

必须有另一种方法来做到这一点,不需要分配100%的稀疏矩阵 .

我愿意接受需要大量内存,但我想我会首先寻求一些建议 . 谢谢 .

1 回答

  • 5

    不可否认,稀疏矩阵并不是我的驾驶室,但ISTM最好的前进方式取决于矩阵类型 . 如果你是DOK:

    >>> S = dok_matrix((5,5))
    >>> S[2,3] = 10; S[4,1] = 20
    >>> S.todense()
    matrix([[  0.,   0.,   0.,   0.,   0.],
            [  0.,   0.,   0.,   0.,   0.],
            [  0.,   0.,   0.,  10.,   0.],
            [  0.,   0.,   0.,   0.,   0.],
            [  0.,  20.,   0.,   0.,   0.]])
    

    然后你可以更新:

    >>> S.update(zip(S.keys(), np.array(S.values()) + 99))
    >>> S
    <5x5 sparse matrix of type '<type 'numpy.float64'>'
        with 2 stored elements in Dictionary Of Keys format>
    >>> S.todense()
    matrix([[   0.,    0.,    0.,    0.,    0.],
            [   0.,    0.,    0.,    0.,    0.],
            [   0.,    0.,    0.,  109.,    0.],
            [   0.,    0.,    0.,    0.,    0.],
            [   0.,  119.,    0.,    0.,    0.]])
    

    不是特别高效,但是O(非零) .

    OTOH,如果你有类似COO,CSC或CSR的东西,你可以直接修改 data 属性:

    >>> C = S.tocoo()
    >>> C
    <5x5 sparse matrix of type '<type 'numpy.float64'>'
        with 2 stored elements in COOrdinate format>
    >>> C.data
    array([ 119.,  109.])
    >>> C.data += 1000
    >>> C
    <5x5 sparse matrix of type '<type 'numpy.float64'>'
        with 2 stored elements in COOrdinate format>
    >>> C.todense()
    matrix([[    0.,     0.,     0.,     0.,     0.],
            [    0.,     0.,     0.,     0.,     0.],
            [    0.,     0.,     0.,  1109.,     0.],
            [    0.,     0.,     0.,     0.,     0.],
            [    0.,  1119.,     0.,     0.,     0.]])
    

    请注意,您可能想要添加其他内容

    >>> C.eliminate_zeros()
    

    处理你现在正在记录的 0 的可能性 . 它本身应该可以正常工作,但是下次你做了 C.data += some_number 技巧时,它会将 somenumber 添加到你引入的零点 .

相关问题