13.12. Algorithme de calcul « NonLinearLeastSquares »¶
Description¶
Cet algorithme réalise une estimation d’état par minimisation variationnelle de
la fonctionnelle d’écart classique de « Moindres Carrés » pondérés:
Il est similaire à un Algorithme de calcul « 3DVAR » privé de sa partie ébauche. L’ébauche, requise dans l’interface, ne sert que de point initial pour la minimisation variationnelle.
Cet algorithme est naturellement écrit pour une estimation unique, sans notion dynamique ou itérative (il n’y a donc pas besoin dans ce cas d’opérateur d’évolution incrémentale, ni de covariance d’erreurs d’évolution). Dans ADAO, il peut aussi être utilisé sur une succession d’observations, plaçant alors l’estimation dans un cadre récursif en partie similaire à un filtre de Kalman. Une estimation standard est effectuée à chaque pas d’observation sur l’état prévu par le modèle d’évolution incrémentale.
Dans tous les cas, il est recommandé de lui préférer un Algorithme de calcul « 3DVAR » pour sa stabilité comme pour son comportement lors de l’optimisation.
Commandes requises et optionnelles¶
Les commandes générales requises, disponibles en édition dans l’interface graphique ou textuelle, sont les suivantes :
- Background
- Vecteur. La variable désigne le vecteur d’ébauche ou d’initialisation,
usuellement noté
. Sa valeur est définie comme un objet de type « Vector » ou « VectorSerie ». Sa disponibilité en sortie est conditionnée par le booléen « Stored » associé en entrée.
- Observation
- Liste de vecteurs. La variable désigne le vecteur d’observation utilisé en
assimilation de données ou en optimisation, et usuellement noté
. Sa valeur est définie comme un objet de type « Vector » si c’est une unique observation (temporelle ou pas) ou « VectorSerie » si c’est une succession d’observations. Sa disponibilité en sortie est conditionnée par le booléen « Stored » associé en entrée.
- ObservationError
- Matrice. La variable désigne la matrice de covariance des erreurs a
priori d’ébauche, usuellement notée
. Cette matrice est définie comme un objet de type « Matrix », de type « ScalarSparseMatrix », ou de type « DiagonalSparseMatrix », comme décrit en détail dans la section Conditions requises pour décrire des matrices de covariance. Sa disponibilité en sortie est conditionnée par le booléen « Stored » associé en entrée.
- ObservationOperator
- Opérateur. La variable désigne l’opérateur d’observation, usuellement noté
, qui transforme les paramètres d’entrée
en résultats
qui sont à comparer aux observations
. Sa valeur est définie comme un objet de type « Function » ou de type « Matrix ». Dans le cas du type « Function », différentes formes fonctionnelles peuvent être utilisées, comme décrit dans la section Conditions requises pour les fonctions décrivant un opérateur. Si un contrôle
est inclus dans le modèle d’observation, l’opérateur doit être appliqué à une paire
.
Les commandes optionnelles générales, disponibles en édition dans l’interface graphique ou textuelle, sont indiquées dans la Liste des commandes et mots-clés pour un cas d’assimilation de données ou d’optimisation. De plus, les paramètres de la commande « AlgorithmParameters » permettent d’indiquer les options particulières, décrites ci-après, de l’algorithme. On se reportera à la Description des options d’un algorithme par « AlgorithmParameters » pour le bon usage de cette commande.
Les options sont les suivantes :
- Bounds
Liste de paires de valeurs réelles. Cette clé permet de définir des paires de bornes supérieure et inférieure pour chaque variable d’état optimisée. Les bornes doivent être données par une liste de liste de paires de bornes inférieure/supérieure pour chaque variable, avec une valeur
None
chaque fois qu’il n’y a pas de borne. Les bornes peuvent toujours être spécifiées, mais seuls les optimiseurs sous contraintes les prennent en compte.Exemple :
{"Bounds":[[2.,5.],[1.e-2,10.],[-30.,None],[None,None]]}
- CostDecrementTolerance
Valeur réelle. Cette clé indique une valeur limite, conduisant à arrêter le processus itératif d’optimisation lorsque la fonction coût décroît moins que cette tolérance au dernier pas. La valeur par défaut est de 1.e-7, et il est recommandé de l’adapter aux besoins pour des problèmes réels. On peut se reporter à la partie décrivant les manières de Contrôler la convergence pour des cas de calculs et algorithmes itératifs pour des recommandations plus détaillées.
Exemple :
{"CostDecrementTolerance":1.e-7}
- EstimationOf
Nom prédéfini. Cette clé permet de choisir le type d’estimation à réaliser. Cela peut être soit une estimation de l’état, avec la valeur « State », ou une estimation de paramètres, avec la valeur « Parameters ». Le choix par défaut est « Parameters ».
Exemple :
{"EstimationOf":"Parameters"}
- GradientNormTolerance
Valeur réelle. Cette clé indique une valeur limite, conduisant à arrêter le processus itératif d’optimisation lorsque la norme du gradient est en dessous de cette limite. C’est utilisé uniquement par les optimiseurs sans contraintes. Le défaut est 1.e-5 et il n’est pas recommandé de le changer.
Exemple :
{"GradientNormTolerance":1.e-5}
- InitializationPoint
Vecteur. La variable désigne un vecteur à utiliser comme l’état initial autour duquel démarre un algorithme itératif. Par défaut, cet état initial n’a pas besoin d’être fourni et il est égal à l’ébauche
. Sa valeur doit permettre de construire un vecteur de taille identique à l’ébauche. Dans le cas où il est fourni, il ne remplace l’ébauche que pour l’initialisation.
Exemple :
{"InitializationPoint":[1, 2, 3, 4, 5]}
- MaximumNumberOfIterations
Valeur entière. Cette clé indique le nombre maximum d’itérations internes possibles en optimisation itérative. Le défaut est 15000, qui est très similaire à une absence de limite sur les itérations. Il est ainsi recommandé d’adapter ce paramètre aux besoins pour des problèmes réels. Pour certains optimiseurs, le nombre de pas effectif d’arrêt peut être légèrement différent de la limite à cause d’exigences de contrôle interne de l’algorithme. On peut se reporter à la partie décrivant les manières de Contrôler la convergence pour des cas de calculs et algorithmes itératifs pour des recommandations plus détaillées.
Exemple :
{"MaximumNumberOfIterations":100}
- Minimizer
Nom prédéfini. Cette clé permet de changer le minimiseur pour l’optimiseur. Le choix par défaut est « LBFGSB », et les choix possibles sont « LBFGSB » (minimisation non linéaire sous contraintes, voir [Byrd95], [Morales11], [Zhu97]), « TNC » (minimisation non linéaire sous contraintes), « CG » (minimisation non linéaire sans contraintes), « BFGS » (minimisation non linéaire sans contraintes), « NCG » (minimisation de type gradient conjugué de Newton). Il est fortement conseillé de conserver la valeur par défaut.
Exemple :
{"Minimizer":"LBFGSB"}
- ProjectedGradientTolerance
Valeur réelle. Cette clé indique une valeur limite, conduisant à arrêter le processus itératif d’optimisation lorsque toutes les composantes du gradient projeté sont en-dessous de cette limite. C’est utilisé uniquement par les optimiseurs sous contraintes. Le défaut est -1, qui désigne le défaut interne de chaque optimiseur (usuellement 1.e-5), et il n’est pas recommandé de le changer.
Exemple :
{"ProjectedGradientTolerance":-1}
- StoreSupplementaryCalculations
Liste de noms. Cette liste indique les noms des variables supplémentaires, qui peuvent être disponibles au cours du déroulement ou à la fin de l’algorithme, si elles sont initialement demandées par l’utilisateur. Leur disponibilité implique, potentiellement, des calculs ou du stockage coûteux. La valeur par défaut est donc une liste vide, aucune de ces variables n’étant calculée et stockée par défaut (sauf les variables inconditionnelles). Les noms possibles pour les variables supplémentaires sont dans la liste suivante (la description détaillée de chaque variable nommée est donnée dans la suite de cette documentation par algorithme spécifique, dans la sous-partie « Informations et variables disponibles à la fin de l’algorithme ») : [ « Analysis », « BMA », « CostFunctionJ », « CostFunctionJAtCurrentOptimum », « CostFunctionJb », « CostFunctionJbAtCurrentOptimum », « CostFunctionJo », « CostFunctionJoAtCurrentOptimum », « CurrentIterationNumber », « CurrentOptimum », « CurrentState », « CurrentStepNumber », « ForecastState », « IndexOfOptimum », « Innovation », « InnovationAtCurrentAnalysis », « InnovationAtCurrentState », « OMA », « OMB », « SimulatedObservationAtBackground », « SimulatedObservationAtCurrentOptimum », « SimulatedObservationAtCurrentState », « SimulatedObservationAtOptimum », ].
Exemple :
{"StoreSupplementaryCalculations":["BMA", "CurrentState"]}
Astuce pour cet algorithme :
Comme la commande « BackgroundError » est requise pour TOUS les algorithmes de calcul dans l’interface graphique EFICAS d’ADAO, vous devez fournir une valeur, malgré le fait que cette commande ne soit pas nécessaire pour cet algorithme, et n’est donc pas utilisée. La manière la plus simple est de donner « 1 » comme un STRING.
Informations et variables disponibles à la fin de l’algorithme¶
En sortie, après exécution de l’algorithme, on dispose d’informations et de
variables issues du calcul. La description des
Variables et informations disponibles en sortie indique la manière de les obtenir par la
méthode nommée get
, de la variable « ADD » du post-processing en interface
graphique, ou du cas en interface textuelle. Les variables d’entrée, mises à
disposition de l’utilisateur en sortie pour faciliter l’écriture des procédures
de post-processing, sont décrites dans l”Inventaire des informations potentiellement disponibles en sortie.
Sorties permanentes (non conditionnelles)
Les sorties non conditionnelles de l’algorithme sont les suivantes :
- Analysis
Liste de vecteurs. Chaque élément de cette variable est un état optimal
en optimisation ou une analyse
en assimilation de données.
Exemple :
Xa = ADD.get("Analysis")[-1]
- CostFunctionJ
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
choisie.
Exemple :
J = ADD.get("CostFunctionJ")[:]
- CostFunctionJb
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’ébauche. Si cette partie n’existe pas dans la fonctionnelle, sa valeur est nulle.
Exemple :
Jb = ADD.get("CostFunctionJb")[:]
- CostFunctionJo
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’observation.
Exemple :
Jo = ADD.get("CostFunctionJo")[:]
Ensemble des sorties à la demande (conditionnelles ou non)
L’ensemble des sorties (conditionnelles ou non) de l’algorithme, classées par ordre alphabétique, est le suivant :
- Analysis
Liste de vecteurs. Chaque élément de cette variable est un état optimal
en optimisation ou une analyse
en assimilation de données.
Exemple :
Xa = ADD.get("Analysis")[-1]
- BMA
Liste de vecteurs. Chaque élément est un vecteur d’écart entre l’ébauche et l’état optimal.
Exemple :
bma = ADD.get("BMA")[-1]
- CostFunctionJ
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
choisie.
Exemple :
J = ADD.get("CostFunctionJ")[:]
- CostFunctionJAtCurrentOptimum
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
. A chaque pas, la valeur correspond à l’état optimal trouvé depuis le début.
Exemple :
JACO = ADD.get("CostFunctionJAtCurrentOptimum")[:]
- CostFunctionJb
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’ébauche. Si cette partie n’existe pas dans la fonctionnelle, sa valeur est nulle.
Exemple :
Jb = ADD.get("CostFunctionJb")[:]
- CostFunctionJbAtCurrentOptimum
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’ébauche. A chaque pas, la valeur correspond à l’état optimal trouvé depuis le début. Si cette partie n’existe pas dans la fonctionnelle, sa valeur est nulle.
Exemple :
JbACO = ADD.get("CostFunctionJbAtCurrentOptimum")[:]
- CostFunctionJo
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’observation.
Exemple :
Jo = ADD.get("CostFunctionJo")[:]
- CostFunctionJoAtCurrentOptimum
Liste de valeurs. Chaque élément est une valeur de fonctionnelle d’écart
, c’est-à-dire de la partie écart à l’observation. A chaque pas, la valeur correspond à l’état optimal trouvé depuis le début.
Exemple :
JoACO = ADD.get("CostFunctionJoAtCurrentOptimum")[:]
- CurrentIterationNumber
Liste d’entiers. Chaque élément est l’index d’itération courant au cours du déroulement itératif de l’algorithme utilisé. Il y a une valeur d’index d’itération par pas d’assimilation correspondant à un état observé.
Exemple :
i = ADD.get("CurrentIterationNumber")[-1]
- CurrentOptimum
Liste de vecteurs. Chaque élément est le vecteur d’état optimal au pas de temps courant au cours du déroulement itératif de l’algorithme d’optimisation utilisé. Ce n’est pas nécessairement le dernier état.
Exemple :
Xo = ADD.get("CurrentOptimum")[:]
- CurrentState
Liste de vecteurs. Chaque élément est un vecteur d’état courant utilisé au cours du déroulement itératif de l’algorithme utilisé.
Exemple :
Xs = ADD.get("CurrentState")[:]
- CurrentStepNumber
Liste d’entiers. Chaque élément est l’index du pas courant au cours du déroulement itératif, piloté par la série des observations, de l’algorithme utilisé. Cela correspond au pas d’observation utilisé. Remarque : ce n’est pas l’index d’itération courant d’algorithme même si cela coïncide pour des algorithmes non itératifs.
Exemple :
i = ADD.get("CurrentStepNumber")[-1]
- ForecastState
Liste de vecteurs. Chaque élément est un vecteur d’état (ou un ensemble de vecteurs d’états selon l’algorithme) prévu(s) par le modèle au cours du déroulement itératif temporel de l’algorithme utilisé.
Exemple :
Xf = ADD.get("ForecastState")[:]
- IndexOfOptimum
Liste d’entiers. Chaque élément est l’index d’itération de l’optimum obtenu au cours du déroulement itératif de l’algorithme d’optimisation utilisé. Ce n’est pas nécessairement le numéro de la dernière itération.
Exemple :
i = ADD.get("IndexOfOptimum")[-1]
- Innovation
Liste de vecteurs. Chaque élément est un vecteur d’innovation, qui est en statique l’écart de l’optimum à l’ébauche, et en dynamique l’incrément d’évolution.
Exemple :
d = ADD.get("Innovation")[-1]
- InnovationAtCurrentAnalysis
Liste de vecteurs. Chaque élément est un vecteur d’innovation à l’état analysé courant. Cette quantité est identique au vecteur d’innovation à l’état analysé dans le cas d’une assimilation mono-état.
Exemple :
ds = ADD.get("InnovationAtCurrentAnalysis")[-1]
- InnovationAtCurrentState
Liste de vecteurs. Chaque élément est un vecteur d’innovation à l’état courant avant analyse.
Exemple :
ds = ADD.get("InnovationAtCurrentState")[-1]
- OMA
Liste de vecteurs. Chaque élément est un vecteur d’écart entre l’observation et l’état optimal dans l’espace des observations.
Exemple :
oma = ADD.get("OMA")[-1]
- OMB
Liste de vecteurs. Chaque élément est un vecteur d’écart entre l’observation et l’état d’ébauche dans l’espace des observations.
Exemple :
omb = ADD.get("OMB")[-1]
- SimulatedObservationAtBackground
Liste de vecteurs. Chaque élément est un vecteur d’observation simulé par l’opérateur d’observation à partir de l’ébauche
. C’est la prévision à partir de l’ébauche, elle est parfois appellée « Dry ».
Exemple :
hxb = ADD.get("SimulatedObservationAtBackground")[-1]
- SimulatedObservationAtCurrentOptimum
Liste de vecteurs. Chaque élément est un vecteur d’observation simulé par l’opérateur d’observation à partir de l’état optimal au pas de temps courant au cours du déroulement de l’algorithme d’optimisation, c’est-à-dire dans l’espace des observations.
Exemple :
hxo = ADD.get("SimulatedObservationAtCurrentOptimum")[-1]
- SimulatedObservationAtCurrentState
Liste de vecteurs. Chaque élément est un vecteur d’observation simulé par l’opérateur d’observation à partir de l’état courant, c’est-à-dire dans l’espace des observations.
Exemple :
hxs = ADD.get("SimulatedObservationAtCurrentState")[-1]
- SimulatedObservationAtOptimum
Liste de vecteurs. Chaque élément est un vecteur d’observation obtenu par l’opérateur d’observation à partir de la simulation d’analyse ou d’état optimal
. C’est l’observation de la prévision à partir de l’analyse ou de l’état optimal, et elle est parfois appellée « Forecast ».
Exemple :
hxa = ADD.get("SimulatedObservationAtOptimum")[-1]
Exemples d’utilisation en Python (TUI)¶
Voici un exemple très simple d’usage de l’algorithme proposé et de ses paramètres, écrit en [DocR] Interface textuelle pour l’utilisateur (TUI/API), et dont les informations indiquées en entrée permettent de définir un cas équivalent en interface graphique.
Cet exemple décrit le recalage des paramètres d’un modèle
d’observation
quadratique. Ce modèle est représenté ici comme une
fonction nommée
QuadFunction
. Cette fonction accepte en entrée le vecteur
de coefficients , et fournit en sortie le vecteur
d’évaluation du modèle quadratique aux points de contrôle
internes prédéfinis dans le modèle. Le calage s’effectue sur la base d’un jeu
initial de coefficients (état d’ébauche désigné par
Xb
dans l’exemple), et
avec l’information (désignée par
Yobs
dans l’exemple)
de 5 mesures obtenues à ces mêmes points de contrôle internes. On se place en
expériences jumelles (voir Pour tester une chaîne d’assimilation de données : les expériences jumelles) et les mesures sont
parfaites.
L’ajustement s’effectue en affichant des résultats intermédiaires lors de l’optimisation itérative.
# -*- coding: utf-8 -*-
#
from numpy import array, ravel
def QuadFunction( coefficients ):
"""
Simulation quadratique aux points x : y = a x^2 + b x + c
"""
a, b, c = list(ravel(coefficients))
x_points = (-5, 0, 1, 3, 10)
y_points = []
for x in x_points:
y_points.append( a*x*x + b*x + c )
return array(y_points)
#
Xb = array([1., 1., 1.])
Yobs = array([57, 2, 3, 17, 192])
#
print("Résolution du problème de calage")
print("--------------------------------")
print("")
from adao import adaoBuilder
case = adaoBuilder.New('')
case.setBackground( Vector = Xb, Stored=True )
case.setObservation( Vector = Yobs, Stored=True )
case.setObservationError( ScalarSparseMatrix = 1. )
case.setObservationOperator( OneFunction = QuadFunction )
case.setAlgorithmParameters(
Algorithm='NonLinearLeastSquares',
Parameters={
'MaximumNumberOfIterations': 100,
'StoreSupplementaryCalculations': [
'CurrentState',
],
},
)
case.setObserver(
Info=" État intermédiaire en itération courante :",
Template='ValuePrinter',
Variable='CurrentState',
)
case.execute()
print("")
#
#-------------------------------------------------------------------------------
#
print("Calage de %i coefficients pour une forme quadratique 1D sur %i mesures"%(
len(case.get('Background')),
len(case.get('Observation')),
))
print("--------------------------------------------------------------------")
print("")
print("Vecteur d'observation.............:", ravel(case.get('Observation')))
print("État d'ébauche a priori...........:", ravel(case.get('Background')))
print("")
print("Coefficients théoriques attendus..:", ravel((2,-1,2)))
print("")
print("Nombre d'itérations...............:", len(case.get('CurrentState')))
print("Nombre de simulations.............:", len(case.get('CurrentState'))*4)
print("Coefficients résultants du calage.:", ravel(case.get('Analysis')[-1]))
#
Xa = case.get('Analysis')[-1]
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (10, 4)
#
plt.figure()
plt.plot((-5,0,1,3,10),QuadFunction(Xb),'b-',label="Simulation à l'ébauche")
plt.plot((-5,0,1,3,10),Yobs, 'kX',label='Observation',markersize=10)
plt.plot((-5,0,1,3,10),QuadFunction(Xa),'r-',label="Simulation à l'optimum")
plt.legend()
plt.title('Calage de coefficients', fontweight='bold')
plt.xlabel('Coordonnée arbitraire')
plt.ylabel('Observations')
plt.savefig("simple_NonLinearLeastSquares.png")
Le résultat de son exécution est le suivant :
Résolution du problème de calage
--------------------------------
État intermédiaire en itération courante : [1. 1. 1.]
État intermédiaire en itération courante : [1.99739508 1.07086406 1.01346638]
État intermédiaire en itération courante : [1.83891966 1.04815981 1.01208385]
État intermédiaire en itération courante : [1.8390702 1.03667176 1.01284797]
État intermédiaire en itération courante : [1.83967236 0.99071957 1.01590445]
État intermédiaire en itération courante : [1.84208099 0.8069108 1.02813037]
État intermédiaire en itération courante : [ 1.93711599 -0.56383147 1.12097995]
État intermédiaire en itération courante : [ 1.99838848 -1.00480576 1.1563713 ]
État intermédiaire en itération courante : [ 2.0135905 -1.04815936 1.16155285]
État intermédiaire en itération courante : [ 2.01385679 -1.03874812 1.16129658]
État intermédiaire en itération courante : [ 2.01377856 -1.03700048 1.16157611]
État intermédiaire en itération courante : [ 2.01338903 -1.02943739 1.16528951]
État intermédiaire en itération courante : [ 2.01265633 -1.01708474 1.17793974]
État intermédiaire en itération courante : [ 2.01124871 -0.99745512 1.21485092]
État intermédiaire en itération courante : [ 2.00863696 -0.96943287 1.30917045]
État intermédiaire en itération courante : [ 2.00453385 -0.94011718 1.51021885]
État intermédiaire en itération courante : [ 2.00013539 -0.93313894 1.80539445]
État intermédiaire en itération courante : [ 1.95437219 -0.76890307 2.04566901]
État intermédiaire en itération courante : [ 1.99797363 -0.92538077 1.81674454]
État intermédiaire en itération courante : [ 1.99760514 -0.9592967 2.01402117]
État intermédiaire en itération courante : [ 1.99917565 -0.99152673 2.03171823]
État intermédiaire en itération courante : [ 1.99990376 -0.99963125 2.00671607]
État intermédiaire en itération courante : [ 1.99999841 -1.00005288 2.00039727]
État intermédiaire en itération courante : [ 2.00000014 -1.00000309 2.00000249]
État intermédiaire en itération courante : [ 2. -0.99999995 2.00000015]
Calage de 3 coefficients pour une forme quadratique 1D sur 5 mesures
--------------------------------------------------------------------
Vecteur d'observation.............: [ 57. 2. 3. 17. 192.]
État d'ébauche a priori...........: [1. 1. 1.]
Coefficients théoriques attendus..: [ 2 -1 2]
Nombre d'itérations...............: 25
Nombre de simulations.............: 100
Coefficients résultants du calage.: [ 2. -0.99999995 2.00000015]
Les graphiques illustrant le résultat de son exécution sont les suivants :

Voir aussi¶
Références vers d’autres sections :
- Algorithme de calcul « LinearLeastSquares »
- Algorithme de calcul « 3DVAR »
- Algorithme de vérification « LinearityTest »
Références bibliographiques :