如何在python中有效地创建稀疏向量?

时间:2015-03-13 13:02:10

标签: python numpy vector

我有一个键字典,其中每个值应该是一个巨大的稀疏矢量(~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,但事实证明它比上面的代码慢得多。

所以问题基本上归结为以下两个问题:

  1. 是否可以在python中动态创建稀疏数据结构

  2. 如何以合适的速度创建这种稀疏数据结构?

1 个答案:

答案 0 :(得分:2)

附加到列表(或列表)总是比附加到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。需要进行一些实验才能将此想法调整为默认字典。

所以基本上我们的目标是创建2个列表:

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

是否从这些创建稀疏矩阵取决于您需要对数据做什么。