gpt4 book ai didi

python - 在 numpy 数组上应用矢量化和非矢量化函数

转载 作者:太空宇宙 更新时间:2023-11-03 11:00:04 26 4
gpt4 key购买 nike

我有一个函数可以执行此操作:它采用给定的 numpy 数组 A 和给定的函数 func 并将该函数应用于数组的每个元素。

def transform(A, func):
return func(A)

Afunc 是从外部提供的,我无法控制它们。如果函数是矢量化函数,例如 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com