2014-12-24 2 views
1

어리석은 것을 묻는다면 미리 사과 할 것이지만 실제로는 apply_along_axis의 작동 방식을 이해하고 있다고 생각합니다. 나는 방금 고려하지 않은 최악의 경우일지도 모르는 무언가에 부딪 쳤지 만 그것은 나에게 당황 스럽다. 즉,이 나를 혼란 코드입니다 :numpy의 축에 대한 혼란과 축의 내포도

class Leaf(object): 

    def __init__(self, location): 
     self.location = location 

    def __len__(self): 
     return self.location.shape[0] 

def bulk_leaves(child_array, axis=0): 
    test = np.array([Leaf(location) for location in child_array]) # This is what I want 
    check = np.apply_along_axis(Leaf, 0, child_array) # This returns an array of individual leafs with the same shape as child_array 
    return test, check 

if __name__ == "__main__": 
    test, check = bulk_leaves(np.random.ran(100, 50)) 
    test == check # False 

난 항상 NumPy와 가진 지능형리스트를 사용하고 배열로 다시 캐스팅 바보 느끼지만, 난 그냥이 작업을 수행하는 또 다른 방법의 확인도 해요 . 나는 명백한 무엇인가 놓치고 있냐?

+0

'apply_along_axis'는 결코 입력을 수정하지 않습니다. 새 배열을 반환합니다. – BrenBarn

+0

잘못 말했는데, 체크가 모양이 child_array와 같음을 의미했습니다. –

+0

'child_array '란 무엇입니까? – BrenBarn

답변

2

문제는 apply_along_axis 반환 된 개체가 스칼라 여부를 확인하는 isscalar를 사용하는 것 같다,하지만 isscalar 반환 사용자 정의 클래스에 대한 False. apply_along_axisdocumentation 말한다 : outarr의

형상은 outarr의 길이 func1d의 반환 값의 크기와 동일 축 치수에 따라 제외 도착의 형상과 동일하다.

클래스의 __len__은 감싸는 배열의 길이를 반환하므로 numpy는 결과 배열을 원래 모양으로 "확장합니다". __len__을 정의하지 않으면 numpy가 사용자 정의 유형이 스칼라라고 생각하지 않으므로 오류가 발생하므로 len을 계속 호출하려고 시도합니다.

필자가 볼 수있는 한 사용자 정의 클래스로이 작업을 수행 할 수있는 방법이 없습니다. __len__에서 1을 반환 할 수 있지만 길이가 N 인 1D 배열이 아닌 Nx1 2D 결과를 얻을 수 있습니다. Numpy가 사용자 정의 인스턴스를 스칼라로 보는 방법은 없습니다.

거기 apply_along_axis 행동에 대해 a numpy bug이지만, 놀랍게도 나는 비 NumPy와 객체에 대한 그 isscalar 반환 거짓 기본 문제의 토론을 찾을 수 없습니다. 사용자 정의 유형이 벡터인지 스칼라인지 아닌지 추측하지 않고 펀치하기로 결정한 것일 수도 있습니다. 그래도 Numpy 목록에서 이것에 대해 물어볼 가치가 있습니다. 이상한 점은 isscalar(object())이 False를 반환한다는 것입니다.

그러나 어쨌든 성능에 신경 쓰지 않는다고해도별로 중요하지 않습니다. 이미 원하는대로하는 목록 이해력으로 첫 번째 방법을 사용하십시오.

+0

아, 정말 고마워! 그래, 내가 말했듯이, 그것은 실제 성능 문제가 아니며, 그것은 나에게 당황 스러웠다. 내 목표는 스칼라가 아닙니다.하지만 len -> 1 해킹 또는 아래의 @hpaulj에서 제안한 해결 방법이 성능상의 이점이 있는지 확인하기 위해 빠른 벤치 마크를 실행할 수 있지만 이것이 일어나는 이유는 알 수 있습니다. 나를 위해 충분하다. 정말 고마워! –

+0

저 numpy 버그가 이제 master에서 패치되었고, 1.13 릴리스를 만들어야합니다. – Eric

+0

@Eric : 감사합니다. 좋은 소식입니다! 'isscalar'의 기본 이슈에서 numpy 위치는 사용자 정의 클래스에서 항상 false를 리턴합니까? – BrenBarn

4

apply_along_axis은 자신을보고 해독 할 수있는 순수한 파이썬입니다. 이 경우에 본질적 않는다 : 다른 말로

check = np.empty(child_array.shape,dtype=object) 
for i in range(child_array.shape[1]): 
    check[:,i] = Leaf(child_array[:,i]) 

, 그것은 반복와 값을 채우고 다음 컨테이너 배열을 미리 할당하고. 확실히 배열에 추가하는 것보다 낫지 만 목록에 값을 추가하는 것보다 더 나은 경우는 거의 없습니다 (이해가 무엇을하는지).

위의 템플릿을 사용하여 실제로 원하는 배열을 만들 수 있습니다.

for i in range(check.shape[0]): 
    check[i]=Leaf(child_array[i,:]) 

빠른 테스트에서이 반복은 이해와 같습니다. apply_along_axis은 잘못된 것 외에도 속도가 느립니다.

+0

소스를 살펴 줘서 고마워. 퍼포먼스에 변화가 있을지 여부에 대한 좋은 직감은 없지만 혼란스러운 핵심 이슈를 찾은 BrenBard의 대답을 받아 들여야합니다. –

관련 문제