Mari kita asumsikan kita memiliki dataset yang mungkin diberikan kira-kira oleh
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
Oleh karena itu kami memiliki variasi 20% dari dataset. Gagasan pertama saya adalah menggunakan fungsi UnivariateSpline dari Scipy, tetapi masalahnya adalah ini tidak mempertimbangkan kebisingan kecil dengan cara yang baik. Jika Anda mempertimbangkan frekuensinya, latar belakangnya jauh lebih kecil daripada sinyal, sehingga hanya spline dari cutoff yang mungkin merupakan ide, tetapi itu akan melibatkan transformasi bolak-balik fourier, yang mungkin mengakibatkan perilaku buruk. Cara lain akan menjadi rata-rata bergerak, tetapi ini juga akan membutuhkan pilihan penundaan yang tepat.
Adakah petunjuk / buku atau tautan bagaimana mengatasi masalah ini?
python
numpy
scipy
signal-processing
data-processing
varantir
sumber
sumber
Jawaban:
Saya lebih suka filter Savitzky-Golay . Menggunakan kuadrat terkecil untuk mundur jendela kecil data Anda ke polinomial, lalu menggunakan polinomial untuk memperkirakan titik di tengah jendela. Akhirnya jendela digeser maju oleh satu titik data dan proses berulang. Ini berlanjut sampai setiap titik telah disesuaikan secara optimal relatif terhadap tetangganya. Ini bekerja sangat baik bahkan dengan sampel berisik dari sumber non-periodik dan non-linear.
Berikut ini adalah contoh buku masak yang menyeluruh . Lihat kode saya di bawah ini untuk mendapatkan ide betapa mudahnya menggunakannya. Catatan: Saya meninggalkan kode untuk mendefinisikan
savitzky_golay()
fungsi karena Anda benar-benar dapat menyalin / menempelnya dari contoh buku masak yang saya tautkan di atas.PEMBARUAN: Telah menjadi perhatian saya bahwa contoh buku resep yang saya tautkan telah dihapus. Untungnya, filter Savitzky-Golay telah dimasukkan ke dalam perpustakaan SciPy , seperti yang ditunjukkan oleh @dodohjk . Untuk mengadaptasi kode di atas dengan menggunakan sumber SciPy, ketik:
sumber
savgol_filter((x, y), ...)
.Cara cepat dan kotor untuk memuluskan data yang saya gunakan, berdasarkan kotak rata-rata bergerak (berdasarkan konvolusi):
sumber
scipy.ndimage.filters.convolve1d()
memungkinkan Anda menentukan sumbu array-nd untuk melakukan penyaringan. Tapi saya pikir keduanya menderita beberapa masalah dalam nilai-nilai yang di-mask.Jika Anda tertarik pada versi "halus" dari sinyal yang periodik (seperti contoh Anda), maka FFT adalah cara yang tepat. Ambil transformasi fourier dan kurangi frekuensi dengan kontribusi rendah:
Bahkan jika sinyal Anda tidak sepenuhnya periodik, ini akan sangat membantu mengurangi white noise. Ada banyak jenis filter untuk digunakan (high-pass, low-pass, dll ...), yang sesuai tergantung pada apa yang Anda cari.
sumber
Memasukkan rata-rata bergerak ke data Anda akan memuluskan kebisingan, lihat jawaban ini untuk cara melakukannya.
Jika Anda ingin menggunakan LOWESS agar sesuai dengan data Anda (ini mirip dengan moving average tetapi lebih canggih), Anda bisa melakukannya menggunakan perpustakaan statsmodels :
Akhirnya, jika Anda tahu bentuk fungsional sinyal Anda, Anda bisa memasukkan kurva ke data Anda, yang mungkin merupakan hal terbaik untuk dilakukan.
sumber
loess
dilaksanakan.Pilihan lain adalah menggunakan KernelReg di statsmodels :
sumber
Lihat ini! Ada definisi yang jelas tentang penghalusan sinyal 1D.
http://scipy-cookbook.readthedocs.io/items/SignalSmooth.html
Jalan pintas:
sumber
Jika Anda merencanakan grafik deret waktu dan jika Anda telah menggunakan mtplotlib untuk menggambar grafik maka gunakan metode median untuk menghaluskan grafik
di mana
timeseries
set data Anda berlalu, Anda dapat mengubahwindowsize
agar lebih halus.sumber