2017-01-03 9 views
3

정상 내적 가정 이 질문은 평행하다 Numpy: Dot product with max instead of sumSciPy 스파 스 및 밀도 행렬을 통해 내적의 일반화는

이제 해결책을 생각하십시오.

또는

M3 = np.max(M1[:,:,None]*M2[None,:,:], axis=1) 

치밀한 매트릭스 M1 및 희소 행렬 M2 참조한다. 불행히도 SciPy에서는 3D 스파 스 행렬을 사용할 수 없습니다.

기본적으로,이

M3[i,k] = max_j(M1[i,j] * M2[j,k]) 

우리는 j 등이 M2[j,k]!=0 반복 것을 의미 할 것입니다.

이 문제를 해결하는 가장 효율적인 방법은 무엇입니까? 검증

from scipy.sparse import csr_matrix 
import scipy as sp 

def reduce_after_multiply(M1, M2): 
    # M1 : Nump array 
    # M2 : Sparse matrix 
    # Output : NumPy array 

    # Get nonzero indices. Get start and stop indices representing 
    # intervaled indices along the axis of reduction containing 
    # the nonzero indices. 
    r,c = sp.sparse.find(M2.T)[:2] 
    IDs, start = np.unique(r,return_index=1) 
    stop = np.append(start[1:], c.size) 

    # Initialize output array and start loop for assigning values 
    m, n = M1.shape[0], M2.shape[1] 
    out = np.zeros((m,n)) 
    for iterID,i in enumerate(IDs): 

     # Non zero indices for each col from M2. Use these to select 
     # M1's cols and M2's rows. Perform elementwise multiplication. 
     idx = c[start[iterID]:stop[iterID]] 
     mult = M1[:,idx]*M2.getcol(i).data 

     # Use the inteneded ufunc along the second axis. 
     out[:,i] = np.max(mult, axis=1) # Use any axis supported ufunc here 
    return out 

샘플 실행 - -

+0

방금 ​​수행하기 위해 찾고 계십니까 따라서, 우리는 희소 행렬에 조밀 한 배열의 첫 번째 입력을 변환 할 수 있습니다 다음과 같이, 희소 행렬의 .dot method를 사용 점 제품이나 '최대'도? – Divakar

+0

궁극적으로'max'. 저는 '합'을 '최대', '최소'또는 다른 함수로 대체 할 수있는 일반화 된 솔루션을 원했습니다. 그러나 '최대'는 그 순간 매우 중요 할 것입니다. –

답변

2

여기 감소의 공통 축을 통해 반복 한 루프를 사용하여 접근 방식 도트 제품에 대한 구체적

In [248]: # Input data 
    ...: M1 = np.random.rand(5,3) 
    ...: M2 = csr_matrix(np.random.randint(0,3,(3,1000))) 
    ...: 
    ...: # For variety, let's make one column as all zero. 
    ...: # This should result in corresponding col as all zeros as well. 
    ...: M2[:,1] = 0 
    ...: 

In [249]: # Verify 
    ...: out1 = np.max(M1[:,:,None]*M2.toarray()[None,:,:], axis=1) 

In [250]: np.allclose(out1, reduce_after_multiply(M1, M2)) 
Out[250]: True 

을, 우리가 가지고 내장 된 도트 방법이며 그와 같이 간단합니다. 의도이를 확인하자

csr_matrix(M1).dot(M2) 

- -

In [252]: # Verify 
    ...: out1 = np.sum(M1[:,:,None]*M2.toarray()[None,:,:], axis=1) 

In [253]: out2 = csr_matrix(M1).dot(M2) 

In [254]: np.allclose(out1, out2.toarray()) 
Out[254]: True 
+0

이 제안서를주의 깊게 읽어야 할 것이지만 파이썬 루프가있는 버전도 구현했습니다. 그러나 여기에 나는 믿을 수 없을 정도로 느린 파이썬이 C와 비교되는 것을 깨달았다. ... –

+0

그것은 여기에 반드시 적용할만한 것은 아니지만,이 오래된 대답이 흥미 롭다. 'as_strided'를 사용하여'csr' 행렬의 행을 반복합니다 : http://stackoverflow.com/a/20062157/901925. 누군가가 방금 코멘트를 달 때까지 나는 그것을 잊었다. – hpaulj

+0

@hpaulj 감사합니다! 스파 스 매트릭스에 걸음 걸이가 나를 위해 새로운 것처럼 들립니다. 그럼, 꼭 봐봐! – Divakar