numpy中两个二维遮罩数组的快速内积

时间:2019-01-21 16:57:53

标签: python numpy

我的问题如下。我有两个形状为n,p的数组XY,其中 p >> n (例如n = 50,p = 10000)。

相对于mask,我也有一个{strong>小密度的遮罩p(大小为p的布尔数的一维数组)(例如{ {1}}是0.05)。

我尝试相对于np.mean(mask)尽可能快地计算XY的内积:输出mask是形状为{的数组{1}},并且这样inner

我尝试使用n, n库,但是使用起来很慢:

inner[i, j] = np.sum(X[i, np.logical_not(mask)] * Y[j, np.logical_not(mask)])

但是,在我的机器上,numpy.maimport numpy as np import numpy.ma as ma n, p = 50, 10000 density = 0.05 mask = np.array(np.random.binomial(1, density, size=p), dtype=np.bool_) mask_big = np.ones(n)[:, None] * mask[None, :] X = np.random.randn(n, p) Y = np.random.randn(n, p) X_ma = ma.array(X, mask=mask_big) Y_ma = ma.array(Y, mask=mask_big) 慢5倍...

首先,我认为这是一个问题,X_ma.dot(Y_ma.T)不知道掩码仅针对X.dot(Y.T),但是我无法使用此信息。

我正在寻找一种执行计算的方法,并且不会比幼稚的点慢很多。

非常感谢!

1 个答案:

答案 0 :(得分:2)

我们可以使用matrix-multiplication带有和不带有蒙版的版本,因为从完整版的蒙版减法会为我们提供所需的输出-

inner = X.dot(Y.T)-X[:,mask].dot(Y[:,mask].T)

或者简单地使用反光罩,虽然对于mask来说很慢-

inner = X[:,~mask].dot(Y[:,~mask].T)

时间-

In [34]: np.random.seed(0)
    ...: p,n = 10000,50
    ...: X = np.random.rand(n,p)
    ...: Y = np.random.rand(n,p)
    ...: mask = np.random.rand(p)>0.95

In [35]: mask.mean()
Out[35]: 0.0507

In [36]: %timeit X.dot(Y.T)-X[:,mask].dot(Y[:,mask].T)
100 loops, best of 3: 2.54 ms per loop

In [37]: %timeit X[:,~mask].dot(Y[:,~mask].T)
100 loops, best of 3: 4.1 ms per loop

In [39]: %%timeit
    ...: inner = np.empty((n,n))
    ...: for i in range(X.shape[0]):
    ...:     for j in range(X.shape[0]):
    ...:         inner[i, j] = np.sum(X[i, ~mask] * Y[j, ~mask])
1 loop, best of 3: 302 ms per loop