cp3*_*028 6 numpy matrix scipy sparse-matrix
对于当前项目,我必须使用相同的矩阵(非常稀疏)计算许多向量的内积.向量与二维网格相关联,因此我将向量存储在三维数组中:
例如:
X是一个暗淡的阵列(I,J,N).矩阵A很暗淡(N,N).现在的任务是计算A.dot(X[i,j])每个i,jin I,J.
对于numpy数组,这很容易实现
Y = X.dot(A.T)
Run Code Online (Sandbox Code Playgroud)
现在我想存储A为稀疏矩阵,因为它是稀疏的并且只包含非常有限数量的非零条目,这导致大量不必要的乘法.遗憾的是,由于numpy点不适用于稀疏矩阵,因此上述解决方案无效.据我所知,scipy稀疏没有类似数字的操作.
有没有人知道Y用稀疏矩阵计算上述数组的一种好而有效的方法A?
显而易见的方法是对向量运行循环并使用稀疏矩阵的.dot方法:
def naive_sps_x_dense_vecs(sps_mat, dense_vecs):
rows, cols = sps_mat.shape
I, J, _ = dense_vecs.shape
out = np.empty((I, J, rows))
for i in xrange(I):
for j in xrange(J):
out[i, j] = sps_mat.dot(dense_vecs[i, j])
return out
Run Code Online (Sandbox Code Playgroud)
但是你可以通过将 3d 数组重塑为 2d 来加快速度并避免 Python 循环:
def sps_x_dense_vecs(sps_mat, dense_vecs):
rows, cols = sps_mat.shape
vecs_shape = dense_vecs.shape
dense_vecs = dense_vecs.reshape(-1, cols)
out = sps_mat.dot(dense_vecs.T).T
return out.reshape(vecs.shape[:-1] + (rows,))
Run Code Online (Sandbox Code Playgroud)
问题是我们需要将稀疏矩阵作为第一个参数,以便我们可以调用它的.dot方法,这意味着返回被转置,这又意味着转置后,最后一次重塑将触发整个阵列。因此,对于相当大的 和 值I,J结合不太大的值N,后一种方法将比前一种方法快几倍,但对于其他参数组合,性能甚至可能会相反:
n, i, j = 100, 500, 500
a = sps.rand(n, n, density=1/n, format='csc')
vecs = np.random.rand(i, j, n)
>>> np.allclose(naive_sps_x_dense_vecs(a, vecs), sps_x_dense_vecs(a, vecs))
True
n, i, j = 100, 500, 500
%timeit naive_sps_x_dense_vecs(a, vecs)
1 loops, best of 3: 3.85 s per loop
%timeit sps_x_dense_vecs(a, vecs)
1 loops, best of 3: 576 ms per
n, i, j = 1000, 200, 200
%timeit naive_sps_x_dense_vecs(a, vecs)
1 loops, best of 3: 791 ms per loop
%timeit sps_x_dense_vecs(a, vecs)
1 loops, best of 3: 1.3 s per loop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
920 次 |
| 最近记录: |