[PYTHON] numpy 배열을 통해 함수를 매핑하는 가장 효율적인 방법
PYTHONnumpy 배열을 통해 함수를 매핑하는 가장 효율적인 방법
numpy 배열을 통해 함수를 매핑하는 가장 효율적인 방법은 무엇입니까? 현재 프로젝트에서 내가 해왔 던 방식은 다음과 같습니다.
import numpy as np
x = np.array([1, 2, 3, 4, 5])
# Obtain array of square of each element in x
squarer = lambda t: t ** 2
squares = np.array([squarer(xi) for xi in x])
그러나 이것은 아마도 매우 비효율적 인 것처럼 보입니다. 왜냐하면 새로운 배열을 파이썬리스트로 생성하기 위해 목록 이해력을 사용하여 다시 numpy 배열로 변환하기 때문입니다.
더 잘할 수 있을까요?
해결법
-
==============================
1.perfplot (내 작은 프로젝트)으로 np.array (map (f, x))와 제안 된 모든 메소드를 테스트했습니다.
perfplot (내 작은 프로젝트)으로 np.array (map (f, x))와 제안 된 모든 메소드를 테스트했습니다.
벡터화하려는 함수가 벡터화 된 경우 (예 : 원래 게시물의 x ** 2 예제),이를 사용하면 다른 어떤 것보다 훨씬 빠릅니다 (로그 스케일 참고).
실제로 벡터화가 필요한 경우 어떤 변형을 사용 하느냐가 중요하지 않습니다.
플롯을 재현하는 코드 :
import numpy as np import perfplot import math def f(x): # return math.sqrt(x) return np.sqrt(x) vf = np.vectorize(f) def array_for(x): return np.array([f(xi) for xi in x]) def array_map(x): return np.array(list(map(f, x))) def fromiter(x): return np.fromiter((f(xi) for xi in x), x.dtype) def vectorize(x): return np.vectorize(f)(x) def vectorize_without_init(x): return vf(x) perfplot.show( setup=lambda n: np.random.rand(n), n_range=[2**k for k in range(20)], kernels=[ f, array_for, array_map, fromiter, vectorize, vectorize_without_init ], logx=True, logy=True, xlabel='len(x)', )
-
==============================
2.numpy.vectorize를 사용하는 것은 어떻습니까?
numpy.vectorize를 사용하는 것은 어떻습니까?
>>> import numpy as np >>> x = np.array([1, 2, 3, 4, 5]) >>> squarer = lambda t: t ** 2 >>> vfunc = np.vectorize(squarer) >>> vfunc(x) array([ 1, 4, 9, 16, 25])
http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.vectorize.html
-
==============================
3.내 경험상, np.fromiter는 일반적으로 서로 다른 크기의 배열과 다른 컴파일러의 Python과 NumPy의 다른 버전에서 가장 빠릅니다. 다음은 간단한 예입니다.
내 경험상, np.fromiter는 일반적으로 서로 다른 크기의 배열과 다른 컴파일러의 Python과 NumPy의 다른 버전에서 가장 빠릅니다. 다음은 간단한 예입니다.
import numpy as np x = np.array([1, 2, 3, 4, 5]) f = lambda x: x ** 2 squares = np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))
count는 선택 사항입니다. 적어도 수백 개의 요소가있는 배열에 대해 np.vectorize를 사용하는 것이 좋습니다 (Nico의 답변에있는 플롯 참조).
다음은 Python 2.7 및 NumPy 1.9를 사용하여 함수를 매핑하는 세 가지 방법을 비교하는 간단한 테스트입니다. 첫째, 테스트를위한 설정 기능 :
import timeit import numpy as np f = lambda x: x ** 2 vf = np.vectorize(f) def test_array(x, n): t = timeit.timeit( 'np.array([f(xi) for xi in x])', 'from __main__ import np, x, f', number=n) print('array: ' + str(t)) def test_fromiter(x, n): t = timeit.timeit( 'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))', 'from __main__ import np, x, f', number=n) print('fromiter: ' + str(t)) def test_vectorized(x, n): t = timeit.timeit( 'vf(x)', 'from __main__ import x, vf', number=n) print('vectorized: ' + str(t))
다섯 가지 요소를 사용하면 np.fromiter가 가장 빠르며 np.vectorize는 설정 비용 때문에 훨씬 느립니다.
x = np.array([1, 2, 3, 4, 5]) n = 100000 test_array(x, n) # 0.616514921188 test_fromiter(x, n) # 0.585698843002 test_vectorized(x, n) # 2.6228120327
요소가 100 개인 모든 메소드는 거의 동일합니다.
x = np.arange(100) n = 10000 test_array(x, n) # 0.519502162933 test_fromiter(x, n) # 0.500586986542 test_vectorized(x, n) # 0.525988101959
그러나 배열 요소가 1000 개 이상인 경우 벡터화 된 방식이 가장 효율적입니다.
x = np.arange(1000) n = 1000 test_array(x, n) # 0.472352981567 test_fromiter(x, n) # 0.453316926956 test_vectorized(x, n) # 0.291934967041
그러나 다른 버전의 Python / NumPy와 컴파일러 최적화는 다른 결과를 가지므로 사용자 환경에 대해 비슷한 테스트를 수행하십시오.
-
==============================
4.
squares = squarer(x)
배열에 대한 산술 연산은 자동으로 요소 단위로 적용되며 효율적인 C 수준 루프는 Python 수준의 루프 나 이해에 적용되는 모든 인터프리터 오버 헤드를 피합니다.
NumPy 배열에 elementwise를 적용하려는 대부분의 함수는 작동하지만 일부는 변경해야 할 수도 있습니다. 예를 들어, if 요소가 작동하지 않습니다. numpy와 같은 구문을 사용하도록 변환하려고합니다.
def using_if(x): if x < 5: return x else: return x**2
된다
def using_where(x): return numpy.where(x < 5, x, x**2)
-
==============================
5.나는 새로운 버전 (나는 1.13을 사용한다)을 numpy로 믿는다. numpy 배열을 넘겨서 스칼라 타입으로 작성한 함수를 호출하면 함수가 numpy 배열을 통해 자동으로 각 요소에 적용되어 반환된다. 또 다른 배열
나는 새로운 버전 (나는 1.13을 사용한다)을 numpy로 믿는다. numpy 배열을 넘겨서 스칼라 타입으로 작성한 함수를 호출하면 함수가 numpy 배열을 통해 자동으로 각 요소에 적용되어 반환된다. 또 다른 배열
>>> import numpy as np >>> squarer = lambda t: t ** 2 >>> x = np.array([1, 2, 3, 4, 5]) >>> squarer(x) array([ 1, 4, 9, 16, 25])
-
==============================
6.이 게시물에서 언급했듯이 생성기 표현식을 다음과 같이 사용하십시오.
이 게시물에서 언급했듯이 생성기 표현식을 다음과 같이 사용하십시오.
numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)
-
==============================
7.어쩌면이 질문에 직접 대답하지 않을 수도 있지만 numba가 기존의 파이썬 코드를 병렬 기계 명령어로 컴파일 할 수 있다고 들었습니다. 나는 실제로 그것을 사용할 기회가있을 때이 게시물을 다시 읽고 개정 할 것입니다.
어쩌면이 질문에 직접 대답하지 않을 수도 있지만 numba가 기존의 파이썬 코드를 병렬 기계 명령어로 컴파일 할 수 있다고 들었습니다. 나는 실제로 그것을 사용할 기회가있을 때이 게시물을 다시 읽고 개정 할 것입니다.
-
==============================
8.아마 vectorize를 사용하는 것이 더 좋습니다.
아마 vectorize를 사용하는 것이 더 좋습니다.
def square(x): return x**2 vfunc=vectorize(square) vfunc([1,2,3,4,5]) output:array([ 1, 4, 9, 16, 25])
from https://stackoverflow.com/questions/35215161/most-efficient-way-to-map-function-over-numpy-array by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] id () 함수는 무엇을 위해 사용됩니까? (0) | 2018.10.03 |
---|---|
[PYTHON] 파이썬에서는 YAML 매핑을 OrderedDicts로 어떻게로드 할 수 있습니까? (0) | 2018.10.03 |
[PYTHON] sys.stdout.flush () 메서드 사용 (0) | 2018.10.03 |
[PYTHON] 바이너리 실행 파일로 파이썬 스크립트를 컴파일하는 법 (0) | 2018.10.03 |
[PYTHON] 다양한 깊이의 중첩 된 사전 값 업데이트 (0) | 2018.10.03 |