[PYTHON] Une histoire qui pourrait améliorer les performances simplement en changeant le type de numpy

introduction

J'ai eu l'occasion de travailler sur l'amélioration de l'efficacité de calcul de numpy. En cela, j'ai appris l'importance de dtype.

En tant que mémorandum personnel, bien sûr, j'espère qu'il sera utile à quelqu'un. Ce que j'ai écrit, c'est cet article.

[Une addition] numpy est un numpy.array créé en appliquant la méthode .values à la version dataframe de pandas read_csv.

Performance avant et après

Quand je l'écris,

  1. Effectuer plusieurs calculs matriciels de taille (10 000 400) @ (4 550 000)
  2. Prenez l'ensemble de produits

J'ai dû faire le processus, mais juste en changeant le type de numpy J'ai pu l'améliorer comme suit. (Comme c'était terrible au début ...)

article before after
temps de traitement 70 minutes 10 minutes
Mémoire utilisée Plus de 100 Go Plus de 30 Go

Ci-dessous, j'écrirai le type de modifications que j'ai apportées.

Ce que tu as fait

À propos de l'accélération

** Définissez dtype de numpy.array sur float32 ou float64 **

Il semble que le calcul matriciel de numpy utilise quelque chose appelé BLAS. Donc, il semble que ce type fera du bon travail s'il s'agit du type de données ci-dessus. (Voir l'article en haut du lien de référence)

Dans mon cas, c'était int au début, mais avec .astype (np.float32) Le temps de traitement a été réduit de 70 minutes à 10 minutes simplement en changeant le type en float32. !!

[Une addition] Après avoir dormi une nuit et relu, j'ai pensé que l'explication de la situation était insuffisante, je vais donc la compléter un peu.

A l'origine un encodage à chaud avec pd.get_dummies puis avec .values J'ai sorti numpy.ndarray et l'ai calculé.

Avec cette méthode, le type de données est uint8, mais il est changé en float32. J'ai pu atteindre une vitesse élevée en la changeant.

Le code ressemble à ceci.

pd.get_dummies([Série Pandas]).astype(np.float32).values

À propos de la sauvegarde de la mémoire

** Si possible, définissez la valeur de la matrice sur la valeur booléenne **

Le processus flottant mentionné ci-dessus a rendu le processus explosif, mais la mémoire a été consommée. Je faisais de la résistance en supprimant fréquemment des objets inutiles, mais cela ne s’est pas beaucoup amélioré.

Cependant, en retenant le résultat du calcul en booléen, j'ai pu économiser beaucoup de mémoire. (Il semble que la mémoire réservée à l'avance soit différente entre le type bool et int, type float)

[Supplément] En python, la relation suivante est valable entre «1/0 et True / False».

true_false.png

Ainsi, une matrice qui peut être représentée par 1/0 (par exemple, une matrice de codage à chaud) est Il peut également être exprimé sous forme de valeur booléenne.

Et la technique de correspondance

Comme mentionné ci-dessus, nous avons pu grandement améliorer l'efficacité en combinant simplement les deux points. En fin de compte, le déroulement du processus était comme ça.

  1. Effectuer un calcul matriciel avec le type float32 ・ ʻArrayA = matrice float32 @ matrice float32`
  2. Convertissez le résultat obtenu en type booléen ・ Faites simplement ʻarrayA = (arrayA> = 1) `
  3. Prenez l'ensemble de produits ・result = arrayA | arrayB | arrayCComme

Impressions

Le flotteur semble être utilisable dans divers cas, mais le booléen est-il limité? Je ne pense pas que cela puisse être appliqué à moins que le résultat ne puisse être représenté par 0/1.

Autre

Lien de référence

Recommended Posts

Une histoire qui pourrait améliorer les performances simplement en changeant le type de numpy
Le mystère du nombre qui peut être vu simplement en arrangeant les 1-Le nombre de repunits et de propriétés mystérieuses-
L'histoire du changement de pep8 en pycodestyle
L'histoire de Django créant une bibliothèque qui pourrait être un peu plus utile
L'histoire de l'impossibilité de créer un point d'accès en bande 5 GHz sur Ubuntu
Une histoire qui réduit l'effort de fonctionnement / maintenance
L'histoire de l'inadéquation de Hash Sum causée par gcrypto20
Une note que pyOSC n'a pas reçu int64
Une histoire sur le changement du nom principal de BlueZ
L'histoire selon laquelle la valeur de retour de tape.gradient () était None
Une histoire qui a analysé la livraison de Nico Nama.
Lister les classes qui peuvent être référencées par ObjCClass
L'histoire de sys.path.append ()
Une petite histoire addictive avec les permissions du répertoire spécifié par expdp (pour les débutants)