一尘不染

Numpy Pure Function用于性能,缓存

python

我正在用numpy编写一些中等性能的代码。该代码将位于计算的最内层循环中,其运行时间以小时为单位。快速计算表明,在计算的某些变化中,此代码将被执行大约10
^ 12次。

因此,函数是计算sigmoid(X),另一个函数是计算其导数(梯度)。Sigmoid具有以下特性:对于
y = sigmoid(x),dy / dx = y(1-y)
在numpy的python中,它看起来像:

sigmoid = vectorize(lambda(x): 1.0/(1.0+exp(-x)))
grad_sigmoid = vectorize(lambda (x): sigmoid(x)*(1-sigmoid(x)))

可以看出,这两个函数都是纯函数(没有副作用),因此它们是理想的记忆选择,至少就短期而言,我担心缓存每次对S型信号的调用:存储10 ^
12个浮点数将占用数TB的RAM。

是否有优化此方法的好方法?
python是否会发现它们是纯函数,并在适当时为我缓存它们?
我有什么担心的吗?


阅读 145

收藏
2020-12-20

共1个答案

一尘不染

这些功能已经存在于scipy中。乙状结肠功能可用scipy.special.expit

In [36]: from scipy.special import expit

expit向量化S型函数比较:

In [38]: x = np.linspace(-6, 6, 1001)

In [39]: %timeit y = sigmoid(x)
100 loops, best of 3: 2.4 ms per loop

In [40]: %timeit y = expit(x)
10000 loops, best of 3: 20.6 µs per loop

expit 比自己实现公式还快:

In [41]: %timeit y = 1.0 / (1.0 + np.exp(-x))
10000 loops, best of 3: 27 µs per loop

逻辑分布的CDF是S形函数。它可以作为的cdf方法使用scipy.stats.logistic,但cdf最终会调用expit,因此使用该方法毫无意义。您可以使用该pdf方法来计算Sigmoid函数的导数,也可以使用_pdf开销较小的方法,但是“自己滚动”的方法更快:

In [44]: def sigmoid_grad(x):
   ....:     ex = np.exp(-x)
   ....:     y = ex / (1 + ex)**2
   ....:     return y

时序(x的长度为1001):

In [45]: from scipy.stats import logistic

In [46]: %timeit y = logistic._pdf(x)
10000 loops, best of 3: 73.8 µs per loop

In [47]: %timeit y = sigmoid_grad(x)
10000 loops, best of 3: 29.7 µs per loop

如果要使用的值太短了,请谨慎执行。指数函数很容易溢出。 logistic._cdf比我快速实现的功能更强大sigmoid_grad

In [60]: sigmoid_grad(-500)
/home/warren/anaconda/bin/ipython:3: RuntimeWarning: overflow encountered in double_scalars
  import sys
Out[60]: 0.0

In [61]: logistic._pdf(-500)
Out[61]: 7.1245764067412855e-218

使用sech**21/cosh**2)的实现比上面的要慢一些sigmoid_grad

In [101]: def sigmoid_grad_sech2(x):
   .....:     y = (0.5 / np.cosh(0.5*x))**2
   .....:     return y
   .....:

In [102]: %timeit y = sigmoid_grad_sech2(x)
10000 loops, best of 3: 34 µs per loop

但是它可以更好地处理尾巴:

In [103]: sigmoid_grad_sech2(-500)
Out[103]: 7.1245764067412855e-218

In [104]: sigmoid_grad_sech2(500)
Out[104]: 7.1245764067412855e-218
2020-12-20