我有一个包含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))