Python 稀疏coo_矩阵的Numpy高效构造或更快的列表扩展

Python 稀疏coo_矩阵的Numpy高效构造或更快的列表扩展,python,numpy,sparse-matrix,Python,Numpy,Sparse Matrix,我有一个10万个项目的列表,每个项目都有一个索引列表。我试着把它放到一个布尔稀疏矩阵中,用于向量乘法。我的代码没有我想要的那么快,所以我正在寻找性能提示,或者可能是将这些数据放入矩阵的替代方法 rows = [] cols = [] for i, item in enumerate(items): indices = item.getIndices() rows += [i]*len(indices) cols += indices data = np.ones(len

我有一个10万个项目的列表,每个项目都有一个索引列表。我试着把它放到一个布尔稀疏矩阵中,用于向量乘法。我的代码没有我想要的那么快,所以我正在寻找性能提示,或者可能是将这些数据放入矩阵的替代方法

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_矩阵占12%。统计数字占13%。我从line_profiler获得这些统计数据,我使用的是python 3.3。

许多稀疏矩阵算法在数据中运行两次,一次计算稀疏矩阵的大小,另一次用正确的值填充。因此,或许值得尝试以下内容:

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))
我所能做的就是:

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%。

那么平均物品大小是8?似乎你必须以某种方式迭代10万个项目?
getindex
的复杂程度如何?是的,平均项目大小为8。不幸的是,我确实需要反复阅读它们<代码>获取索引很简单,但需要大量时间。有一个值字典->索引和
getindex
返回
self.\u memberIndex[v]用于self.members中的v
。对于小问题(
len(items)
),您的方法更快,但对于100K项,速度较慢。这是一个快速的
getindex
函数(
item[:]
)。预先计算
total\u len
会付出代价,但重复索引也会付出代价。谢谢!我并没有看到速度提高了50%,但我的
getindex(item)
方法还是很费时的。通过将
CNT
更改为预先分配的ndarray,我还获得了一点速度提升。