2
votes

Initialiser la matrice creuse de haute dimension

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?


4 commentaires

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 kpie density=0.1 ? le troisième paramètre dans sparse.rand . Même si je vais pour moins (par exemple, densité = 0), cela donne toujours la même erreur


sparse.rand utilise le choice pour générer k 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 style coo - vous pouvez choisir l'index et les valeurs de données de votre choix. Une façon plus lente est de commencer avec un lil 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.


3 Réponses :


1
votes

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


0 commentaires

0
votes

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.


0 commentaires

1
votes

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.


0 commentaires