快速构建非常大的稀疏矩阵

mau*_*zio 2 for-loop scipy sparse-matrix python-2.7

如何加速构造一个非常大的稀疏矩阵,其中每行只有一个非零元素对应于一列,并且每列有相同数量(平均)的非零元素?

N1我有一个大小为×的巨大(稀疏)矩阵N2,例如大小为1e8× 5e4,其中每一行仅包含一个非零元素,该元素是随机选择的,而不用 替换numpy.random.choice(numpy.arange(N2),size=N2,replace=False)

据我所知,构建矩阵的唯一方法是循环numpy.random.choice()运行。由于非常大,为了加快速度,我正在使用:forN1N1scipy.weave

import numpy as np
from scipy import weave
from scipy.weave import converters
import scipy.sparse as sparse # Cython import

def weave_sparse(N1,N2,w):
    conn_matrix = sparse.dok_matrix((N1,N2))
    fac = lambda N : np.random.choice(np.arange(N), size=N, replace=False)[0]
    code = """
           int i;
           py::tuple arg(1);
           arg[0] = N2;
           for(i=0;i<N1;i++) conn_matrix[i,(int) fac.call(arg)] = w;
           """
    weave.inline(code,['conn_matrix','N1','N2', 'w', 'fac'],
                 compiler='gcc',extra_compile_args=['-std=c++11 -Ofast'],force=0)
    return conn_matrix
Run Code Online (Sandbox Code Playgroud)

尽管如此,对于N1接近1e6和超越代码来说,它需要很长时间才能完成。我怀疑可能有一种更有效的方法来构建稀疏矩阵。还有其他策略可以在人类可读的时间内加速和构建矩阵吗?

War*_*ser 5

您不需要weave提高效率。这是一个应该适合您的示例。我使用了较小的N1和值N2以便于检查结果。我也使用了csr_matrix,但任何 scipy 稀疏矩阵类型都应该在很少或没有变化的情况下工作。

In [50]: from scipy.sparse import csr_matrix
Run Code Online (Sandbox Code Playgroud)

N1N2数组w基本上是输入;w是一个长度为 的数组N1。它保存将放入每行的值。这里我填w1。

In [51]: N1 = 15

In [52]: N2 = 12

In [53]: w = np.empty(N1, dtype=int)

In [54]: w[:] = 1
Run Code Online (Sandbox Code Playgroud)

现在创建csr_matrix

In [55]: rows = np.arange(N1)

In [56]: cols = np.random.randint(0, N2, size=N1)

In [57]: conn_matrix = csr_matrix((w, (rows, cols)), shape=(N1, N2), dtype=int)
Run Code Online (Sandbox Code Playgroud)

属性.A只是.toarray()方法的快捷方式;它返回一个常规的 numpy 数组:

In [58]: conn_matrix.A
Out[58]: 
array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], dtype=int64)
Run Code Online (Sandbox Code Playgroud)