Utilisation d’une matrice clairsemée par rapport à un tableau numpy
Le paquet de matrice clairsemée scipy
, et les similaires dans MATLAB, a été basé sur des idées développées à partir de problèmes d’algèbre linéaire, tels que la résolution de grandes équations linéaires clairsemées (par exemple, les implémentations de différences finies et d’éléments finis). Ainsi, des choses comme le produit matriciel (le produit dot
pour les tableaux numpy) et les solveurs d’équation sont bien développés.
Mon expérience approximative est qu’un produit matriciel csr
clairsemé doit avoir une sparsité de 1% pour être plus rapide que l’opération dot
dense équivalente – en d’autres termes, une valeur non nulle pour 99 zéros. (mais voir les tests ci-dessous)
Mais les gens essaient aussi d’utiliser des matrices éparses pour économiser de la mémoire. Mais gardez à l’esprit qu’une telle matrice doit stocker 3 tableaux de valeurs (au moins dans le format coo
). Ainsi, la sparsité doit être inférieure à 1/3 pour commencer à économiser de la mémoire. Évidemment, vous n’allez pas économiser de la mémoire si vous construisez d’abord le tableau dense, et créez le tableau clairsemé à partir de celui-ci.
Le paquet scipy
implémente de nombreux formats clairsemés. Le format coo
est le plus facile à comprendre et à construire. Construisez-en un selon la documentation et regardez ses attributs .data
, .row
et .col
(3 tableaux 1d).
csr
et csc
sont généralement construits à partir du format coo
, et compressent un peu les données, ce qui les rend un peu plus difficiles à comprendre. Mais ils ont la plupart des fonctionnalités mathématiques.
Il est également possible d’indexer le format csr
, bien qu’en général cela soit plus lent que le cas équivalent de matrice/rayon dense. D’autres opérations comme le changement de valeurs (notamment de 0 à non zéro), la concaténation, la croissance incrémentale, sont également plus lentes.
lil
(listes de listes) est également facile à comprendre, et le meilleur pour la construction incrémentale. dok
est en fait une sous-classe de dictionnaire.
Un point clé est qu’une matrice clairsemée est limitée à 2d, et à bien des égards se comporte comme la classe np.matrix
(bien que ce ne soit pas une sous-classe).
Une recherche d’autres questions utilisant scikit-learn
et sparse
pourrait être le meilleur moyen de trouver les pour/contre de l’utilisation de ces matrices. J’ai répondu à un certain nombre de questions, mais je connais mieux le côté ‘sparse’ que le côté ‘learn’. Je pense qu’elles sont utiles, mais j’ai l’impression que l’ajustement n’est pas toujours le meilleur. Toute personnalisation est du côté de learn
. Jusqu’à présent, le paquet sparse
n’a pas été optimisé pour cette application.
Je viens d’essayer quelques tests de produits matriciels, en utilisant la méthode sparse.random
pour créer une matrice éparse avec une sparsité spécifiée. La multiplication de matrices éparses s’est mieux comportée que ce à quoi je m’attendais.
In : M=sparse.random(1000,1000,.5)In : timeit M1=M*M1 loops, best of 3: 2.78 s per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1 loops, best of 3: 4.28 s per loop
C’est un problème de taille ; pour les petites matrices, la dot
dense est plus rapide
In : M=sparse.random(100,100,.5)In : timeit M1=M*M100 loops, best of 3: 3.24 ms per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1000 loops, best of 3: 1.44 ms per loop
Mais comparez l’indexation
In : timeit M.tocsr()10 loops, best of 3: 86.4 ms per loopIn : timeit Ma1000000 loops, best of 3: 318 ns per loopIn : timeit Ma=M.toarray();Ma10 loops, best of 3: 23.6 ms per loop
.