2014-01-31 3 views
2

가장 좋은 방법은 무엇입니까? Python/Numpy - Matrix 다른 2D 배열의 2D 배열과 각 행에 곱하기

a = 3x3 array 
b = 20x3 array 
c = 20x3 array = some_dot_function(a, b) where: 
c[0] = np.dot(a, b[0]) 
c[1] = np.dot(a, b[1]) 
c[2] = np.dot(a, b[2]) 
...etc... 

나는이 간단한 파이썬 루프 또는 NumPy와의 apply_along_axis을 사용하여 수행 할 수 있습니다 알고 있지만, 완전히 NumPy와의 기본 C 코드 내에서이 작업을 수행하는 어떤 좋은 방법이 있는지 궁금 하군요. 나는 텐 드로도 (tensordot)와 다른 기능들을 보았지만 운이 없었습니다. 나는 또한 다음을 시도했다 :

결과는 실제 결과가 나왔지만 결과 배열은 20x3이 아니라는 점만 빼고는 거의 맞았다. 내가 원하는 배열로 바꿀 수있는 방법을 찾을 수 있을지도 모르겠지만 더 쉬울 것/클리너/명확한 내장 메서드가 있어야한다는 것을 알았다. 여기

numpy.dot(b, a.T) 

일부 출력 예이다 :

답변

6

이 (같은 날 모습) 올바른 결과를 제공

>>> a = numpy.arange(9).reshape(3, 3) 
>>> b = numpy.arange(60).reshape(20, 3) 
>>> numpy.dot(b, a.T) 
array([[ 5, 14, 23], 
     [ 14, 50, 86], 
     [ 23, 86, 149], 
     [ 32, 122, 212], 
     .... 
2
import numpy 
a = numpy.arange(9).reshape(3,3) 
b = numpy.arange(60).reshape(20,3) 
c1 = numpy.dot(b, a.T) # as in the answer of senderle 
c2 = numpy.einsum('ji,ki->kj',a,b) 

생성 된 C1 및 C2는 모두 동일하다 무엇을 원하십니까 (c[i] = np.dot(a, b[i])으로 확인)

의 장점3210은이 트릭 인 'ji,ki->kj'이 더 큰 차원에서 어떤 차원에서 수행되어야 하는지를 알려주는 것입니다. 예를 들어

einsum에

더 설명하면 다음 작업을 수행하려는 경우 :

a = numpy.arange(60.).reshape(3,4,5) 
b = numpy.arange(24.).reshape(4,3,2) 
d1 = numpy.zeros((5,2)) 

for i in range(5): 
    for j in range(2): 
     for k in range(3): 
      for n in range(4): 
       d1[i,j] += a[k,n,i] * b[n,k,j] 

당신이 수행하여 훨씬 빠르게 같은 일을 수행 할 수 있습니다

d2 = numpy.einsum('kni,nkj->ij', a, b) 
# the 'kni,nkj->ij' is what you otherwise do with the indices as in 
# d1[i,j] += a[k,n,i] * b[n,k,j] 

또는 이런 일을 지정하는 방식이 마음에 들지 않으면대신 numpy.tensordot을 사용할 수도 있습니다., 그리고 축을 지정 다음과 같이

d3 = numpy.tensordot(a,b, axes=([1,0],[0,1])) 

그래서이 einsum 방법은 (당신이 파이썬에서 그들이 할 수있는 경우는 true, 그렇지 않은 경우 느린 그), 매우 흥미로운 매우 일반적이며, 위해 - 루프 단축 할 수 있습니다 추가 정보를 펑키 텐서-물건

, 나는이 방법을 보았다 http://docs.scipy.org/doc/numpy/reference/generated/numpy.tensordot.htmlhttp://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html

+0

볼 수 있지만, 나는 그것이 어떻게 작동하는지 주위에 내 머리를 정리하고 수없는 것. 그것은 매우 강력 해 보입니다. 그리고 나는 그것에 대해 읽는 데 약간의 시간을 할애합니다. 심지어 문서에서도 예제를 통해이를 이해하는 가장 좋은 방법이 있다고 말합니다. 어쩌면 나는 더 많은 것을 가지고 놀아야 할 필요가 있을지 모르지만, 박쥐가 어떻게 작용 하는지를 이해하지 못한다. –

+0

@ScottB, 문자열을 생각하면 순수한 파이썬에서 일련의 중첩 된 루프를 사용하여 쓰는 경우 할당 문을 취할 양식을 지정하는 생각하십시오. 'i'는 가장 바깥 쪽 인덱스이고'j', next 등이며 형식은 {a 인덱스}, {b 인덱스} -> {출력 인덱스}입니다. 다시 말하면'output [i, j] + = a [i, j] * b [j, k]'는''ij, jk-> ij''가됩니다. 어떻게 작동하는지 확인하십시오. IMO는 '점'과 'T'를 사용하여 더 쉽게 읽을 수 있지만, 비정상적인 합계의 경우 '어둠'은 절대적으로 갈 길입니다. – senderle

+0

@ScottB d2 = 뒤에 몇 줄을 추가했습니다.좀 더 설명하기 위해, 당신이 그 인덱스를 가지고 무엇을하는지, 실제로 당신이 그것에 대해 머리를 갖게되면 아주 간단합니다. (d1 [i, j] = ...와 같은 4 중 for 루프처럼 쓰십시오. 당신이 색인으로하는 일을 쓰지 만, d2 =와 같이 한 줄에 써라. – usethedeathstar