2014-11-22 3 views
2
Y, X = np.mgrid[-3:-3:10j, -3:3:10j] 

위와 같은 meshgrids에서 특정 작업을 적용 할 때 작업이 numpy와 호환되지 않을 수 있으므로 오류가 발생합니다. 때로는 sin, cos에 대한 numpy 함수 대안이 있지만 scipy.integrate의 quad 함수와 같은 모든 함수에 대한 함수가 없을 수 있습니다.numpy meshgrid 작업 문제

이 문제를 해결하려면 어떻게합니까? 전체 meshgrid에 작업을 적용해야합니다.

+3

그것은 당신이 당신이 모든 점에'quad'을 적용 할 필요가 있음을 말할 때 무엇을 의미 명확하지 않다 'meshgrid'에서. 'quad'는 함수가 적분되고, 적분 적분을위한 경계가 필요합니다. 다 변수 함수를 허용하는'integrate.nquad'와 각 좌표축에 대한 적분 한계를 제공하는'ranges'라는 구조가 있습니다. 하지만 질문에서 계산하려고하는 것이 명확하지 않습니다. – ely

+0

안녕하세요. 코드가 너무 길어서 실제로 두 개의 숫자 x와 y를 취하고 다른 숫자를 출력하는 MATHOPERATION (x, y)라는 함수가 있다고 가정 해 보겠습니다. 여기서 x와 y는 meshgrid에서 같은 위치를 차지하는 X와 Y의 숫자입니다. 따라서 MATHOPERATION (X, Y)의 출력은 X와 Y와 같은 크기의 meshgrid가됩니다. – user3065619

+0

이러한 작업이 ndarrays 위에 직접 작성되지 않았거나 C 코드 또는 Numba와 같은 도구로 작성되거나 Cython을 사용하면 meshgrid 배열에 저장된 연속 메모리에서 작동하도록 "벡터화"할 수 없습니다. 최선의 방법은 i와 j (행, 열)에 for 루프를 작성하고 함수를 호출 한 다음 사전 할당 된 2 차원 배열에 그 결과를 쓰는 것입니다. 반복되는 함수 호출은 느려질 것이고 프로파일을 작성하고 너무 느린 경우에는 numba와 같은 것을 사용하거나 C에서 직접 코딩해야합니다. – ely

답변

3

귀하의 질문은 (후속 의견에) 적어도 두 가지 방법으로 수행 할 수 있습니다 : 당신은 여러 인자의 기능이

  1. 을, 당신은에 그 함수를 호출 할 수 있도록하고 싶습니다 기본적으로 numpy로 지원되는 브로드 캐스트 된 통화와 구문 학적으로 유사한 방식입니다. 성능은 문제가 아니며 함수의 호출 구문입니다.

  2. numpy 배열의 시퀀스에서 평가되는 여러 인수의 함수가 있지만이 함수는 numpy 배열의 인접한 메모리 레이아웃을 이용할 수있는 방식으로 구현되지 않습니다. 성능이 문제입니다. 당신은 numpy 배열을 반복하고, 너무 느리다는 점을 제외하고는, 지루하고 평범한 for-loop 스타일로 함수를 호출하게되어 행복 할 것이다.

는 항목의 경우 1. 정기적으로 호출을 받아서 인수로 NumPy와 배열을 호출 할 수 있으며, NumPy와의 방송 규칙을 준수하는 호출을 반환 vectorize라는 NumPy와가 제공하는 편리한 기능이 있습니다. 지금은 2-D 격자 도처에서이 기능을 평가해야한다고 가정

def my_func(x, y): 
    return x + 2*y 

:

이 인위적인 예를 생각해 보자. 여기에 평범한 구식 지루한 방법입니다

Y, X = np.mgrid[0:10:1, 0:10:1] 
Z = np.zeros_like(Y) 

for i in range(Y.shape[0]): 
    for j in range(Y.shape[1]): 
     Z[i,j] = my_func(X[i,j], Y[i,j]) 

우리는 my_func 같은 몇 가지 다른 기능이 있다면, 2 차원 배열을 통해 주어진 함수를 "매핑"하는 기능으로이 과정을 일반화하기 좋은 수 있습니다.

import itertools 
def array_map(some_func, *arg_arrays): 
    output = np.zeros_like(arg_arrays[0]) 
    coordinates = itertools.imap(range, output.shape) 
    for coord in itertools.product(coordinates): 
     args = [arg_array[coord] for arg_array in arg_arrays] 
     output[coord] = some_func(*args) 
    return output 

이제 우리는 것처럼 그 array_map(my_func, X, Y) 행위를 볼 수있는 중첩에 대한 루프 : 우리가 array_map(my_func)를 호출하고 별도의 배열 인수를 생략 할 수 있다면 지금

In [451]: array_map(my_func, X, Y) 
Out[451]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

, 그것은 좋지 않을까? 대신 단지 for-loops를 수행하기 위해 기다리는 새로운 함수를 얻는 것입니다.

우리는 functools.partial하여이 작업을 수행 할 수 있습니다 - 그래서 우리는이 같은 쉽고 간단한 벡터 기 작성할 수 있습니다

import functools 
def vectorizer(regular_function): 
    awesome_function = functools.partial(array_map, regular_function) 
    return awesome_function 

을하고 그것을 밖으로 테스트 :

In [453]: my_awesome_func = vectorizer(my_func) 

In [454]: my_awesome_func(X, Y) 
Out[454]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

이제 my_awesome_func 동작합니다 당신이 할 수있는 것처럼 ndarrays 위에 직접 호출하는 것!

나는 많은 추가적인 작은 성능 세부 사항, 범위 검사 등을 간과했습니다.,이 장난감 버전을 만드는 동안 vectorizer ...하지만 운 좋게도 numpy에 이미 이것을 할 vectorize입니다! vectorize의 영업 이익을 내 이전 의견과 문서에서 강조로 다시 한번

In [455]: my_vectorize_func = np.vectorize(my_func) 

In [456]: my_vectorize_func(X, Y) 
Out[456]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

, -이 하지 속도 최적화입니다. 사실, 오버 루프를 호출하는 추가 함수는 for 루프를 직접 작성하는 것보다 느린 경우가 있습니다. 그러나 속도가 문제가되지 않는 경우이 메서드를 사용하면 사용자 지정 함수가 numpy와 동일한 호출 규칙을 따르도록 할 수 있습니다. 이렇게하면 라이브러리 인터페이스의 일관성을 향상시키고 코드를보다 일관성 있고 읽기 쉽게 만들 수 있습니다.

항목 2에 관해서는 이미 많은 것들이 이미 작성되었습니다. 문제가 있다면 메모리의 연속 블록을 활용하고 중복 된 동적 유형 검사를 사용하여 기능을 최적화해야합니다.) 파이썬 목록에 추가 여기에 몇 가지 링크는 도움이 될 수 있습니다

  1. < http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html>
  2. < http://csl.name/C-functions-from-Python/>
  3. < https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow>
  4. ,451,515,
  5. < nbviewer.ipython.org/url/jakevdp.github.io/downloads/notebooks/NumbaCython.ipynb>
+0

안녕 prpl. forloop 트릭을 시도했지만 사용중인 특정 기능에 대해 작동하지 않았습니다. 여기에 그것에 대해 새로운 질문을 만들었습니다 : http://stackoverflow.com/questions/27091037/numpy-iterating-calculations-in-a-meshgrid – user3065619

+1

'OverflowError' 수학 연산 결과 값이 너무 클 경우 발생합니다 표현할 수 있습니다. 'Emag'라는 이름으로 판단하겠습니다. 전자기 그리드 계산입니다. 그리고 아마도 여러분의 함수가 극을 포함한다면 극에 너무 근접한 값을 계산하고 수치 오버플로를 얻으려는 것입니다.어느 쪽이든, 이것은 그리드에서 계산하는 문제와 관련이 없으며 대신에 Emag의 정의 내에서 수학 연산을 사용하는 데있어 오류가 있습니다. – ely