Je veux initialiser une matrice clairsemée de 300,000 x 300,0000
aide de sklearn
, mais cela nécessite de la mémoire comme si elle n'était pas clairsemée:
>>> from scipy import sparse >>> from scipy import sparse >>> sparse.rand(300000,300000,.000000000001) Traceback (most recent call last): File "<stdin>", line 1, in <module> File ".../python3.8/site-packages/scipy/sparse/construct.py", line 842, in rand return random(m, n, density, format, dtype, random_state) File ".../lib/python3.8/site-packages/scipy/sparse/construct.py", line 788, in random ind = random_state.choice(mn, size=k, replace=False) File "mtrand.pyx", line 980, in numpy.random.mtrand.RandomState.choice File "mtrand.pyx", line 4528, in numpy.random.mtrand.RandomState.permutation MemoryError: Unable to allocate 671. GiB for an array with shape (90000000000,) and data type int64
cela donne l'erreur:
np.random.normal(size=[300000, 300000])
qui est la même erreur que si numpy
utilisant numpy
:
MemoryError: Unable to allocate 671. GiB for an array with shape (300000, 300000) and data type float64
Même lorsque je passe à une densité très faible, cela reproduit l'erreur:
>>> from scipy import sparse >>> sparse.rand(300000,300000,.1)
Existe-t-il un moyen plus efficace en mémoire de créer une matrice aussi clairsemée?
3 Réponses :
Essayez de passer un argument de density
raisonnable comme indiqué dans la documentation ... si vous avez 10 billions de cellules, peut-être 0,00000001 ou quelque chose du genre ...
https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.rand.html#scipy.sparse.rand
Le commentaire de @ hpaulj est parfait. Il y a également un indice dans le message d'erreur.
MemoryError: impossible d'allouer 671. Gio pour un tableau avec la forme (90000000000,) et le type de données int64
Il y a une référence à int64 et non à float64 et à un tableau linéaire de taille 300 000 X 300 000. Il s'agit d'une étape intermédiaire d'échantillonnage aléatoire dans la création de la matrice creuse, qui occupe de toute façon beaucoup de mémoire.
Notez que lors de la création d'une matrice creuse (quel que soit le format), vous devez tenir compte de la mémoire pour les valeurs non nulles et pour représenter la position des valeurs dans la matrice.
Ne générez que ce dont vous avez besoin.
>>> arr <300000x300000 sparse matrix of type '<class 'numpy.float64'>' with 900 stored elements in Compressed Sparse Row format>
Cela vous permet de créer des tableaux clairsemés de monstres à condition qu'ils soient suffisamment clairsemés pour tenir dans la mémoire.
from scipy import sparse import numpy as np n, m = 300000, 300000 density = 0.00000001 size = int(n * m * density) rows = np.random.randint(0, n, size=size) cols = np.random.randint(0, m, size=size) data = np.random.rand(size) arr = sparse.csr_matrix((data, (rows, cols)), shape=(n, m))
C'est probablement ainsi que le constructeur sparse.rand devrait fonctionner de toute façon. Si une ligne, des paires de cols entrent en collision, cela ajoutera les valeurs de données ensemble, ce qui convient probablement à toutes les applications auxquelles je peux penser.
Où spécifiez-vous la densité de la population de la matrice? Autant que je sache, vous utilisez la structure de données des pièces de rechange sur une matrice sans pièces de rechange.
@
density=0.1
kpiedensity=0.1
? le troisième paramètre danssparse.rand
. Même si je vais pour moins (par exemple, densité = 0), cela donne toujours la même erreursparse.rand
utilise lechoice
pour générerk
indices aléatoires à partir d'un espace entier de 300000 * 300000. J'utilise souvent cette fonction pour générer un échantillon de matrice creuse, mais généralement juste pour un cas de test raisonnable comme 10x10. De toute évidence, ce n'est pas un moyen de générer une très grande matrice, quelle que soit la rareté que vous faites. La matrice finale n'occupera pas autant d'espace, mais cette méthode de génération d'indices en a temporairement besoin.scipy.sparse
a plusieurs façons de créer des matrices éparses. Un courant sur utilise 3 tableaux de stylecoo
- vous pouvez choisir l'index et les valeurs de données de votre choix. Une façon plus lente est de commencer avec unlil
de la forme droite, et « au hasard » éléments affecter.sparse.random
est juste un outil pratique pour créer une matrice de test, et serait rarement utile à des fins de production.