今回も,ランダムウォーク解析についてです.ランダムウォーク解析 (fluctuation analysisと呼ばれることも)は,Natureに出版された論文でも使われています (以下のリンク).
www.nature.com
とはいえ,ランダムウォーク解析は,今では実用的な時系列解析法とはいえません.それでも,教育的な題材としては役に立ちます.
以下では,ゆらぎ関数とパワースペクトル
の関係を導いていきます.前回の記事は,これです.
chaos-kiyono.hatenablog.com
基本事項の確認
1. ラグオペレータを,時系列
に作用させると,
2. 時系列のフーリエ変換を
とします.時間の世界でのラグオペレータ
をフーリエ変換すると,
になります.つまり,
3. 時系列のパワースペクトルの推定量
は,長さ
の時系列
のフーリエ変換を
(ここで,
)として,
4. (ここで,
)の全面積は,時系列
の2乗平均 (平均0なら分散)になります.
ランダムウォーク解析を周波数の世界で考える
その増分
の2乗平均の期待値 (ゆらぎ関数: fluctuation function)
を求めるのでした.
増分の計算の部分の計算から考えます.計算が楽になるように和をとる区間を1シフトします.つまり,「1からs」を,「0から (s-1)」にしちゃいました.そうすると,
です.これについて考えます.
ラグオペレータを使えば,
です.最後の行になるのは,等比数列の和の公式を使ったからです.ちなみに等比数列の和の公式は,(初項-末項×公比)/(1-公比)でしたよね.
次に,両辺をフーリエ変換します.のフーリエ変換を
,
のフーリエ変換を
と表せば,
となります.これを使えば,パワースペクトルの関係式を求めることができます.つまり,「両辺の絶対値をとり,2乗して,でわる」の3ステップです.
ここで,のパワースペクトルを
,
のパワースペクトルを
と表せば,
さらに,
となるので,結局,
ここで,ゆらぎ関数
に登場してもらい,上の基本事項の4を使えば,
という関係式が得られます.これで,時系列のパワースペクトルとゆらぎ関数を解析的に結びつけることができました.正しいか心配なので,数値実験してみました.下の図は,同じ時系列 (H = 0.8の非整数ガウスノイズ)のランダムウォーク解析 (左)とパワースペクトル解析 (中)をした結果です.右の図は,ランダムウォーク解析の結果 (青丸)と,上の式を使ってパワースペクトル解析の結果をに変換したもの (赤バツ)の比較です.わずかに違いましたが,丸め誤差の影響だと思います.ポイントは,「ランダムウォーク解析とパワースペクトル解析は同じ情報を持っている」ということです.とはいえ,ランダムウォーク解析の方が,ギザギザしないので,直線の当てはめはやりやすいです.一方で,パワースペクトル解析の結果は,平滑化してやる必要があるということです.

今日は,明日締め切りの原稿があるので,ここまでにしておきます.ミスを見つけたら教えてください.
おまけ
作図に使用したRスクリプトはこれです.
# パッケージのインストールが必要な場合は以下を実行 # install.packages("longmemo") # パッケージのロード require(longmemo) ################################### # パラメタの設定:ハースト指数(0 < H < 1) H <- 0.8 ################################### # 時系列の長さ N <- 10000 ###################### # 解析するスケールs s <- unique(round(exp(seq(log(1),log(N/10),length.out=20)))) n.s <- length(s) ###################### # 時系列の生成 x <- simFGN0(N,H) x <- x - mean(x) # 平均0に ##################### # ランダムウォーク解析 ### # 積分 y <- cumsum(x) ### F.s <- c() for(i in 1:n.s){ D.y <- y[1:(N-s[i])]-y[(1+s[i]):N] F.s[i] <- sqrt(mean(D.y^2)) } freq <- (0:(N-1))/N S.f <- abs(fft(x))^2/N par(mfrow=c(1,3)) ### # log-logプロット par(pty="s") # log-logをとって直線をあてはめ logs <- log10(s) logFs <- log10(F.s) fit <- lm(logFs~logs) # plot(logs,logFs,col=4,xlab="log10 s",ylab="log10 F(s)",las=1, main="Random Walk Analysis") abline(fit,col=1,lty=2,lwd=2) # log-logをとって直線をあてはめ fit <- lm(log10(S.f[freq>0 & freq<1/10])~log10(freq[freq>0 & freq<1/10])) # plot(log10(freq[freq>0 & freq<1/2]),log10(S.f[freq>0 & freq<1/2]),"l",col=2,xlab="log10 f",ylab="log10 S(f)",las=1, main="Spectral Analysis") abline(fit,col=1,lty=2,lwd=2) F2.Sf <- c() for(i in 1:n.s){ F2.Sf[i] <- 0 for(k in 1:N){ fk <- k/N F2.Sf[i] <- F2.Sf[i]+sin(pi*fk*s[i])^2/sin(pi*fk)^2*S.f[k] } } plot(logs,logFs,col=4,xlab="log10 s",ylab="log10 F(s)",las=1,main="Comparison") points(log10(s),log10(F2.Sf/N)/2,pch=4,col=2,xlab="log10 s",ylab="log10 F(s)",las=1)