Nehmen wir an, wir haben einen Datensatz, der ungefähr von gegeben sein könnte
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
Daher haben wir eine Variation von 20% des Datensatzes. Meine erste Idee war, die UnivariateSpline-Funktion von scipy zu verwenden, aber das Problem ist, dass dies das kleine Rauschen nicht gut berücksichtigt. Wenn Sie die Frequenzen berücksichtigen, ist der Hintergrund viel kleiner als das Signal, sodass ein Spline nur des Cutoffs eine Idee sein könnte, aber dies würde eine Hin- und Her-Fourier-Transformation beinhalten, die zu schlechtem Verhalten führen könnte. Ein anderer Weg wäre ein gleitender Durchschnitt, aber dies würde auch die richtige Wahl der Verzögerung erfordern.
Irgendwelche Hinweise / Bücher oder Links, wie man dieses Problem angeht?
python
numpy
scipy
signal-processing
data-processing
varantir
quelle
quelle
Antworten:
Ich bevorzuge einen Savitzky-Golay-Filter . Es verwendet die kleinsten Quadrate, um ein kleines Fenster Ihrer Daten auf ein Polynom zu regressieren, und verwendet dann das Polynom, um den Punkt in der Mitte des Fensters zu schätzen. Schließlich wird das Fenster um einen Datenpunkt nach vorne verschoben und der Vorgang wiederholt. Dies setzt sich fort, bis jeder Punkt im Verhältnis zu seinen Nachbarn optimal angepasst wurde. Es funktioniert auch mit verrauschten Samples aus nicht periodischen und nicht linearen Quellen.
Hier ist ein ausführliches Kochbuchbeispiel . In meinem Code unten finden Sie eine Vorstellung davon, wie einfach die Verwendung ist. Hinweis: Ich habe den Code zum Definieren der
savitzky_golay()
Funktion weggelassen , da Sie ihn buchstäblich aus dem oben verlinkten Kochbuchbeispiel kopieren / einfügen können.UPDATE: Mir ist aufgefallen, dass das von mir verlinkte Kochbuchbeispiel entfernt wurde. Glücklicherweise wurde der Savitzky-Golay-Filter in die SciPy-Bibliothek aufgenommen , wie @dodohjk hervorhob . Geben Sie Folgendes ein, um den obigen Code mithilfe der SciPy-Quelle anzupassen:
quelle
savgol_filter((x, y), ...)
.Ein schneller und schmutziger Weg, um die von mir verwendeten Daten zu glätten, basierend auf einer Box mit gleitendem Durchschnitt (durch Faltung):
quelle
scipy.ndimage.filters.convolve1d()
Mit dieser Option können Sie eine Achse eines nd-Arrays angeben, um die Filterung durchzuführen. Aber ich denke, beide leiden unter einigen Problemen bei maskierten Werten.Wenn Sie an einer "glatten" Version eines Signals interessiert sind, das periodisch ist (wie in Ihrem Beispiel), ist eine FFT der richtige Weg. Nehmen Sie die Fourier-Transformation und subtrahieren Sie die Frequenzen mit niedrigem Beitrag:
Selbst wenn Ihr Signal nicht vollständig periodisch ist, wird dadurch das weiße Rauschen hervorragend subtrahiert. Es gibt viele Arten von Filtern (Hochpass, Tiefpass usw.). Der geeignete Filter hängt davon ab, wonach Sie suchen.
quelle
Wenn Sie einen gleitenden Durchschnitt an Ihre Daten anpassen, wird das Rauschen ausgeglichen. In dieser Antwort erfahren Sie, wie das geht.
Wenn Sie LOWESS verwenden möchten , um Ihre Daten anzupassen (es ähnelt einem gleitenden Durchschnitt, ist jedoch komplexer ), können Sie dies mithilfe der Statistikmodellbibliothek tun :
Wenn Sie die funktionale Form Ihres Signals kennen, können Sie eine Kurve an Ihre Daten anpassen, was wahrscheinlich das Beste ist.
quelle
loess
umgesetzt hätte.Eine weitere Option ist die Verwendung von KernelReg in Statistikmodellen :
quelle
Schau dir das an! Es gibt eine klare Definition der Glättung eines 1D-Signals.
http://scipy-cookbook.readthedocs.io/items/SignalSmooth.html
Abkürzung:
quelle
Wenn Sie ein Zeitreihendiagramm zeichnen und mtplotlib zum Zeichnen von Diagrammen verwendet haben, verwenden Sie die Medianmethode, um das Diagramm zu glätten
Wo
timeseries
Ihr Datensatz übergeben wird, können Siewindowsize
für eine bessere Glättung ändern .quelle