6.17. Solveurs et nombres aléatoires¶
Lorsque la fonction étudiée est définie par du code Python plutôt que par un tampon d’échantillons, une autre famille d’outils est le bon choix : où se trouve la racine de la fonction, son minimum, son intégrale sur un intervalle donné ? Les sous-modules scipy.integrate et scipy.optimize couvrent ce travail. Chaque algorithme rappelle la fonction Python fournie par l’utilisateur, de sorte que le coût par itération est plus élevé qu’une réduction sur tampon ; la commodité réside dans le fait de ne pas avoir à écrire le solveur.
Le sous-module scipy.special couvre les fonctions spéciales statistiques (fonction d’erreur, gamma) qui interviennent lors du calcul de la fonction de répartition (CDF, la probabilité qu’un échantillon soit au plus égal à une valeur donnée) ou de la fonction de densité de probabilité (PDF, la vraisemblance relative à une valeur donnée) d’une distribution de probabilité. numpy.random couvre le générateur pseudo-aléatoire pour le tramage, la simulation et les données de test synthétiques.
6.17.1. Intégration numérique d’une fonction appelable¶
Lorsque l’intégrande est une fonction Python plutôt qu’un tampon d’échantillons, scipy.integrate expose quatre algorithmes de quadrature :
quad()– Gauss-Kronrod adaptatif. Le bon choix par défaut pour les intégrandes lisses. Renvoie(value, error).romberg()– Romberg / Newton-Cotes classique. Renvoie un unique flottant. Déprécié en amont ; inclus pour compatibilité.simpson()– règle de Simpson adaptative. Renvoie un unique flottant.tanhsinh()– quadrature double-exponentielle. À utiliser lorsque l’intégrande présente des singularités aux bornes ou une limite infinie. Renvoie(value, error).
L’intégrale gaussienne évaluée avec la règle double-exponentielle (tanhsinh)
from math import exp
from math import pi
from math import sqrt
from ulab import numpy as np
from ulab import scipy as sp
f = lambda x: exp(-x * x)
value, err = sp.integrate.tanhsinh(f, -np.inf, np.inf)
print("approx:", value, " exact:", sqrt(pi))
Sortie
approx: 1.7724538... exact: 1.7724538...
6.17.2. Recherche de racine et minimisation¶
scipy.optimize couvre trois solveurs classiques à une seule variable. Chaque itération rappelle la fonction Python fournie par l’utilisateur, de sorte que le gain de vitesse par rapport à un solveur en Python pur est modeste (environ 2x) ; la commodité réside dans le fait de ne pas avoir à écrire le solveur.
bisect()– trouve une racine defsur[a, b]en divisant l’intervalle par deux.f(a)etf(b)doivent avoir des signes opposésdef f(x): return x * x - 1 sp.optimize.bisect(f, 0, 4) # ~1.0
newton()– trouve une racine par itération de la sécante / Newton-Raphsondef f(x): return x * x * x - 2.0 sp.optimize.newton(f, 3., tol=0.001, rtol=0.01) # ~1.260
fmin()– trouve un minimum local par la méthode du simplexe descendant (Nelder-Mead)def f(x): return (x - 1) ** 2 - 1 sp.optimize.fmin(f, 3.0) # ~1.0
La portée à une seule variable suffit pour la plupart des optimisations côté caméra – une constante de calibration d’un capteur, le gain qui maximise une mesure de contraste, le seuil où la bimodalité d’un histogramme est la plus marquée. Pour les problèmes à plusieurs variables, la bonne réponse consiste généralement à reformuler le problème comme une petite résolution d’algèbre linéaire plutôt que de recourir à un optimiseur non linéaire général.
6.17.3. Fonctions spéciales¶
scipy.special expose une poignée de fonctions statistiques et de probabilité qui se comportent comme des fonctions universelles – elles acceptent un scalaire, un itérable ou un ndarray et renvoient un ndarray de flottants
x = np.linspace(0, 4, num=8)
sp.special.erf(x) # error function
sp.special.erfc(x) # complementary error function
sp.special.gamma(x + 1) # gamma function
sp.special.gammaln(x + 1) # log-gamma function
La fonction d’erreur et son complément apparaissent dans la CDF d’une gaussienne – l’application de prédilection pour convertir entre un score z mesuré et une probabilité, ou pour calculer l’intégrale de queue d’une distribution normale. Les fonctions gamma et log-gamma apparaissent dans les calculs bêta / khi-deux / student-t ; gammaln est la forme numériquement stable pour les grands arguments où gamma lui-même déborderait.
6.17.4. Nombres aléatoires¶
numpy.random fournit une classe Generator qui tire des échantillons de distributions courantes. Le générateur est à état : chaque appel fait avancer son état interne, de sorte que des appels consécutifs renvoient des échantillons indépendants
from ulab import numpy as np
rng = np.random.Generator(seed=42)
rng.random(size=5) # 5 uniform [0.0, 1.0) samples
rng.uniform(low=-1.0, high=1.0, size=10)
rng.normal(loc=0.0, scale=1.0, size=(2, 4))
Le dtype de sortie est toujours float. size= accepte un entier (sortie à une dimension) ou un uplet (sortie à n dimensions) ; lorsqu’il est omis, un unique flottant Python est renvoyé.
Le générateur convient à la simulation, au tramage, aux données de test synthétiques et à toute autre application où une robustesse cryptographique n’est pas requise. Il n’est pas adapté aux clés ou aux jetons ; utilisez pour cela la source aléatoire du système via os.
6.17.5. Disponibilité à la compilation¶
La présence effective de chaque sous-module dépend de la façon dont la caméra a été compilée. scipy.optimize et scipy.special ne sont pas activés sur toutes les caméras ; appeler une fonction que la caméra n’inclut pas lève AttributeError. dir(sp), dir(sp.optimize), dir(np.random) et consorts indiquent ce qui est disponible sur la caméra ciblée.