如何在 python 中有效地创建一个稀疏向量?
How to efficiently create a sparse vector in python?
我有一个键字典,其中每个值都应该是一个巨大的稀疏向量(约 700000 个元素,也许更多)。我如何有效地增长/构建这个数据结构。
现在我的实现只适用于较小的尺寸。
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]
列表的长度是恒定的。这对我的巨大测试文件有效,但内存消耗不错,但我宁愿找到更好的方法。
我知道有不同类型的稀疏 arrays/matrices 用于此目的,但我不知道哪一种更好。我尝试使用 numpy 包中的 lil_matrix
而不是 myvec
dict,但事实证明它比上面的代码慢得多。
所以问题基本上归结为以下两个问题:
是否可以在 python 中即时创建稀疏数据结构 ?
如何以相当快的速度创建这样的稀疏数据结构?
追加到一个列表(或多个列表)总是比追加到一个 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]
我可以想象将其改编为您的默认字典示例。您可以记录附加 item * 0.5
值的位置,而不是 myvec[id].append(0)
(无论是在单独的列表中,还是通过 lil_matrix
。需要进行一些试验才能使这个想法适应默认字典。
所以基本上目标是创建 2 个列表:
data = [1, 2, 3, 4, 5, 6]
cols = [ 0, 2, 3, 6, 7, 10]
是否根据这些创建稀疏矩阵取决于您还需要对数据做什么。
我有一个键字典,其中每个值都应该是一个巨大的稀疏向量(约 700000 个元素,也许更多)。我如何有效地增长/构建这个数据结构。 现在我的实现只适用于较小的尺寸。
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]
列表的长度是恒定的。这对我的巨大测试文件有效,但内存消耗不错,但我宁愿找到更好的方法。
我知道有不同类型的稀疏 arrays/matrices 用于此目的,但我不知道哪一种更好。我尝试使用 numpy 包中的 lil_matrix
而不是 myvec
dict,但事实证明它比上面的代码慢得多。
所以问题基本上归结为以下两个问题:
是否可以在 python 中即时创建稀疏数据结构 ?
如何以相当快的速度创建这样的稀疏数据结构?
追加到一个列表(或多个列表)总是比追加到一个 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]
我可以想象将其改编为您的默认字典示例。您可以记录附加 item * 0.5
值的位置,而不是 myvec[id].append(0)
(无论是在单独的列表中,还是通过 lil_matrix
。需要进行一些试验才能使这个想法适应默认字典。
所以基本上目标是创建 2 个列表:
data = [1, 2, 3, 4, 5, 6]
cols = [ 0, 2, 3, 6, 7, 10]
是否根据这些创建稀疏矩阵取决于您还需要对数据做什么。