Problème avec la fonction minimiser en JSLSalut tout le monde,
J'essaie d'utiliser la fonction minimiser dans JSL pour obtenir les valeurs de deux (ou plus) variables qui minimisent le carré moyen d'erreur d'un grand modèle. Je n'arrive pas à le faire converger même si je sais vers quelle valeur il doit converger (par essais et erreurs).
La syntaxe de base que j'ai utilisée est la suivante :
minfun = Minimize( min_test, {kD( 0.4, 0.8 ), wshc( 0.1, 1.5 )}, <<DETAILS></DETAILS>J'ai essayé différents messages mais ils ne changent rien.
Le but ici est de trouver les valeurs de kD et wshc en minimisant l'expression min_test qui est elle-même une séquence d'expressions évaluées comme dans
min_test = Expr(
Eval( light );
Eval( parafile );
Eval( runprg );
Eval( reshandling2 );
Eval( SSE2 );
);
Les valeurs kD et wshc modifiées modifient les expressions "light" et "parafile" qui exécutent ensuite un programme exécutable (dans l'expression runprg) dont les résultats sont manipulés et à partir duquel l'erreur quadratique moyenne (MSE) est la dernière chose qui est évalué dans l’expression SSE2. Pour le contexte, l'expression "runprg" soumet plusieurs fichiers créés à un exécutable autonome qui simule l'évolution thermique des lacs. Chaque passage à l'expression « runprg » nécessite environ 10 à 20 secondes de calcul, dont les résultats sont réingérés dans JSL pour calculer le MSE.
Le processus lui-même semble fonctionner correctement dans la mesure où il lit correctement la valeur de la fonction objectif à chaque étape et semble transmettre correctement les valeurs des paramètres à l'expression. Le problème est que l'algorithme "déplace" les paramètres kD et wshc si légèrement (uniquement à la 5ème décimale) par rapport aux valeurs initiales que je leur ai données qu'il ne parvient pas à converger. Par exemple, si je commence avec des valeurs initiales de 0,8 et 0,5 respectivement, j'obtiendrai généralement quelque chose comme
0,8
0,49999945654133
à l'itération suivante et n'affecte donc pas de manière significative le MSE résultant. Avec les limites des paramètres que j'ai données dans la fonction minimiser, il y a beaucoup d'espace pour que les paramètres se déplacent. Je comprends que mon cas est assez loin de la simple fonction différentiable typique. Cependant, en exécutant "manuellement" le programme avec différentes valeurs de paramètres, je sais que la fonction objectif est assez convexe par rapport aux paramètres et j'ai donc pensé que la fonction minimiser fonctionnerait OK , notamment en utilisant le message <
Avez-vous des suggestions de solution de contournement qui pourraient aider dans cette situation ?
Un grand merci d'avance, Yves
Modélisation statistique avancéeAutomatisation et scriptsmacOSRe : Problème avec la fonction minimiser en JSLL'algorithme se terminera après MaxIter itérations - donc je porterais cela à une valeur beaucoup plus grande que la valeur par défaut, et je verrais si cela aide.
Re : Problème avec la fonction minimiser en JSLMerci pour la suggestion David mais j'ai bien peur que cela n'aide pas. Cependant, j'aurais dû être plus clair sur le fait que le nombre d'itérations qu'il effectue réellement avant de planter n'est pas élevé, peut-être quelque chose comme 20-30, mais à chaque fois, le changement dans les valeurs des paramètres est trop faible pour avoir un impact.
Yves
Re : Problème avec la fonction minimiser en JSLCe n'est pas vraiment mon domaine, mais il semble que cela devrait fonctionner. Voici mon test JSL.
aa = expr(
Show( "evaluating", Char( a, 19, 16 ), Char( b, 19, 16 ) ); // peek inside
(a - 10) ^ 2 + (b - 11) ^ 2 // the function, roots at 10 and 11
);
min_test = Expr( Eval( aa ) );
a = 33; // initial guesses
b = -55; // (not very good)
minfun = Minimize(
min_test,
{a( -100, 100 ), b( -100, 100 )},
<<DETAILS></DETAILS>
Voici le journal. Il semble étrange qu'un certain nombre d'appels soient passés avec exactement les mêmes mauvaises suppositions initiales, bien qu'ils semblent obtenir une réponse presque parfaite dès la première *vraie* supposition.
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000005066394806";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "32.9999994933605194";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-54.999999165534973";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000000834465027";
"evaluating";
Char(a, 19, 16) = "33.0002058854513791";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "32.9997941145486209";
Char(b, 19, 16) = "-55.000000000000000";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-54.999660894550665";
"evaluating";
Char(a, 19, 16) = "33.0000000000000000";
Char(b, 19, 16) = "-55.000339105449335";
"evaluating";
Char(a, 19, 16) = "33.0003391054493349";
Char(b, 19, 16) = "-54.999660894550665";
"evaluating";
Char(a, 19, 16) = "32.9996608945506651";
Char(b, 19, 16) = "-54.999660894550665";
"evaluating";
Char(a, 19, 16) = "33.0003391054493349";
Char(b, 19, 16) = "-55.000339105449335";
"evaluating";
Char(a, 19, 16) = "32.9996608945506651";
Char(b, 19, 16) = "-55.000339105449335";
nParm=2 SR1 ******************************************************
Iter nFree Objective RelGrad NormGrad2 Ridge nObj nGrad nHess Parm0 Parm1
0 2 4885 9770 9770 0 1 1 1 33 -55
"evaluating";
Char(a, 19, 16) = "9.9999350076876112";
Char(b, 19, 16) = "11.0000734771922168";
"evaluating";
Char(a, 19, 16) = "9.9999351715994163";
Char(b, 19, 16) = "11.0000734771922168";
"evaluating";
Char(a, 19, 16) = "9.9999348437758062";
Char(b, 19, 16) = "11.0000734771922168";
"evaluating";
Char(a, 19, 16) = "9.9999350076876112";
Char(b, 19, 16) = "11.0000736560072454";
"evaluating";
Char(a, 19, 16) = "9.9999350076876112";
Char(b, 19, 16) = "11.0000732983771883";
1 2 9.623e-9 0.006344 1.925e-8 0 1 1 0 9.999935 11.00007
"evaluating";
Char(a, 19, 16) = "9.9999999999733351";
Char(b, 19, 16) = "10.9999999999907079";
"evaluating";
Char(a, 19, 16) = "10.0000001638861082";
Char(b, 19, 16) = "10.9999999999907079";
"evaluating";
Char(a, 19, 16) = "9.9999998360605620";
Char(b, 19, 16) = "10.9999999999907079";
"evaluating";
Char(a, 19, 16) = "9.9999999999733351";
Char(b, 19, 16) = "11.0000001788046422";
"evaluating";
Char(a, 19, 16) = "9.9999999999733351";
Char(b, 19, 16) = "10.9999998211767736";
2 2 7.97e-22 2.42e-15 1.59e-21 0 1 1 0 10 11
Convergence SUCCESS: Gradient
Time: 0
"evaluating";
Char(a, 19, 16) = "9.9999999999733351";
Char(b, 19, 16) = "10.9999999999907079";
minfun = 7.97360035815878e-22;
a = 9.99999999997334;
b = 10.9999999999907;
Il semble que vous puissiez vous attendre à 27 appels à la fonction de 10 à 20 secondes.
Votre algorithme génère-t-il la même réponse pour la même entrée, ou y a-t-il une composante aléatoire ? Cela pourrait faire une différence.
Re : Problème avec la fonction minimiser en JSLCraige très intéressant. J'ai suivi votre approche et j'ai observé les valeurs pendant son exécution. Dans cet exemple, mes valeurs initiales sont respectivement 0,8 et 0,5.
minfun = Minimize( min_test, {kD( 0.4, 0.8 ), wshc( 0.1, 1.5 )}, <<DETAILS></DETAILS>la deuxième itération donne ceci
/*:2 2 44.86266 210.178 0.080004 128 12 1 0 0.799999 0.50001
et le 3ème
/*:3 2 45.33956 0 0.080004 4096 16 0 0 0.799999 0.50001
et il ne peut pas faire mieux que l'itération 2 donc s'arrête là. Ici, la meilleure valeur de fonction objectif est 44,86 .
Cependant, si je donne "manuellement" à l'algorithme les valeurs de paramètre de 0,52 et 1,13 (respectivement), la fonction objectif (MSE) est d'environ 6,8, bien meilleure que les résultats ci-dessus. La seule chose à laquelle je peux penser, c'est qu'il y a un minimum très local aux valeurs initiales mais cela semble peu probable car j'obtiens le même type de résultats quelles que soient mes valeurs initiales...
Re : Problème avec la fonction minimiser en JSLJe suis presque sûr que la réduction dépend des pentes qui mènent à la réponse.
Dans le passé, j'ai joué avec un tas de points de départ aléatoires pour minimiser, en gardant la meilleure réponse et en créant de nouveaux points de départ aléatoires avec une distribution normale autour de ce point. Mais cela ne fonctionne que si vous disposez de suffisamment de temps... et vous ne savez jamais si vous avez trouvé la meilleure réponse.
Re : Problème avec la fonction minimiser en JSLOui, je penche pour une solution "force brute" similaire à celle que vous proposez. Ou bien, il faudrait que je programme une routine d'optimisation Nelder-Mead qui serait peut-être mieux adaptée à ce genre de problèmes. Y a-t-il une chance que quelqu'un chez JMP ait déjà écrit un tel code ?? 
Merci Yves
Re : Problème avec la fonction minimiser en JSLIl est difficile de dire exactement ce qui se passe sans pouvoir exécuter l'exemple moi-même, mais deux autres approches vous viennent à l'esprit et que vous pourriez éventuellement essayer.La première consiste à utiliser le contrainte minimiser fonctionner sans aucune contrainte linéaire.Il utilise une méthode différente de celle minimiser fonction, donc cela pourrait éventuellement aider. Ainsi, à partir de l'exemple de Craige, vous pourriez faire quelque chose comme ceci :
aa = expr(
Show( "evaluating", Char( a, 19, 16 ), Char( b, 19, 16 ) ); // peek inside
(a - 10) ^ 2 + (b - 11) ^ 2 // the function, roots at 10 and 11
);
min_test = Expr( Eval( aa ) );
minFun =
Constrained Minimize(
min_test,
{a( -100, 100 ), b( -100, 100 )},
<<StartingValues( [0, 0] ), <<show details(true)
);
Eval List( {a, b, minFun} );
Ou une autre approche que vous pouvez essayer consiste à créer une petite table de données et à utiliser le profileur pour effectuer l'optimisation.Je ne sais pas vraiment dans quelle mesure cela fonctionnera avec votre formule, mais je joins un exemple de la façon dont cela fonctionnerait avec l'exemple de Craige. Voici une image de la solution que vous obtenez si vous optimisez la fonction dans le profileur :

Si vous exécutez le premier script attaché à la table de données, vous lancerez le profileur avant l'optimisation.Le deuxième script lance le profileur avec la solution optimale. Le profileur utilise plusieurs démarrages aléatoires, il est donc plus robuste pour trouver la solution optimale globale.
Re : Problème avec la fonction minimiser en JSLSalut Laura,
Merci pour vos suggestions. Jusqu'à présent, je n'ai essayé que le premier (minimisation contrainte) et il se comporte certainement différemment de la fonction minimiser ! Cependant, j'ai maintenant le problème inverse, c'est-à-dire que les paramètres se déplacent partout dans l'espace de paramètres autorisé sans apparemment jamais atteindre des valeurs stables !! Une chose que je ne comprends pas très bien est la différence entre les « itérations » et le nombre de fois où la fonction objectif est évaluée. Ce ne sont évidemment pas les mêmes. J'avais défini un iter maximum (5) mais la fonction a été évaluée plusieurs fois sans converger. J'ai dû forcer la fermeture de JMP après quelques minutes.
Je commence à penser que le type de modèle que j’essaie d’optimiser est plutôt embêtant !
Je vais essayer votre deuxième suggestion ! Bien cordialement, Yves