Вопрос по python, numpy, sparse-matrix, matrix, scipy – Умножение элементов в разреженном массиве со строками в матрице

6

Если у вас разреженная матрица X:

>> X = csr_matrix([[0,2,0,2],[0,2,0,1]])
>> print type(X)    
>> print X.todense()    
<class 'scipy.sparse.csr.csr_matrix'>
[[0 2 0 2]
 [0 2 0 1]]

И матрица Y:

>> print type(Y)
>> print text_scores
<class 'numpy.matrixlib.defmatrix.matrix'>
[[8]
 [5]]

... Как вы можете умножить каждый элемент X на строки Y. Например:

[[0*8 2*8 0*8 2*8]
 [0*5 2*5 0*5 1*5]]

или же:

[[0 16 0 16]
 [0 10 0 5]]

I've tired this but obviously it doesn't work as the dimensions dont match: Z = X.data * Y

Ваш Ответ

2   ответа
8

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

# Assuming that Y is 1D, might need to do Y = Y.A.ravel() or such...

# just to make the point that this works only with CSR:
if not isinstance(X, scipy.sparse.csr_matrix):
    raise ValueError('Matrix must be CSR.')

Z = X.copy()
# simply repeat each value in Y by the number of nnz elements in each row: 
Z.data *= Y.repeat(np.diff(Z.indptr))

Это создает некоторые временные эффекты, но, по крайней мере, полностью векторизовано и не уплотняет разреженную матрицу.


Для матрицы COO эквивалент равен:

Z.data *= Y[Z.row] # you can use np.take which is faster then indexing.

Для матрицы CSC эквивалент будет:

Z.data *= Y[Z.indices]
Будет ли это также работать с матрицами COO? Zach
Я думаю, что я добавлю это к ответу. Как и другой, он только делает Y равным ненулевым элементам Z, он не уплотняет Z.
Нет, для COO, вам нужно сделатьZ.data *= Y[Z.row] Я думаю, или np.take вместо индексации, если вы заботитесь о скорости.
Это работает. Это делает это без уплотнения матрицы правильно? Zach
0

У меня была такая же проблема. Лично я не нашел документациюscipy.sparse очень полезная, не найденная функция, которая обрабатывает это напрямую. Поэтому я попытался написать это сам, и это решило для меня:

Z = X.copy()
for row_y_idx in range(Y.shape[0]):
    Z.data[Z.indptr[row_y_idx]:Z.indptr[row_y_idx+1]] *= Y[row_y_idx, 0]

Идея такова: для каждого элементаY на позицииrow_y_idx-ой, выполнить скалярное умножение сrow_y_idx-й рядX, Подробнее о доступе к элементам в матрицах CSRВот (гдеdata являетсяA, IA являетсяindptr).

ДаноX а такжеY как вы определили:

import numpy as np
import scipy.sparse as sps

X = sps.csr_matrix([[0,2,0,2],[0,2,0,1]])
Y = np.matrix([[8], [5]])

Z = X.copy()
for row_y_idx in range(Y.shape[0]):
    Z.data[Z.indptr[row_y_idx]:Z.indptr[row_y_idx+1]] *= Y[row_y_idx, 0]

print(type(Z))
print(Z.todense())

Вывод такой же, как у вас:

<class 'scipy.sparse.csr.csr_matrix'>
 [[ 0 16  0 16]
  [ 0 10  0  5]]

Похожие вопросы