2016-04-22 2 views
1

У меня есть две разреженных матриц (a и b) в питоне следующих размеров:Dot продукта разреженные матрицы

a = <240760x2177930 sparse matrix of type '<class 'numpy.float64'>' 
    with 1127853 stored elements in Compressed Sparse Row format> 

и

b = <240760x2177930 sparse matrix of type '<class 'numpy.float64'>' 
    with 439309 stored elements in Compressed Sparse Row format> 

Вопрос: Я хотел бы получить вектор-столбец длиной 240760, который является произведением строки по двум точкам двух матриц. Например, dot(a[0],b[0]) будет первым элементом моего выходного вектора. dot(a[1],b[1]) будет вторым, и так далее.

Есть ли векторный простой способ достичь этого?

EDIT: Один из способов сделать это было бы преобразовать каждую строку в плотный вектор, расправьте его и использовать numpy.dot(). Что-то вроде:

np.dot(np.array(a[0]).flatten(),np.array(b[0]).flatten()). 

Но это требует итерация грести мудрой и преобразовать каждую строку в плотный вектор, который очень много времени. Я думаю, что, вероятно, более простой способ сделать это ...

+0

Это сделало бы это: 'a.multiply (b) .sum (1)'? Он дает вектор правильной длины, я просто не уверен, что он делает. Весь API 'csr_matrix' настолько незначителен мне. – David

ответ

4

scipy разреженной матрицы по образцу numpy матрицы подкласса, а также в качестве таких орудий * в качестве матричного умножения. a.multiply является элементным умножением, например, используемым np.array*.

Я предлагаю сделать пару небольших матриц и попробовать различные формы умножения, включая то, что вы считаете эквивалентом np.dot. Будет легче рассказать, что происходит с чем-то маленьким.

a = np.arange(12).reshape(3,4) 
a1 = sparse.csr_matrix(a) 

np.dot(a, a.T) 
a1 * a.T 
a*a 
a1.multiply(a1) 
etc 

Просто для справки, это то, что вы хотите (с использованием плотных массивов):

In [7]: a=np.arange(12).reshape(3,4) 

In [8]: [np.dot(a[i],a[i]) for i in range(3)] 
Out[8]: [14, 126, 366] 

In [9]: np.einsum('ij,ij->i',a,a) 
Out[9]: array([ 14, 126, 366]) 

и разреженный

In [11]: a1=sparse.csr_matrix(a) 

Полная матрица или точка продукт более, что вы хотите, правильно? Вам просто нужна диагональ.

In [15]: (a1*a1.T).A 
Out[15]: 
array([[ 14, 38, 62], 
     [ 38, 126, 214], 
     [ 62, 214, 366]], dtype=int32) 

In [16]: a.dot(a.T) 
Out[16]: 
array([[ 14, 38, 62], 
     [ 38, 126, 214], 
     [ 62, 214, 366]]) 

In [21]: (a1*a1.T).diagonal() 
Out[21]: array([ 14, 126, 366], dtype=int32) 

Для чего-то, что является довольно скудно принимая полное матричное умножение с последующим диагональным может быть столь же быстро, как и любой другой альтернатива. Итерация по строкам разреженной матрицы является относительно медленной операцией, в то время как матричное умножение реализовано в быстром c-коде.

Другой способ - умножение элемента, за которым следует сумма.

In [22]: np.sum(a*a,axis=1) 
Out[22]: array([ 14, 126, 366]) 

In [23]: a1.multiply(a1).sum(axis=1) 
Out[23]: 
matrix([[ 14], 
     [126], 
     [366]], dtype=int32) 

разреженные реализует sum в качестве матричного умножения (на колонке единиц).

In [26]: a1.multiply(a1)*np.array([1,1,1,1])[:,None] 
Out[26]: 
array([[ 14], 
     [126], 
     [366]], dtype=int32) 
+0

отлично, спасибо огромное. – David

+0

Такой отличный ответ. Большое вам спасибо за разные варианты! – keshr3106

Смежные вопросы