numpy 如何在Python中有效地增加稀疏向量的大小?

rta7y2nd  于 2023-05-17  发布在  Python
关注(0)|答案(1)|浏览(137)

我有一个键的字典,其中每个值都应该是一个巨大的稀疏向量(~ 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]列表的长度是恒定的。这在我的巨大的测试文件上工作,内存消耗相当可观,但我宁愿找到一个更好的方法来做。
我知道有不同类型的稀疏数组/矩阵用于此目的,但我没有直觉哪一个更好。我尝试使用numpy包中的lil_matrix而不是myvec dict,但结果比上面的代码慢得多。
所以这个问题基本上可以归结为以下两个问题:
1.在python中是否可以创建一个稀疏的数据结构 on the fly
1.如何以相当快的速度创建这样的稀疏数据结构?

flseospp

flseospp1#

追加到一个列表(或多个列表)总是比追加到numpy.arraysparse矩阵(将数据存储在几个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)。要将这种想法应用到默认字典中需要一些实验。
因此,基本上目标是创建两个列表:

data = [1, 2, 3, 4, 5, 6]
cols = [ 0,  2,  3,  6,  7, 10]

是否根据这些数据创建稀疏矩阵取决于您需要对数据执行的其他操作。

相关问题