numpy.vectorize:为什么这么慢? [英] numpy.vectorize: Why so slow?

查看:57
本文介绍了numpy.vectorize:为什么这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

scipy.special中的expit函数是向量化的S型函数.它计算1/(1 + e ^(-x))很复杂,可能涉及泰勒级数.

The expit function, in scipy.special, is a vectorized sigmoid function. It computes 1 / (1+e^(-x)), which is complicated, probably involving a Taylor series.

我了解了快速S形",1/(1 + abs(x)),它应该快得多-但是内置的expit函数的性能大大超过了它,即使当我将其作为lambda表达式传递给numpy.vectorize.

I learned about the "fast sigmoid", 1 / (1 + abs(x)), which ought to be much faster -- but the builtin expit function massively outperforms it, even when I hand it as a lambda expression to numpy.vectorize.

这里是测试它们的一种方法:

Here's one way to test them:

from scipy.special import expit
data = np.random.rand(1000000)

内置的,复杂的Sigmoid速度很快:

The built-in, complicated sigmoid is fast:

%prun expit(data)

3 function calls in 0.064 seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.064    0.064    0.064    0.064 <string>:1(<module>)
     1    0.000    0.000    0.064    0.064 {built-in method builtins.exec}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

更简单的乙状结肠慢了约20倍:

The simpler sigmoid is around 20 times slower:

%prun np.vectorize( lambda x: (x / (1 + abs(x)) + 1) / 2 )(data)

2000023 function calls in 1.992 seconds

Ordered by: internal time

 ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1000001    1.123    0.000    1.294    0.000 <string>:1(<lambda>)
      1    0.558    0.558    1.950    1.950 function_base.py:2276(_vectorize_call)
1000001    0.170    0.000    0.170    0.000 {built-in method builtins.abs}
      4    0.098    0.025    0.098    0.025 {built-in method numpy.core.multiarray.array}
      1    0.041    0.041    1.991    1.991 function_base.py:2190(__call__)
      1    0.000    0.000    0.068    0.068 function_base.py:2284(<listcomp>)
      1    0.000    0.000    1.992    1.992 {built-in method builtins.exec}
      1    0.000    0.000    1.991    1.991 <string>:1(<module>)
      1    0.000    0.000    0.000    0.000 function_base.py:2220(_get_ufunc_and_otypes)
      1    0.000    0.000    0.000    0.000 function_base.py:2162(__init__)
      1    0.000    0.000    0.000    0.000 function_base.py:2242(<listcomp>)
      2    0.000    0.000    0.000    0.000 numeric.py:414(asarray)
      1    0.000    0.000    0.000    0.000 {built-in method numpy.core.umath.frompyfunc}
      1    0.000    0.000    0.000    0.000 function_base.py:2266(<listcomp>)
      2    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
      1    0.000    0.000    0.000    0.000 {built-in method builtins.len}
      1    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
      1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

推荐答案

我将引用

I'll just quote the the vectorize docstring: "The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop."

您想使 1/(1 + abs(x))快速.numpy具有称为 numpy.abs 的功能(也称为

You want to make 1/(1 + abs(x)) fast. numpy has a function called numpy.abs (also called numpy.absolute--they are different names for the same object). It computes the absolute value of each element of its argument, and it does this in C code, so it is fast. Also, the Python built-in function abs knows how to dispatch arguments to objects that have the method __abs__, which numpy arrays do, so you can also use Python's abs() to compute the element-wise absolute value of a numpy array. In the following, though, I'll use np.abs.

以下是使用 np.abs 的示例:

In [25]: x = np.array([-2, -1.5, 0, 5, 10])

In [26]: np.abs(x)
Out[26]: array([  2. ,   1.5,   0. ,   5. ,  10. ])

这里是大型阵列 x的 scipy.special.expit 1.0/(1 + np.abs(x))性能的比较:

Here's a comparision of the performance of scipy.special.expit and 1.0/(1 + np.abs(x)) for a large array x:

In [34]: from scipy.special import expit

In [35]: x = np.random.randn(100000)

In [36]: %timeit expit(x)
1000 loops, best of 3: 771 µs per loop

In [37]: %timeit 1.0/(1 + np.abs(x))
1000 loops, best of 3: 279 µs per loop

所以 1.0/(1 + np.abs(x)) expit(x)快很多.

这篇关于numpy.vectorize:为什么这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆