Jika saya memiliki kumpulan data yang menghasilkan grafik seperti berikut ini, bagaimana saya secara algoritmik menentukan nilai x dari puncak yang ditampilkan (dalam hal ini tiga di antaranya):
Jika saya memiliki kumpulan data yang menghasilkan grafik seperti berikut ini, bagaimana saya secara algoritmik menentukan nilai x dari puncak yang ditampilkan (dalam hal ini tiga di antaranya):
Jawaban:
Pendekatan umum adalah memuluskan data dan kemudian menemukan puncak dengan membandingkan filter maksimum lokal dengan smooth . Di R
:
argmax <- function(x, y, w=1, ...) {
require(zoo)
n <- length(y)
y.smooth <- loess(y ~ x, ...)$fitted
y.max <- rollapply(zoo(y.smooth), 2*w+1, max, align="center")
delta <- y.max - y.smooth[-c(1:w, n+1-1:w)]
i.max <- which(delta <= 0) + w
list(x=x[i.max], i=i.max, y.hat=y.smooth)
}
Nilai kembalinya meliputi argumen dari maxima lokal ( x
) - yang menjawab pertanyaan - dan indeks ke dalam array x dan y di mana maxima lokal tersebut muncul ( i
).
Ada dua parameter yang harus disesuaikan dengan keadaan: w
adalah setengah lebar jendela yang digunakan untuk menghitung maksimum lokal. (Nilainya harus secara substansial kurang dari setengah panjang array data.) Nilai kecil akan mengambil benjolan lokal kecil sedangkan nilai yang lebih besar akan melewati itu. Lain - tidak eksplisit dalam kode ini - adalah span
argumen yang loess
lebih halus. (Ini biasanya antara nol dan satu; itu mencerminkan lebar jendela sebagai proporsi dari kisaran nilai x.) Nilai yang lebih besar akan memuluskan data lebih agresif, membuat benjolan lokal hilang sama sekali.
Untuk melihat penyempurnaan ini, mari buat fungsi uji kecil untuk memplot hasil:
test <- function(w, span) {
peaks <- argmax(x, y, w=w, span=span)
plot(x, y, cex=0.75, col="Gray", main=paste("w = ", w, ", span = ", span, sep=""))
lines(x, peaks$y.hat, lwd=2) #$
y.min <- min(y)
sapply(peaks$i, function(i) lines(c(x[i],x[i]), c(y.min, peaks$y.hat[i]),
col="Red", lty=2))
points(x[peaks$i], peaks$y.hat[peaks$i], col="Red", pch=19, cex=1.25)
}
Berikut adalah beberapa percobaan yang diterapkan pada beberapa data sintetis dan sedikit bising.
x <- 1:1000 / 100 - 5
y <- exp(abs(x)/20) * sin(2 * x + (x/5)^2) + cos(10*x) / 5 + rnorm(length(x), sd=0.05)
par(mfrow=c(3,1))
test(2, 0.05)
test(30, 0.05)
test(2, 0.2)
Baik jendela lebar (plot tengah) atau smooth yang lebih agresif (plot bawah) menghilangkan maxima lokal yang terdeteksi di plot atas. Kombinasi terbaik di sini kemungkinan adalah jendela lebar dan hanya penghalusan lembut, karena pemulusan agresif muncul untuk menggeser puncak ini (lihat titik tengah dan kanan di plot bawah dan membandingkan lokasi mereka dengan puncak nyata dari data mentah). Dalam contoh ini, w=50
dan span=0.05
melakukan pekerjaan dengan baik (tidak ditampilkan).
Perhatikan maxima lokal di titik akhir tidak terdeteksi. Ini dapat diperiksa secara terpisah. (Untuk mendukung ini, argmax
kembalikan nilai-y yang dihaluskan.)
Pendekatan ini memiliki beberapa keunggulan dibandingkan pemodelan yang lebih formal untuk pekerjaan tujuan umum:
Itu tidak mengadopsi model data yang terbentuk sebelumnya.
Dapat disesuaikan dengan karakteristik data.
Dapat disesuaikan untuk mendeteksi jenis-jenis puncak yang diminati.
w
dan span
, dan juga untuk menemukan bahwa nilai yang lebih tinggi dari span
sedang menggeser puncak. Rasanya bahkan langkah-langkah ini bisa otomatis. Misalnya untuk masalah pertama, jika kita dapat mengevaluasi kualitas puncak yang ditemukan, kita dapat menjalankan optimize
parameter! Untuk masalah kedua, mis. Pilih jendela di kedua sisi dari puncak yang ditemukan dan cari nilai yang lebih tinggi.
Seperti yang saya sebutkan dalam komentar jika deret waktu tampak pas secara berkala, model regresi harmonik menyediakan cara untuk memperlancar fungsi dan mengidentifikasi puncak dengan menerapkan tes turunan pertama dan kedua. Huber telah menunjukkan tes nonparametrik yang memiliki keunggulan ketika ada beberapa puncak dan fungsinya tidak harus berkala. Tapi tidak ada makan siang gratis. Meskipun ada keuntungan dari metodenya yang ia sebutkan ada kerugian jika model parametrik sesuai. Itu selalu menjadi sisi lain dari menggunakan teknik nonparametrik. Meskipun menghindari asumsi parametrik, pendekatan parametrik lebih baik ketika asumsi parametrik sesuai. Prosedurnya juga tidak memanfaatkan sepenuhnya struktur deret waktu dalam data.
Saya pikir meskipun tepat untuk menunjukkan kelebihan dari prosedur yang disarankan, penting juga untuk menunjukkan potensi kerugiannya. Baik pendekatan saya dan Huber menemukan puncak secara efisien. Namun saya pikir prosedurnya membutuhkan lebih banyak kerja ketika maksimum lokal lebih rendah dari puncak tertinggi yang ditentukan sebelumnya.
Pendekatan deteksi puncak klasik dalam pemrosesan sinyal adalah sebagai berikut:
Pendekatan lain yang berfungsi adalah membandingkan sinyal highpass filtered tajam terhadap sangat halus (low-pass atau median filtered) dan menerapkan langkah 3.
Semoga ini membantu.