Numpy 在两个数组之间执行矩阵乘法,并仅在屏蔽位置上获得结果

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,

我有两个稠密矩阵,A[200000,10],B[10100000]。我需要将它们相乘得到矩阵C。我不能直接这样做,因为生成的矩阵无法放入内存。此外,我只需要结果矩阵中的几个元素,比如元素总数的1-2%。我有第三个矩阵W[20000100000],它是稀疏的,并且在矩阵C中我感兴趣的地方有非零元素。
有没有一种方法可以使用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)。