Załóżmy, że mamy zestaw danych, który może być podany w przybliżeniu przez
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
Dlatego mamy zmianę o 20% zbioru danych. Moim pierwszym pomysłem było użycie funkcji scipy UnivariateSpline, ale problem polega na tym, że nie uwzględnia to właściwie małego szumu. Jeśli weźmie się pod uwagę częstotliwości, tło jest znacznie mniejsze niż sygnał, więc pomysłem może być tylko splajn odcięcia, ale wymagałoby to transformacji Fouriera w przód iw tył, co może skutkować złym zachowaniem. Innym sposobem byłaby średnia ruchoma, ale wymagałoby to również właściwego wyboru opóźnienia.
Wszelkie wskazówki / książki lub linki, jak rozwiązać ten problem?
python
numpy
scipy
signal-processing
data-processing
varantir
źródło
źródło
Odpowiedzi:
Wolę filtr Savitzky-Golay . Używa najmniejszych kwadratów, aby regresować małe okno danych do wielomianu, a następnie używa wielomianu do oszacowania punktu na środku okna. Na koniec okno zostaje przesunięte o jeden punkt danych do przodu i proces się powtarza. Trwa to do momentu, aż każdy punkt zostanie optymalnie dostosowany w stosunku do swoich sąsiadów. Działa świetnie nawet w przypadku głośnych próbek ze źródeł nieokresowych i nieliniowych.
Oto dokładny przykład książki kucharskiej . Zobacz mój kod poniżej, aby dowiedzieć się, jak łatwo jest go używać. Uwaga: Pominąłem kod definiujący
savitzky_golay()
funkcję, ponieważ możesz dosłownie skopiować / wkleić go z przykładu książki kucharskiej, który podałem powyżej.AKTUALIZACJA: Zwróciłem uwagę, że przykład książki kucharskiej, z którym się łączyłem, został usunięty. Na szczęście filtr Savitzky-Golay został włączony do biblioteki SciPy , jak wskazał @dodohjk . Aby dostosować powyższy kod za pomocą źródła SciPy, wpisz:
źródło
savgol_filter((x, y), ...)
.Szybki i brudny sposób na wygładzanie danych, którego używam, w oparciu o średnią ruchomą (przez splot):
źródło
scipy.ndimage.filters.convolve1d()
pozwala określić oś nd-tablicy, aby wykonać filtrowanie. Ale myślę, że oboje cierpią na pewne problemy związane z zamaskowanymi wartościami.Jeśli interesuje Cię „gładka” wersja sygnału, który jest okresowy (jak twój przykład), to FFT jest właściwą drogą. Weź transformatę Fouriera i odejmij niskie częstotliwości:
Nawet jeśli twój sygnał nie jest całkowicie okresowy, to doskonale odciąży biały szum. Istnieje wiele rodzajów filtrów do użycia (górnoprzepustowy, dolnoprzepustowy itp.), Odpowiedni jest zależny od tego, czego szukasz.
źródło
Dopasowanie średniej ruchomej do danych zmniejszy hałas, zapoznaj się z tą odpowiedzią, jak to zrobić.
Jeśli chcesz użyć opcji LOWESS, aby dopasować swoje dane (jest podobny do średniej ruchomej, ale bardziej wyrafinowany), możesz to zrobić za pomocą biblioteki statsmodels :
Wreszcie, jeśli znasz funkcjonalną formę sygnału, możesz dopasować krzywą do swoich danych, co prawdopodobnie byłoby najlepszą rzeczą do zrobienia.
źródło
loess
wdrożył.Inną opcją jest użycie KernelReg w statsmodels :
źródło
Sprawdź to! Istnieje jasna definicja wygładzania sygnału 1D.
http://scipy-cookbook.readthedocs.io/items/SignalSmooth.html
Skrót:
źródło
Jeśli drukujesz wykres szeregów czasowych i użyłeś mtplotlib do rysowania wykresów, użyj metody mediany, aby wygładzić wykres
gdzie
timeseries
jest przekazywany zestaw danych, który możesz zmienić,windowsize
aby uzyskać bardziej wygładzenie.źródło