2010-07-14 5 views
39

2d 희소 배열이 있다고 가정합니다.scipy.sparse 행렬을 브로드 캐스트 된 1 차원 배열로 요소 단위로 곱하는 방법은 무엇입니까?

>>> import numpy as np 
>>> import scipy.sparse as ssp 

>>> a = ssp.lil_matrix((5, 3)) 
>>> a[1, 2] = -1 
>>> a[4, 1] = 2 
>>> a.todense() 
matrix([[ 0., 0., 0.], 
     [ 0., 0., -1.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 2., 0.]]) 

을 지금은 모두와 고밀도 1D 배열이 있다고 가정 내 진짜 유스 케이스에서 행과 열의 수를 모두 (20000 및 50000을 말한다) 조밀 한 표현이 사용되는 경우 따라서는 메모리에 맞지 않을 수 있습니다 훨씬 더 큰 있습니다 (내 실제 생활 경우 또는 50000) 크기의 3 비 - 제로 구성 요소 :

>>> d = np.ones(3) * 3 
>>> d 
array([ 3., 3., 3.]) 

나는의 elementwise 곱셈을 계산하기 좋아하고 NumPy와의 일반적인 방송의 의미를 사용하는 거라고합니다. 그러나, scipy 스파 스 매트릭스는 np.matrix의 다음과 같습니다 '*'연산자 대신의-곱셈 매트릭스처럼 행동해야하는 오버로드 된 elementwise - 곱셈 :

>>> a * d 
array([ 0., -3., 0., 0., 6.]) 

하나의 해결책은 '할 것 *는 '을위한 배열 의미로 전환' '연산자, 즉 예상 된 결과 줄 것입니다 :

>>> a.toarray() * d 
array([[ 0., 0., 0.], 
     [ 0., 0., -3.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 6., 0.]]) 

을하지만 호출으로써 toArray()가의 조밀 한 버전 실현 것이라고 할 수 없다'A '를하는 메모리에 맞지 않습니다 (결과도 빽빽하게 나타납니다).

>>> ssp.issparse(a.toarray()) 
False 

'a'열에 비효율적 인 파이썬 루프를 수행 할 필요없이 드문 드문 한 데이터 구조 만 유지하면서 어떻게 구축 할 것인지 생각하십시오.

+0

''d'가 사용할 수 A' a.multiply '(d)'과 동일한 크기의 희소 행렬 인 경우. 아마도''d '를 N 행으로 만들고'a'의 N 행을 한 번에 반복 할 수 있습니까? – mtrw

+1

그러나 d는 밀도가 높으며 곱셈 모양 요구 사항을 충족시키기 위해 메모리에 명시 적으로 브로드 캐스트 할 수 없습니다. 일괄 처리 루핑은 옵션이지만 조금 hackish 찾으십시오. 나는 파이썬 루프없이 이것을 수행 할 바닐라 벡터화/scipy 방법이 있다고 생각했을 것이다. – ogrisel

+0

나는 (희소 한) 모체의 표현을 원하지만 배열의 다중 연산을 원한다고 생각한다. 나는 불행하게도 당신 자신을 굴려야한다고 생각합니다. – mtrw

답변

42

나는 scipy.org에서도 답장을 보냈지 만, 다른 사람들이이 페이지를 검색 할 때를 대비하여 여기에 답을 추가해야한다고 생각했습니다.

벡터를 희소 대각선 행렬로 변환 한 다음 행렬 곱셈 (* 사용)을 사용하여 방송과 동일한 작업을 효율적으로 수행 할 수 있습니다.

>>> d = ssp.lil_matrix((3,3)) 
>>> d.setdiag(np.ones(3)*3) 
>>> a*d 
<5x3 sparse matrix of type '<type 'numpy.float64'>' 
with 2 stored elements in Compressed Sparse Row format> 
>>> (a*d).todense() 
matrix([[ 0., 0., 0.], 
     [ 0., 0., -3.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 6., 0.]]) 

희망 하시겠습니까?

+0

문제가 해결 될 것 같습니다. – ogrisel

+0

이것에 대한 좋은 점은'X '가'ndarray' 또는 조밀 한 행렬 일 때도 작동한다는 것입니다. +1. –

+4

['scipy.sparse.diags (d, 0)'] (http://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy.sparse.diags)를 사용하면이 작업을 더욱 단순화 할 수 있습니다. html) 대신에'lil_matrix' –

1

글쎄, 여기에 원하는대로 할 수있는 간단한 코드가 있습니다. 나는 당신이 원하는만큼 효율적입니다 알고, 그래서 그것을 가지고하거나 떠나지 말아요 : 그것은 단지 릴 매트릭스와 함께 작동

import scipy.sparse as ssp 
def pointmult(a,b): 
    x = a.copy() 
    for i in xrange(a.shape[0]): 
     if x.data[i]: 
      for j in xrange(len(x.data[i])): 
       x.data[i] *= b[x.rows[i]] 
    return x 

을 당신이 작업 할 경우 일부 내용을 변경해야합니다 있도록 다른 형식으로.

+0

감사하지만 나는 파이썬에서 루프를 피하기를 좋아했을 것이다.하지만이 사용 사례에 대한 현재 scipy.sparse 클래스를 사용할 수있는 방법이 없을 수도 있습니다. – ogrisel

23

A.multiply (B)는 scipy sparse에서 작동해야한다고 생각합니다. 이 방법은 행렬 곱셈이 아닌 "점 현명한"곱셈을 곱합니다.

HTH

+1

결과는 조밀 한 행렬입니다. 안좋다. –

+3

@ K3 --- rnc 결과가 B가 조밀 한 경우에만 밀도가 높습니다. B를 스파 스 형식 중 하나로 변환하면 트릭을 수행합니다. 예 : A.multiply (csc_matrix (B)) – markhor

관련 문제