2017-02-14 5 views
1

В python, что является лучшим способом добавить вектор CSR в определенную строку матрицы CSR? Я нашел one workaround here, но задаюсь вопросом, есть ли лучший/более эффективный способ сделать это. Поблагодарили бы за любую помощь.scipy: добавление разреженного вектора в определенную строку разреженной матрицы

Учитывая матрицу NxM КСО A и матрица 1xM КСО В, и индекс строки я, цель состоит в том, чтобы добавить Аргументы B к я -й строке A эффективно ,

+0

Просьба уточнить ваш вопрос --SO Обзор –

+0

вы имеете в виду не- место? –

+0

На месте. Другой вопрос заключается в добавлении двух CSR-матриц (с теми же размерами). Это основные операции, но я не могу найти правильный способ их выполнения. – beygel

ответ

1

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

In [1049]: B.A 
Out[1049]: 
array([[0, 9, 0, 0, 1, 0], 
     [2, 0, 5, 0, 0, 9], 
     [0, 2, 0, 0, 0, 0], 
     [2, 0, 0, 0, 0, 0], 
     [0, 9, 5, 3, 0, 7], 
     [1, 0, 0, 8, 9, 0]], dtype=int32) 
In [1051]: B[1,:] += np.array([1,0,1,0,0,0]) 
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient. 
    SparseEfficiencyWarning) 
In [1052]: B 
Out[1052]: 
<6x6 sparse matrix of type '<class 'numpy.int32'>' 
    with 17 stored elements in Compressed Sparse Row format> 
In [1053]: B.A 
Out[1053]: 
array([[0, 9, 0, 0, 1, 0], 
     [3, 0, 6, 0, 0, 9], 
     [0, 2, 0, 0, 0, 0], 
     [2, 0, 0, 0, 0, 0], 
     [0, 9, 5, 3, 0, 7], 
     [1, 0, 0, 8, 9, 0]]) 

Как показывает связанный вами вопрос, можно действовать непосредственно по атрибутам разреженной матрицы. Его код показывает, почему есть предупреждение об эффективности - в общем случае он должен перестроить атрибуты матрицы.

lil более эффективен для замены строк, поскольку он просто должен изменить подсписку в матрицах .data и .rows атрибутов. Изменение одной строки не изменяет атрибуты любого из других.

Это сказало, если ваша добавка имеет такую ​​же разреженность, что и исходный ряд, то можно изменить отдельные элементы атрибута data без переделки .indices или .indptr. Опираясь на связанный коде

A.data[:idx_start_row : idx_end_row] 

является кусочком A.data, который будет изменен. Конечно, вам нужен соответствующий фрагмент из «вектора».

Начиная с In [1049] B

In [1085]: B.indptr 
Out[1085]: array([ 0, 2, 5, 6, 7, 11, 14], dtype=int32) 
In [1086]: B.data 
Out[1086]: array([9, 1, 2, 5, 9, 2, 2, 9, 5, 3, 7, 1, 8, 9], dtype=int32) 
In [1087]: B.indptr[[1,2]] # row 1 
Out[1087]: array([2, 5], dtype=int32) 
In [1088]: B.data[2:5] 
Out[1088]: array([2, 5, 9], dtype=int32) 
In [1089]: B.indices[2:5] # row 1 column indices 
Out[1089]: array([0, 2, 5], dtype=int32) 
In [1090]: B.data[2:5] += np.array([1,2,3]) 
In [1091]: B.A 
Out[1091]: 
array([[ 0, 9, 0, 0, 1, 0], 
     [ 3, 0, 7, 0, 0, 12], 
     [ 0, 2, 0, 0, 0, 0], 
     [ 2, 0, 0, 0, 0, 0], 
     [ 0, 9, 5, 3, 0, 7], 
     [ 1, 0, 0, 8, 9, 0]], dtype=int32) 

Обратите внимание, где измененные значения, [3,7,12], в формате lil:

In [1092]: B.tolil().data 
Out[1092]: array([[9, 1], [3, 7, 12], [2], [2], [9, 5, 3, 7], [1, 8, 9]], dtype=object) 
+0

Спасибо, я буду экспериментировать с этим. Добавленная строка также разрежена, но необязательно имеет одинаковые ненулевые значения в качестве строки, в которую она добавлена. – beygel

+0

Если у него нет разреженности, то вы не можете использовать мой простой код. Вам придется изменить 'nnz',' indices' и 'indptr', как это сделал связанный ответ. Это можно сделать, но я сомневаюсь, стоит ли это усилий. – hpaulj

+0

Есть ли еще более эффективное решение? – beygel

0

ксо/CSC матрицы являются эффективными для большинства операций, включая сложение (O (nnz)). Однако небольшие изменения, влияющие на структуру разреженности, такие как ваш пример или даже переключение одной позиции с 0 на 1, не связаны с тем, что они требуют реорганизации представления O (nnz). Значения и индексы упакованы; вставляя один, все вышеперечисленное нужно переместить.

Если вы выполняете только одну такую ​​операцию, я бы предположил, что вы не можете легко реализовать реализацию Scipy. Однако, если вы добавляете несколько строк, например, сначала можно сделать небольшую матрицу, а затем добавить это за один раз.

Создание матрицы csr вручную из строк, скажем, не так уж сложно.Например, если ваши ряды плотно и в порядке:

row_numbers, indices = np.where(rows) 
data = rows[row_numbers, indices] 
indptr = np.searchsorted(np.r_[true_row_numbers[row_numbers], N], np.arange(N+1)) 

Если у вас есть коллекция разреженных строк и их номеров строк:

data = np.r_[tuple([r.data for r in rows])] 
indices = np.r_[tuple(r.indices for r in rows])] 
jumps = np.add.accumulate([0] + [len(r) for r in rows]) 
indptr = np.repeat(jumps, np.diff(np.r_[-1, true_row_numbers, N])) 

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

  • Нет связанных вопросов^_^