Почему формат CSR превосходит формат CSC при выборе строк?

Я провожу этот небольшой эксперимент с форматом CSR и CSC на основе scipy.sparse. Как утверждает документация, формат CSC более эффективен, чем формат CSR, при работе со столбцами. Итак, я провел небольшой эксперимент:

from scipy.sparse import diags
d = diags([-1, 1, 1], [-1, 0, -1], shape= (100, 100))
%timeit d.tocsc()[:, 1]
%timeit d.tocsr()[:, 1]

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

%timeit d.tocsc()[1]
%timeit d.tocsr()[1]

Но в некоторых случаях CSR превосходит CSC по времени. Мне было интересно, есть ли какая-то структурная причина для таких результатов, или мои тесты просто предвзяты?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
762
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Также индексация со скаляром, срезом и списком может отличаться.

Имейте в виду, что разреженное индексирование, независимо от формата, намного медленнее, чем numpy.ndarray. Старайтесь не использовать sparse, если вам нужно повторить. (И если вам необходимо выполнить итерацию, рассмотрите возможность работы непосредственно с «сырыми» разреженными атрибутами.)

In [64]: d = sparse.diags([-1, 1, 1], [-1, 0, 1], shape= (100, 100))                 
In [65]: d                                                                           
Out[65]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 298 stored elements (3 diagonals) in DIAgonal format>

In [66]: %timeit d.tocsr()[:,1]                                                      
422 µs ± 13.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [67]: %timeit d.tocsc()[:,1]                                                      
506 µs ± 5.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [68]: %timeit d.tocsc()[1,:]                                                      
506 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Отделите конверсию от индексации:

In [69]: %%timeit x=d.tocsr() 
    ...: x[:,1]                                                                              
121 µs ± 2.05 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [70]: %%timeit x=d.tocsr() 
    ...: x[1,:]                                                                           
118 µs ± 2.95 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [71]: %%timeit x=d.tocsc() 
    ...: x[:,1]                                                                            
290 µs ± 5.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [72]: %%timeit x=d.tocsc() 
    ...: x[1,:]                                                                            
297 µs ± 14.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Я немного удивлен, что csr раз постоянно быстрее. Но немного. csc и csr используют общий базовый класс compressed (sparse.compressed._cs_matrix), но детали кодирования, похоже, благоприятствуют csr.

===

И просто для удовольствия проиндексируйте формат lil

In [73]: %%timeit x=d.tolil() 
    ...: x[1,:]                                                                            
76.4 µs ± 231 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [74]: %%timeit x=d.tolil() 
    ...: x[:,1]                                                                       
118 µs ± 647 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Как и ожидалось от хранилища lil, индексирование строк происходит быстрее, хотя время индексирования столбцов неплохое.

lil имеет вид getrow, который ближе всего в sparse к представлению numpy:

In [75]: %%timeit x=d.tolil() 
    ...: x.getrow(1)                                                                          
36.7 µs ± 233 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

===

Индексация плотного массива, даже с учетом времени преобразования, выполняется быстрее:

In [83]: %%timeit x=d.A 
    ...: x[:,1]                                                                          
277 ns ± 9.97 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [84]: timeit d.A[:,1]                                                             
197 µs ± 587 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Спасибо, действительно познавательно!! Два дополнительных вопроса: каким-то образом, когда я тестировал на своем ноутбуке, tolil был самым медленным из трех? и поэтому, если бы моя задача состояла в том, чтобы обрабатывать огромную диагональную полосатую матрицу в длинном цикле, должен ли я жертвовать своей памятью ради эффективности? (по вашему мнению)

Wunderbar 28.04.2019 18:46

Другие вопросы по теме