如何加速构建一个非常大的稀疏矩阵,其中每一行只有一个非零元素对应一列,每列有一个相等数量(平均)的非零元素?
我有一个大小N1
的巨大(稀疏)矩阵 - 按 - N2
,例如大小为1e8
- 由 - 5e4
,其中每行包含只有一个非零元素是随机选择的,不会被numpy.random.choice(numpy.arange(N2),size=N2,replace=False)
替换。
据我所知,构建矩阵的唯一方法是在numpy.random.choice()
循环for
次运行N1
。由于N1
非常大,为了加快速度,我使用scipy.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
仍然,N1
接近1e6
并超出代码,需要很长时间才能完成。我怀疑可能有一种更有效的方法来构建稀疏矩阵。还有其他任何策略可以在人类可读的时间内加速和构建矩阵吗?
答案 0 :(得分:4)
您不应该weave
来提高效率。这是一个适合你的例子。我使用N1
和N2
的小值来轻松检查结果。我也使用了csr_matrix
,但任何scipy稀疏矩阵类型都应该在很少或没有变化的情况下工作。
In [50]: from scipy.sparse import csr_matrix
N1
,N2
和数组w
基本上是输入; w
是一个长度为N1
的数组。它包含将放在每一行中的值。在这里,我将w
填入1。
In [51]: N1 = 15
In [52]: N2 = 12
In [53]: w = np.empty(N1, dtype=int)
In [54]: w[:] = 1
现在创建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)
.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)
答案 1 :(得分:1)
因此,这里的速度问题可以重新构建为构建非常大的稀疏矩阵的有效问题。正如@Warren所指出的np.random.choice(np.arange(N2),size=N2,replace=False)
元素N1
仍然是一个随机排列问题。因此,经过一些思考后,上述内容的简明实现最终可能如下:
N1 = 10000000 #1e8
N2 = 5000
rows = np.arange(N1)
cols = (np.floor(np.random.permutation(N1)/float(N1)*N2)).astype(int) # Randomly pick N1 objects and assign to N2 categories in almost equal proportion
w = np.ones(N1)
conn_matrix = sparse.csr_matrix((w, (rows, cols)), shape=(N1, N2), dtype=int)