English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Fonctions ufunc générales de NumPy

NumPy fournit deux types d'objets de base, à savoir ndarray et objets ufunc. Ufunc est l'abréviation de universal function, ce qui signifie “fonction universelle”, c'est une fonction qui peut opérer sur chaque élément d'un tableau.
De nombreuses fonctions ufunc sont implémentées au niveau du langage C, donc elles sont très rapides en termes de calcul.
En plus, ufun est plus flexible que les fonctions du module math. Les entrées du module math sont généralement des scalaires, mais les fonctions de NumPy peuvent être des vecteurs ou des matrices, et utiliser des vecteurs ou des matrices peut éviter l'utilisation de boucles, ce qui est très important dans l'apprentissage automatique et l'apprentissage profond.

Pourquoi utiliser ufunc ?

Ufunc est utilisé pour la vectorisation dans NumPy, ce qui est beaucoup plus rapide que l'itération des éléments.
Ils fournissent également des méthodes de diffusion et d'autres, telles que la réduction, l'ajout, etc., ce qui est très utile pour les calculs.
Les ufunc acceptent également d'autres paramètres, par exemple :
where est un tableau de valeurs booléennes ou une condition, utilisé pour définir où l'opération doit être effectuée.
dtype définit le type de retour des éléments.
La valeur de retour out doit être copiée dans le tableau de sortie.

Fonctions universelles couramment utilisées dans NumPy
FonctionMéthode d'utilisation
sqrt()Calcul de la racine carrée des données sérialisées
sin()、cos()Fonctions trigonométriques
abs()Calcul de l'absolu des données sérialisées
dot()Opérations matricielles
log()、logl()、log2()Fonction logarithmique
exp()Fonction exponentielle
cumsum()、cumproduct()Somme et produit cumulés
sum()Somme d'une séquence sérialisée
mean()Calcul de la moyenne
median()Calcul de la médiane
std()Calcul de l'écart type
var()Calcul de la variance
corrcoef()Calcul de la corrélation

Comparaison des performances des fonctions math et numpy

import time
 import math
 import numpy as np
 x = [i * 0.001 for i in np.arange(1000000)
 start = time.clock()
 for i, t in enumerate(x):
 x[i] = math.sin(t)
 print("math.sin:", time.clock()) - start)
 x = [i * 0.001 for i in np.arange(1000000)
 x = np.array(x)
 start = time.clock()
 np.sin(x)
 print("numpy.sin:", time.clock()) - start)

Résultat de l'exécution :

math.sin: 0.5169950000000005
 numpy.sin: 0.05381199999999886

Il ressort donc que numpy.sin est presque aussi rapide que math.sin. 10 fois.

Vectorisation

Convertir une instruction itérative en une opération vectorielle s'appelle vectorisation.
Comme les CPU modernes sont optimisés pour ce type d'opération, la vitesse est plus rapide.
Additionner les éléments des deux listes :
list 1: [1, 2, 3, 4]
list 2: [4, 5, 6, 7]
Une méthode consiste à parcourir les deux listes et à additionner chaque élément.

Si l'ufunc n'est pas disponible, nous pouvons utiliser la méthode intégrée zip() de Python :

x = [1, 2, 3, 4]
 y = [4, 5, 6, 7]
 z = []
 for i, j in zip(x, y):
   z.append(i + j)
 print(z)

Résultat de l'exécution :

[5, 7, 9, 11]

Pour cela, NumPy dispose d'une ufunc appelée add(x, y), qui génère le même résultat. Grâce à l'ufunc, nous pouvons utiliser la fonction add() :

import numpy as np
 x = [1, 2, 3, 4]
 y = [4, 5, 6, 7]
 z = np.add(x, y)
 print(z)

Résultat de l'exécution :

[5, 7, 9, 11]

Comparaison entre boucles et opérations vectorielles

Utiliser pleinement les fonctions intégrées de la bibliothèque NumPy de Python (Built-en utilisant la vectorisation dans la fonction (Function), cela peut grandement améliorer la vitesse d'exécution. Les fonctions intégrées de la bibliothèque NumPy utilisent des instructions SIMD. Comme l'utilisation de la vectorisation est beaucoup plus rapide que le calcul avec une boucle, si l'on utilise un GPU, la performance sera encore plus puissante, bien que NumPy ne supporte pas le GPU.
Voyons le code suivant :

import time
 import numpy as np
 x1 = np.random.rand(1000000)
 x2 = np.random.rand(1000000)
 ##Calcul du produit scalaire en utilisant une boucle
 tic = time.process_time()
 dot = 0
 for i in range(len(x1)) :
 dot+= x1[i]*x2[i]
 toc = time.process_time()
 print("dot = " + str(dot) + ##Boucle for-----Temps de calcul = " + str(1000*(toc - tic)) + "ms")
 ##Calcul du produit scalaire en utilisant la fonction numpy
 tic = time.process_time()
 dot = 0
 dot = np.dot(x1,x2)
 toc = time.process_time()
 print("dot = " + str(dot) + "\nVersion Vector---- Temps de calcul = " + str(1000*(toc - tic)) + "ms")

Résultat de l'exécution :

 dot = 250215.601995
 Boucle for-----Temps de calcul = 798.3389819999998ms
 dot = 250215.601995
 Version Vector---- Temps de calcul = 1.885051999999554ms