2011-12-01 9 views
5

Python/Scipy에서 다소 큰 행렬을 처리합니다. 큰 행렬 (coo_matrix에로드 됨)에서 행을 추출하여 대각선 요소로 사용해야합니다. 현재 나는 다음과 같은 방식으로 그렇게 : 내가이 profile 출력에서 ​​볼 것은 diag_elems를 추출하는 동안 대부분의 시간이 get_csr_submatrix 기능에 의해 소비되고 있다는 것입니다희소 행렬의 행에서 희소 대각선 행렬을 만듭니다.

import numpy as np 
from scipy import sparse 

def computation(A): 
    for i in range(A.shape[0]): 
    diag_elems = np.array(A[i,:].todense()) 
    ith_diag = sparse.spdiags(diag_elems,0,A.shape[1],A.shape[1], format = "csc") 
    #... 

#create some random matrix 
A = (sparse.rand(1000,100000,0.02,format="csc")*5).astype(np.ubyte) 
#get timings 
profile.run('computation(A)') 

. 따라서 초기 데이터의 비효율적 인 표현이나 스파 스 행렬에서 행을 추출하는 잘못된 방법을 사용한다고 생각합니다. 스파 스 매트릭스에서 행을 추출하고 대각선 형태로 표현하는 더 나은 방법을 제안 할 수 있습니까?

EDIT

다음 변형 로우 추출에서의 병목 현상을 제거 할 수있다 (간단한 csr'csc' 변경 통지하는 것이 충분하지 않은, A[i,:]A.getrow(i) 치환되어야 함). 그러나 가장 큰 문제는 구체화 (.todense())를 생략하고 행의 희소 표현에서 대각선 행렬을 작성하는 방법입니다. 다음과 같이

import numpy as np 
from scipy import sparse 

def computation(A): 
    for i in range(A.shape[0]): 
    diag_elems = np.array(A.getrow(i).todense()) 
    ith_diag = sparse.spdiags(diag_elems,0,A.shape[1],A.shape[1], format = "csc") 
    #... 

#create some random matrix 
A = (sparse.rand(1000,100000,0.02,format="csr")*5).astype(np.ubyte) 
#get timings 
profile.run('computation(A)') 

내가 직접 1 행 CSR 행렬에서 대각 행렬을 만드는 경우 :

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.6/profile.py", line 70, in run 
    prof = prof.run(statement) 
    File "/usr/local/lib/python2.6/profile.py", line 456, in run 
    return self.runctx(cmd, dict, dict) 
    File "/usr/local/lib/python2.6/profile.py", line 462, in runctx 
    exec cmd in globals, locals 
    File "<string>", line 1, in <module> 
    File "<stdin>", line 4, in computation 
    File "/usr/local/lib/python2.6/site-packages/scipy/sparse/construct.py", line 56, in spdiags 
    return dia_matrix((data, diags), shape=(m,n)).asformat(format) 
    File "/usr/local/lib/python2.6/site-packages/scipy/sparse/base.py", line 211, in asformat 
    return getattr(self,'to' + format)() 
    File "/usr/local/lib/python2.6/site-packages/scipy/sparse/dia.py", line 173, in tocsc 
    return self.tocoo().tocsc() 
    File "/usr/local/lib/python2.6/site-packages/scipy/sparse/coo.py", line 263, in tocsc 
    data = np.empty(self.nnz, dtype=upcast(self.dtype)) 
    File "/usr/local/lib/python2.6/site-packages/scipy/sparse/sputils.py", line 47, in upcast 
    raise TypeError,'no supported conversion for types: %s' % args 
TypeError: no supported conversion for types: object` 
: 나는 어느 쪽도 아니 format="csc" 인수를 지정하지 않으며, CSC 형식으로 ith_diags을 변환 할 수 있습니다 다음
diag_elems = A.getrow(i) 
ith_diag = sparse.spdiags(diag_elems,0,A.shape[1],A.shape[1]) 

+1

대신'format = "csr"'을 사용해 보셨습니까? – cyborg

+0

초기 데이터의 경우 'csr'이고 'A.getrow (i)'로 대체 된 [A [i, :]]의 경우 상당히 빨라졌습니다. 그러나 내가 찾고있는 것은 대각선 행렬의 생성을 시작한 행을 구체화하는 것을 생략하는 것입니다. 어떤 아이디어? – savenkov

답변

3

다음은 내가 생각해 낸 것입니다.

def computation(A): 
    for i in range(A.shape[0]): 
     idx_begin = A.indptr[i] 
     idx_end = A.indptr[i+1] 
     row_nnz = idx_end - idx_begin 
     diag_elems = A.data[idx_begin:idx_end] 
     diag_indices = A.indices[idx_begin:idx_end] 
     ith_diag = sparse.csc_matrix((diag_elems, (diag_indices, diag_indices)),shape=(A.shape[1], A.shape[1])) 
     ith_diag.eliminate_zeros() 

Python 프로파일 러는 5.574 초 전에 비해 1.464 초라고 말합니다. 스파 스 매트릭스를 정의하는 기본 밀도 배열 (indptr, indices, data)을 이용합니다. 내 충돌 과정은 다음과 같습니다. A.indptr [i] : A.indptr [i + 1]은 밀도가 높은 배열의 어떤 요소가 행 i의 0이 아닌 값과 일치하는지 정의합니다. A.data는 A와 A의 값이 0이 아닌 조밀 한 1 차원 배열입니다. indptr은 해당 값이있는 열입니다.

이전과 똑같은 것을 확실히하기 위해 더 많은 테스트를 해보겠습니다. 나는 단지 몇 가지 경우에만 체크했다.

+0

Kevin, 멋지 네요! – savenkov

+0

BTW, row_nnz은 사용되지 않습니다. – savenkov

관련 문제