如何在不调用`np.vectorize`的情况下强制广播功能

时间:2019-05-15 22:24:27

标签: python numpy-broadcasting

我想寻找一种强制广播功能的方法。

在某些情况下,以后可能会将函数/方法覆盖为常数函数。在这种情况下,如果

arr = np.arange(0, 1, 0.0001)
f = lambda x: 5
f(arr) # this gives just integer 5, i want [5, 5,..., 5]

我知道像np.vectorize这样的方法会强制广播函数,但是问题是效率低下,因为它本质上是在幕后循环。 (请参阅documentation

我们还可以使用诸如np.frompyfunc之类的工厂方法,该方法允许我们将python函数转换为numpy通用函数ufunc,例如参见here。这种方法的性能优于np.vectorize,但仍然比内置ufunc的方法效率低。

我想知道是否有任何有效的numpy方法来处理此问题,即强制该函数广播?

2 个答案:

答案 0 :(得分:1)

如果有更好的方法来广播任意Python函数,则numpy.vectorize将使用它。如果要有效地广播,您确实必须在编写广播功能时就考虑到这一点。

在常量函数的特定情况下,您可以使用numpy.full编写广播常量函数:

def f(x):
    return numpy.full(numpy.shape(x), 5)

numba.vectorize还可以比numpy.vectorize更有效地向量化函数,但是您需要Numba,并且需要以Numba可以有效编译的方式编写函数。

答案 1 :(得分:0)

对于那些无法获得通用答案的人来说,最好的答案是np.full_like(arr, val),它比np.full(arr.shape, val)改善约20%

在将此issue提交给作者之后,我发现了一些最佳的中间立场,可以兼顾一般性和良好表现:

np.broadcast_arrays(x, f(x))[1]

这是一些时间分析:

arr = np.arange(1, 2, 0.0001).reshape(10, -1)

def master_f(x): return np.broadcast_arrays(x, f(x))[-1].copy('K')
def master_f_nocopy(x): return np.broadcast_arrays(x, f(x))[-1]
def vector_f(x): return np.vectorize(f)(x)

%timeit arr+1 # this takes about 10microsec
%timeit master_f(arr) # this takes about 40 mircrosec
%timeit master_f_nocopy(arr) # this takes about 20 microsec

请注意,这允许将其应用于诸如f(x,y):=y之类的投影功能,这超出了np.full_like的帮助。

此外,当出现诸如np.sinnp.cos之类的更复杂的功能时,您会注意到f(arr)master_f_nocopy(arr)之间的区别几乎可以忽略不计。

相关问题