Python 稀疏coo_矩阵的Numpy高效构造或更快的列表扩展
我有一个10万个项目的列表,每个项目都有一个索引列表。我试着把它放到一个布尔稀疏矩阵中,用于向量乘法。我的代码没有我想要的那么快,所以我正在寻找性能提示,或者可能是将这些数据放入矩阵的替代方法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
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,我还获得了一点速度提升。