scipy.sparse: установить строку в нули

Предположим, у меня есть матрица в формате CSR, каков наиболее эффективный способ установить строку (или строки) в нули?

Следующий код работает довольно медленно:

A = A.tolil()
A[indices, :] = 0
A = A.tocsr()

Я должен был преобразовать вscipy.sparse.lil_matrix потому что формат CSR, кажется, не поддерживает ни причудливую индексацию, ни установку значений для срезов.

 Pierre GM26 авг. 2012 г., 14:36
Ну, я только что попробовал[A.__setitem__((i, j), 0) for i in indices for j in range(A.shape[1])] а такжеSciPy сказал мне, чтоSparseEfficiencyWarning: changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient....
 seberg26 авг. 2012 г., 14:38
Понятия не имею, есть ли у scipy какая-либо поддержка, но поскольку это матрица CSR, это может быть эффективно обработано (по крайней мере, вручную). Один вопрос: хотите ли вы изменить шаблон разреженности, или эти 0 должны быть просто численно 0?
 seberg26 авг. 2012 г., 14:57
@AshwinSrinath Я отправил ответ, я думаю, вы, вероятно, не заботитесь об этом. Это могло быmaybe быть интересным, если вы взаимодействуете с решателем относительно низкого уровня, и это похоже на возвращение якобиана для каждой только что измененной итерации, тогда решатель может ожидать, что шаблон разреженности не изменится. Прочитайте статью в Википедии, но я думаю, что выshould изменить его (для экономии места и расчета).
 Ashwin Srinath26 авг. 2012 г., 14:52
Я не уверен, что подразумевается под шаблоном разреженности. Я перехожу к решению системы уравнений с помощью функции scipy.sparse.linalg.spsolve. Я надеюсь, что это устанавливает необходимость изменения модели разреженности или ее отсутствия.

Ответы на вопрос(3)

ю.

Решение Вопроса

Я думаю, что scipy просто не реализует это, но формат CSR вполне бы это поддержал, пожалуйста, прочитайте статью в Википедии на тему «Разреженная матрица». о чемindptrи т. д. являются:

# A.indptr is an array, one for each row (+1 for the nnz):

def csr_row_set_nz_to_val(csr, row, value=0):
    """Set all nonzero elements (elements currently in the sparsity pattern)
    to the given value. Useful to set to 0 mostly.
    """
    if not isinstance(csr, scipy.sparse.csr_matrix):
        raise ValueError('Matrix given must be of CSR format.')
    csr.data[csr.indptr[row]:csr.indptr[row+1]] = value

# Now you can just do:
for row in indices:
    csr_row_set_nz_to_val(A, row, 0)

# And to remove zeros from the sparsity pattern:
A.eliminate_zeros()

Конечно, это удаляет 0, которые были установлены из другого места сeliminate_zeros из разреженной картины. Если вы хотите сделать это (на данный момент), зависит от того, что вы делаете на самом деле, т.е. Исключение может иметь смысл откладывать до тех пор, пока не будут выполнены все другие вычисления, которые могут добавить новые нули, или в некоторых случаях у вас могут быть значения 0, которые вы захотите изменить позже, поэтому было бы очень плохо их исключать!

Вы можете в принципе, конечно, замкнутьeliminate_zeros а такжеprune, но это должно быть много хлопот, и может быть даже медленнее (потому что вы не будете делать это в C).

Details about eliminiate_zeros (and prune)

Разреженная матрица, как правило, не сохраняет нулевые элементы, а просто хранит там, где находятся ненулевые элементы (грубо и разными способами).eliminate_zeros удаляет все нули в вашей матрице из шаблона разреженности (т. е. для этой позиции не сохраняется значение, если до этогоwas vlaue хранится, но это было 0). Исключение плохо, если вы хотите изменить 0 на другое значение позже, в противном случае, это экономит место.

Prune просто сжимает массивы данных, хранящиеся, когда они длиннее, чем необходимо. Обратите внимание, что хотя я впервыеA.prune() там,A.eliminiate_zeros() уже включает чернослив.

 26 авг. 2012 г., 15:22
Добавлено (надеюсь понятное) предложение. Обратите внимание, чтоprune() было ненужно,eliminate_zeros уже звонитprune
 Ashwin Srinath26 авг. 2012 г., 15:07
Спасибо! Это значительно ускорило ситуацию! Я просто хотел бы знать, что там делают операторы remove_zeros и prune?

Вы можете использовать матричный продукт для достижения этого обнуления. Поскольку матрица, которую мы будем использовать, очень разрежена (диагональ с нулями для строк / столбцов, которые мы обнуляем), умножение должно быть эффективным.

Вам понадобится одна из следующих функций:

import scipy.sparse

def zero_rows(M, rows):
    diag = scipy.sparse.eye(M.shape[0]).tolil()
    for r in rows:
        diag[r, r] = 0
    return diag.dot(M)

def zero_columns(M, columns):
    diag = scipy.sparse.eye(M.shape[1]).tolil()
    for c in columns:
        diag[c, c] = 0
    return M.dot(diag)

Пример использования:

>>> A = scipy.sparse.csr_matrix([[1,0,3,4], [5,6,0,8], [9,10,11,0]])
>>> A
<3x4 sparse matrix of type '<class 'numpy.int64'>'
        with 9 stored elements in Compressed Sparse Row format>
>>> A.toarray()
array([[ 1,  0,  3,  4],
       [ 5,  6,  0,  8],
       [ 9, 10, 11,  0]], dtype=int64)

>>> B = zero_rows(A, [1])
>>> B
<3x4 sparse matrix of type '<class 'numpy.float64'>'
        with 6 stored elements in Compressed Sparse Row format>
>>> B.toarray()
array([[  1.,   0.,   3.,   4.],
       [  0.,   0.,   0.,   0.],
       [  9.,  10.,  11.,   0.]])

>>> C = zero_columns(A, [1, 3])
>>> C
<3x4 sparse matrix of type '<class 'numpy.float64'>'
        with 5 stored elements in Compressed Sparse Row format>
>>> C.toarray()
array([[  1.,   0.,   3.,   0.],
       [  5.,   0.,   0.,   0.],
       [  9.,   0.,  11.,   0.]])

Ваш ответ на вопрос