Verfasst am: 30.06.2011, 14:49
Titel: iterative zeitreihenerstellung - wie beschleunigen?
Hallo in die Runde,
ich habe ein kleines Problemchen:
Im Rahmen einer Simulation muss ich Zeitreihen immer mal wieder iterativ erstellen, da im Grunde ein Zirkelschluss vorliegt, der sich nicht verhindern lässt.
Grundsätzlich geht es darum, eine Zeitreihe eZR auf Basis einer anderen Zeitreihe gZR und Koeffizienten KV zu erstellen, wobei die Zeitreihe eZR zwangsläufig zeitverschoben auf sich selbst verweist. Das ist der besagte Zirkelschluss, der sich nicht verhindern lässt.
Hierzu ganz kurz:
Der Grund hierfür ist der Wert, durch den bei "iterative Zeitreihenerstellung" geteilt wird. Ist dieser zu klein, explodiert die Zeitreihe. Ist dieser "größte" Wert jedoch im Vektor KV nicht an erste oder an letzter Stelle, muss die Zeitreihe eben iterativ aufgebaut werden.
Mein Problem ist jetzt: Diese iterative Ermittlung funktioniert zwar, jedoch dauert sie Mitunter sehr lange. Die gesetzte Grenze von 50.000 Iterationen wird häufig verletzt. Mitunter können das auch zig Millionen werden.
Aktuell ist mein Abbruchkriterium das Unterschreiten einer minimalen Abweichung zwischen Iteration A und Iteration B, die Erreichung der maximalen Iterationsanzahl von aktuell 50.000 sowie im Idealfall die Situation, dass die aktuelle Zeitreihe einer der letzten 20 zeitreihen gleicht, d.h. die Iteration ist im Rahmen der Genauigkeit von Matlab konvergiert.
Grundsätzlich klappt das, jedoch dauert es ganz einfach viel zu lange. An den Grenzen kann ich eigentlich nicht viel ändern, da sofort die Genauigkeit und damit die Güte des zu testenden Ansatzes leidet.
Hat jemand eine Idee, wie sich so eine Iteration deutlich schneller lösen lässt? Gibt es vielleicht sogar in Matlab selbst die Möglichkeit, Iterationen schneller lösen zu lassen?
Für Hilfe wäre ich echt dankbar!
Anbei die Programmierung, die etwas unübersichtlich ist, da sie mit der Zeit wuchs und immer wieder verändert wurde. Dafür jetzt schon mal ein Sorry
Noch ein paar Erläuterungen:
eZR = Zeitreihe die (gegebenenfalls durch Iteration) erstellt wird
gZR = Zeitreihe, die in die Erstellung von eZR einfließt
AK = Länge des Vektors KV
KV = Vektor mit Koeffizienten für die Erstellung der Zeitreihe eZR
PD = Position des größten Wertes im Vektor KV (durch diesen Wert wird stets geteilt, da sonst eZR explodiert)
eTRM = eine Hilfsmatrix, in der eZR Zeit- bzw. Zeilenverschoben steht, damit ich die Iteration selbst nicht mit einer for-Schleife zeilenweise machen muss
eZR2 = eine Hilfsmatrix, in der ich jeweils die letzten 20 Iterationen von eZR ablege, um die Abnahme der Abweichung der einzelnen Iterationen verfolgen zu können.
Das Programm ist nur mit großer Mühe lesbar. Kannst Du realistische Testdaten posten, so dass wir das Programm laufen lassen könnten? Ansonsten ist es schwer herauszubekommen, wo die Zeit verloren geht.
Ich habe zwar ein paar Ideen:
1. Vom Vektor K wird immer nur das erste Element verwendet, dann besser einen Skalar verwenden.
2. "marker==0" ist schneller als "isequal(marker, 0)"
3. Die Schleife für "marker" läßt sich aber auch ganz vermeiden:
Code:
ifany(eZR2(:,1), eZR2(:, 1:20))
IT = 0;
sprintf('Gleicher Wert!');
end
4. Soweit ich sehe, ändert gZR nie seinen Wert. Dann musst Du auch nicht in jeder Iteration den MEAN neu berechnen.
5. Ist die Länge von eZR konstant? Dann wäre das wiederholte Berechnen der Länge per "size(eZR, 1)" auch Zeitverschwendung und sollte lediglich einmal ausgeführt werden.
Es gibt sicherlich noch einen Menge weiterer Möglichkeiten den Code zu beschleunigen. Soweit ich das sehen kann (was aber wegen der eingeschränkten Lesbarkeit nicht sehr weit her ist), wird das aber nicht um einen Faktor 10 schneller sein. Aber 20% schneller bringt Dir eigentlich nichts...
Also poste bitte einen kompakteren Code und irgendwelche Testdaten, die realistische Laufzeiten erzeugen - falls möglich einfach per RAND.
Mit deiner Schleife für den Zeitreihenvergleich komme ich noch nicht klar. Ansonsten habe ich mal das isequal ersetzt und zumindest hier bei dem einen Test die benötigte Zeit um fast 50 % reduzieren können ... krass!
Leider habe ich direkt kein Beispiel parat, in dem es deutlich länger dauert. Aber die Funktionalität als solche sollte damit zu testen sein.
Diese Iteration ist eingebunden in eine Minimierung mit fmincon, welche wiederum mit Globalsearch verwendet wird. Ziel ist letztlich die Variierung der Werte in KV um eine Zielgröße zu minimieren.
%% Beginn der Iterationschleife while IT==1 % Aufstellen der Zeitreihe eZR for i = 1:AK
eTRM(:,i) = eZR(AK-i+1:end-i+1,1);
end
eZR((AK-PD)+1:end-PD+1,1) = (gZR(:,1)-eTRM*LV)/KV(PD,1);
% Ablegen bisheriger Werte und Erstellung von Prüfgrößen
KS = sum(abs(eZR));
eZR2(1:anzahl,2:20) = eZR2(1:anzahl,1:19);
eZR2(1:anzahl,1) = eZR;
Wert = sum(abs(eZR2(:,1)-eZR2(:,2)));
% Überprüfung, ob Zeitreihe explodiert oder Abbruchkriterien erfüllt sind, % wenn alternierend gegen unendlich ==> IT = 0 oder wenn Abbruchkriterium % erfüllt ==> IT = 0, ansonsten nochmaliges Aufstellen der Zeitreihe eZR
ifisinf(KS)
IT = 0;
elseifisnan(KS)
IT = 0;
elseif iterationen > 500000
IT = 0;
elseif Wert/anzahl < mittelwert*1e-15
IT = 0;
else
iterationen = iterationen +1;
marker = 0;
k = 1;
while marker==0
k = k+1;
if eZR2(:,1)==eZR2(:,k)
IT = 0 ;
marker = 1;
elseif k==20
marker = 1;
end end end end
zeit = toc;
end
Einfach für sich 500 mal, da ich diese ja sowieso je nach schwierigkeit einige hundert bis zu hundertausend malen durchführen muss - so spare ich mir, dass bei jedem umlauf die ganze folgende überprüfung durchgeführt werden muss. siehe da: wieder etwas reduziert ... jetzt bin ich von ca. 1,6 Sekunden auf ca. 0,25 Sekunden ... und das mit den paar Anpassungen.
Aber wie gesagt: für weitere Hilfe bin ich dankbar, insbesondere, ob sich die konvergenz obiges codes schneller erzielen lässt.
_Peter_: Bitte Quellcode nicht unnötig breit machen. Danke.
Wieso ist Dein Sourcecode so tief eingerückt? Er ist auf meinem Laptop-Monitor deshalb breiter als eine Zeile und der Umbruch mach das Lesen schwer. (_Peter_: Habe ich angepasst.)
die Bedingung ist dann erfüllt, wenn alle Elemente der Vektoren identisch sind - alternativ müsste ich dann vielleicht mit der absoluten summe der Vektordifferenzen arbeiten ...
mfg
Mirko
_Peter_: Bitte Quellcode nicht unnötig breit machen. Danke.
Einstellungen und Berechtigungen
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
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.