4

numpy에서 두 개의 2 차원 배열의 요소 별 바깥 쪽 생성을 수행하려고합니다.numpy 요소 단위 바깥 쪽

A.shape = (100, 3) # A numpy ndarray 
B.shape = (100, 5) # A numpy ndarray 

C = element_wise_outer_product(A, B) # A function that does the trick 
C.shape = (100, 3, 5) # This should be the result 
C[i] = np.outer(A[i], B[i]) # This should be the result 

순진 구현은 다음과 같습니다.

tmp = [] 
for i in range(len(A): 
    outer_product = np.outer(A[i], B[i]) 
    tmp.append(outer_product) 
C = np.array(tmp) 

더 나은 솔루션은 스택 오버플로에서 영감을 얻었습니다.

big_outer = np.multiply.outer(A, B) 
tmp = np.swapaxes(tmp, 1, 2) 
C_tmp = [tmp[i][i] for i in range(len(A)] 
C = np.array(C_tmp) 

for 루프를 제거하는 벡터화 된 구현을 찾고 있습니다. 누구나 아이디어가 있습니까? 감사합니다.

+0

을 ', 형태로'100, 3, 100, 5' – Eric

답변

7

그들의 제 1 축과 정렬 유지 None/np.newaxis와, 상기 제 3 및 제 것과 함께 새로운 축을 도입 3DAB 연장하고 서로 곱한다. 이렇게하면 broadcasting을 벡터화 된 솔루션으로 사용할 수 있습니다.

따라서, 구현 될 것이다 -

A[:,:,None]*B[:,None,:] 

우리가의를 위해 ellipsis를 사용하여 조금을 단축 할 수있다 : :,:과 같은, B에 남은 마지막 축 목록 건너 -

A[...,None]*B[:,None] 

또 다른 벡터화 된 접근 방식으로 np.einsum을 사용할 수도 있습니다. 일단 문자열 표기법을 지나치면 더 직관적 일 수 있습니다. 구문 등 같은 순진 깨어나 구현에 관련된 반복자의 대표가되는 그 표기법, 고려 - 그것은 (A, B)`np.outer`에 다른`가치 np.multiply.outer 무엇이 들어

np.einsum('ij,ik->ijk',A,B) 
+0

또는 3 차원 이상에서 작동하는'np.einsum ('... j, ... k -> ... jk', A, B)' – Eric

+0

이러한 방법 중 어느 것도 루프보다 빠릅니다. 'Einsum'은 어레이에 대해 900ms가 걸리는데, 간단한 루프가 700ms 걸립니다. 'A [:, :, 없음] * B [:, 없음, :]'는 약 800입니다. – Swift