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 scipy.optimize import root
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 scipy.optimize import root
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:

from scipy.optimize import minimize

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 scipy.optimize import fsolve
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

from scipy.optimize import root

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

from scipy.optimize import root

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:

from scipy.optimize import minimize

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:

from scipy.optimize import minimize

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 scipy.optimize import minimize
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 lesuccesschamp `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 leargsparamè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 leconstraintsParamètre `constraints` pour ajouter des contraintes d'égalité et d'inégalité
  • Contraintes de bornes: utilisezboundsLe 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.

Autres extensions