对于当前项目,我必须计算具有相同矩阵(相当稀疏)的许多向量的内积。向量与二维网格相关联,因此我将向量存储在三维数组中:
例如:X
是暗(I,J,N)
的数组。矩阵A
为dim (N,N)
。现在的任务是为A.dot(X[i,j])
中的每个i,j
计算I,J
。
对于numpy数组,这很容易完成
Y = X.dot(A.T)
现在,我想将
A
存储为稀疏矩阵,因为它是稀疏的,并且仅包含数量非常有限的非零条目,这会导致许多不必要的乘法。不幸的是,由于numpy点不适用于稀疏矩阵,因此上述解决方案无效。据我所知,没有稀疏的类似于张量点的操作。有人知道用稀疏矩阵
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
但是您可以通过将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,))
问题是我们需要将稀疏矩阵作为第一个参数,以便我们可以调用它的
.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
关于numpy - Tensordot用于numpy数组和scipy稀疏矩阵,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18901938/