scipy.linalg.block_diag против scipy.sparse.block_diag с точки зрения эффективности
У меня есть вопрос о том, как Сципи строит блочные диагональные матрицы. Я ожидал, что создание разреженной блочной диагональной матрицы будет гораздо быстрее и эффективнее, чем создание плотной (из-за разреженных сжатий). Но оказывается, что это не так (или, может быть, я использую какой-то неэффективный метод):
from timeit import default_timer as timer
import numpy as np
from scipy.sparse import block_diag as bd_sp
from scipy.linalg import block_diag as bd_la
m = [np.identity(1)] * 10000
before = timer()
res = bd_sp(m)
timer()-before
#takes 33.79 secs
before = timer()
res = bd_la(*m)
timer()-before
#takes 0.069 secs
Что мне не хватает? Заранее благодарю за ваши ответы.
1 ответ
In [625]: [np.identity(1)*i for i in range(1,5)]
Out[625]: [array([[1.]]), array([[2.]]), array([[3.]]), array([[4.]])]
In [626]: sparse.block_diag(_)
Out[626]:
<4x4 sparse matrix of type '<class 'numpy.float64'>'
with 4 stored elements in COOrdinate format>
In [627]: _.A
Out[627]:
array([[1., 0., 0., 0.],
[0., 2., 0., 0.],
[0., 0., 3., 0.],
[0., 0., 0., 4.]])
block_diag
использования bmat
присоединиться к элементам. bmat
марки coo
матрицы из всех элементов, и объединяет их атрибуты со смещениями, и делает новый coo
матрица. Код читаемый Python.
Это может быть более эффективным, чтобы построить свой собственный data, row, col
массивы. block_diag
это удобство и хорошо для объединения нескольких больших матриц, но неэффективно при объединении многих маленьких.
linalg
Функция также Python (и довольно короткая). Если создает out
массив правильной формы, и вставляет блоки с нарезкой индексации. Это эффективное решение с плотным массивом. Большая часть тяжелой работы выполняется в скомпилированном виде. numpy
код.
Разреженные матрицы могут быть быстрее при выполнении умножения матриц (и связанных с ними вычислителей linalg). Для большинства других операций, включая инициализацию, они медленнее, чем эквивалентный плотный код. Они также ценны, когда проблема слишком велика.