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

标签 python numpy

我有一个函数可以执行此操作:它采用给定的 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/

相关文章:

python - 如何在谷歌应用引擎中执行多个异步查询?

python - 使 numpy.sum() 返回矩阵总和而不是单个数字

python - numpy随机采样 bool 数组

python - 类型错误 : 'ABCMeta' object is not subscriptable on Callable

python - Django 中带有多对多字段的 Dumpdata

python - Numpy 切片慢?

python - 当 NaN 包含在索引中时,如何有效地删除?

python - 将解决方案应用于实际数据时结果不正确

python - 在python中返回一个数字及其平方的数组

python - 带有日期和 sqlite 的 QSortFilterProxyModel