Numpy 在两个数组之间执行矩阵乘法,并仅在屏蔽位置上获得结果
我有两个稠密矩阵,A[200000,10],B[10100000]。我需要将它们相乘得到矩阵C。我不能直接这样做,因为生成的矩阵无法放入内存。此外,我只需要结果矩阵中的几个元素,比如元素总数的1-2%。我有第三个矩阵W[20000100000],它是稀疏的,并且在矩阵C中我感兴趣的地方有非零元素。Numpy 在两个数组之间执行矩阵乘法,并仅在屏蔽位置上获得结果,numpy,scipy,sparse-matrix,matrix-multiplication,Numpy,Scipy,Sparse Matrix,Matrix Multiplication,我有两个稠密矩阵,A[200000,10],B[10100000]。我需要将它们相乘得到矩阵C。我不能直接这样做,因为生成的矩阵无法放入内存。此外,我只需要结果矩阵中的几个元素,比如元素总数的1-2%。我有第三个矩阵W[20000100000],它是稀疏的,并且在矩阵C中我感兴趣的地方有非零元素。 有没有一种方法可以使用W作为“遮罩”,这样生成的矩阵C将是稀疏的,并且只包含所需的元素?首先,获取W中非零位置的索引,然后您就可以得到(i,j)将A中的第i行与B中的第j列相乘,将结果保存为元组(i,
有没有一种方法可以使用W作为“遮罩”,这样生成的矩阵C将是稀疏的,并且只包含所需的元素?首先,获取W中非零位置的索引,然后您就可以得到
(i,j)
将A中的第i行与B中的第j列相乘,将结果保存为元组(i,j,res)
而不是保存为矩阵(这是保存稀疏矩阵的正确方法) 首先,获取W中非零位置的索引,然后通过将A中的第i行与B中的第j列相乘,只需获取结果矩阵的(i,j)
元素,并将结果保存为元组(i,j,res)
,而不是将其保存为矩阵(这是保存稀疏矩阵的正确方法) 因为矩阵乘法只是一个点积表,所以我们可以以矢量化的方式执行我们需要的特定点积
import numpy as np
import scipy as sp
iX, iY = sp.nonzero(W)
values = np.sum(A[iX]*B[:, iY].T, axis=-1) #batched dot product
C = sp.sparse.coo_matrix(values, np.asarray([iX,iY]).T)
因为矩阵乘法只是一个点积表,所以我们可以以矢量化的方式执行我们需要的特定点积
import numpy as np
import scipy as sp
iX, iY = sp.nonzero(W)
values = np.sum(A[iX]*B[:, iY].T, axis=-1) #batched dot product
C = sp.sparse.coo_matrix(values, np.asarray([iX,iY]).T)
下面是一种用于矢量化解决方案的方法-
from scipy import sparse
from scipy.sparse import coo_matrix
# Get row, col for the output array
r,c,_= sparse.find(W)
# Get the sum-reduction using valid rows and corresponding cols from A, B
out = np.einsum('ij,ji->i',A[r],B[:,c])
# Store as sparse matrix
out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
样本运行-
1) 投入:
3) 使用建议的代码并获得稀疏矩阵输出:
In [172]: # Using proposed codes
...: r,c,_= sparse.find(W)
...: out = np.einsum('ij,ji->i',A[r],B[:,c])
...: out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
...:
4) 最后,通过转换为密集/阵列版本并检查直接版本来验证结果-
In [173]: out_sparse.toarray()
Out[173]:
array([[52, 0, 0],
[ 0, 0, 0],
[73, 57, 0],
[84, 0, 56]])
下面是一种用于矢量化解决方案的方法-
from scipy import sparse
from scipy.sparse import coo_matrix
# Get row, col for the output array
r,c,_= sparse.find(W)
# Get the sum-reduction using valid rows and corresponding cols from A, B
out = np.einsum('ij,ji->i',A[r],B[:,c])
# Store as sparse matrix
out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
样本运行-
1) 投入:
3) 使用建议的代码并获得稀疏矩阵输出:
In [172]: # Using proposed codes
...: r,c,_= sparse.find(W)
...: out = np.einsum('ij,ji->i',A[r],B[:,c])
...: out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
...:
4) 最后,通过转换为密集/阵列版本并检查直接版本来验证结果-
In [173]: out_sparse.toarray()
Out[173]:
array([[52, 0, 0],
[ 0, 0, 0],
[73, 57, 0],
[84, 0, 56]])
如果你把你的答案再充实一点,我相信这是解决这个问题的正确方法。这当然是一个可能的解决办法。但是,它将包括迭代2亿个元素(200000x10000的1%)。我更喜欢矢量化的解决方案(如果有)如果你有W中只有零个元素的完整行,你可以将a中对应的行归零,同样,如果你有只包含零的完整列,你可以将B中对应的元素归零,然后使用
scipy.sparse
乘以矩阵。如果你的答案更具体一些,我相信这是解决这个问题的正确方法。这当然是一个可能的解决方案。但是,它将包括迭代2亿个元素(200000x10000的1%)。我更喜欢矢量化的解决方案(如果有)如果你有W中只有零个元素的完整行,你可以将a中对应的行归零,同样的,如果你有一个只有零的完整列,你可以把B中对应的元素归零,然后用scipy.sparse
乘以矩阵。很好地使用sp.nonzero
!可能是一个更快的选择。你介意我在我的帖子里提到它吗?:)sp.nonzero
和sp.find
几乎相同-返回coo
格式的属性find
也只返回data
属性。如果W
已经是coo
,只需直接使用其row
和col
属性。scipy.nonzero
是np.nonzero
,这反过来又遵从W.nonzero
。进一步检查后,sparse.find
速度较慢,因为它需要通过csr
格式对重复项求和iX,iY=W.row,W.col
甚至更快(如果W已经是coo)。很好地使用sp.nonzero
!可能是一个更快的选择。你介意我在我的帖子里提到它吗?:)sp.nonzero
和sp.find
几乎相同-返回coo
格式的属性find
也只返回data
属性。如果W
已经是coo
,只需直接使用其row
和col
属性。scipy.nonzero
是np.nonzero
,这反过来又遵从W.nonzero
。进一步检查后,sparse.find
速度较慢,因为它需要通过csr
格式对重复项求和iX,iY=W.row,W.col
甚至更快(如果W已经是coo)。