今回は,Savitzky-Golayフィルタの畳込み表現の係数 (下図のピンク図形)と周波数特性の話です.

Savitzky-Golayフィルタは,中央移動平均を一般化したものの一つです.中央移動平均の場合,奇数の長さの部分区間に,定数関数
をフィットし,中央の値を平滑化された値として採用します.部分区間は1点ずつシフトしていきます.Savitzky-Golayフィルタでは,当てはめる関数を次多項式
に変えてフィットし,中央の値を平滑化された値として採用します.以前にも,この考え方は説明しました.
chaos-kiyono.hatenablog.com
実際にRを使ってフィルタをかけるとき,私はsignalパッケージのsgolayfilt
を使います.
今回は,Savitzky-Golayフィルタについての理解を深めるために,Savitzky-Golayフィルタを畳込み
で表現したときの係数を与えます.さらに,Savitzky-Golay微分フィルタを紹介します.
Savitzky-Golay平滑化フィルタの係数
計算を簡単にするために,多項式をフィットする部分区間をにします.部分区間の場所が変っても畳込みの係数は変りません.
とおくと,考える部分時系列は
です.
今回は2次のSavitzky-Golayフィルタを考えます.部分時系列 に最小2乗法で2次関数を当てはめます.
を最小にするのは,
を満たすです.上の条件を計算して,行列にまとめれば,
これを,について解けば,
部分区間の中央点
のみを採用するので,
になります.
ということで,畳込み用に係数の順番をひっくり返しても同じなので,
です.
Savitzky-Golay微分フィルタの係数
Savitzky-Golayフィルタでは,平滑化した時系列の微分係数を求めることも可能です.
2次Savitzky-Golayフィルタで部分区間にフィットした関数
を微分し,を代入すると,
です.
ということで,畳込み用に係数の順番をひっくり返して,
です.

Rスクリプト
2次Savitzky-Golay平滑化フィルタの係数.
sg <- function(k,s){ return((9*s^2-21-60*k^2)/(4*s^3-16*s)) } # 幅 s <- 9 k <- (-(s-1)/2):((s-1)/2) plot(k,sg(k,s),col=2,ylab="a_k",main="SG smoothing filter")
2次Savitzky-Golay微分フィルタの係数.
dsg <- function(k,s){ return(-(12*k)/(s^3-s)) } # 幅 s <- 9 k <- (-(s-1)/2):((s-1)/2) plot(k,dsg(k,s),col=2,ylab="a_k",main="SG differentiation filter")
周波数特性もプロット
### 平滑化フィルタの係数 sg <- function(k,s){ return((9*s^2-21-60*k^2)/(4*s^3-16*s)) } ### 微分フィルタの係数 dsg <- function(k,s){ return((12*k)/(s^3-s)) } ######################## # フィルタ幅 s <- 9 ######################## k <- (-(s-1)/2):((s-1)/2) # 周波数 f.list <- exp(seq(log(0.001),log(0.5),length.out=1000)) # インパルス応答の計算 Freq.Resp <- c() for(f in f.list){ vcos <- cos(2*pi*f*k) Freq.Resp <- c(Freq.Resp,sg(k,s) %*% vcos) } # plot par(mfrow=c(2,2)) plot(k,sg(k,s),col=2,ylab="a_k",main="SG smoothing filter") y.max <- max(Freq.Resp) plot(f.list,abs(Freq.Resp),"l",col=2,log="xy",xlim=c(0.001,0.5),ylim=c(y.max/100,y.max),xaxs="i",lwd=2,xlab="f [Hz]",ylab="|A(f)|",main="SG smoothing filter") ################################ # インパルス応答の計算 Freq.Resp <- c() for(f in f.list){ vcos <- sin(2*pi*f*k) Freq.Resp <- c(Freq.Resp,dsg(k,s) %*% vcos) } plot(k,dsg(k,s),col=2,ylab="a_k",main="SG differentiation filter") y.max <- max(Freq.Resp) plot(f.list,abs(Freq.Resp),"l",col=2,log="xy",xlim=c(0.001,0.5),ylim=c(y.max/100,y.max),xaxs="i",lwd=2,xlab="f [Hz]",ylab="|A(f)|",main="SG differentiation filter")