[200000,10], [10,100000]의 두 개의 조밀 한 행렬이 있습니다. 행렬을 얻으려면 이들을 곱해야합니다 C. 결과 행렬이 메모리에 맞지 않기 때문에 직접 할 수는 없습니다. 게다가, 전체 요소 수의 1-2 %와 같이 결과 행렬에서 몇 개의 요소 만 필요합니다. 제 3의 매트릭스 W [200000100000]은 희박하며 행렬에서 나에게 흥미로운 장소에 0이 아닌 요소를 가지고 있습니다. C. W을 "마스크"로 사용하여 결과 행렬 C이 희박하고 필요한 요소 만 포함 할 수 있습니까?두 배열 간의 행렬 곱셈을 수행하고 마스크 된 위치에서만 결과 얻기
답변
행렬 곱셈은 점 제품의 테이블 일 뿐이므로 필요한 특정 점 곱을 벡터화 된 방식으로 수행 할 수 있습니다.
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)
먼저 W에서 0이 아닌 장소의 색인을 가져온 다음 A의 i 번째 행에 B의 j 번째 열을 곱하여 결과 행렬의 (i,j)
요소를 가져와 저장할 수 있습니다. 그 결과를 행렬로 저장하는 대신 튜플 (i,j,res)
(이것은 희소 행렬을 저장하는 올바른 방법입니다)으로 저장합니다.
경우 당신이 당신의 대답을 조금 더 살피면, 나는 이것이이 문제와 함께 갈 수있는 적절한 방법이라고 믿습니다. –
이것은 확실히 가능한 해결책입니다. 그러나 200m 요소 (200000x100000의 1 %)를 반복하는 것을 포함합니다. 나는 벡터화 된 솔루션을 원할 것입니다. (만약 하나가 있다면) – tokarev
W에 0 요소 만있는 완전한 라인을 가지고 있다면, A에있는 해당 라인을 0으로 만들 수 있고 0으로 끝나는 완전한 컬럼을 가지고 있다면 똑같이 할 수 있습니다. B에 해당 요소를 넣은 다음'scipy.sparse '를 사용하여 행렬을 곱합니다. –
는 여기 벡터화 된 솔루션을 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]])
'sp.nonzero'를 잘 사용했습니다! 빠른 대안이 될 수 있습니다. 내 게시물에서 언급해도 괜찮습니까? :) – Divakar
'sp.nonzero'와'sp.find'는 거의 동일합니다.'coo' 형식의 속성을 반환합니다. 'find'는'data' 속성도 반환합니다. 'W'가 이미'coo' 인 경우'row'와'col' 속성을 직접 사용하십시오. – hpaulj
'scipy.nonzero'는'np.nonzero'이며, 차례로'W.nonzero'를 나타냅니다. 더 자세히 살펴보면'sparse.find'는'csr' 형식을 통해 왕복하여 중복을 합산하기 때문에 속도가 느립니다. 'iX, iY = W.row, W.col'은 더 빠릅니다 (W가 이미 coo 인 경우). – hpaulj