Построение Indptr для матрицы SciPy Sparse CS C - PullRequest
2 голосов
/ 16 февраля 2020

У меня есть много списков, которые представляют разреженную матрицу (то есть столбцы с ненулевыми записями), которые мне нужно представить как SciPy sparse csc_matrix. Однако обратите внимание, что в моей разреженной матрице есть только одна строка, и поэтому список просто указывает на столбцы в этой строке, которые имеют ненулевые записи. Например:

sparse_input = [4, 10, 21]  # My lists are much, much longer but very sparse

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

x = np.array([[0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1]])

Я мог бы использовать синтаксис (data, (row, col)), но поскольку мои списки очень длинные, для csc_matrix требуется много времени и памяти. Итак, я думал об использовании интерфейса indptr, но мне сложно понять, как быстро и автоматически построить indptr непосредственно из заданного разреженного списка ненулевых записей столбцов. Я попытался взглянуть на csr_matrix(x).indptr и увидел, что indptr выглядит следующим образом:

array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       3], dtype=int32)

Я прочитал документы SciPy и страницу Википедии с разреженной матрицей , но я не могу ' Похоже, что он придумал эффективный метод для построения indptr непосредственно из списка ненулевых столбцов. Такое ощущение, что indptr не должно быть такой длинной, учитывая, что в разреженной матрице есть только три ненулевых элемента.

1 Ответ

0 голосов
/ 16 февраля 2020

Как насчет создания матриц и изучения их атрибутов?

In [144]: from scipy import sparse                                                             
In [145]: x = np.array([[0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1]])                        

In [146]: M = sparse.coo_matrix(x)                                                             
In [147]: M                                                                                    
Out[147]: 
<1x22 sparse matrix of type '<class 'numpy.int64'>'
    with 3 stored elements in COOrdinate format>
In [148]: M.row                                                                                
Out[148]: array([0, 0, 0], dtype=int32)
In [149]: M.col                                                                                
Out[149]: array([ 4, 10, 21], dtype=int32)
In [150]: M.data                                                                               
Out[150]: array([1, 1, 1])

csr:

In [152]: Mr = M.tocsr()                                                                       
In [153]: Mr.indptr                                                                            
Out[153]: array([0, 3], dtype=int32)
In [155]: Mr.indices                                                                           
Out[155]: array([ 4, 10, 21], dtype=int32)
In [156]: Mr.data                                                                              
Out[156]: array([1, 1, 1], dtype=int64)

cs c:

In [157]: Mc = M.tocsc()                                                                       
In [158]: Mc.indptr                                                                            
Out[158]: 
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       3], dtype=int32)
In [159]: Mc.indices                                                                           
Out[159]: array([0, 0, 0], dtype=int32)
In [160]: Mc.data                                                                              
Out[160]: array([1, 1, 1], dtype=int64)

И прямое nonzero для x:

In [161]: np.nonzero(x)                                                                        
Out[161]: (array([0, 0, 0]), array([ 4, 10, 21]))

Для такой матрицы из 1 строки, я сомневаюсь, что вы сэкономите много времени, создав csr indptr напрямую. Большая часть работы будет в шаге nonzero. Но не стесняйтесь экспериментировать.

===

Некоторые моменты времени

In [162]: timeit sparse.coo_matrix(x)                                                          
95.8 µs ± 110 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [163]: timeit sparse.csr_matrix(x)                                                          
335 µs ± 2.59 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [164]: timeit M.tocsr()                                                                     
115 µs ± 948 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [165]: timeit M.tocsc()                                                                     
117 µs ± 90.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [166]: sparse.csr_matrix?                                                                   
In [167]: timeit M.tocsc()                                                                     
117 µs ± 1.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [168]: timeit sparse.csc_matrix(x)                                                          
335 µs ± 257 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [169]: timeit sparse.coo_matrix(x).tocsr()                                                  
219 µs ± 3.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Я немного удивлен, что csr_matrix медленнее, чем coo путем преобразования.

Теперь давайте попробуем сделать матрицу с indptr et c.

In [170]: timeit np.nonzero(x)                                                                 
2.52 µs ± 65.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [173]: timeit sparse.csr_matrix((Mr.data, Mr.indices, Mr.indptr))                           
92.5 µs ± 79.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [174]: %%timeit 
     ...: indices = np.nonzero(x)[1] 
     ...: data = np.ones_like(indices) 
     ...: indptr = np.array([0,len(indices)]) 
     ...: sparse.csr_matrix((data, indices, indptr)) 
     ...:  
     ...:                                                                                      
161 µs ± 605 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...