6.9. Fonctions universelles¶
Une fonction universelle (ufunc) est une fonction mathématique qui s’applique à chaque élément d’un tableau en un seul appel. Les opérateurs arithmétiques de la page précédente sont des fonctions universelles habillées d’une syntaxe d’opérateur ; cette page est le catalogue de celles qui sont nommées et qui couvrent la trigonométrie, exp / log, l’arrondi et quelques autres.
Chaque ufunc accepte un scalaire, un itérable Python ou un ndarray, et renvoie soit un unique flottant (lorsque l’entrée était scalaire) soit un ndarray de flottants
from ulab import numpy as np
np.exp(2.0) # 7.389...
np.sin(range(4)) # 1-D float ndarray
np.sqrt([1, 4, 9, 16]) # array([1.0, 2.0, 3.0, 4.0])
a = np.arange(9).reshape((3, 3))
np.exp(a) # 3x3 float ndarray
6.9.1. Le catalogue¶
numpy expose les fonctions mathématiques auxquelles une application embarquée recourt le plus souvent :
Trigonométrie –
sin(),cos(),tan(),asin(),acos(),atan(),arctan2(),sinh(),cosh(),tanh(),asinh(),acosh(),atanh(),sinc().Exponentielles et logarithmes –
exp(),expm1(),log(),log10(),log2(),sqrt().
Chaque fonction traite l’ensemble du tableau en un seul appel de bibliothèque. Le gain de vitesse par rapport à une compréhension de liste Python qui appelle math.sin() élément par élément est de 10 à 30x sur un tampon typique.
6.9.2. Le mot-clé out=¶
Chaque appel d’ufunc alloue normalement un nouveau tableau de résultat pour stocker sa sortie. Dans une boucle qui s’exécute plusieurs fois par seconde, ces allocations s’additionnent et gaspillent de la RAM. Passer out= – un tableau de flottants déjà existant, de la même forme que l’entrée – écrit le résultat dans ce tableau au lieu d’en allouer un nouveau
x = np.linspace(0, 2 * np.pi, num=256)
y = np.zeros(256)
while True:
np.sin(x, out=y)
# use y ...
Si out a un dtype ou une forme incorrects, la fonction lève une exception. Le mot-clé est pris en charge par chaque ufunc de cette page ; c’est la manière la plus propre de garder une boucle de traitement de signal en flux exempte d’allocations.
6.9.3. Ufuncs à deux arguments¶
arctan2() est la seule véritable ufunc à deux arguments de la liste ci-dessus – elle renvoie l’arctangente tenant compte du quadrant de y / x et diffuse les deux opérandes
y = np.array([1, 2.2, 33.33, 444.444])
np.arctan2(y, 1.0) # against a scalar
np.arctan2(1.0, y) # the other way
np.arctan2(y, y) # against another array
6.9.4. Composer des fonctions universelles¶
Les fonctions universelles se composent comme n’importe quelle autre expression de tableau. Quelques motifs qui reviennent sur la caméra :
Correction gamma (en espace flottant)
gamma = 0.5
out = 255.0 * (frame / 255.0) ** gamma
Un lisseur passe-bas simple (alpha proche de 1.0 signifie une mise à jour lente)
alpha = 0.95
filtered = alpha * filtered + (1.0 - alpha) * sample
Sigmoïde
sigmoid = 1.0 / (1.0 + np.exp(-x))
Spectre de puissance en dB
spectrum = 20.0 * np.log10(np.abs(real) + 1e-12)
6.9.5. np.vectorize¶
Une fonction Python classique peut être promue en une fonction de forme ufunc par vectorize(). L’appelable résultant accepte des scalaires, des itérables ou des valeurs ndarray
def f(x):
return x * x
vf = np.vectorize(f)
vf(44.0) # array([1936.0])
vf(np.array([1, 2, 3, 4])) # array([1.0, 4.0, 9.0, 16.0])
vf([2, 3, 4]) # array([4.0, 9.0, 16.0])
Par défaut, le dtype du résultat est float. otypes= le remplace
vf_u8 = np.vectorize(f, otypes=np.uint8)
vf_u8([1, 2, 3, 4])
# array([1, 4, 9, 16], dtype=uint8)
La fonction Python doit prendre un seul argument et renvoyer un seul nombre.
vectorize() est surtout syntaxique – la fonction Python encapsulée doit toujours s’exécuter une fois par élément, de sorte que la majeure partie du coût d’interpréteur par élément qu’une vraie ufunc évite est de retour. Attendez-vous à un gain modeste de 30 % à 50 % par rapport à une compréhension de liste, et non au 30x d’une vraie fonction universelle. C’est l’outil approprié lorsqu’une même fonction doit travailler sur des scalaires, des listes et des tableaux sous le même nom – pas lorsque la vitesse brute est l’objectif.
Pour les signatures d’appel complètes de chaque fonction universelle listée ci-dessus, voir numpy — opérations sur tableaux compatibles numpy.