3 votes

Vectorisation de l'ajout des résultats à un tableau numpy

J'ai une fonction qui fonctionne un peu comme ceci :

def Function(x):
   a = random.random()
   b = random.random()
   c = OtherFunctionThatReturnsAThreeColumnArray()
   results = np.zeros((1,5))
   results[0,0] = a
   results[0,1] = b
   results[0,2] = c[-1,0]
   results[0,3] = c[-1,1]
   results[0,4] = c[-1,2]
   return results

Ce que j'essaie de faire, c'est d'exécuter cette fonction de nombreuses fois, en ajoutant la ligne retournée, avec 5 colonnes de résultats, à un jeu de données en cours d'exécution. Mais la fonction d'ajout et une boucle for sont tous deux extrêmement inefficaces selon ce que je comprends, et je cherche à améliorer mon code, sachant que le nombre d'exécutions va être assez important pour que ce type d'inefficacité ne me soit pas favorable.

Quel est le meilleur moyen de faire ce qui suit de manière à causer le moins de surcharge possible :

  1. Créer un nouveau tableau numpy pour contenir les résultats
  2. Insérer les résultats de N appels de cette fonction dans le tableau en 1?

2voto

danodonovan Points 5268

Vous avez raison de penser que numpy.append ou numpy.concatenate vont être coûteux s'ils sont répétés de nombreuses fois (cela est dû au fait que numpy déclare un nouveau tableau pour les deux tableaux précédents).

La meilleure suggestion (si vous savez exactement combien d'espace vous allez avoir besoin au total) serait de le déclarer avant d'exécuter votre routine, puis de simplement placer les résultats au fur et à mesure qu'ils deviennent disponibles.

Si vous allez exécuter cela nrows fois, alors

results = np.zeros([nrows, 5])

et ensuite ajoutez vos résultats

def fonction(x, i, résultats):
    <.. snip ..>
    résultats[i,0] = a
    résultats[i,1] = b
    résultats[i,2] = c[-1,0]
    résultats[i,3] = c[-1,1]
    résultats[0,4] = c[-1,2]

Bien sûr, si vous ne savez pas combien de fois vous allez exécuter la fonction, cela ne fonctionnera pas. Dans ce cas, je vous suggère une approche moins élégante ;

  1. Déclarez un tableau résultats potentiellement grand et ajoutez à résultats[i, x] comme ci-dessus (en suivant i et la taille des résultats).

  2. Lorsque vous atteignez la taille de résultats, alors faites le numpy.append (ou concatenate) sur un nouveau tableau. C'est moins mauvais que d'ajouter de manière répétée et ne devrait pas affecter les performances - mais vous devrez écrire un peu de code d'enrobage.

Il y a d'autres idées que vous pourriez poursuivre. Au premier abord, vous pourriez

  1. Écrire les résultats sur le disque, en fonction de la vitesse de AutreFonctionQuiRenvoieUnTableauATroisColonnes et de la taille de vos données, cette idée n'est peut-être pas si absurde.

  2. Enregistrez vos résultats dans une compréhension de liste (en oubliant numpy jusqu'après l'exécution). Si la fonction renvoyait (a, b, c) au lieu des résultats ;

résultats = [fonction(x) for x in mes_données]

et maintenant effectuez quelques opérations pour obtenir les résultats sous la forme nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X