2017-01-13 2 views
1

대각선 블록 블록 행렬과 해당 크기의 벡터 사이에 희소 행렬 벡터 multplicatiuon을 표현식으로 표현하는 식 (아마도 np.tensordot 사용)이 있습니까?Numpy의 Tensor 곱셈을 통한 대각선 블록 곱셈

내가 원하는 정확한 작업을 수행하는 작업 구현이 있지만 적절한 numpy 명령 대신 두 개의 파이썬 루프 (아래 참조)를 사용했습니다.

import numpy as np 

outer_size = 2 
inner_size = 5 
shape = (outer_size, outer_size, inner_size) 
diag_block = np.arange(np.prod(shape)).reshape(shape) 
true_diag = np.bmat([[np.diag(diag_block[i,j]) for j in range(shape[1])] for i in range(shape[0])]).A 
x = np.arange(shape[1] * shape[2]) 

def sparse_prod(diags, x): 
    outer_size = diags.shape[0] 
    return np.hstack(sum(diags[i] * x.reshape(outer_size, -1)) for i in range(outer_size)) 

print(true_diag.dot(x)) 
print(sparse_prod(diag_block, x)) 

답변

2

접근 # 1 : 예를 들어

당신은 np.einsum 사용할 수 있습니다 - 기본적으로

np.einsum('ijk,jk->ik', diag_block, x.reshape(outer_size, -1)).ravel() 

을, 우리는 두 입력 사이에 정렬 마지막 축을 유지하는 합계 감소 제 2 및 제 1 축을 각각 나타낸다.


접근 방법 # 2 : 입력 배열의 형태에 따라 this post 일부 자세히 설명으로 루프에서 np.dot/np.tensordot을 사용할 수 있습니다.

m,_,n = diag_block.shape 
x2D = x.reshape(outer_size, -1) 
out = np.empty((m,n)) 
for i in range(n): 
    out[:,i] = np.dot(diag_block[...,i], x2D[:,i]) 
out.shape = out.size # Flatten 
+0

오른쪽, 당신의 링크가 지적 하듯, 그것은 대안보다 훨씬 느립니다, einsum가 작동합니다 동의하지만 -

여기에 루프와 같은 접근 방식이다. Tensordot은 동일하지만, 아인슈타인 합계 첨자 구문에 대한 지식이 필요하지 않으며 첨자 합병이 필요 없습니다. 완성도를 위해 텐 드로도 등가물을 추가하는 것이 좋겠습니까 (알아낼 수는 없었습니다). – VF1

+0

@ VF1 방금 추가되었습니다. – Divakar

+0

(m, k) 배열로'(n, m, k) 배열을 '점'으로 쓰고 싶다면'einsum' 표기법은 사소하다. 당신의'block_diagonal' 프레이밍은 어느 정도 그것을가립니다. 왜 당신은'subscript compilation'에 관심이 있습니까? 그것은 C 코드로 수행됩니다. – hpaulj