我有一个函数可以执行此操作:它采用给定的 numpy 数组 A
和给定的函数 func
并将该函数应用于数组的每个元素。
def transform(A, func):
return func(A)
A
和 func
是从外部提供的,我无法控制它们。如果函数是矢量化函数,例如 transform(A, np.sin)
,我希望这些函数能够工作,但我也希望能够接受普通的 numpy 函数,例如像 transform(A, lambda x: x^2 if x > 5 else 0)
这样的 lambda。当然,第二个不是矢量化的,所以我需要在应用它之前调用 np.vectorize()
。像这样:transform(A, np.vectorize(lambda x: x^2 if x > 5 else 0))
... 但我不想把这种负担强加给用户。我想要一个统一的方法来处理所有功能。我只是从外部获取一个函数并应用它。
是否有一种方法可以决定哪些函数需要矢量化,哪些不需要?像这样的东西:
def transform(A, func):
if requires_vectorization(func): # how to do this???
func = np.vectorize(func)
return func(A)
或者我应该默认向量化所有
def transform(A, func):
func = np.vectorize(func) # is this correct and efficient?
return func(A)
这个解决方案好吗?换句话说,在已经向量化的函数上调用 np.vectorize
会不会有什么坏处?还是有其他选择?
最佳答案
在 EAFP principle 之后,您可以先尝试直接在 A
上调用该函数,看看是否会引发异常:
import numpy as np
def transform(A, func):
try:
return func(A)
except TypeError:
return np.vectorize(func)(A)
例如:
import math
A = np.linspace(0, np.pi, 5)
print(transform(A, np.sin)) # vectorized function
# [ 0.00000000e+00 7.07106781e-01 1.00000000e+00 7.07106781e-01
# 1.22464680e-16]
print(transform(A, math.sin)) # non-vectorized function
# [ 0.00000000e+00 7.07106781e-01 1.00000000e+00 7.07106781e-01
# 1.22464680e-16]
does it hurt to call np.vectorize on already vectorized function?
是的,绝对是。当您将 np.vectorize
应用于函数时,所有对输入数组元素的循环都是在 Python 中完成的,这与在 C 中进行循环的“适当”矢量化 numpy 函数不同。来自 the documentation :
The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.
我觉得这句话应该用粗体全部大写。
恰当的例子:
In [1]: vecsin = np.vectorize(np.sin)
In [2]: %%timeit A = np.random.randn(10000);
np.sin(A)
....:
1000 loops, best of 3: 243 µs per loop
In [3]: %%timeit A = np.random.randn(10000);
vecsin(A)
....:
100 loops, best of 3: 11.7 ms per loop
In [4]: %%timeit A = np.random.randn(10000);
[np.sin(a) for a in A]
....:
100 loops, best of 3: 12.5 ms per loop
在这个例子中,将 np.vectorize
应用到 np.sin
会减慢它约 50 倍,使其与常规 Python 列表理解一样慢.
编辑:
为了完整起见,这里是“转换后”的版本。如您所见,try
/except
block 对性能的影响可以忽略不计:
In [5]: %%timeit A = np.random.randn(10000);
transform(A, np.sin)
...:
1000 loops, best of 3: 241 µs per loop
关于python - 在 numpy 数组上应用矢量化和非矢量化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34665488/