web-dev-qa-db-fra.com

De très grandes matrices utilisant Python et NumPy

NumPy est une bibliothèque extrêmement utile, et en l'utilisant, j'ai découvert qu'elle est capable de manipuler facilement des matrices assez volumineuses (10000 x 10000), mais commence à se débattre avec quelque chose de beaucoup plus grand de 50000 x 50000 échoue). Évidemment, cela est dû aux énormes besoins en mémoire.

Existe-t-il un moyen de créer d’énormes matrices nativement dans NumPy (disons 1 million sur 1 million) d’une manière ou d’une autre (sans disposer de plusieurs terrabytes de RAM)?

78
Peter

PyTables et NumPy sont la voie à suivre.

PyTables stockera les données sur le disque au format HDF, avec compression facultative. Mes ensembles de données reçoivent souvent une compression 10x, ce qui est pratique pour traiter des dizaines, voire des centaines de millions de lignes. C'est aussi très rapide. mon ordinateur portable de 5 ans peut gérer des données en effectuant une agrégation GROUP BY similaire à SQL à 1 000 000 lignes/seconde Pas mal pour une solution basée sur Python!

Accéder à nouveau aux données sous forme de recueil NumPy est aussi simple que:

data = table[row_from:row_to]

La bibliothèque HDF prend en charge la lecture des fragments de données pertinents et la conversion en NumPy.

87
Stephen Simmons

numpy.arrays sont censés vivre en mémoire. Si vous voulez travailler avec des matrices plus grandes que votre RAM, vous devez contourner ce problème. Vous pouvez suivre au moins deux approches:

  1. Essayez une représentation matricielle plus efficace exploitant toutes les structures spéciales de vos matrices. Par exemple, comme d'autres l'ont déjà souligné, il existe des structures de données efficaces pour les matrices creuses (matrices avec beaucoup de zéros), comme scipy.sparse.csc_matrix .
  2. Modifiez votre algorithme pour travailler sur les sous-matrices. Vous ne pouvez lire sur le disque que les blocs de matrice actuellement utilisés dans les calculs. Les algorithmes conçus pour fonctionner sur des clusters fonctionnent généralement par blocs, car les données sont réparties sur différents ordinateurs et ne sont transmises que lorsque cela est nécessaire. Par exemple, l'algorithme de Fox pour la multiplication matricielle (fichier PDF) .
53
Roberto Bonvallet

Vous devriez pouvoir utiliser numpy.memmap pour mapper en mémoire un fichier sur le disque. Avec les nouveaux ordinateurs python et 64 bits, vous devez disposer de l'espace d'adressage nécessaire, sans tout charger en mémoire. Le système d'exploitation ne doit gérer qu'une partie du fichier en mémoire.

30
DopplerShift

Pour gérer les matrices creuses, vous avez besoin du paquetage scipy qui se trouve au-dessus de numpy - voir ici pour plus de détails sur les options de matrice creuse que scipy vous donne.

24
Alex Martelli

Le post de Stefano Borini m'a demandé de voir jusqu'où est ce genre de choses. 

Ça y est. Il semble faire fondamentalement ce que vous voulez. HDF5 vous permettra de stocker de très grands ensembles de données, puis d'y accéder et de les utiliser de la même manière que NumPy. 

Assurez-vous que vous utilisez un système d'exploitation 64 bits et une version 64 bits de Python/NumPy. Notez que sur les architectures 32 bits, vous pouvez généralement utiliser 3 Go de mémoire (avec environ 1 Go de perte d’entrées/sorties mappées en mémoire, etc.). 

Avec des baies 64 bits et plus volumineuses que la RAM disponible, vous pouvez vous en sortir avec de la mémoire virtuelle, bien que les choses deviennent plus lentes si vous devez permuter. De plus, les mappes de mémoire (voir numpy.memmap) sont un moyen de travailler avec d’énormes fichiers sur disque sans les charger en mémoire, mais là encore, vous devez disposer d’un espace adresse de 64 bits pour que cela soit très utile. PyTables fera également la plupart de ces tâches pour vous.

5
dwf

C'est un peu alpha, mais http://blaze.pydata.org/ semble travailler à résoudre ce problème. 

5
wisty

Voulez-vous savoir comment gérer une matrice de 2 500 000 000 d'éléments sans téraoctets de RAM? 

Pour gérer 2 milliards d'éléments sans 8 milliards d'octets de RAM, vous ne devez pas conserver la matrice en mémoire.

Cela signifie des algorithmes beaucoup plus sophistiqués pour le récupérer en morceaux dans le système de fichiers.

4
S.Lott

Parfois, une solution simple consiste à utiliser un type personnalisé pour vos éléments de matrice. En fonction de la plage de chiffres dont vous avez besoin, vous pouvez utiliser une variable manuelle dtype et spécialement plus petite pour vos articles. Étant donné que Numpy considère le type le plus large d'objet par défaut, cela peut être une idée utile dans de nombreux cas. Voici un exemple:

In [70]: a = np.arange(5)

In [71]: a[0].dtype
Out[71]: dtype('int64')

In [72]: a.nbytes
Out[72]: 40

In [73]: a = np.arange(0, 2, 0.5)

In [74]: a[0].dtype
Out[74]: dtype('float64')

In [75]: a.nbytes
Out[75]: 32

Et avec un type personnalisé:

In [80]: a = np.arange(5, dtype=np.int8)

In [81]: a.nbytes
Out[81]: 5

In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16)

In [78]: a.nbytes
Out[78]: 8
3
Kasrâmvd

Autant que je sache à propos de numpy, non, mais je peux me tromper. 

Je peux vous proposer cette solution alternative: écrivez la matrice sur le disque et accédez-y en morceaux. Je vous suggère le format de fichier HDF5. Si vous en avez besoin de manière transparente, vous pouvez réimplémenter l'interface ndarray pour paginer votre matrice stockée sur disque en mémoire. Faites attention si vous modifiez les données pour les synchroniser sur le disque. 

1
Stefano Borini

Habituellement, lorsque nous traitons de grandes matrices, nous les implémentons en tant que Matrices creuses .

Je ne sais pas si numpy prend en charge les matrices creuses, mais j'ai trouvé this à la place.

1
Nick Dandoulakis

Vous pouvez exécuter votre code sur Google Colab.Google Colab est un service cloud gratuit qui prend désormais en charge le GPU gratuit! Je pourrais construire une matrice (870199 * 14425) sur Google Colab que je ne pouvais pas l'exécuter sur mon PC.

0
hamed baziyad