Как к поэлементному - умножают scipy.sparse матрицу на широковещательно переданное плотное 1d массив?

Предположим, что у меня есть 2-й разреженный массив. В моем реальном варианте использования и количество строк и столбцы намного больше (скажите 20000 и 50000), следовательно это не может уместиться в памяти, когда плотное представление используется:

>>> 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 массив со всеми ненулевыми компонентами с размером 3 (или 50000 в моем реальном случае):

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

Я хотел бы вычислить поэлементное умножение a и d использование обычной широковещательной семантики numpy. Однако разреженные матрицы в scipy имеют np.matrix: '*' оператор перегружается, чтобы иметь его, ведут себя как умножение матриц вместо поэлементного - умножьтесь:

>>> 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 () осуществил бы плотную версию, который не умещается в памяти (и результат будет плотным также):

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

Какая-либо идея, как создать это при хранении только редкого datastructures и не имея необходимость делать неэффективный цикл Python на столбцах 'a'?

41
задан ogrisel 14 July 2010 в 15:39
поделиться

2 ответа

Я также ответил на 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.]])

Надеюсь, это поможет!

45
ответ дан 27 November 2019 в 00:40
поделиться

Вот простой код, который сделает то, что вы хотите. Я не знаю, настолько ли он эффективен, как вам хотелось бы, так что возьмите его или оставьте:

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

Он работает только с матрицами lil, поэтому вам придется внести некоторые изменения, если вы хотите, чтобы он работал с другими форматами.

1
ответ дан 27 November 2019 в 00:40
поделиться
Другие вопросы по тегам:

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