2016-12-04 2 views
0

expity.special의 expit 함수는 벡터화 된 시그 모이 드 함수입니다. 그것은 1/(1 + e^(- x))를 계산하는데, 이것은 아마도 Taylor 시리즈와 관련되어 복잡합니다.numpy.vectorize : 왜 이렇게 느린가요?

"fast sigmoid", 1/(1 + abs (x))에 대해 알게되었는데, 훨씬 빨라야합니다. 그러나 내장 된 expit 함수는 람다 식으로 전달할 때조차도 훨씬 뛰어납니다. ~ numpy.vectorize.

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

(가) 내장, 복잡한 시그 모이가 빠른 :

여기를 테스트하는 하나의 방법

%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 배 느린 :

%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} 

답변

2

numpy.vectorize의 속도가 느린 이유는 이전에 거의 확실하게 물어 보았지만 간단한 검색에서 분명히이 사실을 복제본으로 만드는 질문을 찾지 못했습니다. 여기에 답변하려면 vectorize docstring을 인용하자. "vectorize 함수는 주로 성능이 아닌 편의를 위해 제공되며 구현은 본질적으로 for 루프입니다."

1/(1 + abs(x))을 빠르게 만들고 싶습니다. numpy는 numpy.abs (또는 numpy.absolute이라고도 함 - 같은 개체의 다른 이름 임)이라는 기능이 있습니다. 인수의 각 요소의 절대 값을 계산하고 C 코드에서이를 수행하므로 빠릅니다. 또한 파이썬 내장 함수 abs은 numpy 배열이 수행하는 __abs__ 메서드를 가진 객체에 인수를 전달하는 방법을 알고 있으므로 파이썬의 abs()을 사용하여 numpy 배열의 요소 별 절대 값을 계산할 수도 있습니다. 다음에서는 np.abs을 사용하겠습니다.

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))가 상당히 빠르다 : 큰 배열 x에 대한 scipy.special.expit1.0/(1 + np.abs(x))의 성능을 비교 한 다음

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. ]) 

것 : 여기

np.abs의 사용의 예 expit(x)보다.

+0

; 이것은 확실히 내 문제를 해결합니다. 고마워, 워렌! –