Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mongodb到python稀疏矩阵,如何让它更快?_Python_Performance_Mongodb_Scipy_Sparse Matrix - Fatal编程技术网

mongodb到python稀疏矩阵,如何让它更快?

mongodb到python稀疏矩阵,如何让它更快?,python,performance,mongodb,scipy,sparse-matrix,Python,Performance,Mongodb,Scipy,Sparse Matrix,我在MongoDB中有n个文档,其中包含一个scipy稀疏向量,存储为pickle对象,最初使用scipy.sparse.lil创建。向量都是相同大小的,比如px1 我需要做的是将所有这些向量放到python中的稀疏Nxp矩阵中。我正在使用mongoengine,因此定义了一个属性来加载每个pickle向量: class MyClass(Document): vector_text = StringField() @property def vector(self):

我在MongoDB中有n个文档,其中包含一个scipy稀疏向量,存储为pickle对象,最初使用scipy.sparse.lil创建。向量都是相同大小的,比如px1

我需要做的是将所有这些向量放到python中的稀疏Nxp矩阵中。我正在使用mongoengine,因此定义了一个属性来加载每个pickle向量:

class MyClass(Document):

    vector_text = StringField()

    @property
    def vector(self):
        return cPickle.loads(self.vector_text)
这是我现在做的,n=4700,p=67:

items = MyClass.objects()
M = items[0].vector
for item in items[1:]:
    to_add = item.vector
    M = scipy.sparse.hstack((M, to_add))
加载部分(即调用n次属性)大约需要1.3秒。堆叠部分约为2.7s。因为在未来n将严重增加(可能超过几十万),我感觉这不是最优的:)
有没有加快整个过程的想法?如果你只知道如何固定“装载”或“堆叠”,我很高兴听到。例如,也许解决方案是将整个矩阵存储在mongoDB中?谢谢

我认为,您应该尝试使用,它本质上是BSON数组的python列表表示形式来存储向量。在这种情况下,您不必每次都解开它们

    class MyClass(Document):

        vector = ListField()



    items = MyClass.objects()
    M = items[0].vector

我在该解决方案中看到的唯一问题是,您必须将python列表转换为scipy稀疏向量类型,但我认为,这应该更快。

首先,您所描述的您想要做的是使用
vstack
,而不是
hstack
。在任何情况下,稀疏格式的选择都是性能问题的一部分。请尝试以下操作:

n, p = 4700, 67
csr_vecs = [sps.rand(1, p, density=0.5, format='csr') for j in xrange(n)]
lil_vecs = [vec.tolil() for vec in csr_vecs]

%timeit sps.vstack(csr_vecs, format='csr')
1 loops, best of 3: 722 ms per loop

%timeit sps.vstack(lil_vecs, format='lil')
1 loops, best of 3: 1.34 s per loop
因此,从swithcing到CSR已经有了2倍的改进。此外,
scipy.sparse
的叠加函数似乎没有得到很好的优化,对于稀疏向量肯定没有。以下两个函数堆叠CSR或LIL向量列表,返回CSR稀疏矩阵:

def csr_stack(vectors):
    data = np.concatenate([vec.data for vec in vectors])
    indices = np.concatenate([vec.indices for vec in vectors])
    indptr = np.cumsum([0] + [vec.nnz for vec in vectors])
    return sps.csr_matrix((data, indices, indptr), shape=(len(vectors),
                                                          vectors[0].shape[1]))
import itertools as it
def lil_stack(vectors):
    indptr = np.cumsum([0] + [vec.nnz for vec in vectors])
    data = np.fromiter(it.chain(*(vec.data[0] for vec in vectors)),
                       dtype=vectors[0].dtype, count=indptr[-1])
    indices = np.fromiter(it.chain(*(vec.rows[0] for vec in vectors)),
                          dtype=np.intp, count=indptr[-1])
    return sps.csr_matrix((data, indices, indptr), shape=(len(vectors),
                                                          vectors[0].shape[1]))
它的工作原理是:

>>> np.allclose(sps.vstack(csr_vecs).A, csr_stack(csr_vecs).A)
True
>>> np.allclose(csr_stack(csr_vecs).A, lil_stack(lil_vecs).A)
True
而且速度大大加快:

%timeit csr_stack(csr_vecs)
100 loops, best of 3: 11.7 ms per loop

%timeit lil_stack(lil_vecs)
10 loops, best of 3: 37.6 ms per loop

%timeit lil_stack(lil_vecs).tolil()
10 loops, best of 3: 53.6 ms per loop

因此,通过切换到CSR,您可以将性能提高100倍以上。如果你坚持LIL,你的绩效提升将只有30倍左右,如果你能在组合矩阵中接受CSR,提升幅度会更大,如果你坚持LIL,提升幅度会更小。

有趣。如果vector是一个numpy数组或一个列表,它就像一个符咒。似乎存储稀疏向量比较困难。但就像你说的,我可以在事后再转换。这是第一步,它会加快速度,谢谢!真是令人印象深刻,我肯定要换了!使用Jaime和Alexander的答案,我的程序现在真的非常快(事实证明,当你的程序基于运行数千次相同的方法,并且你使所述方法快100倍时,我可能不需要说:))。太棒了,谢谢。