2016-11-27 3 views
1

[200000,10], [10,100000]의 두 개의 조밀 한 행렬이 있습니다. 행렬을 얻으려면 이들을 곱해야합니다 C. 결과 행렬이 메모리에 맞지 않기 때문에 직접 할 수는 없습니다. 게다가, 전체 요소 수의 1-2 %와 같이 결과 행렬에서 몇 개의 요소 만 필요합니다. 제 3의 매트릭스 W [200000100000]은 희박하며 행렬에서 나에게 흥미로운 장소에 0이 아닌 요소를 가지고 있습니다. C. W을 "마스크"로 사용하여 결과 행렬 C이 희박하고 필요한 요소 만 포함 할 수 있습니까?두 배열 간의 행렬 곱셈을 수행하고 마스크 된 위치에서만 결과 얻기

답변

3

행렬 곱셈은 점 제품의 테이블 일 뿐이므로 필요한 특정 점 곱을 벡터화 된 방식으로 수행 할 수 있습니다.

import numpy as np 
import scipy as sp 

iX, iY = sp.nonzero(W) 
values = np.sum(A[iX]*B[:, iY].T, axis=-1) #batched dot product 
C = sp.sparse.coo_matrix(values, np.asarray([iX,iY]).T) 
+0

'sp.nonzero'를 잘 사용했습니다! 빠른 대안이 될 수 있습니다. 내 게시물에서 언급해도 괜찮습니까? :) – Divakar

+0

'sp.nonzero'와'sp.find'는 거의 동일합니다.'coo' 형식의 속성을 반환합니다. 'find'는'data' 속성도 반환합니다. 'W'가 이미'coo' 인 경우'row'와'col' 속성을 직접 사용하십시오. – hpaulj

+1

'scipy.nonzero'는'np.nonzero'이며, 차례로'W.nonzero'를 나타냅니다. 더 자세히 살펴보면'sparse.find'는'csr' 형식을 통해 왕복하여 중복을 합산하기 때문에 속도가 느립니다. 'iX, iY = W.row, W.col'은 더 빠릅니다 (W가 이미 coo 인 경우). – hpaulj

3

먼저 W에서 0이 아닌 장소의 색인을 가져온 다음 A의 i 번째 행에 B의 j 번째 열을 곱하여 결과 행렬의 (i,j) 요소를 가져와 저장할 수 있습니다. 그 결과를 행렬로 저장하는 대신 튜플 (i,j,res) (이것은 희소 행렬을 저장하는 올바른 방법입니다)으로 저장합니다.

+1

경우 당신이 당신의 대답을 조금 더 살피면, 나는 이것이이 문제와 함께 갈 수있는 적절한 방법이라고 믿습니다. –

+0

이것은 확실히 가능한 해결책입니다. 그러나 200m 요소 (200000x100000의 1 %)를 반복하는 것을 포함합니다. 나는 벡터화 된 솔루션을 원할 것입니다. (만약 하나가 있다면) – tokarev

+0

W에 0 요소 만있는 완전한 라인을 가지고 있다면, A에있는 해당 라인을 0으로 만들 수 있고 0으로 끝나는 완전한 컬럼을 가지고 있다면 똑같이 할 수 있습니다. B에 해당 요소를 넣은 다음'scipy.sparse '를 사용하여 행렬을 곱합니다. –

3

는 여기 벡터화 된 솔루션을 np.einsum를 사용하여 하나의 접근 방식 -

from scipy import sparse 
from scipy.sparse import coo_matrix 

# Get row, col for the output array 
r,c,_= sparse.find(W) 

# Get the sum-reduction using valid rows and corresponding cols from A, B 
out = np.einsum('ij,ji->i',A[r],B[:,c]) 

# Store as sparse matrix 
out_sparse = coo_matrix((out, (r, c)), shape=W.shape) 

샘플 실행 -

1) 입력 : 직접 수행하는 조밀 한 배열을 사용하여

In [168]: A 
Out[168]: 
array([[4, 6, 1, 1, 1], 
     [0, 8, 1, 3, 7], 
     [2, 8, 3, 2, 2], 
     [3, 4, 1, 6, 3]]) 

In [169]: B 
Out[169]: 
array([[5, 2, 4], 
     [2, 1, 3], 
     [7, 7, 2], 
     [5, 7, 5], 
     [8, 5, 0]]) 

In [176]: W 
Out[176]: 
<4x3 sparse matrix of type '<type 'numpy.bool_'>' 
    with 5 stored elements in Compressed Sparse Row format> 

In [177]: W.toarray() 
Out[177]: 
array([[ True, False, False], 
     [False, False, False], 
     [ True, True, False], 
     [ True, False, True]], dtype=bool) 

2) 나중에 계산 및 결과 확인 :

,515,
In [171]: (A.dot(B))*W.toarray() 
Out[171]: 
array([[52, 0, 0], 
     [ 0, 0, 0], 
     [73, 57, 0], 
     [84, 0, 56]]) 

3) 제안 된 코드를 사용하여 스파 스 매트릭스 출력을 얻을 :

In [172]: # Using proposed codes 
    ...: r,c,_= sparse.find(W) 
    ...: out = np.einsum('ij,ji->i',A[r],B[:,c]) 
    ...: out_sparse = coo_matrix((out, (r, c)), shape=W.shape) 
    ...: 

4) 마지막으로 조밀/배열 버전으로 변환하는 직접 버전에서 확인하여 결과를 확인 -

In [173]: out_sparse.toarray() 
Out[173]: 
array([[52, 0, 0], 
     [ 0, 0, 0], 
     [73, 57, 0], 
     [84, 0, 56]])