Как вернуть блоки из скудной матрицы разреженных блоков? - PullRequest
0 голосов
/ 01 декабря 2018

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

>>> A = [[1, 1],
...      [1, 1]]
>>> B = [[2, 2],
...      [2, 2]]
>>> C = [[3, 3],
...      [3, 3]]
>>> results = scipy.sparse.block_diag(A, B, C)
>>> print(results.toarray())
[[1 1 0 0 0 0]
 [1 1 0 0 0 0]
 [0 0 2 2 0 0]
 [0 0 2 2 0 0]
 [0 0 0 0 3 3]
 [0 0 0 0 3 3]]

Как эффективно вернуть эти массивы A, B, C, если необходимо, предоставив свою форму (2,2)?

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018
In [177]: >>> A = [[1, 1],
     ...: ...      [1, 1]]
     ...: >>> B = [[2, 2],
     ...: ...      [2, 2]]
     ...: >>> C = [[3, 3],
     ...: ...      [3, 3]]
     ...: >>> results = sparse.block_diag([A, B, C])
     ...:      
In [178]: results
Out[178]: 
<6x6 sparse matrix of type '<class 'numpy.int64'>'
    with 12 stored elements in COOrdinate format>

block_diag не сохраняет входы;скорее он создает матрицу формата coo, представляющую всю матрицу, а не части.

In [194]: results.data
Out[194]: array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], dtype=int64)
In [195]: results.row
Out[195]: array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5], dtype=int32)
In [196]: results.col
Out[196]: array([0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5], dtype=int32)


In [179]: results.A
Out[179]: 
array([[1, 1, 0, 0, 0, 0],
       [1, 1, 0, 0, 0, 0],
       [0, 0, 2, 2, 0, 0],
       [0, 0, 2, 2, 0, 0],
       [0, 0, 0, 0, 3, 3],
       [0, 0, 0, 0, 3, 3]], dtype=int64)

block_diag передает массивы в sparse.bmat.Это, в свою очередь, создает матрицу coo из каждого, а затем объединяет атрибуты coo в 3 массива, которые являются входными данными для глобальной разреженной матрицы.


Существует еще один разреженный формат bsrэто может сохранить блоки (до преобразования в csr для расчета), но мне придется поэкспериментировать, чтобы убедиться, что это так.

Давайте сделаем bsr из этого results coo:

In [186]: bresults = sparse.bsr_matrix(results)
In [187]: bresults
Out[187]: 
<6x6 sparse matrix of type '<class 'numpy.int64'>'
    with 12 stored elements (blocksize = 2x2) in Block Sparse Row format>
In [188]: bresults.blocksize
Out[188]: (2, 2)
In [189]: bresults.data
Out[189]: 
array([[[1, 1],
        [1, 1]],

       [[2, 2],
        [2, 2]],

       [[3, 3],
        [3, 3]]], dtype=int64)

Таким образом, он выводит, что есть блоки, как вы и хотели.

In [191]: bresults.indices
Out[191]: array([0, 1, 2], dtype=int32)
In [192]: bresults.indptr
Out[192]: array([0, 1, 2, 3], dtype=int32)

Так что это csr как хранилище, но с data, сгруппированным в блоки.

Может быть возможно создать это из вашего A,B,C без посредника block_diag, но мне нужно больше взглянуть на документы.

0 голосов
/ 01 декабря 2018

это небольшая забавная проблема.

Я не думаю, что есть функция, которая решает эту проблему в одну строку, но есть способ сделать это программно.

Проверьте, что.данные распечатываются, я использую их здесь.

Работает, когда фигуры одинаковы.

from scipy.sparse import block_diag

a = [[1, 2, 4],
    [3, 4, 4]]
b = [[2, 2, 1],
    [2, 2, 1]]
c = [[3, 3, 6],
    [3, 3, 6]]

res = block_diag((a, b, c))

def goBack(res, shape):
    s = shape[0]*shape[1]
    num = int(len(res.data)/s)
    for i in range (num):
        mat = res.data[i*s:(i+1)*s].reshape(shape)
        print(mat)

goBack(res, [2,3])

Вывод:

[[1 2 4]
 [3 4 4]]
[[2 2 1]
 [2 2 1]]
[[3 3 6]
 [3 3 6]]

Редактировать:

Хорошо, это не работает, когда любой из элементов предоставленных матриц равен нулю, так как тогда он не будет учитываться в res.data.

Также, забудьте, ссылка, предоставленная cleb, должнапомочь вам.

...