python - numpy 中两个二维掩码数组的快速内积

标签 python numpy

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

我还有一个关于p的掩码mask(大小为p的 bool 值的一维数组),密度(例如np.mean(mask)为0.05)。

我尝试尽快计算 XY 相对于 mask 的内积:输出 inner 是一个形状为 n, n 的数组,并且满足 inner[i, j] = np.sum(X[i, np.logic_not(mask)) ] * Y[j, np.logic_not(mask)]).

我尝试过使用numpy.ma库,但它对我来说相当慢:

import 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)

但是,在我的机器上,X_ma.dot(Y_ma.T)X.dot(Y.T) 慢大约 5 倍...

首先,我认为这是一个问题,.dot不知道掩码仅相对于p,但如果可能的话我不知道使用此信息。

我正在寻找一种执行计算的方法,而又不会比天真的点慢很多。

非常感谢!

最佳答案

我们可以使用带或不带屏蔽版本的矩阵乘法,因为从完整版本中进行屏蔽减法会产生我们所需的输出 -

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

或者简单地使用反向掩码,但对于稀疏掩码来说会更慢 -

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

关于python - numpy 中两个二维掩码数组的快速内积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54294577/

相关文章:

python - Numpy 数组 python 维度统一

python - Numpy isnan() 在 float 组上失败(来自 pandas 数据框应用)

applymap 中的 Python 引用行

python - 如何修复原子编辑器中的 `flake8 D100 — Missing docstring` 错误

python - 在python中以不同颜色绘制bool-int散点图

Python 遍历列表以将项目添加到另一个列表?

python - 如何将复数放入 numpy 的数组中?

python - WTForms-JSON 不适用于 FormFields

python - 带有所需子命令的 argparse

Python Pandas 0.14.0。使用 dataframe.to_sql 时时间戳格式错误