我有一个键字典,其中每个值应该是一个巨大的稀疏矢量(~70万个元素,可能更多)。如何有效地增长/构建此数据结构。 现在我的实现仅适用于较小的尺寸。
myvec = defaultdict(list)
for id in id_data:
for item in item_data:
if item in item_data[id]:
myvec[id].append(item * 0.5)
else:
myvec[id].append(0)
上面的代码与大文件一起使用时会快速占用所有可用内存。我尝试删除myvec[id].append(0)
条件并仅存储非零值,因为每个myvec[id]
列表的长度是常量。这对我的大量测试文件起了很大的作用,但是我更愿意找到更好的方法。
我知道为此目的有不同类型的稀疏数组/矩阵,但我没有直觉哪一个更好。我尝试使用numpy包中的lil_matrix
而不是myvec
dict,但事实证明它比上面的代码慢得多。
所以问题基本上归结为以下两个问题:
是否可以在python中动态创建稀疏数据结构?
如何以合适的速度创建这种稀疏数据结构?
答案 0 :(得分:2)
附加到列表(或列表)总是比附加到numpy.array
或sparse
矩阵(将数据存储在几个numpy数组中)更快。当你必须逐步增长矩阵时,lil
应该是最快的,但它仍然比直接使用列表更慢。
Numpy数组具有固定大小。因此,np.append
函数实际上通过将旧数据与新数据连接来创建新数组。
如果你给我们一些数据,你的示例代码会更有用,所以我们剪切,粘贴和运行。
为简单起见,我们来定义
data_dict=dict(one=[1,0,2,3,0,0,4,5,0,0,6])
稀疏矩阵可以通过以下方式直接创建:
sparse.coo_matrix(data_dict['one'])
的属性是:
data: array([1, 2, 3, 4, 5, 6])
row: array([0, 0, 0, 0, 0, 0], dtype=int32)
col: array([ 0, 2, 3, 6, 7, 10], dtype=int32)
或
sparse.lil_matrix(id_data['one'])
data: array([[1, 2, 3, 4, 5, 6]], dtype=object)
rows: array([[0, 2, 3, 6, 7, 10]], dtype=object)
coo
版本的速度要快很多。
稀疏矩阵只保存非零数据,但它也必须保存索引。还有一种字典格式,它使用元组(row,col)
作为键。
增量构建的例子是:
llm = sparse.lil_matrix((1,11),dtype=int)
for i in range(11):
llm[0,i]=data_dict['one'][i]
对于这个小案例,这种增量方法更快。
我只通过向稀疏矩阵添加非零项来获得更好的速度:
llm = sparse.lil_matrix((1,11),dtype=int)
for i in range(11):
if data_dict['one'][i]!=0:
llm[0,i]=data_dict['one'][i]
我可以想象将其调整为默认的dict示例。您可以记录myvec[id].append(0)
值附加的位置(无论是在单独的列表中,还是通过item * 0.5
,而不是lil_matrix
。需要进行一些实验才能将此想法调整为默认字典。
所以基本上我们的目标是创建2个列表:
data = [1, 2, 3, 4, 5, 6]
cols = [ 0, 2, 3, 6, 7, 10]
是否从这些创建稀疏矩阵取决于您需要对数据做什么。