ピリオドグラム (Periodogram) の歴史について調べてみると、そもそもの目的は観測データに潜む周期性を見つけることのようです。これは、Arthur Schusterの論文 (1898)の導入に書いてありました。名前からして「周期 (period)」の「記録 (-gram)」なので、これは当然のことだと言えます。
この点を踏まえると、確率過程のパワースペクトルをピリオドグラムと呼ぶことには少し違和感 があります。なぜなら、確率過程のパワースペクトルでは、ピーク位置にのみ注目するのではなく、構造全体を読み解く必要があるからです。
そんな私の感想はどうでもよいので、今回は、正弦波の最小二乗フィッティングを用いたピリオドグラム (パワースペクトル) の推定 について考えてみます。 この方法は、Lomb-Scargleスペクトル、コサイナー解析と密接に関係していますので,これらの方法について理解するために、今回の内容は役に立つと思います。
最小2乗法でフーリエ変換をまねてみる
フーリエ変換を用いると、時系列データを異なる周波数の正弦波に分解できます。フーリエ変換の計算は、sin と cos の直交性を利用した内積に基づいています。
ここではいったんフーリエ変換のことは忘れて、時系列データに対し sin と cos を最小二乗フィッティングすることで、「フーリエ変換っぽいこと」を試みます。
時系列
に対し、
を最小2乗法でフィットします.
下の図はこの方法で振幅の周波数依存性を調べた結果です。実はこの最小2乗フィットの結果は、フーリエ変換を使った計算結果と一致します (周波数を同じ値で計算すれば完全一致)。
.
残差の2乗和を
として、これを最小化する と
を求めます。この関数は、
と
の2次関数なので、必ず最小値が存在します。ですので、
となる、 と
を求めれば良いということになります。
ちょっと計算を省略して、行列の形で書けば、
になります。式を繰り返し書くのが面倒なので、以下の省略した表現を定義します。
この表記を使えば、
上の式の左辺の行列の逆行列を両辺にかければ、 と
が求まります。
この計算は、2次の行列の逆行列の公式を使っただけです。
上の式は、めんどくさい形に見えるかもしれません。しかし、周波数がある条件を満たすときは、もっと簡単になります。
周波数 を、離散フーリエ変換と同じく、
を整数として、
に設定すれば、
となります (計算は【補足】を参照)。
したがって、 と
を、それぞれ、
と
と書くことにして、
となります。つまり、
です。
どこかで見たことのある形です。
を整数として、周波数を
で選んで、フィットした結果は、以下のようになります。
ここで、 と
は、
です。この式に登場する、和 の部分を
と表すことにします。そうすると、
となります。
フーリエ変換もやってみる
上の最小2乗法の結果とフーリエ変換の結果を比較してみます。
時系列
のフーリエ変換は、 を虚数単位として、以下のようになりkます:
ここで、周波数は、
なので、
です。ただ、みなさんご存じのように、適切な周波数領域は、
ですので、注意してください (過去の記事参照)。
先ほど定義した、
を使えば、フーリエ変換の結果は、
と書けます。
この が表す時間領域の周波数成分
] は以下のようになります。
この結果は、先ほど計算した最小2乗フィットの結果
と2倍だけ違います。
フーリエ変換では、
となり、最小2乗フィットの結果と一致します。
フーリエ変換でも最小2乗法でも結果は一致
今回のポイントは、最小2乗法で正弦波をフィットしても、フーリエ変換してその結果から特定の周波数成分(正弦波の成分)を抽出しても結果は同じということです.
この事実を使って、不等間隔にサンプリングされたデータのペリオドグラム(パワースペクトル)を推定できないか、と考えたのがLomb-Scargleスペクトルです。 また、24時間周期のように、事前に特定の周期だけを仮定して分析するのがコサイナー解析です。
Rで検証
最小2乗フィットでもフーリエ変換でも結果が一致することを確かめるRスクリプトの例は以下です。
# 振動成分をもつ2次自己回帰過程の時系列を生成する #set.seed(1) # 乱数の指定 n <- 256 # 時系列の長さ a1 <- 0.5 # AR(2)の係数 a2 <- -0.75 # sig <- 0.5 # ノイズの標準偏差 # ホワイトノイズ eps <- rnorm(n,mean=0,sd=sig) # 時系列データの初期値を設定 x <- numeric(n) x[1] <- eps[1] x[2] <- a1*y[1]+eps[2] # AR(2)プロセスの生成 for (t in 3:n) { x[t] <- a1 * x[t-1] + a2 * x[t-2] + eps[t] } # time <- 1:n-1 # FT <- fft(x) A.FT <- abs(FT)/n f.FT <- time/n freq <- f.FT[f.FT > 0 & f.FT < 0.5] n.freq <- length(freq) Amp <- c() ### for(i in 1:n.freq){ f <- freq[i] # 最小二乗フィット xx <- cos(2*pi*f*time) zz <- sin(2*pi*f*time) # Y <- matrix(c(sum(x),sum(x*xx),sum(x*zz)),ncol=1) X <- matrix(c(n,sx<-sum(xx),sz <- sum(zz),sx,sum(xx^2),sxz <- sum(xx*zz),sz,sxz,sum(zz^2)),ncol=3) X.inv <- solve(X) A <- X.inv %*% Y # モデルパラメタの推定結果 mesor.est <- A[1,1] phase.est <- atan2(A[3,1],A[2,1]) Amp[i] <- sqrt(A[2,1]^2+A[3,1]^2) } ## # グラフのプロット par(mfrow=c(3,1),mar=c(5,5,3,2),cex.main=1.8) plot(time, x,"l", xlab = "t", ylab = "x[t]", pch = 16, col=4,lwd=2,xaxs="i",main="Sample time series of AR(2)") plot(freq,Amp,"l",xaxs="i",col=2,lwd=2,xlim=c(0,0.5),main="Amplitude spectrum |A(f)| of least-square sinusoidal fitting",xlab="Frequency",ylab="") plot(f.FT,A.FT*2,"l",xaxs="i",col=3,lwd=2,xlim=c(0,0.5),main="Amplitude spectrum |A(f)| of Fourier transform",xlab="Frequency",ylab="")
【補足】計算の説明
以下の計算について説明しておきます。
まずは、高校で習う公式
を
に適用すると、
上の式の最初の和は
したがって、第一項は
次に、第二項
については、オイラーの公式
から、以下の等比級数の和について、その実部として計算できます。等比数列の和の公式を使えば、
ここで、
なので、
この実部を取ると、
以上から、
となります。