WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Optimisierungsproblem: Parameter einer DGL optimal wählen

 

Johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.06.2017, 18:44     Titel: Optimisierungsproblem: Parameter einer DGL optimal wählen
  Antworten mit Zitat      
Hallo Matlabianer,

ich habe gerade ein kleines Problem. Eine Differentialgleichung (linear inhomogen, nicht konstante Koeffizienten; Lösungsalgorithmus ist ode23s()) liefert mir für eine Versuchsnachrechnung eine Ergebniskurve für eine bestimmte Einwirkung. Die Ergebniskurve soll nun optimal eine "Sollkurve" treffen. Hierfür ist es notwendig einige der Eingangsparameter der DGL optimal zu wählen.

Gibt es hierfür in Matlab eine (einfache?) Möglichkeit auf diese optimalen Parameter zu kommen? Ich dachte an eine Art Least-Squares-Fit oder eines der Trust-Region-Verfahren aus der Optimization-Toolbox ... allerdings: welches Verfahren/welche Funktion ist hierfür eine Möglichkeit?

Könnte mir hierbei jemand weiterhelfen, z.B. mit einem "Dummy-Beispiel" das eine derartige Optimierung zeigt oder hat jemand einen Link-Tipp parat? In der Matlab-Dokumentation bin ich irgendwie "versumpft" bzw. nicht noch wirklich an das Ziel gekommen ...

Ich hoffe, ich habe mich einigermaßen verständlich ausgedrückt.

Vielen Dank und Liebe Grüße,
johepet


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 24.06.2017, 19:55     Titel:
  Antworten mit Zitat      
Hallo,

das geht z.B. mit lsqnonlin .

Ein Beispiel siehe hier, nur dass du eben ode23s statt Simulink verwendest.

Hilfreiche Tips siehe zudem hier:
https://www.mathworks.com/help/opti.....ifferential-equation.html

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.06.2017, 16:40     Titel:
  Antworten mit Zitat      
Hallo,

das hat mir schon sehr viel geholfen. - Ich poste später mein Beispiel, für alle anderen, die das noch benötigen.

Bei einer Kleinigkeit (?) stehe ich allerdings noch an: wenn ich einen Einzelnen Fit machen möchte, der sich aus Messdaten einer Zeitreihe (1:0.01:24 Tage) zusammensetzt, klappt alles wunderbar.

Allerdings muss ich nun mehrere Zeitreihen bzw. entsprechend mehrere Messdaten berücksichtigen. D.h. ich habe nicht nur Messwerte von der Zeitreihe 1:0.01:24 Tage, sondern auch welche ab 2.5:0.01:24 Tage bzw. 3.0:0.01:24 Tage.

Zunächst dachte ich daran, alle Zeitreihen und Messergebnisse in einen Vektor zusammenzukoperien (d.h. Zeilenweise anhängen), aber hier schimpft mich nun lsqnonlin, dass das so nicht möglich ist, da für eine Optimierung kontinuierlich steigende oder fallende Zeitreihen erforderlich sind.

Hat jemand von euch eine Idee, wie man dieses Problem lösen könnte?

Vielen lieben Dank im Voraus,
johepet
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.06.2017, 18:44     Titel:
  Antworten mit Zitat      
... Nachtrag: Ich habe mich etwas ungeschickt ausgedrückt. - Also ich habe wie gesagt mehrere Messkurven, und möchte die freien Parameter meiner Zielfunktion so wählen, dass diese jede der Messkurven optimal treffen.

Die Messergebnisse sind nämlich stark vom Belastungszeitpunkt abhängig, d.h. von jenem Zeitpunkt, ab dem ich jeweils unterschiedliche Messkurven/Ergebnisse zur Verfügung habe. Ich habe z.B. Messdaten von t1 = 1d ... 24d; t2 = 2d ... 24d; t3 = 3d ... 24d etc. - Die freien Parameter Sollen nun so bestimmt werden, dass meine Funktion für jeden Belastungszeitpunkt das Optimale Ergebnis liefern kann.
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 25.06.2017, 20:25     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
Zunächst dachte ich daran, alle Zeitreihen und Messergebnisse in einen Vektor zusammenzukoperien (d.h. Zeilenweise anhängen), aber hier schimpft mich nun lsqnonlin, dass das so nicht möglich ist, da für eine Optimierung kontinuierlich steigende oder fallende Zeitreihen erforderlich sind.

Poste doch bitte deinen genauen Versuch. Wenn das Zusammenkopieren in der richtigen Reihenfolge erfolgt, sollte das ja an sich gehen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.06.2017, 23:46     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
Poste doch bitte deinen genauen Versuch. Wenn das Zusammenkopieren in der richtigen Reihenfolge erfolgt, sollte das ja an sich gehen.


Ich habe das nun noch etwas anders gelöst, mein Versuch bzw. nun eingesetztes Skript sieht so aus:

Code:
%%%%%%

% Hauptdatei
clear all; clc;

% Zeitachse der Messkurven einlesen
timearray(:,1) = xlsread('KkZD.xlsx','24h','B9:B680')/24;
timearray(:,2) = xlsread('KkZD.xlsx','32h','B9:B680')/24;
timearray(:,3) = xlsread('KkZD.xlsx','48h','B9:B680')/24;

% Ergebnisse der Messkurven einlesen
epsarray(:,1) = xlsread('KkZD.xlsx','24h','G9:G680')/1000;
epsarray(:,2) = xlsread('KkZD.xlsx','32h','G9:G680')/1000;
epsarray(:,3) = xlsread('KkZD.xlsx','48h','G9:G680')/1000;


% Parameter - Startwerte (aus vorhergehenden Berechnungen in entsprechenden Variablen)
InitialGuess = [xe(1); xe(2); xe(3); x1; xe1(1); xe1(2); ...
     xe2(1); xe3(1); xe4(1); xed1; xed2; xed3; ...
     xed4; xed5];
 
 % Bestimmen der Parameter
 calcParam = lsqnonlin(@(PAR) objectiveFunction_lsq_2(PAR,timearray,epsarray), ...
     InitialGuess);
 
%%%%%%


% Funktion zur Ermittlung des Fehlers entsprechend der gewaehlten
% Parameter gegenueber den Messwerten
function [ error ] = objectiveFunction_lsq_2( PAR, tmeas, epsmeas )

 % Startbedingungen fuer Berechnung eines jeden Lastfalls
 fp1_s = 1;
 fp2_eps = [0 0 0 0];
 fp3_kor = 1;
 
 for ii=1:size(tmeas,2)
     
     % Berechne Ergebnisse fuer jeweiliges Zeitintervall und entsprechende
     % Parameter (eps_nonlin_calcmodel --> dahinter versteckt sich eine DGL, die mit ode23s gelöst wird)
      eps_calculated(:,ii) = eps_nonlin_calcmodel( tmeas(:,ii), ...
      fp1_s, fp2_eps, [PAR(1); PAR(2); PAR(3)], PAR(4), [PAR(5); PAR(6)], ...
      [PAR(7); PAR(6)], [PAR(8); PAR(6)], [PAR(9); PAR(6)], PAR(10), ...
      PAR(11), PAR(12), PAR(13), PAR(14),fp3_kor);
 
      % Fehler bestimmen
      error(:,ii) = (epsmeas(:,ii)-eps_calculated(:,ii));
     
  end

end
 


Soweit scheint das eigentlich zu klappen, zumindest gibt es keine "Fehlermeldung", vielmehr meldet Matlab:
"Local minimum found.

Optimization completed because the size of the gradient is less than
the default value of the function tolerance.

<stopping criteria details>"
... die Ergebnisse selbst sehen für mich zunächst aber einmal plausibel aus.


Allerdings bin ich mir in meinem obigen Beispiel nicht so sicher, ob ich das richtig mache, so wie ich den jeweiligen Fehler bestimme und diesen dann an lsqnonlin() gebe. Ich habe das aus einem Beispiel, das ich via Google gefunden hatte abgekupfert - sollten bei error(:,ii) = ... nicht die Fehlerquadrat[summ]e[n] stehen? Oder bestimmt die dann lsqnonlin() für die Optimierung aus meinem "einfachen" Fehler?

Liebe Grüße,
johepet
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 26.06.2017, 08:48     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
zumindest gibt es keine "Fehlermeldung", vielmehr meldet Matlab:
"Local minimum found.

... und das ist eine gute Nachricht: es ist nämlich das beste, was ein gradientenbasierter Löser liefern kann.

Zitat:
sollten bei error(:,ii) = ... nicht die Fehlerquadrat[summ]e[n] stehen? Oder bestimmt die dann lsqnonlin() für die Optimierung aus meinem "einfachen" Fehler?

Das macht lsqnonlin automatisch.

Was ich mich eher frage ist, ob error bei dir am Ende nicht eine Matrix wird. Falls ja, würde ich das (sicherheitshalber) mit reshape in einen Vektor umwandeln.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 26.06.2017, 10:59     Titel:
  Antworten mit Zitat      
Hallo,
Zitat:
Das macht lsqnonlin automatisch.

Was ich mich eher frage ist, ob error bei dir am Ende nicht eine Matrix wird. Falls ja, würde ich das (sicherheitshalber) mit reshape in einen Vektor umwandeln.


Stimmt ... der wird zu einer Matrix. Ich habe nun nach der for-Schleife folgendes Stückchen ergänzt:
Code:
 [n m] = size(error);
  num_lines_errvec = n*m;
  error = reshape(error,num_lines_errvec,1);


Soweit funktioniert das alles ganz fein! Vielen Dank für die Hilfe!

... eines vielleicht noch: Gibt es irgendwelche "Tricks", wie man die Startwerte für die Optimierung bestimmen könnte? Ich habe hier momentan Parameter der DGL verwendet, die ich in der Literatur gefunden habe. Allerdings sind die zum Teil recht "sensibel", sodass eine schlechte Wahl nicht unbedingt zur Lösbarkeit der DGL führt bzw. so dann die ganze Optimierung eigentlich fehlschlägt.

Viele Grüße,
johepet
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 26.06.2017, 11:23     Titel:
  Antworten mit Zitat      
Hallo,

alternativ:
Code:


Da error auch ein Befehl ist (um Fehlermeldungen zu erzeugen), würde ich das als Variablenname vermeiden.

Die Startwerte können da durchaus ein Problem werden. Abhilfe können Ansätze aus der globalen Optimierung schaffen, z.B. hier:
https://www.mathworks.com/help/gads.....urvefit-or-lsqnonlin.html

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 26.06.2017, 18:09     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
Da error auch ein Befehl ist (um Fehlermeldungen zu erzeugen), würde ich das als Variablenname vermeiden.


ahh, danke für den Hinweis. - In meinem Programm selbst heißt die Variable "diff"; ich dachte mir nur, als ich das Beispiel auf den obigen Code reduziert hatte, dass ichs für das bessere Verständnis in "error" umbenenne ... war wohl eher kontraproduktiv Smile

Zitat:
Die Startwerte können da durchaus ein Problem werden. Abhilfe können Ansätze aus der globalen Optimierung schaffen, z.B. hier:
https://www.mathworks.com/help/gads.....urvefit-or-lsqnonlin.html


Vielen Dank für den Hinweis, ich werde mich damit mal beschäftigten! ... Ich frage mich generell, wie das mit diesen Startwerten ist ... wenn ich diese unglücklich wähle, kann es sein, dass meine DGL dahinter "versagt", weil die einzelnen Parameter diese sehr stark beeinlussen; als Startwerte wähle ich deshalb ein "funktionierendes" Parameterset, das aber nicht unbedingt die besten Ergebnisse liefert, weswegen ich diesen Optimierungsalgorithmus benötige.
- Kann man mit dieser globalen Optimierung das Problem "umschiffen", dass ich durch die Vorgabe meiner Startwerte die Genauigkeit/Güte der Optimierung irgendwie "einschränke"? (Was macht lsqnonlin() z.B. wenn es "versehentlich" Parameter erwischt, für die die DGL unlösbar wäre? Bricht es dann ab, oder wählt es das Parmeterset anders? ... oder muss ich mich um diese Art der "Fehlervermeidung" selbst kümmern?)

Viele Grüße,
johepet
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 26.06.2017, 21:07     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
In meinem Programm selbst heißt die Variable "diff";

diff ist eine Funktion für die Differenz aufeinanderfolgender Werte.
Variablen mit selbem Namen machen allerdings i.d.R. nur dann Probleme, wenn man auch die Funktion dieses Namens verwenden möchte.

Was die anderen Fragen angeht, ist das ein Stück weit auch ausprobieren. Ich würde innerhalb von eps_nonlin_calcmodel abfragen, ob die Simulation bis zum Ende durchläuft (letztes t mit Endzeitpunkt abgleichen). Falls in der Funktion Fehler auftreten, try-catch verwenden und im Fehlerfall hohe Differenzen zurückgeben.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.06.2017, 17:36     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
diff ist eine Funktion für die Differenz aufeinanderfolgender Werte.
Variablen mit selbem Namen machen allerdings i.d.R. nur dann Probleme, wenn man auch die Funktion dieses Namens verwenden möchte.


oh nein ... aber Danke für den Hinweis!

Zitat:
Was die anderen Fragen angeht, ist das ein Stück weit auch ausprobieren. Ich würde innerhalb von eps_nonlin_calcmodel abfragen, ob die Simulation bis zum Ende durchläuft (letztes t mit Endzeitpunkt abgleichen). Falls in der Funktion Fehler auftreten, try-catch verwenden und im Fehlerfall hohe Differenzen zurückgeben.


Diese Idee klingt sehr gut, ich werde sie die Tage ausprobieren bzw. implementieren - vorstellen kann ich mir das schon sehr gut.

Gibt es eigentlich eine Einschränkung bzgl. der Funktionen, die mittels lsqnonlin() gefittet werden können?
Also ich habe auch eine andere "Variante" der Zielfunktion, die ohne den ode23-Löser, der in meiner objective-Function das Ergebnis jeweils bereitstellt, auskommt und die DGL stückweise über ein Anfangswert-Problem nähert. ... d.h. dahinter verbergen sich recht viele Schleifen, usw. ... letztlich wird aber auch ein Array eps_calculated geliefert, das dann mit epsmeas verglichen wird und entsprechend den fehler liefert.
- Meiner Meinung nach sollte ich das auch problemlos verwenden können, oder gibt es hierbei bei lsqnonlin() eine Einschränkung o.ä.?

Vielen Grüße,
johepet
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 27.06.2017, 19:06     Titel:
  Antworten mit Zitat      
Hallo,

grundsätzlich keine Einschränkungen. Die Funktion sollte zumindest theoretisch differenzierbar sein. Das ist sie mit ODEs nicht, daher der Link in meinem ersten Beitrag, was dabei zu beachten ist.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
johepet

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.06.2017, 17:33     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
grundsätzlich keine Einschränkungen. Die Funktion sollte zumindest theoretisch differenzierbar sein. Das ist sie mit ODEs nicht, daher der Link in meinem ersten Beitrag, was dabei zu beachten ist.


Vielen Dank. Ich habe mein Skript nun - bzw. die Zielfunktion - nach den Infos in deinem ersten Beitrag adaptiert; dort wird u.a. geraten, dass im Falle eines "Versagens" der Zielfunktion, "NaN" zurückgeben soll:

"Suggestions for Evaluation Failures: Return NaN. If your simulation or ODE solver does not successfully evaluate an objective or nonlinear constraint function at a point x, have your function return NaN. Most Optimization Toolbox and Global Optimization Toolbox solvers have the robustness to attempt a different iterative step if they encounter a NaN value. "

Entsprechend sieht meine Zielfunktion nun aus:

Code:
% Funktion zur Ermittlung des Fehlers entsprechend der gewaehlten
% Parameter gegenueber den Messwerten
function [ fit_diff ] = objectiveFunction_lsq_2( PAR, tmeas, epsmeas )

 % Startbedingungen fuer Berechnung eines jeden Lastfalls
 fp1_s = 1;
 fp2_eps = [0 0 0 0];
 fp3_kor = 1;
 
 for ii=1:size(tmeas,2)

   try      
     % Berechne Ergebnisse fuer jeweiliges Zeitintervall und entsprechende
     % Parameter (eps_nonlin_calcmodel --> dahinter versteckt sich eine DGL, die mit ode23s gelöst wird)
      eps_calculated(:,ii) = eps_nonlin_calcmodel( tmeas(:,ii), ...
      fp1_s, fp2_eps, [PAR(1); PAR(2); PAR(3)], PAR(4), [PAR(5); PAR(6)], ...
      [PAR(7); PAR(6)], [PAR(8); PAR(6)], [PAR(9); PAR(6)], PAR(10), ...
      PAR(11), PAR(12), PAR(13), PAR(14),fp3_kor);
 
      % Fehler bestimmen
      fit_diff(:,ii) = (epsmeas(:,ii)-eps_calculated(:,ii));
    catch
      fit_diff(:,ii) = nan(size(eps_calculated,1),1);
    end
     
  end

  fit_diff = reshape(fit_diff, [], 1);

end


Nun habe ich als Anfangswerte absichtlich einen Parameter so gewählt, dass die Gleichung nicht lösbar ist, in der Hoffnung, dass lsqnonlin() nun den Rest "handled", und sich - auch wenn's länger dauern sollte - zum Zielwert nähert.

Leider meldet Matlab nun:
Code:
Warning: Failure at t=1.128319e+00.  Unable to meet integration tolerances without reducing the step size below the
smallest value allowed (4.008594e-15) at time t.
> In ode23s at 402
  In eps_nonlin_calcmodel at 47
  In objectiveFunction_lsq_2 at 21
  In @(PAR)objectiveFunction_lsq_2(PAR,timevec,epsvec)
  In lsqnonlin at 197
  In Optimierungsalgorithmus at 111
Error using snls (line 48)
Objective function is returning undefined values at initial point. lsqnonlin cannot continue.

Error in lsqncommon (line 175)
    [xC,FVAL,LAMBDA,JACOB,EXITFLAG,OUTPUT,msgData]=...

Error in lsqnonlin (line 235)
[xCurrent,Resnorm,FVAL,EXITFLAG,OUTPUT,LAMBDA,JACOB] = ...

Error in Optimierungsalgorithmus (line 111)
 calcParam = lsqnonlin(@(PAR) objectiveFunction_lsq_2(PAR,timevec,epsvec), ...


... kann man das irgendwie umgehen oder den Optimierungsvorgang "retten"? Oder habe ich hier grundsätzlich etwas falsch gemacht?

Viele Grüße,
johepet
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.448
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 28.06.2017, 19:37     Titel:
  Antworten mit Zitat      
Hallo,

meine Interpretation:
der Anfangsvektor muss einen endlichen Wert zurückgeben.
Die Aussage im Link wird sich darauf beziehen, dass die Solver damit klar kommen, wenn irgendwann im späteren Verlauf der Optimierung NaN zurückgegeben werden.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2024 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.