矢量化 "is in"

Vectorize "is in"

我尝试构建 m 个向量样本(带有整数条目)以及 m 个评估。如果其中一个条目是数字 2,则形状 (n,1) 的向量 x 的计算结果为 y=1。否则,它被评估为 y=0.
为了处理许多这样的向量和评估,样本向量存储在 (n,m)ndarray 中,评估存储在 (1,m)ndarray 中。见代码:

import numpy as np

n = 10 # number of entries in each sample vector
m = 1000 # number of samples

X = np.random.randint(-10, 10, (n, m))
Y = []
for i in range(m):
    if 2 in X[:, i]:
        Y.append(1)
    else:
        Y.append(0)
Y = np.array(Y).reshape((1,-1))
assert (Y.shape == (1,m))

如何向量化 Y 的计算?我尝试用以下内容替换 XY 的 initialization/computation:

X = np.random.randint(-10,10,(n,m))
Y = np.apply_along_axis(func1d=lambda x: 1 if 2 in x else 0, axis=0, arr=X)

一些执行表明这在大多数情况下甚至比我的第一种方法慢一点。 (实际上 this anser 首先说 numpy.apply_along_axis 不是为了速度。我也不知道 lambda 在这种情况下有多好。)

有没有办法对 Y 的计算进行矢量化,即根据该列是否包含元素,为每一列分配值 10 的方法2?

当使用 Numpy 数组和逻辑语句时,它会进行大量优化,而无需用户手动矢量化任务。以下代码达到相同的解决方案:

# assign logical 1 where element == 2 everywhere in the array X,
# then, for each column (axis = 0), if any element == 1 assign column logical 1
Y = (X == 2).any(axis = 0).reshape(1, -1)
print(Y.shape)

使用 timeit 评估执行时间:

循环方法:每个 运行

3240 微秒

numpy 方法:每 运行

6.57 微秒

如果您有兴趣,您可以看看是否使用其他矢量化方法(例如 np.vectorise)可以进一步缩短时间,尽管我很确定底层 Numpy 优化在 [=31] 执行它们自己的矢量化=] 默认指令级 (SIMD)。

底线是在使用 numpy 时始终尝试使用逻辑数组和 numpy functions/methods 找到解决方案,因为它们已经在编译的二进制文件中进行了高度优化,并且任何 python 函数用于操作、访问或迭代数据会显着降低执行速度。

顺便说一句,要加快 for 循环执行速度以构建输出列表(如您所做的那样)的最常见方法是使用列表理解:

Y = np.array([2 in X[:, i] for i in range(m)]).reshape((1, -1))

每个循环执行 3070 微秒。