$ \newcommand\bm[1]{\boldsymbol{#1}} \newcommand\ve{\varepsilon} \newcommand\vecseq[3]{{#1}_{#2}, \ldots, {#1}_{#3}} \newcommand\alg[1]{\color{blue}{\mathrm{#1}}} $
 

MATLABで『時系列解析入門』7章

ARモデルの推定.

ここまででは, ある係数や次数をもつARモデルの性質 ( どのようなスペクトルをもつか, など ) について考察してきた. この章では, 実際のデータをARモデルとして扱う時, どのように係数や次数を推定するのかについて述べられている.


非専門家が書いています. 十分に批判的に読んで頂くようお願いいたします. 間違い・疑問点などあれば, ぜひコンタクトフォームへ連絡いただけると幸いです.

ARモデル

モデル

この章では, 時系列 $\{ y_n \}_{n=1}^N$ に対して以下で示される自己回帰モデルを当てはめる問題について考える.

\begin{align}\large{ y_n = \sum_{i=1}^{m} a_i y_{n-i} + v_n, \quad v_n \sim \mathcal{N}(0, \sigma^2). }\end{align}
ここで, $m$ をARモデルの次数, $a_i$ を自己回帰係数という. この問題で推定すべきパラメータは,
\begin{align}\large{ \theta = (a_1, \ldots , a_m, \sigma^2)^{\mathrm{T}} \notag }\end{align}
である.

尤度

ARモデルに従う時系列 $\{ y_n \}_{n=1}^N = \bm{y}$ の同時分布はN次元正規分布となり, 尤度は以下でかける.

\begin{align} \large \mathcal{L}(\theta) & = p(\vecseq{y}{1}{N} \mid \theta) \\[10pt] \large & = \frac{1}{\sqrt{(2 \pi)^{D} |\Sigma|}} \exp{\left( -\frac{1}{2} \bm{y}^{T} \Sigma^{-1} \bm{y} \right)}. \end{align}
ここで,
\begin{align} \Sigma = \begin{pmatrix} C_0 & C_1 & & \cdots & C_{N-1} \\ C_1 & C_0 & & \cdots & C_{N-2} \\ \vdots & \vdots & & \ddots & \vdots \\ C_{N-1}& C_{N-2}& & \cdots & C_{0} \\ \end{pmatrix} \notag \end{align}
である. $\vecseq{y}{1}{N}$ のそれぞれについて, 自分自身 ( つまりラグ0 ) の分散, つまり自己分散が $C_0$ で, ラグが $i$ のときは, 相互分散が $C_i$ であったことを思い出すと, 上の $\Sigma$ が出てくるのがわかると思う.

$\mathcal{L}(\theta)$ を最大化する $\hat{\theta}$ がみつかれば, AICも以下となる.

\begin{align}\large{ \mathrm{AIC} = -2 \log{\mathcal{L}(\hat{\theta})} + 2(m + 1) }\end{align}

では, どのように $\hat{\theta}$ を算出するか. 教科書では

  • Levinsonのアルゴリズム
  • 最小二乗法
  • PARCOR法
の3つが紹介されている. この記事では, 上2つをとりあえず計算してみようと思う.

Yule-Walker法

Yule-Walker推定量

第六章 で紹介した Yule-Walker方程式に, 標本自己共分散函数 $\hat{C}_k$ を代入した以下の式

\begin{align}\large{ \hat{C}_0 = \sum_{i=1}^{m} a_i \hat{C}_i + \sigma^2, \tag{Yule-Walker Eq.} \\ \hat{C}_k = \sum_{i=1}^{m} a_i \hat{C}_{k-i} }\end{align}
を解いて求めたAR係数, すなわち $\hat{\theta} = (\vecseq{\hat{a}}{1}{m}, \hat{\sigma}^2 \)$ をYule-Walker推定量という. 推定分散 $\hat{\sigma}^2$ は第1式から当然,
\begin{align}\large{ \hat{\sigma}^2 = \hat{C}_0 - \sum_{i=1}^{m} a_i \hat{C}_i }\end{align}
となる.

Levinsonのアルゴリズム

では, 上のYule-Walker方程式をどう解いて, $m$ 次のYule-Walker推定量を求めようか. 第六章で作ったプログラムでコツコツ計算してもできるであろうが, Levinsonのアルゴリズムを使えばこれを効率的に解ける. 証明は教科書を見てほしい.

\begin{array}{clc} \hline & \mathbf{Algorithm\;7.1} & \\ & \mathrm{Levinson's\;Algorithm\;for\;multivariate\;AR\;model} & \\ \hline & \begin{align} & \hat{\sigma}_0^2 = \hat{C}_0 \notag \\[2.5pt] & \mathrm{AIC}_0 = N(\log{ 2 \pi \hat{\sigma}_0^2} +1) +2 \notag\\[2.5pt] & \alg{for} \quad m = 1 : M \notag \\[2.5pt] & \qquad \hat{a}_{m}^{m} = \left( \hat{C}_m - \sum_{j=1}^{m-1} \hat{a}_{j}^{m-1} \hat{C}_{m-j} \right) (\hat{\sigma}_{m-1}^{2})^{-1} \notag \\[2.5pt] & \qquad \alg{for} \quad i = 1 : m-1 \notag \\[2.5pt] & \qquad \qquad \hat{a}_{i}^{m} = \hat{a}_{i}^{m-1} - \hat{a}_{m}^{m} \hat{a}_{m-i}^{m-1} \notag \\[2.5pt] & \qquad \alg{end\;for} \notag \\[2.5pt] & \qquad \hat{\sigma}_{m}^{2} = \hat{\sigma}_{m-1}^{2} \{ 1 - (\hat{a}_{m}^{m})^2 \} \notag \\[2.5pt] & \qquad \mathrm{AIC}_{m} = N(\log{ 2 \pi \hat{\sigma}_m^2} +1) +2(m+1) \notag \\[2.5pt] & \alg{end\;for} \notag \end{align} & \\ \hline \end{array}
MATLAB
function [aic, Arcoef, s2, maic] = arLevinson(d, M)
%ARLEVINSON
%
% INPUT
% d:data
% M:maximum AR degree (lag)
% 
% OUTPUT
% aic     : AIC
% Arcoef  : AR coefficient (structure)
% s2      : sigma^2
% maic    : The order which provides the minimum AIC

% 前処理
d = d - mean(d);
N = length(d);

% 標本自己共分散を求める
C = xcorr(d, M)/N;
C = C(M+1:end);

% preallocation
aic = zeros(1, M+1);
s2  = zeros(1, M+1);
a   = zeros(M);

% AIC_0
s2(1) = C(1);
aic(1) = N * (log(2 * pi * s2(1))+1) + 2;

% m = 1に対してアルゴリズムを回す
m = 1;
a(m, m) = C(m+1) / s2(1);
s2(2)    = s2(1) * (1 - a(m, m)^2);
aic(m+1) =  N * (log(2 * pi * s2(2)) + 1) + 2*(m + 1);

% m = 2, ... , Mに対してアルゴリズムを回す
for m = 2:M
  % calculate a_m^m
  a(m, m) = (C(m+1) - dot(a(m-1, 1:m-1), C(m:-1:2))) / s2(m);
  % calculate a_i^m
  for i = 1:m-1
     a(m, i) = a(m-1, i) - a(m, m)*a(m-1, m-i); 
  end
  % calculate sigma_{m-1}^2
  s2(m+1) = s2(m) * (1 - a(m, m)^2);
  % calculate AIC_m
  aic(m+1) = N * (log(2 * pi * s2(m+1)) + 1) + 2*(m + 1);
end

% make Arcoef
for m = 1:M
  name = ['order' num2str(m)];
  Arcoef.(name) = a(m, 1:m);
end

% calculate maic
[~, maic] = min(aic);
end

最小二乗法

最小二乗法は, 多変量ARモデルの解析をする際に柔軟性が高いらしいので, ここに紹介する. データ$\vecseq{y}{1}{N}$ に対する, $M$ 次のARモデルの最小二乗階を求める手順だけ示す. とてもシンプル. MATLABのコードは, 可能な限り手順と一致するように書いている.

まず. 以下の行列 $X$ を作る.

\begin{align}\large{ X = [ Z \mid y ] = \left(\begin{array}{cccc|c} y_M & y_{M-1} & \cdots & y_1 & y_{M+1} \\ y_{M+1} & y_M & \cdots & y_2 & y_{M+2} \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ y_{N-1} & y_{N-2} & \cdots & y_{N-M}& y_N \\ \end{array}\right). \tag{7.19} }\end{align}
ハウスホルダー法 ( MATLABのqrを使える ) によって,
\begin{align}\large{ HX = \left(\begin{array}{c} S \\ 0 \\ \end{array}\right) = \left(\begin{array}{cccc} s_{11} & \cdots & s_{1M} & s_{1, M+1} \\ & \ddots & \vdots & \vdots \\ & & s_{MM} & s_{M, M+1} \\ \Large{0} & & & s_{M+1, M+1} \\ \end{array}\right) \tag{7.20} }\end{align}
と上三角行列に変換する. 以下のコードでは, 変換する行列 $H$ は必要でないため, アウトプットしていない.

あとは, $j$ 次の自己回帰モデルの残差分散 $\hat{\sigma}^2$, AIC, 自己回帰係数は以下の式を解くことで得られる.

\begin{align} \large \hat{\sigma}^2 = \frac{1}{N-M} \sum_{i = j+1}^{M+1} s_{i, M+1}^2, \tag{7.21} \\[10pt] \large \mathrm{AIC}_j = (N-M) (\log{2 \pi \hat{\sigma}^2_j + 1}) + 2(j+1), \notag \\[10pt] \large{ \left(\begin{array}{ccc} s_{11} & \cdots & s_{1j} \\ & \ddots & \vdots \\ & & s_{jj} \\ \end{array}\right) \left(\begin{array}{c} a_1 \\ \vdots \\ a_j \end{array}\right) = \left(\begin{array}{c} s_{1, M+1} \\ \vdots \\ s_{j, M+1} \\ \end{array}\right).\tag{7.22} }\end{align}
最後の線形方程式は, 後退代入で解ける. MATLABは, 特に指定しなくても A\b を使えば, 後退代入できるときは後退代入してくれるので便利.

MATLAB
function [aic, Arcoef, s2, maic] = arLeastsquares(d, M)
%ARLEASTSQUARES
%
% INPUT
% d:data
% M:maximum AR degree (lag)
% 
% OUTPUT
% aic     : AIC
% Arcoef  : AR coefficient (structure)
% s2      : sigma^2
% maic    : The order which provides the minimum AIC

% preprocessing
d = d - mean(d);
N = length(d);

% make matrix X Eq.(7.19)
Z = zeros(N-M, M);
for I = 1:M
    Z(:, I) = d(M-I+1:N-I); 
end
y = d(M+1:N);
X = [Z y'];

% Householder(QR decomposition)
[~, R] = qr(X);
S      = R(1:M+1, 1:M+1);

% calculate sigma^2, AIC
s2 = flipud(cumsum(flipud(S(:, end).^2)));
s2 = s2/(N-M);
aic = (N-M) * (log(2*pi*s2)+1) + 2*((0:M)' + 1);

% make Arcoef
for m = 1:M
    name = ['order' num2str(m)];
    res  = S(1:m, 1:m)\S(1:m, M+1);
    Arcoef.(name) = res';
end

% calculate maic
[~, maic] = min(aic);
maic = maic-1;
end

多変量ARモデル

モデル

多変量ARモデルでは, 時系列 $\bm{y}_n$ は以下の関係を想定する. ここで, データは $k$ 次元, ARモデルは $m$ 次とする.

\begin{align}\large{ \bm{y}_n = \sum_{i=1}^{m}A_i^m \bm{y}_{n-i} + \bm{v}_n, \quad \bm{v}_n \sim \mathcal{N}(0, V_m) \notag }\end{align}
パラメータは, AR係数行列 $A$, $\bm{v}_n$ の分散共分散行列 $V_m$ である.

Yule-Walker法

\begin{array}{clc} \hline & \mathbf{Algorithm\;7.2} & \\ & \mathrm{Levinson's\;Algorithm\;for\;multivariate\;AR\;model} & \\ \hline & \begin{align} & \hat{V}_0 = \hat{U}_0 = \hat{C}_0 \notag \\[2.5pt] & \mathrm{AIC}_0 = N(k \log{2 \pi} + \log{|\hat{V}_0|} + k) + k(k+1) \notag \\[2.5pt] & \alg{for}\; m = 1:M \notag \\[2.5pt] & \qquad W_m = \hat{C}_m - \sum_{i=1}^{m-1} A_i^{m-1} \hat{C}_{m-i} \notag \\[2.5pt] & \qquad A_m^m = W_m U_{m-1}^{-1} \notag \\[2.5pt] & \qquad B_m^m = W_m^{T} \hat{V}_{m-1}^{-1} \notag \\[2.5pt] & \qquad \alg{for} \quad i = 1:m-1 \notag \\[2.5pt] & \qquad \qquad A_i^m = A_i^{m-1} - A_m^m B_{m-i}^{m-1} \notag \\[2.5pt] & \qquad \qquad B_i^m = B_i^{m-1} - B_m^m A_{m-i}^{m-1} \notag \\[2.5pt] & \qquad \alg{end\;for} \quad i = 1:m-1 \notag \\[2.5pt] & \qquad \hat{V}_m = \hat{C}_0 - \sum_{i=1}^{m} A_i^m C_i^{T} \notag \\[2.5pt] & \qquad U_m = \hat{C}_0 - \sum_{i=1}^{m} B_i^m C_i \notag \\[2.5pt] & \qquad \mathrm{AIC}_m = N(k \log{2 \pi} + \log{|\hat{V}_m|} + k) + k(k+1) + 2k^2m \notag \\[2.5pt] & \alg{end\;for} \notag \\ \end{align} & \\ \hline \end{array}
MATLAB
function [aic, V, Arcoef, maic] = mvArLevinson(d, K, M)
%MVARLEVINSON
%
% INPUT
% d:data
% k:dimension of the data
% M:maximum AR degree (lag)
% 
% OUTPUT
% aic     : AIC (size = lag * k)
% Arcoef  : AR coefficient, size = K * K * M * M
% V      : variance-covariance matrix
% maic    : The order which provides the minimum AIC


% preprocessing
d = reshape(d, [], K);
d = d - mean(d);
N = size(d, 1);

% calculate C
C = xcorr(d, M)/N;
C = C(M+1:end, :);
C = reshape(C, M+1, K, K);
C = permute(C,[3 2 1]); 
C0 = C(:, :, 1);
C  = C(:, :, 2:end);

% preallocation
aic = zeros(1, M);
V   = zeros(K, K, M); % = zeros(size(C))
U   = zeros(K, K, M);
A   = zeros(K, K, M, M);
B   = zeros(K, K, M, M);

% Yule Walker
% m = 0
V0   = C0;
U0   = C0;
aic0 = N * (K*log(2*pi) + log(det(V0)) + K) + K*(K+1);

% m = 1 (W_1 = C_1)
A(:, :, 1, 1) = C(:, :, 1) / U0;
B(:, :, 1, 1) = C(:, :, 1)'/ V0;
V(:, :, 1)    = C0 - A(:, :, 1, 1) * C(:, :, 1)';
U(:, :, 1)    = C0 - B(:, :, 1, 1) * C(:, :, 1);
aic(1)        = N * (K*log(2*pi) + log(det(V(:, :, 1))) + K) + K*(K+1) + 2*K^2*1;

% m = 2 ,..., M
for m = 2:M
    W             = C(:, :, m) - sum(pagemtimes(squeeze(A(:, :, m-1, 1:m-1)), C(:, :, m-1:-1:1)), 3);
    A(:, :, m, m) = W /U(:, :, m-1);
    B(:, :, m, m) = W'/V(:, :, m-1);
    for i = 1:m-1
        A(:, :, m, i) = A(:, :, m-1, i) - A(:, :, m, m) * B(:, :, m-1, m-i);
        B(:, :, m, i) = B(:, :, m-1, i) - B(:, :, m, m) * A(:, :, m-1, m-i);
    end
    tC = permute(C, [2 1 3]); 
    V(:, :, m) = C0 - sum(pagemtimes(squeeze(A(:, :, m, 1:m)), tC(:, :, 1:m)), 3);
    U(:, :, m) = C0 - sum(pagemtimes(squeeze(B(:, :, m, 1:m)),  C(:, :, 1:m)), 3);
    aic(m)     = N * (K*log(2*pi) + log(det(V(:, :, m))) + K) + K*(K+1) + 2*K^2*m;
end

% make Arcoef
for m = 1:M
    name = ['order' num2str(m)];
    Arcoef.(name) = squeeze(A(:, :, m, 1:m));
end

% calculate maic
aic = [aic0 aic];
[~, maic] = min(aic);
maic = maic-1;

end

例として, 船舶データ ( HAKUSAN ) に適用してみた. 4変数, 最大次数60でトライ. 正直複雑でコードに自信がないけど, 最小AICを与える次数は10で, 教科書とおなじになった. AICの増加の仕方も直線的でいい感じ.

name
MATLABコード MATLAB
d = hakusan.velocity;
d = [d hakusan.yoko];
d = [d hakusan.tate];
d = [d hakusan.dakaku];

K = 4;
M = 60;

[aic, V, Arcoef, maic] = mvArLevinson(d, K, M);
bar(0:M, aic - min(aic), 0.5, 'LineStyle', 'none');
ylim([0 1000])
ylabel('AIC')
xlabel('multivariate AR order')

数値例: ( 単変量 ) ARモデル

太陽黒点数 ( Yule-Walker法 )

SUNSPOTデータを対数変換 ( 底は10, 0には $10^{0.1}$ を代入 ) し, Yule-Walker法を用いて, 次数20までのARモデルを推定し, AICを計算した.

AICは最小値を0にシフトして表示している. 教科書通り次数10のARモデルが選択されている ( maicは10 ) . 残差分散は単調に減少している.

name
MATLABコード MATLAB
d = sunspot; % data
d(d==0) = 10^0.1;
d = log10(d);
M = 20; % 最大AR次数

[aic, Arcoef, s2, maic] = arLevinson(d, M);

t = tiledlayout(1, 2); t.Padding = 'compact'; t.TileSpacing = 'compact';
nexttile
bar(0:20, aic-min(aic), 0.5, 'LineStyle', 'none')
ylim([0 50]);
xlabel('AR order')
ylabel('AIC')

nexttile
bar(0:20, s2, 0.5, 'LineStyle', 'none')
% ylim([0 50]);
xlabel('AR order')
ylabel('$\hat{\sigma}^2$','Interpreter','latex')

次に, AR(10)のパワースペクトルをみてみる. 教科書とほとんどおなじになった. ピークは, 0.09 [cycle/year] にあり, 1/0.09 = 約11で, 約11年周期の黒点数の変動が表現されている.

name

太陽黒点数 ( 最小二乗法 )

念の為, 最小二乗法も使ってみる.

同じ結果であろう.

name
name
MATLABコード MATLAB
d = sunspot; % data
d(d==0) = 10^0.1;
d = log10(d);
M = 20; % 最大AR次数

[aic, Arcoef, s2, maic] = arLeastsquares(d, M);
t = tiledlayout(1, 2); t.Padding = 'compact'; t.TileSpacing = 'compact';
nexttile
bar(0:M, aic-min(aic), 0.5, 'LineStyle', 'none')
ylim([0 50]);
xlabel('AR order')
ylabel('AIC')

nexttile
bar(0:M, s2, 0.5, 'LineStyle', 'none')
xlabel('AR order')
ylabel('$\hat{\sigma}^2$','Interpreter','latex')

%% - Spectrum
lag = 10;
order = ['order' num2str(lag)];
[~, ~] = spectrumARMA(Arcoef.(order), 0, s2(lag+1), true);

シミュレーション

せっかくなので選ばれたAR(10)モデルから発生する時系列をシミュレーションしてみた. 内容的には. 教科書16.3節「ARMAモデルのシミュレーション」である.

もちろん, 乱数によって発生するデータの雰囲気はかわる. よさげ ( つまり, 太陽黒点数の原データと雰囲気が似ている ) ものと, 微妙なものを以下に載せる.

Good

name

Bad

name
MATLABコード MATLAB
lag = 10; % AR次数
stdev = sqrt(s2(lag+1)); % 残差の標準偏差
order = ['order' num2str(lag)];
arcoef = Arcoef.(order); % AR係数
rng('shuffle')
L = 231; % シミュレーションする時系列の長さ ( 原データに合わせた ) . 

ySim = zeros(L, 1);
ySim(1:lag) = d(end-lag+1:end) - mean(d);

for I = lag:L
    ySim(I+1) = dot(arcoef, ySim(I:-1:I-lag+1)) + randn * stdev;
end

% plot
y = sunspot;
t = tiledlayout(2, 1); t.Padding = 'compact'; t.TileSpacing = 'compact';
nexttile
plot(10.^(ySim + mean(d)))
ylabel('simulated Sunspot')

nexttile
plot(y)
ylabel('True Sunspot') 

書かなかった内容

今回, うまく再現できなかったなどの理由で書かなかった内容は, 以下.

  • 最小二乗法による多変量ARモデル推定
  • クロススペクトル・コヒーレンシー
  • パワースペクトル分解・相対パワー寄与率
はやく状態空間モデルに行きたいので一旦スキップするが, 今後追記するかもしれない.

主な参考文献


今回から, 新装版に変えた. Rによる 時系列モデリング入門

この記事のTOP    BACK    TOP