次のようなグラフを生成するデータセットがある場合、表示されたピーク(この場合は3つ)のx値をアルゴリズムで決定するにはどうすればよいでしょうか。
次のようなグラフを生成するデータセットがある場合、表示されたピーク(この場合は3つ)のx値をアルゴリズムで決定するにはどうすればよいでしょうか。
回答:
一般的なアプローチは、データを平滑化してから、極大フィルターと平滑化を比較してピークを見つけることです。で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)
}
その戻り値には、x
質問に答えるローカル最大値()の引数と、ローカル最大値が発生するxおよびy配列へのインデックス(i
)が含まれます。
状況に合わせて調整する2つのパラメーターがあります w
。ローカル最大値の計算に使用されるウィンドウの半幅です。(その値は、データの配列の長さの半分よりも大幅に短くする必要があります。)小さな値は小さなローカルバンプを拾いますが、大きな値はそれらの上を通過します。もう1つ(このコードでは明示的ではありません)span
は、loess
スムーザーの引数です。(通常は0〜1です。x値の範囲の割合としてウィンドウ幅を反映します。)値を大きくすると、データがより積極的に平滑化され、ローカルバンプが完全に消えます。
このチューニングが有効であることを確認するために、結果をプロットするための小さなテスト関数を作成しましょう。
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)
}
以下に、若干のノイズの多い合成データに適用したいくつかの実験を示します。
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)
広いウィンドウ(中央のプロット)またはより積極的なスムーズ(下のプロット)のいずれかが、上のプロットで検出された局所的な最大値を除去します。積極的な平滑化はこれらのピークをシフトするように見えるため、ここでの最良の組み合わせは、おそらく広いウィンドウと穏やかな平滑化のみです(下のプロットの中央と右側のポイントを参照し、それらの位置を生データの見かけのピークと比較します)。この例では、w=50
とspan=0.05
偉大な仕事(図示せず)ん。
エンドポイントでの極大が検出されないことに注意してください。これらは個別に検査できます。(これをサポートするためにargmax
、平滑化されたy値を返します。)
このアプローチには、汎用の作業のためのより正式なモデリングよりもいくつかの利点があります。
データの先入観のあるモデルは採用していません。
データ特性に適合させることができます。
興味のあるピークの種類を検出するように適合させることができます。
w
とspan
し、また、より高い値があることを発見しspan
たピークをずらしました。これらの手順も自動化できるように感じます。たとえば、最初の問題では、発見されたピークの品質を評価できればoptimize
、パラメーターを実行できます。2番目の問題については、たとえば、検出されたピークの両側のウィンドウを選択し、より高い値を探します。
コメントで述べたように、時系列が周期的に適合しているように見える場合、調和回帰モデルは関数を平滑化し、1次および2次導関数テストを適用してピークを特定する方法を提供します。Huberは、複数のピークがあり、関数が必ずしも周期的ではない場合に利点があるノンパラメトリックテストを指摘しました。しかし、無料のランチはありません。彼が言及した彼の方法には利点がありますが、パラメトリックモデルが適切な場合は欠点があります。それは常にノンパラメトリック手法を使用することの裏返しです。パラメトリックな仮定を回避しますが、パラメトリックなアプローチは、パラメトリックな仮定が適切な場合に優れています。彼の手順は、データの時系列構造を十分に活用していません。
提案された手順の利点を指摘することは適切ですが、潜在的な欠点を指摘することも重要だと思います。私のアプローチとフーバーの両方が、効率的な方法でピークを見つけます。しかし、局所的最大値が以前に決定された最高ピークよりも低い場合、彼の手順はもう少し手間がかかると思います。
信号処理における古典的なピーク検出アプローチは次のとおりです。
機能するもう1つのアプローチは、シャープにハイパスフィルター処理された信号を非常に平滑化された(ローパスまたは中央値フィルター処理)と比較し、ステップ3を適用することです。
お役に立てれば。