Numpy高效的稀疏coo_matrix构造或更快的列表扩展



我有一个包含100k个项目的列表,每个项目都有一个索引列表。我试着把它变成一个布尔稀疏矩阵用于向量乘法。我的代码没有像我想的那样运行得那么快,所以我正在寻找性能提示,或者可能是将这些数据转换为矩阵的替代方法。

rows = []
cols = []
for i, item in enumerate(items):
    indices = item.getIndices()
    rows += [i]*len(indices)
    cols += indices
data = np.ones(len(rows), dtype='?')
mat = coo_matrix(data,(rows,cols)),shape=(len(items),totalIndices),dtype='?')
mat = mat.tocsr()

在rows/cols列表中有800k个项目,仅这些列表的扩展似乎就占用了16%和13%的构建时间。转换为coo_matrix则需要12%的时间。人口普查占13%。我从line_profiler得到了这些统计数据,我使用python 3.3。

我只能:

def foo3(items,totalIndices):
    N = len(items)
    cols=[]
    cnts=[]
    for item in items:
        indices = getIndices(item)
        cols += indices
        cnts.append(len(indices))
    rows = np.arange(N).repeat(cnts) # main change
    data = np.ones(rows.shape, dtype=bool)
    mat = sparse.coo_matrix((data,(rows,cols)),shape=(N,totalIndices))
    mat = mat.tocsr()
    return mat

对于100000项,速度只增加50%。

很多稀疏矩阵算法会对数据运行两次,一次计算出稀疏矩阵的大小,另一次用正确的值填充它。因此,也许值得尝试这样做:

total_len = 0
for item in items:
    total_len += len(item.getIndices())
rows = np.empty((total_len,), dtype=np.int32)
cols = np.empty((total_len,), dtype=np.int32)
total_len = 0
for i, item in enumerate(items):
    indices = item.getIndices()
    len_ = len(indices)
    rows[total_len:total_len + len_] = i
    cols[total_len:total_len + len_] = indices
    total_len += len_

后面跟着你正在做的事情。您也可以直接构建CSR矩阵,避免构建COO矩阵,这也会节省一些时间。在第一次运行后找出总大小,您可以这样做:

indptr = np.empty((len(items) + 1,), dtype=np.int32)
indptr[0] = 0
indices = np.empty((total_len,), dtype=np.int32)
for i, item in enumerate(items):
    item_indices = item.getIndices()
    len_ = len(item_indices)
    indptr[i+1] = indptr[i] + len_
    indices[indptr[i]:indptr[i+1]] = item_indices
data = np.ones(total_len,), dtype=np.bool)
mat = csr_matrix((data, indices, indptr))

最新更新