2015-01-31 2 views
1

3D 공간에서 스칼라, 벡터 및 행렬의 시퀀스를 나타내는 모양이 (N,), (N, 3) 및 (N, 3,3)의 numpy 배열로 작업하고 있습니다.numpy 점 제품 및 행렬 제품

def dot_product(v, w): 
    return np.einsum('ij, ij -> i', v, w) 

def matrix_vector_product(M, v): 
    return np.einsum('ijk, ik -> ij', M, v) 

def matrix_matrix_product(A, B): 
    return np.einsum('ijk, ikl -> ijl', A, B) 

당신은 내가 더 나은 솔루션의 부족 einsum을 사용하여 볼 수 있듯이 다음과 같이 나는 점별 내적, 행렬 곱셈, 행렬/벡터 곱셈을 구현했습니다. 놀랍게도 나는 np.dot를 사용할 수 없었습니다 ...이 필요에 적합하지 않은 것 같습니다. 이 기능을 구현하기 위해 더 절제된 방법이 있습니까?

특히 함수가 첫 번째 누락 축을 브로드 캐스팅하여 shape (3,) 및 (3,3)에서도 작동 할 수 있으면 좋을 것입니다. 줄임표가 필요하다고 생각하지만 결과를 얻는 방법을 이해하지 못합니다.

+0

2 개의 입력의 크기에 따라''ij, ij ... '문자열을 생성하는 것이 어렵지 않아야합니다. 이러한 인덱스를 지정하는 하위 목록 방법도 있습니다. – hpaulj

+0

'N = 3'이면 규칙은 무엇입니까? 즉. 2 개 (3,3) 배열. 'ij, ij-> i'또는 'jk, ik-> ij'또는 'jk, kl-> jl'? – hpaulj

답변

4

이러한 조작은 일반 BLAS 호출로 재 형성 될 수 없으며 BLAS 호출을 루핑하면이 크기의 배열에 대해 매우 느립니다. 이와 같이 einsum은 이러한 종류의 작업에 최적 일 수 있습니다. 그냥 메모를 작업으로

def dot_product(v, w): 
    return np.einsum('...j,...j->...', v, w) 

def matrix_vector_product(M, v): 
    return np.einsum('...jk,...k->...j', M, v) 

def matrix_matrix_product(A, B): 
    return np.einsum('...jk,...kl->...jl', A, B) 
+1

그리고 이것들은'v = np.ones ((3))'와'A = np.ones ((3,3))'와 함께 작동합니다. 세 가지 시나리오를 결합하는 분명한 방법은 없습니다. – hpaulj

+0

나에게 이상한 것,이 다른 질문 http://stackoverflow.com/questions/28230296/numpy-row-order-in-the-representation-of-vector-funcions 나는 http : //로 지적했다. /legacy.python.org/dev/peps/pep-0465/ 새로운 연산자 '@'를 파이썬에 추가하여 필요한 작업을 정확하게 수행해야한다고 제안합니다 (올바르게 이해한다면). 그래서 numpy 커뮤니티는 현재 어떤 전용 함수에 의해서도 수행되지 않는 연산을 수행하는 새로운 파이썬 연산자를 제안하고있는 것 같습니다. –

+2

파이썬 커뮤니티는'@'연산자를 추가 할 수 있지만'numpy' 개발자가 될 것입니다 누가'ndarray '에 의미를 부여 하느냐고. 당신이 원하는 종류의 방송을 포함할지 여부는 공개적인 질문입니다. – hpaulj

2

,이 3 계산도 같이 쓸 수있다 : 다음과 같이

귀하의 기능을 타원으로 일반화 될 수

np.einsum(A,[0,1,2],B,[0,2,3],[0,1,3]) 
np.einsum(M,[0,1,2],v,[0,2],[0,1]) 
np.einsum(w,[0,1],v,[0,1],[0]) 

또는 오피 온의 일반화와

np.einsum(A,[Ellipsis,1,2], B, ...) 

[0,1,..] 목록을 생성하는 것이 어렵지 않습니다. b 입력 배열의 차원에 따라 달라집니다. einsum 식을 일반화에 초점을 맞춤으로써


, 나는 당신이 재현하려고하는 것은 N 작은 점의 제품이라는 사실을 놓쳤다.

np.array([np.dot(i,j) for i,j in zip(a,b)]) 

그것은 np.dot 빠른 컴파일 된 코드를 사용하는 마음을 유지하는 가치와 배열이 큰 계산에 초점을 맞추고 있습니다. 문제가 많은 작은 점 제품을 계산하는 것입니다.

그리고 축을 정의 여분의 인수없이

np.dot는 다음과 같이 표현 될 수있는 가능한 조합들 중 2 수행

np.einsum('i,i', v1, v2) 
np.einsum('...ij,...jk->...ik', m1, m2) 

동일한 제약에 직면 할 dot의 조작 판 - 별도 파라미터 축을 결합하는 방법을 지정하십시오.

또한 tensordotdot을 일반화하기 위해 무엇을주의하는 것이 유익 할 수있다 :

def tensordot(a, b, axes=2): 
    .... 
    newshape_a = (-1, N2) 
    ... 
    newshape_b = (N2, -1) 
    .... 
    at = a.transpose(newaxes_a).reshape(newshape_a) 
    bt = b.transpose(newaxes_b).reshape(newshape_b) 
    res = dot(at, bt) 
    return res.reshape(olda + oldb) 

그것은 여러 축에 걸쳐 합계와 dot을 수행 할 수 있습니다. 그러나 조 변경 및 재 형성이 완료되면 계산은 2 차원 배열이있는 표준 dot이됩니다.


이것은 중복 문제로 표시되었을 수 있습니다. 사람들은 한동안 여러 점 제품을 사용하는 것에 대해 묻고 있습니다.

Matrix vector multiplication along array axes 는 동일시 numpy.core.umath_tests.matrix_multiply

https://stackoverflow.com/a/24174347/901925 사용하여 제안 :

matrix_multiply 노트에 대한 C 문서
matrix_multiply(matrices, vectors[..., None]) 
np.einsum('ijk,ik->ij', matrices, vectors) 

:

* This implements the function 
* out[k, m, p] = sum_n { in1[k, m, n] * in2[k, n, p] }. 

inner1d 같은 디렉토리에서이에 대해 동일한 같은 일벡터

inner1d(vector, vector) 
np.einsum('ij,ij->i', vector, vector) 
# out[n] = sum_i { in1[n, i] * in2[n, i] } 

모두 UFunc, 그리고 가장 오른쪽 차원에 방송 처리 할 수 ​​있습니다. numpy/core/test/test_ufunc.py에서 이러한 기능은 UFunc 메커니즘을 실행하는 데 사용됩니다.

matrix_multiply(np.ones((4,5,6,2,3)),np.ones((3,2))) 

https://stackoverflow.com/a/16704079/901925는, 계산 이런 종류의

(w*v).sum(-1) 
(M*v[...,None]).sum(-1) 
(A*B.swapaxes(...)).sum(-1) 
추가 시험에

, 나는 inner1dmatrix_multiplydotmatrix-matrix 제품의 경우 일치합니다 예를 들어, * 및 합계와 함께 할 수있는 추가 [...,None]을 추가하면 matrix-vector 사례가 표시됩니다. 그들은 내 기계 및 테스트 배열에서 einsum 버전보다 2 배 빠릅니다.

numpy@ 삽입 연산자에 대한 설명입니다. 나는 numpy 개발자들이 파이썬 프로젝트보다이 PEP에 대한 열정이 적다 고 생각한다.

+0

BLAS가 왜 느린지에 대한 좋은 설명. 중간 텐서 (intermediate tensors)와 BLAS 콜을 사용하여 'einsum'표현을 최적화하려고합니다. 이것이 우리가 고려해야 할 시나리오인지 궁금합니다. PR [여기] (https://github.com/numpy/numpy/pull/5488)을 확인하십시오. – Daniel

+0

작년에'einsum' 버그 (Ellipsis 관련) 작업을하면서 필자는 순수한 Python 시뮬레이터를 작성했습니다. 인덱스 문자열의 구문 분석을 추적하는 데 도움이 될 수 있습니다.코드는 https://github.com/hpaulj/numpy-einsum에 있으며, – hpaulj