高效的点积密集到稀疏

时间:2019-06-24 12:55:45

标签: python numpy scipy

我只想为特定索引有效地计算两个低秩矩阵A和B的点积。通常,A和B的形状为(100,10000),我只想获得A.T @ B的1%。

我已经尝试使用Numba库,但它似乎比计算密集点积np.dot(A.T,B)慢得多。

2 个答案:

答案 0 :(得分:0)

如果要获得点乘积的结果数组的子集,只需在使用点之前取该子集即可。即,如果您想要输出的“左上” 10x10矩阵,只需执行

np.dot(A.T[:10,:], B[:, :10])

如果需要某些特定的索引,则可以使用更多的精美索引。例如,如果您想要索引3、5和29,则可以执行以下操作:

indices = np.array([3, 5, 29]).reshape(-1, 1)
inner_all = np.arange(A.shape[0]).reshape(-1, 1)
result = np.dot(A.T[indices, inner_all.T], B[inner_all, indices.T])

如果仅对于第一行,则需要第1、3和5列:

rows = np.array([1]).reshape(-1, 1)
columns = rows = np.array([1, 3, 5]).reshape(-1, 1)
inner_all = np.arange(A.shape[0]).reshape(-1, 1)
result = np.dot(A.T[rows, inner_all.T], B[inner_all, columns.T])

答案 1 :(得分:0)

您可以使用einsum

import numpy as np

def direct():
    return (A.T@B)[iy, ix]

def einsum():
    return np.einsum('ij,ij->j',A[:,iy],B[:,ix])

def make(M,N,p):
    global A,B,iy,ix
    A,B = (np.random.randint(0,10,(M,N)) for _ in "AB")
    iy,ix = np.random.randint(0,N,(2,int(N*N*p)))

from time import time

make(100,10000,0.01)
T=[]
T.append(time())
d = direct()
T.append(time())
e = einsum()
T.append(time())
print("results equal: ",np.allclose(d,e))
print("direct {:.6f} einsum {:.6f}".format(*np.diff(T)))

样品运行:

results equal:  True
direct 18.463711 einsum 1.947425