我正在为一个应用程序使用 logistic sigmoid。我比较了使用 scipy.special
函数 expit
与使用 sigmoidal 的双曲正切定义的时间。
我发现双曲正切的速度快了 3 倍。这里发生了什么?我还在排序数组上测试了时间,看看结果是否有任何不同。
这是一个在 IPython 中运行的例子:
In [1]: from scipy.special import expit
In [2]: myexpit = lambda x: 0.5*tanh(0.5*x) + 0.5
In [3]: x = randn(100000)
In [4]: allclose(expit(x), myexpit(x))
Out[4]: True
In [5]: timeit expit(x)
100 loops, best of 3: 15.2 ms per loop
In [6]: timeit myexpit(x)
100 loops, best of 3: 4.94 ms per loop
In [7]: y = sort(x)
In [8]: timeit expit(y)
100 loops, best of 3: 15.3 ms per loop
In [9]: timeit myexpit(y)
100 loops, best of 3: 4.37 ms per loop
编辑:
机器信息:
- Ubuntu 16.04
- 内存:7.4GB
- 英特尔酷睿 i7-3517U CPU @ 1.90GHz × 4
Numpy/Scipy 信息:
In [1]: np.__version__
Out[1]: '1.12.0'
In [2]: np.__config__.show()
lapack_opt_info:
libraries = ['openblas', 'openblas']
library_dirs = ['/usr/local/lib']
define_macros = [('HAVE_CBLAS', None)]
language = c
blas_opt_info:
libraries = ['openblas', 'openblas']
library_dirs = ['/usr/local/lib']
define_macros = [('HAVE_CBLAS', None)]
language = c
openblas_info:
libraries = ['openblas', 'openblas']
library_dirs = ['/usr/local/lib']
define_macros = [('HAVE_CBLAS', None)]
language = c
blis_info:
NOT AVAILABLE
openblas_lapack_info:
libraries = ['openblas', 'openblas']
library_dirs = ['/usr/local/lib']
define_macros = [('HAVE_CBLAS', None)]
language = c
lapack_mkl_info:
NOT AVAILABLE
blas_mkl_info:
NOT AVAILABLE
In [3]: import scipy
In [4]: scipy.__version__
Out[4]: '0.18.1'
请您参考如下方法:
编辑:
我会让以后的人引用 this question .
总结有用评论的结果:
"Why is using tanh definition of logistic sigmoid faster than scipy's expit?"
回答:不是; tanh
和 exp
C 函数在我特定的机器上发生了一些有趣的事情。
事实证明,在我的机器上,tanh
的 C 函数比 exp
更快。为什么会这样的答案显然属于另一个问题。当我运行下面列出的 C++ 代码时,我看到了
tanh: 5.22203
exp: 14.9393
当从 Python 调用时,这与 tanh
函数的 ~3 倍增长相匹配。奇怪的是,当我在具有相同操作系统的另一台机器上运行相同的代码时,我得到了 tanh
和 exp
的相似计时结果。
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;
int main() {
double a = -5;
double b = 5;
int N = 10001;
double x[10001];
double y[10001];
double h = (b-a) / (N-1);
clock_t begin, end;
for(int i=0; i < N; i++)
x[i] = a + i*h;
begin = clock();
for(int i=0; i < N; i++)
for(int j=0; j < N; j++)
y[i] = tanh(x[i]);
end = clock();
cout << "tanh: " << double(end - begin) / CLOCKS_PER_SEC << "\n";
begin = clock();
for(int i=0; i < N; i++)
for(int j=0; j < N; j++)
y[i] = exp(x[i]);
end = clock();
cout << "exp: " << double(end - begin) / CLOCKS_PER_SEC << "\n";
return 0;
}