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

Python 2.7 快速构建非常大的稀疏矩阵,python-2.7,for-loop,scipy,sparse-matrix,Python 2.7,For Loop,Scipy,Sparse Matrix,如何加速构建一个非常大的稀疏矩阵,其中每行只有一个对应于列的非零元素,并且每列有相等数量(平均)的非零元素 我有一个巨大的(稀疏的)矩阵,大小为N1-by-N2,比如大小为1e8-by-5e4,其中每一行只包含一个非零元素,该元素是随机选择的,不需要替换为numpy.random.choice(numpy.arange(N2),size=N2,replace=False) 据我所知,构建矩阵的唯一方法是在循环N1中运行numpy.random.choice()。由于N1非常大,为了加快速度,我使

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

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

据我所知,构建矩阵的唯一方法是在
循环
N1
中运行
numpy.random.choice()
。由于
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
将numpy导入为np
从scipy进口织物
从scipy.weave导入转换器
导入scipy.sparse作为稀疏#Cython导入
def weave_稀疏(N1、N2、w):
conn_矩阵=稀疏的dok_矩阵((N1,N2))
fac=lambda N:np.random.choice(np.arange(N),size=N,replace=False)[0]
代码=”“
int i;
py::元组arg(1);
arg[0]=N2;

对于(i=0;i您不需要
weave
来提高效率。下面是一个适合您的示例。我使用了
N1
N2
的小值来轻松检查结果。我还使用了
csr\u矩阵
,但任何scipy稀疏矩阵类型都应该可以在很少或没有更改的情况下工作

In [50]: from scipy.sparse import csr_matrix
N1
N2
和数组
w
基本上都是输入;
w
是长度
N1
的数组。它保存将放入每行的值。这里,我用1填充
w

In [51]: N1 = 15

In [52]: N2 = 12

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

In [54]: w[:] = 1
现在创建
csr\u矩阵

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)

因此,这里的速度问题可以被重新描述为构建非常大的稀疏矩阵的有效问题。正如@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)

仅供参考:在问题文本中,你说的是
numpy.random.choice(numpy.arange(N2),size=N2,replace=False)
。这相当于
np.random.shuffle(np.arange(N2))
np.random.permutation(N2)
。在代码中你使用
np.random.choice(np.arange(N),size=N,replace=True)[0]
。这相当于
np.random.randint(0,N)
(为什么生成
size=N
,然后只取第一个元素?@Warren yes抱歉。代码中应该是
False
。谢谢@Warren。这正是我所寻找的方法。它让我走上了正确的道路。