Optimiseur SciPy
Le module de SciPyoptimizefournit des implémentations d'algorithmes courants d'optimisation numérique et de résolution d'équations. Nous pouvons appeler directement ces fonctions pour résoudre des problèmes pratiques, comme trouver le minimum ou le maximum d'une fonction, ou trouver les racines d'équations.
NumPy lui-même se concentre principalement sur le calcul de tableaux et les opérations d'algèbre linéaire. Il fournitdes outils de recherche de racines de polynômes(tels quenumpy.roots), mais cela ne fournit pas d'interface génériquede recherche numérique de racines d'équations non linéaires.
Par exemple, l'équation non linéaire suivante :
x + cos(x)
Pour de tels problèmes, vous pouvez utiliser lascipy.optimize.rootfonction pour le résoudre. Les deux paramètres essentiels couramment utilisés par cette fonction sont les suivants :
- fun- La fonction représentant l'équation (une valeur de retour de 0 indique que la racine a été trouvée)
- x0- L'estimation initiale de la racine
rootLa fonction renvoie un objet résultat (OptimizeResult), qui contient des informations telles que l'état de résolution, la réussite ou non, la valeur de la fonction et la solution finale.
La solution effective est stockée dans l'xattribut de l'objet renvoyé. Exemple :
Exemple
Trouvez lax + cos(x) = 0racine de l'équation :
from math import cos
def eqn(x):
return x + cos(x)
myroot = root(eqn, 0)
print(myroot.x)
# Voir plus d'informations
# print(myroot)
L'exécution du code ci-dessus produit la sortie suivante :
[-0.73908513]
Si vous imprimez directement l'objet renvoyé, vous pouvez afficher des informations plus complètes sur la solution :
Exemple
from math import cos
def eqn(x):
return x + cos(x)
myroot = root(eqn, 0)
print(myroot)
L'exécution du code ci-dessus produit la sortie suivante :
fjac: array([[-1.]])
fun: array([0.])
message: 'The solution converged.'
nfev: 9
qtf: array([-2.66786593e-13])
r: array([-1.67361202])
status: 1
success: True
x: array([-0.73908513])
Où :
- successIndique si l'algorithme a convergé avec succès
- messageDécrit le résultat du processus de résolution
- xLa racine finale de l'équation obtenue
Fonctions de minimisation
Dans les problèmes de mathématiques et d'ingénierie, une fonction peut généralement être représentée par une courbe, et la courbe présente souvent des points hauts et des points bas.
Les points hauts d'une courbe sont appelésmaxima。
Les points bas d'une courbe sont appelésminima。
Le point le plus haut sur toute la courbe est appelé lemaximum global, tandis que les autres points plus élevés mais pas les plus élevés sont appelésmaxima locaux。
De même, le point le plus bas sur toute la courbe est appelé leminimum global, tandis que les autres points plus bas mais pas les plus bas sont appelésminima locaux。
Dans SciPy, vous pouvez utiliser la fonctionscipy.optimize.minimize()pour trouver le minimum d'une fonction.
minimize()Les paramètres couramment utilisés de la fonction sont décrits ci-dessous :
-
fun- La fonction objectif à minimiser
-
x0- L'estimation initiale pour la variable indépendante
-
method- Le nom de l'algorithme d'optimisation utilisé. Les valeurs facultatives courantes incluent :
'CG'、'BFGS'、'Newton-CG'、'L-BFGS-B'、'TNC'、'COBYLA'、'SLSQP' -
callback- Une fonction de rappel appelée après chaque itération
-
options- Un dictionnaire d'autres paramètres de contrôle, par exemple :
{ "disp": boolean, # 是否打印详细的优化过程信息 "gtol": number # 梯度收敛容差(部分算法适用) }
Exemple
Utilisez la méthode BFGS pour minimiser la fonctionx² + x + 2:
def eqn(x):
return x**2 + x + 2
mymin = minimize(eqn, 0, method='BFGS')
print(mymin)
L'exécution du code ci-dessus produit la sortie suivante :
fun: 1.75
hess_inv: array([[0.50000001]])
jac: array([0.])
message: 'Optimization terminated successfully.'
nfev: 8
nit: 2
njev: 4
status: 0
success: True
x: array([-0.50000001])
D'après le résultat, nous pouvons voir que la fonction, àx ≈ -0.5atteint son minimum, et la valeur minimale correspondante de la fonction est1.75, ce qui est cohérent avec le résultat analytique.
minimize()La fonction prend également en charge les problèmes d'optimisation sous contraintes. Vous pouvez ajouter des contraintes via leconstraintsparamètre en spécifiant des contraintes d'égalité ou d'inégalité, ce qui convient aux scénarios d'application pratiques plus complexes.
Lorsque la fonction objectif ne peut pas être différenciée directement, vous pouvez choisirmethod='Nelder-Mead'`Nelder-Mead` ou d'autres algorithmes d'optimisation qui ne nécessitent pas d'informations de gradient. Ces méthodes s'approchent progressivement de la solution optimale par recherche simplex.
En pratique,successle champ `success` indique si l'optimisation a convergé avec succès,funle champ `fun` est la valeur optimale de la fonction objectif,xet le champ `x` est la solution optimale.successIl est recommandé de toujours vérifier l'état `success` pour garantir la fiabilité de la solution.
Recherche avancée de racines
En plus de laroot()fonction, SciPy fournit également lafsolve()fonction pour résoudre les racines d'équations. Elle est plus concise et adaptée à la résolution rapide d'équations simples.
Exemple
Utiliserfsolvepour résoudrex + cos(x) = 0:
from math import cos
def eqn(x):
return x + cos(x)
result = fsolve(eqn, 0)
print(result)
L'exécution du code ci-dessus produit la sortie suivante :
[-0.73908513]
fsolve()Il renvoie directement un tableau de solutions, tandis queroot()ce dernier renvoie un objet résultat contenant plus d'informations.fsolveLe premier est plus pratique.
Résolution avec plusieurs valeurs initiales
Pour les équations avec plusieurs racines, partir de différentes valeurs initiales peut donner des racines différentes. Ce qui suit résoutx² - 4 = 0les deux racines :
Exemple
def eqn(x):
return x**2 - 4
# Résoudre à partir de différentes valeurs initiales
for guess in [-3, 0, 3]:
result = root(eqn, guess)
if result.success:
print(ff"Valeur initiale {guess:2d} -> racine: {result.x)
L'exécution du code ci-dessus produit la sortie suivante :
初始值 -3 -> 根: -2.000000 初始值 0 -> 根: 2.000000 初始值 3 -> 根: 2.000000
Résolution d'équations avec paramètres
Dans les problèmes pratiques, les équations contiennent souvent des paramètres. On peut passer des paramètres supplémentaires à la fonction objectif via leargsparamètre :
Exemple
def eqn(x, a, b):
return a * x + b * cos(x)
# Résoudre 2x + cos(x) = 0
result = root(eqn, 0, args=(2, 1))
print(ff"Solution: {result.x)
L'exécution du code ci-dessus produit la sortie suivante :
解: -0.450184
Optimisation sous contraintes
minimize()La fonction prend en charge l'ajout de contraintes, y compris les contraintes d'égalité et d'inégalité. Voici un exemple de problème d'optimisation sous contraintes :
Exemple
Minimiserx² + y², avec la contraintex + y = 1:
def objective(x):
return x[0]**2 + x[1]**2
def constraint(x):
return x[0] + x[1] - 1
# Définir les contraintes
con = {'type': 'eq', 'fun': contrainte}
result = minimize(objective, [0, 0], constraints=con)
print(ff"Solution optimale : x={result.x)
print(ff"Valeur minimale : {result.fun:.6f}")
L'exécution du code ci-dessus produit la sortie suivante :
最优解: x=0.500000, y=0.500000 最小值: 0.500000
Types de contraintes'eq'Indique une contrainte d'égalité (la fonction de contrainte doit être égale à 0),'ineq'Indique une contrainte d'inégalité (la fonction de contrainte doit être supérieure ou égale à 0).
Optimisation sous contraintes de bornes
En plus des contraintes fonctionnelles, vous pouvez également utiliser leboundsparamètre pour limiter la plage de valeurs de la variable indépendante :
Exemple
Dansx ∈ [0, 2]Minimiser dans l'intervalle(x - 1)² + 2:
def objective(x):
return (x - 1)**2 + 2
# Définir les bornes
bounds = [(0, 2)]
result = minimize(objective, 0, bounds=bounds)
print(ff"Solution optimale : x={result.x)
print(ff"Valeur minimale : {result.fun:.6f}")
L'exécution du code ci-dessus produit la sortie suivante :
最优解: x=1.000000 最小值: 2.000000
Optimisation sans gradient
Lorsque la fonction objectif n'est pas différentiable ou que sa dérivée est difficile à calculer, vous pouvez utiliser un algorithme d'optimisation qui ne nécessite pas d'informations de gradient, comme laNelder-Meadméthode :
Exemple
Utilisez la méthode Nelder-Mead pour minimisersin(x) + 0.5*x:
from math import sin
def objective(x):
return sin(x) + 0.5 * x
result = minimize(objective, 0, method='Nelder-Mead')
print(ff"Solution optimale : x={result.x)
print(ff"Valeur minimale : {result.fun:.6f}")
print(ff"Success: {result.success}")
L'exécution du code ci-dessus produit la sortie suivante :
最优解: x=-1.047198 最小值: -1.523599 是否成功: True
Problèmes courants et suggestions
- Choisissez une valeur initiale appropriée- Le choix de la valeur initiale a un grand impact sur le résultat de la solution. Il est recommandé d'effectuer une visualisation ou une analyse simple de la fonction objectif avant de résoudre.
-
Vérifiez l'état de convergence- Vérifiez toujours le
successchamp `success` pour vous assurer que l'algorithme a convergé avec succès. Si la résolution échoue, essayez de modifier la valeur initiale ou l'algorithme d'optimisation. -
Choisissez un algorithme approprié- Pour les problèmes sans contraintes,
BFGS`BFGS` est un bon choix par défaut ; pour les problèmes de grande dimension, vous pouvez essayer `L-BFGS-B` ;L-BFGS-Bpour les fonctions non différentiables, utilisez `Nelder-Mead`.Nelder-Mead。 - Gestion des racines multiples- Pour les problèmes comportant plusieurs racines, il est recommandé de résoudre en partant de plusieurs valeurs initiales différentes.
-
Passage de paramètres- Utilisez le
argsparamètre `args` pour transmettre des arguments supplémentaires, en évitant l'utilisation de variables globales.
Résumé
Le module de SciPyoptimizemodule fournit de puissants outils d'optimisation et de résolution d'équations :
- Recherche de racines:
root()etfsolve()pour résoudre des équations non linéaires - Optimisation sans contraintes:
minimize()combinée avec lemethodParamètre `method` pour implémenter plusieurs algorithmes - Optimisation sous contraintes: via le
constraintsParamètre `constraints` pour ajouter des contraintes d'égalité et d'inégalité - Contraintes de bornes: utilisez
boundsLe paramètre limite la plage des valeurs des variables - Méthodes sans gradient:
Nelder-MeadApplicables aux fonctions non différentiables
Après avoir maîtrisé ces fonctions de base, les lecteurs peuvent explorer plus loinoptimizeD'autres fonctionnalités du module, telles que l'ajustement de courbes (curve_fit), optimisation globale (basinhopping、differential_evolution) et d'autres fonctionnalités avancées.