Saturday 14 October 2017

Moving Average Effiziente Umsetzung


Der Moving Average als Filter Der gleitende Durchschnitt wird oft für die Glättung von Daten in Anwesenheit von Rauschen verwendet. Der einfache gleitende Durchschnitt wird nicht immer als der Finite Impulse Response (FIR) - Filter erkannt, der es ist, während er tatsächlich einer der gebräuchlichsten Filter in der Signalverarbeitung ist. Wenn man sie als Filter betrachtet, kann man sie beispielsweise mit gefensterten Filtern vergleichen (siehe Artikel zu Tiefpaß-, Hochpass - und Bandpass - und Bandsperrfiltern für Beispiele). Der Hauptunterschied zu diesen Filtern besteht darin, daß der gleitende Durchschnitt für Signale geeignet ist, für die die Nutzinformation im Zeitbereich enthalten ist. Von denen Glättungsmessungen durch Mittelung ein Paradebeispiel sind. Window-sinc-Filter, auf der anderen Seite, sind starke Künstler im Frequenzbereich. Mit Ausgleich in der Audioverarbeitung als typisches Beispiel. Es gibt einen detaillierteren Vergleich beider Arten von Filtern in Time Domain vs. Frequency Domain Performance von Filtern. Wenn Sie Daten haben, für die sowohl die Zeit als auch die Frequenzdomäne wichtig sind, dann möchten Sie vielleicht einen Blick auf Variationen auf den Moving Average werfen. Die eine Anzahl gewichteter Versionen des gleitenden Durchschnitts zeigt, die besser sind. Der gleitende Durchschnitt der Länge (N) kann so definiert werden, wie er üblicherweise implementiert ist, wobei der aktuelle Ausgabeabtastwert der Durchschnitt der vorhergehenden (N) Abtastwerte ist. Als Filter betrachtet, führt der gleitende Durchschnitt eine Faltung der Eingangsfolge (xn) mit einem rechteckigen Puls der Länge (N) und der Höhe (1N) durch (um den Bereich des Pulses und damit die Verstärkung des Filters zu erzeugen , eins ). In der Praxis ist es am besten, (N) ungerade zu nehmen. Obwohl ein gleitender Durchschnitt auch unter Verwendung einer geraden Anzahl von Abtastwerten berechnet werden kann, hat die Verwendung eines ungeradzahligen Wertes für (N) den Vorteil, daß die Verzögerung des Filters eine ganzzahlige Anzahl von Abtastwerten ist, da die Verzögerung eines Filters mit (N) Proben genau ((N-1) 2). Der gleitende Durchschnitt kann dann exakt mit den ursprünglichen Daten ausgerichtet werden, indem er um eine ganze Zahl von Abtastwerten verschoben wird. Zeitdomäne Da der gleitende Durchschnitt eine Faltung mit einem rechteckigen Puls ist, ist sein Frequenzgang eine sinc-Funktion. Dies macht es ähnlich dem Dual des Fenstersynchronfilters, da es sich hierbei um eine Faltung mit einem Sinc-Puls handelt, der zu einem rechteckigen Frequenzgang führt. Es ist diese sinc Frequenzantwort, die den gleitenden Durchschnitt ein schlechter Darsteller im Frequenzbereich macht. Allerdings führt es sehr gut im Zeitbereich. Daher ist es perfekt, um Daten zu löschen, um Rauschen zu entfernen, während gleichzeitig eine schnelle Sprungantwort beibehalten wird (1). Für das typische Additiv-Weiß-Gauß-Rauschen (AWGN), das oft angenommen wird, bewirkt die Mittelung (N) - Proben, dass das SNR um einen Faktor (sqrt N) erhöht wird. Da das Rauschen für die einzelnen Proben unkorreliert ist, gibt es keinen Grund, jede Probe unterschiedlich zu behandeln. Daher wird der gleitende Durchschnitt, der jeder Probe das gleiche Gewicht gibt, die maximale Menge an Rauschen für eine gegebene Sprungantwortschärfe beseitigen. Implementierung Da es sich um ein FIR-Filter handelt, kann der gleitende Durchschnitt durch Faltung implementiert werden. Es hat dann die gleiche Effizienz (oder das Fehlen davon) wie jedes andere FIR-Filter. Sie kann aber auch rekursiv und effizient umgesetzt werden. Es folgt unmittelbar aus der Definition, daß diese Formel das Ergebnis der Ausdrücke für (yn) und (yn1) ist, dh, daß die Veränderung zwischen (yn1) und (yn) ein zusätzlicher Term (xn1N) ist Das Ende, während der Term (xn-N1N) von Anfang entfernt wird. In praktischen Anwendungen ist es oft möglich, die Division durch (N) für jeden Term auszulassen, indem die resultierende Verstärkung von (N) an einer anderen Stelle kompensiert wird. Diese rekursive Umsetzung wird viel schneller als Faltung. Jeder neue Wert von (y) kann mit nur zwei Additionen anstelle der (N) Additionen berechnet werden, die für eine einfache Implementierung der Definition erforderlich wären. Eine Sache, mit der Sie nach einer rekursiven Implementierung Ausschau halten, ist, dass Rundungsfehler akkumulieren. Dies kann ein Problem für Ihre Anwendung sein oder auch nicht, aber es bedeutet auch, dass diese rekursive Implementierung tatsächlich mit einer Integer-Implementierung besser funktionieren wird als mit Gleitkommazahlen. Dies ist sehr ungewöhnlich, da eine Gleitkomma-Implementierung gewöhnlich einfacher ist. Der Schluss davon muss sein, dass Sie die Nützlichkeit des einfachen gleitenden Durchschnittsfilters in Signalverarbeitungsanwendungen nie unterschätzen sollten. Filter Design Tool Dieser Artikel wird mit einem Filter Design Tool ergänzt. Experimentiere mit verschiedenen Werten für (N) und visualisiere die resultierenden Filter. Versuchen Sie es jetztIch habe eine Reihe von Werten wie folgt: Das obige Array ist oversimplified, Im sammeln 1 Wert pro Millisekunde in meinem realen Code und ich muss die Ausgabe auf einem Algorithmus, den ich schrieb, um die nächste Peak vor einem Zeitpunkt zu finden verarbeiten . Meine Logik schlägt fehl, weil in meinem Beispiel oben 0.36 die wahre Spitze ist, aber mein Algorithmus würde rückwärts schauen und sehen die sehr letzte Zahl 0.25 als die Spitze, als theres eine Abnahme zu 0.24 vor ihm. Das Ziel ist, diese Werte zu nehmen und einen Algorithmus auf sie, die glätten sie ein wenig, so dass ich mehr lineare Werte. (Dh: Id wie meine Ergebnisse curvy, nicht jaggedy) Ive wurde gesagt, um einen exponentiellen gleitenden durchschnittlichen Filter auf meine Werte anwenden. Wie kann ich dies tun Es ist wirklich schwer für mich, mathematische Gleichungen zu lesen, gehe ich viel besser mit Code. Wie verarbeite ich Werte in meinem Array, die Anwendung einer exponentiellen gleitenden Durchschnittsberechnung, um sie herauszufordern, um einen exponentiellen gleitenden Durchschnitt zu berechnen. Müssen Sie einige Zustand zu halten und Sie benötigen einen Tuning-Parameter. Dies erfordert eine kleine Klasse (vorausgesetzt, Sie verwenden Java 5 oder höher): Instantiate mit dem Decay-Parameter, die Sie wollen (kann Abstimmung sollte zwischen 0 und 1) und dann mit Average () zu filtern. Beim Lesen einer Seite auf einige mathematische Rekursion, alles, was Sie wirklich wissen müssen, wenn Sie es in Code ist, dass Mathematiker gerne Indizes in Arrays und Sequenzen mit Indizes schreiben. (Theyve einige andere Anmerkungen außerdem, die nicht helfen.) Jedoch ist die EMA ziemlich einfach, da Sie nur an einen alten Wert erinnern müssen, der keine komplizierten Zustandarrays erfordert. Beantwortet Feb 8 12 at 20:42 TKKocheran: Ziemlich viel. Isn39t es schön, wenn die Dinge einfach sein können (Wenn Sie mit einer neuen Sequenz beginnen, erhalten Sie einen neuen Mittelwert.) Beachten Sie, dass die ersten paar Begriffe in der gemittelten Sequenz um ein bisschen durch Randeffekte springen, aber Sie erhalten diese mit anderen gleitenden Durchschnitten auch. Allerdings ist ein guter Vorteil, dass Sie die gleitende durchschnittliche Logik in die Mittelung einwickeln und experimentieren können, ohne den Rest des Programms zu viel zu stören. Ndash Donal Fellows Ich habe eine harte Zeit, Ihre Fragen zu verstehen, aber ich werde versuchen, trotzdem zu beantworten. 1) Wenn Ihr Algorithmus 0,25 statt 0,36 gefunden hat, dann ist es falsch. Es ist falsch, weil es eine monotone Zunahme oder Abnahme (das ist immer nach oben oder immer nach unten). Wenn Sie ALLE Ihre Daten nicht klassifizieren, sind Ihre Datenpunkte - wie Sie sie darstellen - nichtlinear. Wenn Sie wirklich den maximalen Wert zwischen zwei Zeitpunkten finden wollen, dann schneiden Sie Ihr Array von tmin zu tmax und finden Sie das Maximum dieses Unterarrays. 2) Nun ist das Konzept der gleitenden Durchschnitte sehr einfach: vorstellen, dass ich die folgende Liste haben: 1.4, 1.5, 1.4, 1.5, 1.5. Ich kann es glätten, indem ich den Durchschnitt von zwei Zahlen: 1.45, 1.45, 1.45, 1.5. Beachten Sie, dass die erste Zahl ist der Durchschnitt von 1,5 und 1,4 (zweite und erste Zahlen) die zweite (neue Liste) ist der Durchschnitt von 1,4 und 1,5 (dritte und zweite alte Liste) die dritte (neue Liste) der Durchschnitt von 1,5 und 1,4 (Vierte und dritte), und so weiter. Ich könnte es Zeitraum drei oder vier gemacht haben, oder n. Beachten Sie, wie die Daten viel glatter sind. Ein guter Weg, um zu sehen, gleitende Durchschnitte bei der Arbeit ist, gehen Sie zu Google Finance, wählen Sie eine Aktie (versuchen Tesla Motors ziemlich volatil (TSLA)) und klicken Sie auf Technische Daten am unteren Rand des Diagramms. Wählen Sie Moving Average mit einer bestimmten Periode und Exponential gleitenden Durchschnitt, um ihre Differenzen zu vergleichen. Exponentielle gleitende Durchschnitt ist nur eine weitere Ausarbeitung dieser, aber Gewichte die älteren Daten weniger als die neuen Daten ist dies ein Weg, um die Glättung nach hinten auszugleichen. Bitte lesen Sie den Wikipedia-Eintrag. Also, dies ist eher ein Kommentar als eine Antwort, aber die kleine Kommentar-Box war nur zu klein. Viel Glück. Wenn Sie Probleme mit der Mathematik haben, könnten Sie mit einem einfachen gleitenden Durchschnitt statt exponentiell gehen. Also die Ausgabe erhalten Sie die letzten x-Terme durch x geteilt werden. Ungetestetes Pseudocode: Beachten Sie, dass Sie die Anfangs - und Endteile der Daten behandeln müssen, da deutlich, dass Sie die letzten 5 Ausdrücke nicht durchschnittlich sind, wenn Sie auf Ihrem 2. Datenpunkt sind. Außerdem gibt es effizientere Methoden, diesen gleitenden Durchschnitt (sum sum - älteste neueste) zu berechnen, aber dies ist, um das Konzept von dem, was passiert, zu bekommen. Antwort # 2 am: August 20, 2010, 09:10:25 pm »Antwort # 1 am: August 20, 2010, um 12:48 Uhr Ihre Antwort 2017 Stack Exchange, IncA Simple Moving Durchschnittliche Implementierung in Java Bei mehreren Gelegenheiten wollte ich einfache Metriken in meiner Java-Anwendungen, zum Beispiel die Anzahl der Treffer pro Stunde oder Fehler während eines Zeitraums zu berechnen . Während der Berechnung einfacher Metriken ist nicht schrecklich schwierig, seine nur extra Arbeit und Id eher verbringen diese Zeit auf der Problem-Domain. Ich war überrascht, keine allgemein akzeptierten Lösungen für Metriken in Java zu finden. Ich fand Metrics, aber es schien ein wenig zu kompliziert und nicht gut dokumentiert - Alles, was ich wollte, war es, einen gleitenden Durchschnitt zu berechnen. Ich dachte über das Problem einiges mehr und entschied es nicht ein schwieriges Problem. Heres meine Lösung Dies funktioniert durch die Schaffung eines Arrays von Fenster-Update-Frequenz Größe, dann ein Thread setzt die Zählung auf den nächsten Index im Array auf die Aktualisierungsfrequenz. Die Zählung für das Intervall ist einfach arrayi - arrayi1, das ist die jüngste Zählung minus der ältesten Zählung. Für ein 10-Minuten-Intervall ist die älteste Zählung (i1) genau 10 Minuten alt. Um einen gleitenden Durchschnitt zu unserem Code hinzuzufügen, benötigen Sie zunächst einen Zähler mit AtomicLong. Dieser Zähler sollte basierend auf den Ereignissen inkrementiert werden, die für das Berechnen interessant sind (z. B. POST-Anforderungen für einen REST-Dienst). Wir müssen die Implementierung mit Zugriff auf den Zähler bereitstellen und das wird durch die GetCount-Schnittstelle erreicht. Hier Ill erstellen einen gleitenden Durchschnitt mit einem 5-Minuten-Fenster, das jede Sekunde aktualisiert. Und um den aktuellen Durchschnitt zu erhalten, rufen wir einfach die getAverage-Methode auf: Ein wichtiges Implementierungs-Detail ist, wie die Array-Größe bestimmt wird: indem Sie das Fenster durch die Aktualisierungshäufigkeit teilen. So kann ein großes Fenster mit einer häufigen Aktualisierungshäufigkeit eine beträchtliche Menge an Speicher verbrauchen. In diesem Beispiel ist die Array-Größe vernünftig 300. Wenn wir jedoch einen 24-Stunden-gleitenden Durchschnitt mit einem Intervall von 1 Sekunde erstellt haben, wäre die Größe 86400 Eine vernünftigere Aktualisierungsfrequenz für einen Zeitraum von 24 Stunden kann alle 5 Minuten betragen (Arraygröße von 288 ). Eine weitere Überlegung der Auswahl der Fenster-und Update-Frequenz ist das Fenster muss durch die Frequenz teilbar. Zum Beispiel ist ein 2-minütiges Fenster mit einer 6-Sekunden-Aktualisierungsfrequenz ok, aber eine 7-Sekunden-Aktualisierungsfrequenz ist nicht vorhanden, da es nicht durch 120 teilbar ist. Eine IllegalArgumentException wird geworfen, wenn die Fenstermodul-Aktualisierungsfrequenz nicht Null ist. Diese Implementierung erfordert einen Thread pro gleitenden Durchschnitt, was nicht sehr effizient ist. Eine bessere Lösung wäre, einen Thread über viele Durchschnitte zu teilen. Aktualisieren. Ich habe den Code aktualisiert, um einen Thread hier zu teilen. Schließlich theres ein Anfangszustandproblem: wir dont haben Daten noch für das gesamte Fenster. Zum Beispiel, wenn Sie ein 5-Minuten-Fenster und nur 15 Sekunden Daten haben. Diese Implementierung gibt null zurück, bis wir 5 Minuten Daten haben. Ein anderer Ansatz ist, den Durchschnitt abzuschätzen. Angenommen, wir haben eine Zählung von 10 in 30 Sekunden, dann können wir den Durchschnitt als 40 in 2 Minuten abschätzen. Es besteht jedoch das Risiko eines signifikanten Fehlers, indem unvollständige Daten extrapoliert werden. Zum Beispiel, wenn wir einen Burst von 20 Hits in 2 Sekunden hatten, schätzte man 1200 pro 2 Minuten, was aller Wahrscheinlichkeit nach weg ist.

No comments:

Post a Comment