use*_*931 5 python numpy scipy sparse-matrix
我写了一个程序,并一直在分析它.瓶颈如下(如果我使用稀疏矩阵):
26534 0.775 0.000 66.657 0.003 compressed.py:638(__setitem__)
26534 2.240 0.000 59.438 0.002 compressed.py:688(_set_many)
13318 2.993 0.000 50.024 0.004 compressed.py:742(_insert_many)
3034231 23.087 0.000 38.101 0.000 defmatrix.py:312(__getitem__)
Run Code Online (Sandbox Code Playgroud)
如果我使用密集矩阵,那么这些操作很慢(必须将init矩阵设为零)
3034072 24.902 0.000 41.135 0.000 defmatrix.py:312(__getitem__)
11780 19.586 0.002 19.586 0.002 {numpy.core.multiarray.zeros}
Run Code Online (Sandbox Code Playgroud)
稀疏矩阵版本更快(193秒对178秒).但检索和放入行显然是我的瓶颈.我尝试使用该take函数,我用它range()来创建一个包含行索引的数组.然而,这比我目前正在做的更糟糕(比10000倍),这对于矩阵X来说,X[idx,:]用于放置和X.getrow(idx).todense()取出.
有没有更好的方法来访问和替换这些行?我的矩阵非常大(~100000行20-500 cols).
编辑:我正在使用csr_matrix(但对任何类型的稀疏矩阵开放 - 这个似乎适合抓取行).以下是一系列测试,只是为了给出一个MWE.速度约为3E-4s,7E-3s,.1s.这对我来说是令人惊讶的,我想知道是否有一种比顶级方法更快的方法.如果我删除todense()调用稀疏时间减少一半 - 但这似乎仍然很慢.
import numpy as np
from time import time
from scipy.sparse import csr_matrix
def testFancy(mat,idxs):
for i in idxs:
x = mat[i,:]
def testTake(mat,idxs):
for i in idxs:
x = mat.take(range(i*50,i*50+50))
def testSparse(mat,idxs):
for i in idxs:
x = mat.getrow(i).todense()
mat = np.random.rand(50000,50)
idxs = np.random.randint(50000-1, size=1000)
#fancy
t0 = time()
testFancy(mat,idxs)
t1 = time()
print str(t1-t0)
#take
t0 = time()
testTake(mat,idxs)
t1 = time()
print str(t1-t0)
#sparse
mat = csr_matrix((50000,50))
t0 = time()
testSparse(mat,idxs)
t1 = time()
print str(t1-t0)
Run Code Online (Sandbox Code Playgroud)
只需使用花哨的索引即可获取和设置数组中的行,
\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix\n\nmat_ds = np.random.rand(50000,50)\nmat_csr = csr_matrix((50000,50))\nmat_lil = mat_csr.tolil()\n\nidxs = np.random.randint(50000-1, size=1000)\n\nprint(mat_sp[idxs, :].todense())\nprint(mat_csr[idxs, :])\n\nmat_sp[idxs, :] = 2.0 # or any other expression that makes sens here\nmat_csr[idxs, :] = 2.0 \nRun Code Online (Sandbox Code Playgroud)\n\n数组是否稀疏并不重要。这将比任何带有循环的自定义解决方案更快(比快约 250 倍)testSparse我的情况快约 250 倍)。
当然,对稀疏数组的分配应该以保持稀疏性的方式完成,否则它将被重新分配,这对于csr_matrix. 例如上面的例子,因此产生警告。
编辑:回应评论。让我们考虑只查询一行,
\n\nIn [1]: %timeit -n 1 mat_csr[0, :].todense()\n1 loops, best of 3: 101 \xc2\xb5s per loop\n\nIn [2]: %timeit -n 1 mat_lil[0, :].todense()\n1 loops, best of 3: 157 \xc2\xb5s per loop\n\nIn [3]: %timeit -n 1 mat_ds[0, :]\nThe slowest run took 8.25 times longer than the fastest. This could mean that an intermediate result is being cached \n1 loops, best of 3: 954 ns per loop\nRun Code Online (Sandbox Code Playgroud)\n\n所以,是的,查询密集数组比稀疏数组快 10 到 100 倍,结果转换为密集数组(无论您使用 csr 还是 lil 数组),因为开销更少。对此我们无能为力,您只需选择是否需要稀疏数组即可。
\n| 归档时间: |
|
| 查看次数: |
552 次 |
| 最近记录: |