2014-12-07 11 views
1

이것은 내 코드에서 자주 발생하는 상황입니다. do_sth(a,b)이라는 함수가 있다고 가정 해보십시오.이 예에서는 단지 a+b이고, 배열이나 스칼라는 1D numpya,b으로 계산됩니다. 많은 경우에 연산을 브로드 캐스팅하는 함수가 필요하므로 a,b이 모두 1D 배열 인 경우 결과는 2D 배열이됩니다. 무슨 뜻인지의 예는 다음과 같습니다numpy 계산의 입출력 유효성 검사/캐스팅

do_sth(1,2) -> 3 
do_sth([1,2],0) -> array([1, 2]) 
do_sth(0,[3,4]) -> array([3, 4]) 
do_sth([1,2],[3,4]) -> array([[4, 5], [5, 6]]) 

이는 방법 NumPy와에게 ufunc 동작합니다에 조금 비슷합니다. 가능한 구현은 다음과 같습니다.

from numpy import newaxis, atleast_1d 

def do_sth(a, b): 
    "a,b should be either 1d numpy arrays or scalars" 
    a, b = map(atleast_1d, [a, b]) 
    # the line below mocks a more complicated calculation 
    res = a[:, newaxis] + b[newaxis] 

    conds = [a.size == 1, b.size == 1] 

    if all(conds): 
     return res[0, 0] 
    elif any(conds): 
     return res.ravel() 
    else: 
     return res 

보시다시피 상당히 많은 상용구가 있습니다. 첫 번째 질문은이 입출력 캐스트를 수행하는 올바른 방법인가? 이와 같은 상황을 처리하기 위해 데코레이터를 사용하지 않는 이유가 있습니까? 이 문제에 대한 지침이 있습니까?

a 또는 b이 2D, 3D 모양의 numpy 배열 인 경우 더욱 복잡한 계산이 추가로 잘못 처리되는 경우가 종종 있습니다. 나는 계산이 실패하는 지점이 분명하지 않거나 코드의 다른 개정에서 시간에 따라 변할 수 있다는 점에서 나쁘게 말하며 오류와 잘못된 입력 모양 사이의 연결을 보는 것은 어렵습니다. 그런 다음 복잡한 계산을 try/except 블록 (다음 Python EAFP)에 두는 것은 좋지 않습니다. 이 경우 함수의 시작 부분에있는 2 개의 배열의 모양을 확인하는 것이 맞습니까? 어떤 대안이 있습니까? 동시에 numpy 배열로 입력을 변환 할 수있는 numpy 함수가 있습니까? 또한 입력이 특정 수의 차원 (예 : asarray_withdim(arr,ndim=5))과 호환되는지 확인하십시오.

+0

ufuncs에는'outer' 메쏘드가 있습니다 - 당신의 함수'do_sth (a, b)'는 정확하게'np.add.outer (a, b)'처럼 보입니다. 비록 이것이 완전히 당신의 질문을 해결하는지 모르겠습니다. –

+1

'numpy' 함수를 준수하지 않는 경우 종종 입력을 편리한 차원으로 분류하는 많은 코드가 있습니다. 그런 다음 핵심 작업을 수행 한 다음 최종 재 형식화 및 유형 랩핑을 수행합니다. 그들은 충분한 차원이 있는지 확인하기 위해'np.atleast_2d'와 같은 함수를 사용할 수도 있고 초과 된 차원을 압축하는'.reshape (-1,1,1)'을 사용할 수도 있습니다. – hpaulj

+0

@ajcr, 이것에 대해 조사해 주셔서 감사합니다,하지만 여기에 추가는 간단한 예입니다. 제 코드에서는 좀 더 복잡한 계산을하고 있습니다. – gg349

답변

1

데코레이터 사용에 관해서는 numpy 코드에서 데코레이터를 많이 사용하지는 않았지만 대부분의 기능은 데코레이터가 파이썬에서 일반적으로 사용되기 전에 개발 되었기 때문에 생각합니다. 작동하도록 만들 수 있다면 단점이 있어서는 안됩니다 (하지만 장식가 또는 ufunc의 전문가가 아닙니다).

표준을 준수하지 않는 numpy 함수는 입력을 편리한 치수로 마사지하는 코드가 많습니다. 그런 다음 핵심 작업을 수행 한 다음 최종 재 형식화 및 유형 랩핑을 수행합니다. np.atleast_2d와 같은 함수를 사용하여 차원이 충분한 지 확인하고 초과 된 차원을 압축하려면 .reshape (-1,1,1)를 사용합니다.

np.tensordot은 입력에 축 전치 + 변형을 수행하여 컴파일 된 np.dot을 적용 할 수있는 예제입니다. np.insertndimisinstance 테스트로 시작합니다. 특별한 경우는 조기에 처리되지만 일반적인 경우는 끝까지 처리됩니다. np.einsum이 컴파일되었지만 C 코드에서 많은 양의 사전 처리가 이루어지기 전에 최종적으로 nditer 개체가 생성되고 계산됩니다.