Analiza Szeregów Czasowych/Techniki analizy szeregów czasowych

Z Skrypty dla studentów Ekonofizyki UPGOW

(Różnice między wersjami)
(Metoda Yule-Walkera)
m (Algorytm innowacyjny)
 
(Nie pokazano 33 wersji pomiędzy niniejszymi.)
Linia 55: Linia 55:
Jeżeli tylko <math> \hat{\gamma}(0) > 0 </math> to możemy podzielić obie strony przez <math> \hat{\gamma}(0) </math> i otrzymamy wtedy
Jeżeli tylko <math> \hat{\gamma}(0) > 0 </math> to możemy podzielić obie strony przez <math> \hat{\gamma}(0) </math> i otrzymamy wtedy
 +
: <math>
 +
\begin{align}
 +
\hat{\bar{\varphi}} &= \hat{R}^{-1}_p \hat{\rho}_p, \\
 +
\hat{\sigma}^2 &= \hat{\gamma}(0) [1 - \hat{\rho'}_p \hat{R}^{-1}_p \hat{\rho}_p],
 +
\end{align}
 +
</math>
 +
gdzie
 +
: <math> \hat{\rho}_p = (\hat{\rho}(1), \hat{\rho}(2), \dots, \hat{\rho}(p) )' = \hat{\gamma}_p/\hat{\gamma}(0)</math> - wektor autokorelacji próby.
 +
Z tak określonym <math> \hat{\bar{\varphi}} </math> można pokazać, że powyższy model jest losowy. Autokowariancje <math> \gamma_F(h) </math>  fitowanego modelu powinny spełniać
 +
:<math> \gamma_F(h) - \hat{\varphi}_1 \gamma_F(h-1) - \dots - \hat{\varphi}_p \gamma_F(h-p) = \left \{ {{\sigma^2, h = 0} \atop {0, h = 1,\dots, p}} \right. </math>
 +
Każdej niesingularnej macierzy <math> \Gamma_p </math> odpowiada proces AR(p). Niestety nie możemy stwierdzić w ogólności tego samego dla procesu MA(q).
 +
 +
Generalnie (czyli teoretycznie) rząd ''p'' nie jest nam znany, gdy zaczynamy dopasowywać dane do modelu AR(p). Jeżeli założymy, że prawdziwym rzędem modelu jest rząd ''p'' a zamierzamy dopasować model rzędu ''m'' to powinniśmy oczekiwać, że oszacowany estymator <math> \bar{\varphi}_m = \bar{\varphi}_{m1}, \bar{\varphi}_{m2}, \dots, \bar{\varphi}_{mm}) </math> wykaże dla indeksów większych od ''p'' niskie wartości <math> \bar{\varphi}_{mm}. </math>
====Algorytm Durbina - Levinsona====
====Algorytm Durbina - Levinsona====
-
====Algorytm Burga====
+
Wiemy jak wstępnie oszacować parametry metodą Yule-Walkera
 +
: <math> X_t - \varphi_{m1} X_{t-1} - \dots - \varphi_{mp} X_{t-m} = Z_t, ~~Z_t \sim BS(0, \sigma^2). </math>
 +
z odpowiednimi
 +
: <math> \hat{\varphi}_m = (\hat{\varphi}_{m1}, \dots, \hat{\varphi}_{mm}) = \hat{R}^{-1}_m \hat{\rho}_m </math> - predyktory <math> \varphi_i, </math>
 +
: <math> \hat{v}_m = \hat{\gamma}(0) [1 - \hat{\rho'}_p \hat{R}^{-1}_p \hat{\rho}_p]</math> - predyktor <math> \sigma^2. </math>
 +
 
 +
; Algorytm DL : pozwala na sukcesywne obliczanie kolejnych rzędów procesu AR.
 +
Jeżeli <math> \hat{\gamma}(0) > 0 </math> to dla ''m = 1, 2, ..., n-1'' możemy rekursywnie dopasować model AR
 +
: <math> \hat{\varphi}_{11} = \hat{\rho}(1),\ </math>
 +
: <math> \hat{v}_1 = \hat{\gamma}(0) [1 - \hat{\rho}^2(1)], \ </math>
 +
: <math> \hat{\varphi}_{mm} = [\hat{\gamma}(m) - \sum_{j=1}^{m-1} \hat{\varphi}_{m-1,j} \hat{\gamma}(m-j)] / \hat{v}_{m-1}, </math>
 +
: <math> \begin{bmatrix} \hat{\varphi}_{m1} \\ \vdots \\ \hat{\varphi}_{m,m-1}\end{bmatrix} = \hat{\bar{\varphi}}_{m-1} - \hat{\varphi}_{m,m}
 +
\begin{bmatrix} \hat{\varphi}_{m-1,m-1} \\ \vdots \\ \hat{\varphi}_{m-1,1}\end{bmatrix}, </math>
 +
: <math> \hat{v}_m = \hat{v}_{m-1} (1 - \hat{\varphi}^2_{mm}). </math>
 +
 
 +
<source lang="matlab">
 +
function [phi, v] = asc_durbin_levinson(x, p)
 +
   
 +
  if ( isempty (x) || (!isvector(x)) )
 +
    error ("DL: pierwszy agrument musi byc niepustym wektorem");
 +
    return;
 +
  endif
 +
 
 +
  %dlugosc wektora
 +
  lx = length(x);
 +
 
 +
  if ( !isnumeric(p) || p < 1)
 +
    error ("DL: drugi argument musi byc liczba naturalna 0 < |h| <= dim(wektor)\n");
 +
    return;
 +
  endif
 +
 
 +
  %%%
 +
  % algorytm Durbina - Levinsona
 +
 
 +
  fi = [];
 +
  v  = [];
 +
 
 +
  % krok 0
 +
  if (p == 1)
 +
    p;
 +
    phi = asc_kor(x,1);
 +
    v  = asc_kow(x,0) * (1.0 - power(phi,2.0));
 +
  else
 +
    [fi, w] = asc_durbin_levinson(x, p - 1);
 +
    p;
 +
 
 +
    suma = 0.0;
 +
    for j=1:p-1
 +
      suma += fi(p-1,j) * asc_kow(x,p-j);
 +
    endfor
 +
   
 +
    fi(p, p) = (asc_kow(x,p) - suma) / w(p-1);
 +
 
 +
    for m=1:p-1
 +
      fi(p,m) = fi(p-1,m) - fi(p,p)*fi(p-1,p-m);
 +
    endfor
 +
 
 +
    w(p)    = w(p-1) * (1.0 - power(fi(p,p),2.0));
 +
 
 +
    phi = fi;
 +
    v  = w;
 +
  end
 +
 
 +
endfunction
 +
</source>
 +
 
 +
Przy okazji, korzystając z powyższego algorytmu dostajemy funkcję autokorelacji częściowej próby <math> \hat{\alpha}(m) = \hat{\varphi}_{mm} </math>. Wiemy, że dla modelu AR(p) dla wszystkich ''m > p'' mamy <math> \alpha (m) = \varphi_{mm} = 0 </math>. Dodatkowo estymator <math> \varphi_{mm} </math> dla ''m > p'' ma z dobrym przybliżeniem rozkład normalny ''N(0,1/n)'', czyli - jeżeli model AR(p) jest dobrze dobrany to dla dostatecznie dużych ''m'' wartości <math> \varphi_{mm} </math> powinny się zgadzać z rozkładem normalnym ''N(0,1/n)''. W szczególności, jeżeli rząd AR jest równy ''p'' to <math> \varphi_{mm} </math> dla ''m > p'' powinno zawierać się w granicy 95% zgodności, czyli leżeć pomiędzy granicami <math> \pm 1.96/\sqrt{n} </math> z prawdopodobieństwem bliskim 0.95 (tylko 5% wartości może się nie zgadzać, czyli wypaść poza podane granice). Jeżeli tak jest w rzeczywistości to obliczony model AR(p) będzie dobrym oszacowaniem procesu losowego stojącego za danym szeregiem czasowym.
 +
 
 +
; Przykład : Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces AR(2), z <math> \varphi_1 = 0.9, \varphi = -0.3 </math> i wariancją <math> \sigma^2 = 1 </math>. Następnie proces ten poddajemy działaniu algorytmu DL aż do ''p=5''. Widzimy, że oszacowanie parametrów wielomianu <math> \varphi </math> dla pierwszych dwóch wartości różni się o kilka procent dla wszystkich ''p > 1'', natomiast oszacowane wielkości <math> \varphi_3, ...,  \varphi_5</math> są znikomo małe (maksymalnie 4% <math> \varphi_1 </math> lub 12% <math> \varphi_2 </math>) i dodanie ich do modelu nie zmieni w zasadzie niczego, dlatego można je odrzucić jako mało istotne. Wartość wariancji obliczona została na poziomie 99% wartości prawdziwej, <math> \varphi_1 </math> na poziomie 98% a <math> \varphi_2 </math> na poziomie mniejszym niż 1%, dając. Reasumując
 +
* oryginalny model
 +
: <math> X_t - 0.9 X_{t-1} - 0.3 X_{t-2} = Z_t \ </math>
 +
* dopasowany model [dla asc_durbin_levinson(x, 2)]
 +
: <math> \hat{X}_t - 0.91710 \hat{X}_{t-1} - 0.30064 \hat{X}_{t-2} = \hat{Z}_t \ </math>
 +
 
 +
<source lang="Matlab">
 +
octave:69> x = arma_rnd([0.9,-0.3], [0], 1, 10000, 10000);
 +
octave:70> [phi, v] = asc_durbin_levinson(x, 5)
 +
phi =
 +
 
 +
  0.70512  0.00000  0.00000  0.00000  0.00000
 +
  0.91710  -0.30064  0.00000  0.00000  0.00000
 +
  0.92346  -0.32003  0.02114  0.00000  0.00000
 +
  0.92403  -0.32871  0.04618  -0.02712  0.00000
 +
  0.92404  -0.32872  0.04625  -0.02732  0.00022
 +
 
 +
v =
 +
 
 +
  1.09071  0.99213  0.99169  0.99096  0.99096
 +
</source>
 +
 
 +
<!-- ====Algorytm Burga==== -->
===MA===
===MA===
Dla przypadków, gdy ''q > 0'' metoda zaprezentowana wcześniej nie do końca zdaje egzamin. W tym przypadku posługujemy się algorytmem '''innowacyjnym'''.
Dla przypadków, gdy ''q > 0'' metoda zaprezentowana wcześniej nie do końca zdaje egzamin. W tym przypadku posługujemy się algorytmem '''innowacyjnym'''.
 +
 +
Tak samo, jak możemy dopasować modele AR do posiadanych szeregów stosując algorytm Durbina-Levinsona do sutokorelacji częściowych, w podobny sposób, możemy rekursywnie dopasowywać dane do procesów średniej kroczącej
 +
: <math> X_t = Z_t + \hat{\theta_{m1}} Z_{t-1} + \dots + \hat{\theta_{mm}} Z_{t-m}, \{ Z_t \} = BS(0,\sigma^2), \,</math>
 +
dla ''m = 1,2,...'' używając '''algorytmu innowacyjnego'''.
====Algorytm innowacyjny====
====Algorytm innowacyjny====
 +
Będziemy szacować wektor MA, czyli wektor <math> \hat{\mathbf{\theta}}_m = (\hat{\theta}_{m1}, \dots, \hat{\theta}_{mm})', \,</math> oraz wariancję procesu ''BS'' <math> \hat{v}_m. \,</math>
 +
 +
; Algorytm :
 +
Jeżeli <math> \{ X_t \} \,</math> ma średnią zerową oraz wartość oczekiwana korelatora <math> E(X_iX_j) = \kappa(i,j) </math> jest zdefiniowana przez niesingularną macierz kowariancji <math>[\kappa(i,j)]_{i,j=1}^n \,</math> dla każdego ''n=1,2,...'' wtedy wartości <math> \hat{X}_{n+1}, n \ge 0 \,</math> oraz odpowiednie średnio-kwadratowe błędy <math>v_n, n \ge 1 \,</math> dane są poprzez równanie
 +
: <math> \hat{X}_{n+1} = \left \{ {{0, n = 0} \atop {\sum_{j=0}^n \theta_{nj} (X_{n+1-j} - \hat{X}_{n+1-j}), n \ge 1}} \right. </math>
 +
a estymatory modelu liczymy rekurencyjnie z równań
 +
: <math>
 +
\begin{align}
 +
v_0 &= \kappa(1,1), \\
 +
\theta_{n,n-k} &= v_k^{-1} \Big( \kappa(n+1,k+1) - \sum_{j=0}^{k-1} \theta_{k,k-j} \theta_{n,n-j} v_j, ~~k=0,\dots,n-1\\
 +
v_n &=  \kappa(n+1,n+1) - \sum_{j=0}^{n-1} \theta^2_{n,n-j} v_j
 +
\end{align}
 +
</math>
 +
 +
Poniżej prezentujemy skrypt Matlab / GNU Octave realizujący algorytm innowacyjny.
 +
 +
<source lang="matlab">
 +
function [theta,v] = asc_innovation(x, qIn)
 +
   
 +
  if ( isempty (x) || (!isvector(x)) )
 +
    error ("I: pierwszy agrument musi byc niepustym wektorem");
 +
    return;
 +
  endif
 +
 +
  %dlugosc wektora
 +
  lx = length(x);
 +
 +
  if ( !isnumeric(qIn) || qIn < 1)
 +
    error ("I: drugi argument musi byc liczba naturalna q > 0\n");
 +
    return;
 +
  endif
 +
 +
  %%%
 +
  % algorytm innowacyjny
 +
 +
  %%%
 +
  % pracujemy na wektorach
 +
  w    = [];
 +
  teta = [];
 +
 +
  %%%
 +
  % wartości startowe
 +
  % dla v(1) i theta(1,1)
 +
  v_zero = asc_kow(x,0);
 +
  w = v_zero;
 +
  teta  = asc_kor(x,1);
 +
 +
  %%%
 +
  % właściwy algorytm innowacyjny
 +
  for q = 1 : qIn  % dla rzedu = MA(1)...MA(q)
 +
 +
    %%%
 +
    % kolejne wartości \theta_{q,q-k}
 +
    for k=0:q-1
 +
      suma = 0;
 +
      for j=0:k-1
 +
      if k > j
 +
  suma += teta(q,q-j) * teta(k,k-j) * w(j+1);
 +
      endif
 +
      endfor
 +
      teta(q,q-k) = (asc_kow(x,q-k) - suma) / w(k+1);
 +
 +
      %%%
 +
      % kolejne wartości v_q
 +
      suma = 0;
 +
      for j=0:q-1
 +
      if j == 0
 +
  fau = v_zero;
 +
else
 +
  fau = w(j);
 +
      endif
 +
        if q > j
 +
  suma += power(teta(q,q-j),2) * fau;
 +
        endif
 +
      endfor
 +
      w(q) = asc_kow(x,0) - suma;
 +
    endfor
 +
 +
  endfor
 +
 +
  theta = teta;
 +
  v    = w';
 +
 +
endfunction
 +
</source>
 +
 +
; Przykład :
 +
Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces MA(2), z <math> \theta_1 = 0.5, \theta_2 = -0.3 </math> i wariancją <math> \sigma^2 = 0.3 </math>. Następnie proces ten poddajemy działaniu algorytmu innowacyjnego aż do ''q=5''. Widzimy, że oszacowanie parametrów wielomianu <math> \theta </math> dla pierwszych dwóch wartości różni się o kilka procent dla wszystkich ''q > 1'', natomiast oszacowane wielkości <math> \theta_3, ...,  \theta_5</math> są znikomo małe (maksymalnie 3% <math> \theta_1 </math> lub 4% <math> \theta_2 </math>) i dodanie ich do modelu nie zmieni w zasadzie niczego, dlatego można je odrzucić jako mało istotne. Wartość wariancji obliczona została na poziomie 81% wartości prawdziwej, <math> \theta_1 </math> na poziomie 62% a <math> \theta_2 </math> na poziomie 81%, dając
 +
* oryginalny model
 +
: <math> X_t = Z_t + 0.5 Z_{t-1} - 0.3 Z_{t-2}, \sigma^2 = 0.3 \ </math>
 +
* dopasowany model [dla asc_innovation(x, 2)]
 +
: <math> \hat{X}_t = \hat{Z}_t + 0.31128 \hat{Z}_{t-1} - 0.24571 \hat{Z}_{t-2}, \hat{\sigma}^2 = 0.36761 \ </math>
 +
 +
<source lang="Matlab">
 +
octave:90> x = arma_rnd([0], [0.5,-0.3], 0.3, 10000, 10000);
 +
octave:91> [theta, v] = asc_innovation(x,5)
 +
theta =
 +
 +
  0.25308  0.00000  0.00000  0.00000  0.00000
 +
  0.31128  -0.24571  0.00000  0.00000  0.00000
 +
  0.32776  -0.25557  0.01019  0.00000  0.00000
 +
  0.33206  -0.25853  0.01077  -0.00110  0.00000
 +
  0.33087  -0.25614  0.00534  0.00319  -0.01660
 +
 +
v =
 +
 +
  0.37838  0.36761  0.36478  0.36405  0.36442
 +
</source>
===ARMA===
===ARMA===
 +
Tak więc wiemy już jak szacować parametry procesów AR(p) i MA(q) w przypadkach gdy szeregi czasowe mogą być nimi opisane. Najbardziej jednak ogólną metodą szacowania parametrów modeli będzie znalezienie modelu ARMA(p,q) jako dopasowania do analizowanych danych. W przypadku gdy będziemy analizować np: dane AR(3) metodami dopasowywania do ARMA(p,q), powinniśmy z dobrym przybliżeniem dostać model ARMA(3,0).
====Rekurencyjny algorytm dopasowania ARMA====
====Rekurencyjny algorytm dopasowania ARMA====
 +
W tym przypadku zakładamy, że mamy do czynienia z przyczynowym procesem ARMA(p,q)
 +
: <math> X_t - \varphi_{1} X_{t-1} - \dots - \varphi_{p} X_{t-p} = Z_t + \hat{\theta_{1}} Z_{t-1} + \dots + \hat{\theta_{q}} Z_{t-q}, ~~\{ Z_t \} = BS(0,\sigma^2). \,</math>
 +
Przyczynowość zakłada, że
 +
: <math> X_t = \sum_{j=0}^\infty \Psi_j Z_{t-j}, \,</math>
 +
czyli, że
 +
: <math>
 +
\begin{align}
 +
\Psi_0 &= 1,\\
 +
\Psi_j &= \theta_j + \sum_{i=1}^{\min(j,p)} \varphi_i \Psi_j-i, ~~~j \ne 0.
 +
\end{align}
 +
</math>
 +
Oczywiście dla <math>j > q, \theta_j = 0</math> oraz dla <math> j>p, \varphi_j = 0 </math>. Aby obliczyć <math>\Psi_j </math> możemy użyć np: [[Analiza_Szeregów_Czasowych/Techniki_analizy_szeregów_czasowych#Algorytm_innowacyjny|algorytmu innowacyjnego]] a następnie podstawić <math>\Psi_i = \hat{\theta}_{mi}. , i=1,\dots,p+q</math>. Dostaniemy dzięki temu równanie
 +
: <math> \hat{\theta}_{mj} = \theta_j + \sum_{i=1}^{\min(j,p)} \varphi_i \hat{\theta}_{mj-i}, ~~~j=1,\dots,p+q. </math>
 +
Dzięki tej transformacji znaleźliśmy wstępnie oszacowane parametry <math> \hat{\bar{\varphi}} </math> i <math> \hat{\bar{\theta}} </math> (wektory parametrów modeli AR i MA). Jeżeli z powyższego równania odrzucimy część związaną z losową częścią średniej kroczącej i zostawimy parametry dla ''j = q + 1, ..., q + p'', to możemy łatwo zobaczyć, że spełnione będzie poniższe równanie na parametry wektora <math> \hat{\bar{\varphi}} </math>
 +
: <math>
 +
\begin{bmatrix} \hat{\theta}_{m,q} & \hat{\theta}_{m,q-1} & \hat{\theta}_{m,q-2} & \cdots & \hat{\theta}_{m,q+1-p} \\ \hat{\theta}_{m,q+1} & \hat{\theta}_{m,q} & \hat{\theta}_{m,q-1} & \cdots & \hat{\theta}_{m,q+2-p} \\  \hat{\theta}_{m,q+2} & \hat{\theta}_{m,q+1} & \hat{\theta}_{m,q} & \cdots & \hat{\theta}_{m,q+3-p} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ \hat{\theta}_{m,q+p-1} & \hat{\theta}_{m,q+p-2} & \hat{\theta}_{m,q+p-3} & \cdots & \hat{\theta}_{m,q} \end{bmatrix}
 +
\begin{bmatrix} \hat{\varphi}_{1} \\ \hat{\varphi}_{2} \\ \hat{\varphi}_{3} \\ \vdots \\ \hat{\varphi}_{p}\end{bmatrix} =
 +
\begin{bmatrix} \hat{\theta}_{m,q+1} \\ \hat{\theta}_{m,q+2} \\ \hat{\theta}_{m,q+3} \\ \vdots \\ \hat{\theta}_{m,q+p}\end{bmatrix}.
 +
</math>
-
====Estymacja modelem ''maximum Likelihood''====
+
Rozwiązując powyższe równanie macierzowe dostaniemy cały wektor <math> \hat{\bar{\varphi}} </math>, który następnie użyjemy do obliczenia
 +
: <math> \theta_j = \hat{\theta}_{mj} - \sum_{i=1}^{\min(j,p)} \varphi_i \hat{\theta}_{mj-i}, ~~~\mathbf{j=1,\dots,q}. </math>
 +
Na samym końcu znajdujemy oszacowanie wariancji procesu
 +
: <math> \hat{\sigma}^2 = \hat{v}_m. \,</math>
 +
 +
Jak zwykle prezentujemy program w języku MATLAB / GNU Octave implementujący powyższy algorytm. Poniższy algorytm odwołuje się do powyższej zaprezentowanego [[Analiza_Szeregów_Czasowych/Techniki_analizy_szeregów_czasowych#Algorytm_innowacyjny|algorytmu innowacyjnego]].
 +
 +
<source lang="matlab">
 +
function [phi, theta, v] = asc_armafit(x, p, q)
 +
 +
  if ( isempty (x) || (!isvector(x)) )
 +
    error ("armafit: pierwszy agrument musi byc niepustym wektorem");
 +
    return;
 +
  endif
 +
 +
  lx = length(x);
 +
 +
  if ( !isnumeric(p) || p < 0 || !isnumeric(p) || q < 0)
 +
    error ("armafit: drugi i trzeci argument musi byc liczba naturalna p,q >= 0\n");
 +
    return;
 +
  endif
 +
 +
  disp("armafit(x,p,q)");
 +
  p = p
 +
  q = q
 +
  disp("--------------");
 +
 +
  v    = [];
 +
  phi  = [];
 +
  theta = [];
 +
 +
  [preTheta, v] = asc_innovation(x,p+q);
 +
 
 +
  preTheta = preTheta(p+q,:);
 +
 +
  MpreTheta = [];
 +
  for i=1:p
 +
    for j=1:p
 +
      index = q + j - i;
 +
      if index < 1
 +
      localPreTheta = 0;
 +
      else
 +
      localPreTheta = preTheta(index);
 +
      endif
 +
      MpreTheta(i,j) = localPreTheta;
 +
    end
 +
  end
 +
 +
  phi = inv(MpreTheta) * preTheta(q+1:q+p)';
 +
 +
  suma = [];
 +
  for j = 1:q
 +
    suma(j) = 0;
 +
    for i = 1:min(j,p)
 +
      suma(j) += phi(i) * preTheta(j-i+1);
 +
    end
 +
  end
 +
  theta = preTheta(1:q) - suma;
 +
 +
  % oszacowanie
 +
  phi  = phi;
 +
  theta = theta';
 +
  v    = v(p+q);
 +
 +
endfunction
 +
</source>
 +
 +
; Przykład :
 +
Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces ARMA(2,1):
 +
: <math> X_t - 0.2 X_{t-1} - 0.1 X_{t-2} = Z_t + 0.3 Z_{t-1}, ~~~\sigma^2 = 0.1. \ </math>
 +
Następnie proces ten poddajemy działaniu powyższego algorytmu ''armafit''.
 +
Wartość wariancji obliczona została na poziomie 99% wartości prawdziwej, <math> \theta_1 </math> na poziomie 96%, <math> \varphi_1 </math> na poziomie 32% a <math> \varphi_2 </math>na poziomie 19% dając model
 +
* dopasowany model [dla asc_armafit(x, 2, 1)]
 +
: <math> X_t - 0.33490 X_{t-1} - 0.28179 X_{t-2} = Z_t + 0.26164 Z_{t-1}, ~~~\sigma^2 = 0.10983. \ </math>
 +
 +
<source lang="Matlab">
 +
octave:20> x = arma_rnd([0.2,0.1], [0.3], 0.1, 10000, 10000);
 +
octave:21> [phi, theta, v] = asc_armafit(x, 2, 1)
 +
armafit(x,p,q)
 +
p =  2
 +
q =  1
 +
--------------
 +
phi =
 +
 +
  0.33490
 +
  0.28179
 +
 +
theta =  0.26164
 +
v =  0.10983
 +
</source>
 +
 +
====Estymacja modelem maksimum wiarygodności====
 +
Zakładamy, że mamy do czynienia z przyczynowym procesem ARMA(p,q)
 +
: <math> X_t - \varphi_{1} X_{t-1} - \dots - \varphi_{p} X_{t-p} = Z_t + \hat{\theta_{1}} Z_{t-1} + \dots + \hat{\theta_{q}} Z_{t-q}, ~~\{ Z_t \} = BS(0,\sigma^2), \theta_0 = 1. \,</math>
 +
Przyczynowość zakłada, że dla <math> |u| \le 1 </math> część równania związana z procesem AR będzie niezerowa (<math> 1 + \varphi_{1} u - \dots - \varphi_{p} u^p \ne 0 </math>). Podobnie zakładamy z częścią odpowiedzialną za losowość w układzie dla <math> |u| < 1 </math>, <math> 1 + \theta_{1} u - \dots - \theta_{q} u^q \ne 0 </math> (czyli zakładamy zaszumienie układu).
 +
 +
Zadaniem naszym jest oszacować wektory <math> \hat{\bar{\varphi}} </math> i <math> \hat{\bar{\theta}} </math> oraz wariancję szumu metodą największej wiarygodności.
 +
Musimy zatem zmaksymalizować funkcję wiarygodności Gaussa daną poprzez
 +
 +
: <math> L(\hat{\bar{\varphi}}, \hat{\bar{\theta}}, \hat{\sigma}) = \frac{1}{\sqrt{(2 \pi \hat{\sigma}^2)^n r_0 \cdots r_{n-1}}} \exp \Big[ - \frac{\hat{\sigma}^2}{2} \sum_{j=1}^n  \frac{(X_j - \hat{X}_j)^2}{r_{j-1}}\Big].</math>
 +
 +
W powyższym wzorze
 +
* <math> \hat{X}_i </math> to jednokrokowe predyktory <math> X_i </math> obliczane po wstępnym szacowaniu parametrów modelu,
 +
* <math> r_i </math> - to ich odpowiednie średniokwadratowe błędy (szacowania).
 +
Predyktory te obliczamy z wzorów rekurencyjnych (patrz program ''asc_one_step_predictors'')
 +
: <math> \hat{X}_1 = 0, </math>
 +
: <math> \hat{X}_i = \sum_{j=1}^i \theta_{ij} (X_{i-j} - \hat{X}_{i-j}) , ~~~2 \le i < \max(p,q)</math>
 +
: <math> \hat{X}_i = \sum_{j=1}^p\varphi_{j} X_{i-j} + \sum_{j=1}^q \theta_{ij} (X_{i-j} - \hat{X}_{i-j}) , ~~~i \ge \max(p,q)</math>
 +
 +
Błędy ''r'' szacowane są z kolei za pomocą wzorów rekurencyjnych (pamiętając, że <math>\theta_{kj} = 0</math> dla ''j > q'' i danego ''k'')
 +
: <math> r_1 = 1, </math>
 +
: <math> r_k = 1 - \sum_{j=0}^{k-1} \theta^2_{k,k-j} r_j, k = 2, \dots, n.</math>
 +
 +
; Algorytm :
 +
# Wstępnie szacujemy wektory <math> \hat{\bar{\varphi}} </math> i <math> \hat{\bar{\theta}} </math> oraz wariancję szumu  dowolnym algorytmem (rekurencyjnym dla ARMA, czy innowacyjnym dla modelu losowego).
 +
# Obliczamy predyktory jednokrokowe i ich błędy dla konkretnych wartości <math> \hat{\bar{\varphi}}, \hat{\bar{\theta}}.</math>
 +
# Liczymy funkcję <math> S = \sum_{j=1}^n  \frac{(X_j - \hat{X}_j)^2}{r_{j-1}}. </math> Jest ona podstawą szacowania maksimum wiarygodności. Możemy teraz postąpić dwojako
 +
## Znajdujemy minimum funkcji kwadratów błędów S.
 +
## Znajdujemy minimum zredukowanej funkcji wiarygodności <math> l = \ln(S/n) + \sum_{j=1}^n \ln r_{j-1} / n. </math>
 +
# Mając parametry minimalizujące jedną z powyższych funkcji kończymy obliczając wariancję szumu z wzoru <math> \hat{\sigma}^2 = S / n </math> (dla minimalnej wartości danej statystyki.
 +
 +
Poniżej znajdziecie program obliczający predyktory jednokrokowe oraz realizujący powyższy algorytm znajdywania parametrów modelu w oparciu o minimalizację wybranej statystyki (''l'' lub ''S'').
 +
 +
<source lang="matlab">
 +
function [phi, theta, v, stat] = asc_armafit_likelihood(x, P, Q, method='likeli')
 +
 +
    if ( isempty (x) || (!isvector(x)) )
 +
    error ("armafit: pierwszy agrument musi byc niepustym wektorem");
 +
    return;
 +
  endif
 +
 +
  %dlugosc wektora
 +
  lx = length(x);
 +
 +
  if ( !isnumeric(P) || P < 0 || !isnumeric(Q) || Q < 0)
 +
    error ("armafit: drugi i trzeci argument musi byc liczba naturalna p,q >= 0\n");
 +
    return;
 +
  endif
 +
 +
  v    = [];
 +
  phi  = [];
 +
  theta = [];
 +
 
 +
  S_params = zeros(P * Q, P + Q);
 +
  S        = zeros(P*Q,1);
 +
  indexes  = zeros(P*Q,2);
 +
  for p = 1 : P
 +
    for q = 1 : Q
 +
      i = (p - 1) * Q + q;
 +
     
 +
      indexes(i,1:2) = [p,q];
 +
     
 +
      [phi_tmp, theta_tmp, v_tmp] = asc_armafit(x, p, q);
 +
      S_params(i, 1 : p + q) = [phi_tmp', theta_tmp'];
 +
     
 +
      [xbar, r] = asc_one_step_predictors(x, phi_tmp, theta_tmp);
 +
      S(i) = sum(power(x(2:end)' - xbar(2:end),2)./r(1:end-1));     
 +
    endfor
 +
  endfor
 +
 
 +
  if method == "square" 
 +
    stat = S;
 +
  else
 +
    stat = log(S / lx) + sum(log(r)) / lx;   
 +
  endif
 +
 +
  [S_value, S_index] = min(stat); 
 +
  v    = min(S) / lx;
 +
  phi  = S_params(S_index, 1 : indexes(S_index, 1));
 +
  theta = S_params(S_index, indexes(S_index,1) + 1 : indexes(S_index, 1) + indexes(S_index, 2));
 +
 +
endfunction
 +
</source>
 +
 +
<source lang="matlab">
 +
function [xbar, r] = asc_one_step_predictors(x, phi, theta)
 +
 +
    if ( isempty (x) || (!isvector(x)) )
 +
    error ("OSP: pierwszy agrument musi byc niepustym wektorem");
 +
    return;
 +
  endif
 +
 +
  %dlugosc wektora
 +
  lx = length(x);
 +
  q  = length(theta);
 +
  p  = length(phi);
 +
 
 +
  if ( !isvector(phi) || isempty(phi) || !isvector(theta) || isempty(theta))
 +
    error ("OSP: drugi i trzeci argument musi byc niepustym wektorem\n");
 +
    return;
 +
  endif
 +
 
 +
  xbar = zeros(1, lx);
 +
  r    = zeros(1, lx);
 +
  %m    = q;
 +
  m    = max(q,p); %TO DO & RETHINK!
 +
 
 +
  if q == m
 +
    vec = theta;
 +
  else
 +
    vec = phi;
 +
  endif
 +
 
 +
  % m pierwszych predyktorów
 +
  for i = 2 : m
 +
    suma = 0;
 +
    for j = 1 : i
 +
      suma += vec(j) * (x(i+1-j) - xbar(i+1-j));
 +
    endfor
 +
    xbar(i) = suma;
 +
  endfor
 +
 
 +
  % lx - m - 1 kolejnych predyktorów
 +
  for i = m + 1: lx
 +
    suma_phi  = 0;
 +
    for k = 1 : p
 +
      suma_phi += phi(k) * x(i + 1 - k);
 +
    endfor
 +
    suma_theta = 0;
 +
    for j = 1 : q
 +
      suma_theta += theta(j) * (x(i+1-j) - xbar(i+1-j));
 +
    endfor
 +
    xbar(i) = suma_phi + suma_theta;
 +
  endfor
 +
 
 +
  % wektor błędów predyktorów
 +
  r            = [];
 +
  theta_r      = zeros(1, lx);
 +
  theta_r(1:q) = theta;
 +
 
 +
  r(1) = 1;
 +
  for n = 2 : lx
 +
    suma_r = 0;
 +
    for j = 1 : n - 1
 +
      suma_r += power(theta_r(n-j),2) * r(j);
 +
    endfor
 +
    r(n) = 1 - suma_r;
 +
  endfor
 +
 
 +
endfunction
 +
</source>
 +
 +
<!--
==Testy==
==Testy==
===AICC===
===AICC===
-
 
==Prognoza==
==Prognoza==
 +
-->

Aktualna wersja na dzień 18:19, 27 maj 2013

Analiza Szeregów Czasowych
<<< Modelowanie szeregów czasowych | Matlab / GNU Octave >>>

Spis treści


Estymacja parametrów modeli

Szacowanie parametrów modeli rządzących szeregami czasowymi to niełatwe zagadnienie. Jest to również przedostatni krok w analizie szeregów czasowych. Ostatnim krokiem jest predykcja przyszłych wartości szeregu w oparciu o dane posiadane. ,

Aby oszacować jaki to model ARMA(p,q) stoi za analizowanym szeregiem czasowym musimy wykonać kilka kroków

  • jakie p i q należy wybrać
  • oszacować średnią oraz współczynniki AR \( \varphi_i \ \) oraz MA \( \theta_j \ \), i=1,...,p, j=1,...,q,
  • oszacować wariancję szumu \(\sigma^2 \ \) dla wybranych parametrów,
  • sprawdzić poprawność wybranego modelu (najlepiej dla różnych zestawów parametrów p i q).

Ostateczna decyzja, czy dany model dobrze reprezentuje dane zależy od kilku możliwych testów.

Zakładamy obecnie, że fitować będziemy model ARMA do danych których średnia wynosi 0

\( \langle X_t \rangle = EX_t = 0. \)

Jeżeli \( \{ Y_t \} \) oznacza oryginalne dane, to \( X_t = Y_t - EY_t \).

Będziemy dopasowywać dane do modelu

\( X_t - \varphi_1X_{t-1} - \dots - \varphi_p X_{t-p} = Z_t + \theta_1Z_{t-1} - \dots - \varphi_q Z_{t-q}, \{ Z_t \} = BS(0,\sigma^2) \ \)

Czyli dla wybranych przez na p i q celem będzie znalezienie wektorów \( \bar{\varphi} = (\varphi_1, \dots, \varphi_p) \) oraz \( \bar{\theta} = (\theta_1, \dots, \theta_q) \).

AR

W przypadku, gdy posiadane dane mogą być przybliżone poprzez model autoregresji rzędu p (tj: q = 0), dość dobrym estymatorem wektora \( \bar{\varphi} \) okazuje się być prosty algorytm porównujący autokowariancję próby oraz teoretyczną wyliczoną z modelu AR(p). Metoda ta nosi nazwę Yule-Walkera.

Metoda Yule-Walkera

Niech \( \{ X_t \} \ \) będzie procesem AR(p) o średniej zerowej

\( X_t - \varphi_1 X_{t-1} - \dots - \varphi_p X_{t-p} = Z_t, ~~Z_t \sim BS(0, \sigma^2). \)

Postaramy się teraz oszacować \( \bar{\varphi} \) oraz \( \sigma^2 \).

Korzystając z założenia, że \( \{ X_t \} \ \) jest losowy \( \big( X_t = \sum \Psi_j Z_{t-j} \ \big),\) otrzymujemy równania Yole - Walkera

\( \begin{align} \Gamma_p \bar{\varphi} &= \gamma_p \\ \sigma^2 &= \gamma(0) - \bar{\varphi}' \gamma_p \end{align} \)

gdzie

\( \Gamma_p = [\gamma(i-j)]_{i,j=1}^p \) - macierz kowariancji,
\( \gamma_p = (\gamma(1), \gamma(2), \dots, \gamma(p) )'. \)

Z równań tych możemy łatwo oszacować \( \gamma(0), \dots, \gamma(p) \) znając \( \sigma^2, \bar{\varphi} \). Z drugiej strony, jeżeli zamienimy występujące tutaj funkcje autokowariancji na odpowiednie funkcje autokowariancji próby otrzymamy estymatory Yule-Walkera

\( \begin{align} \hat{\Gamma}_p \hat{\varphi} &= \hat{\gamma}_p, \\ \hat{\sigma}^2 &= \hat{\gamma}(0) - \hat{\varphi}' \hat{\gamma}_p, \end{align} \)

gdzie odpowiednie

\( \hat{\Gamma}_p = [\hat{\gamma}(i-j)]_{i,j=1}^p \) - macierz kowariancji próby,
\( \hat{\gamma}_p = (\hat{\gamma}(1), \hat{\gamma}(2), \dots, \hat{\gamma}(p) )' \) - wektor kowariancji próby.

Jeżeli tylko \( \hat{\gamma}(0) > 0 \) to możemy podzielić obie strony przez \( \hat{\gamma}(0) \) i otrzymamy wtedy

\( \begin{align} \hat{\bar{\varphi}} &= \hat{R}^{-1}_p \hat{\rho}_p, \\ \hat{\sigma}^2 &= \hat{\gamma}(0) [1 - \hat{\rho'}_p \hat{R}^{-1}_p \hat{\rho}_p], \end{align} \)

gdzie

\( \hat{\rho}_p = (\hat{\rho}(1), \hat{\rho}(2), \dots, \hat{\rho}(p) )' = \hat{\gamma}_p/\hat{\gamma}(0)\) - wektor autokorelacji próby.

Z tak określonym \( \hat{\bar{\varphi}} \) można pokazać, że powyższy model jest losowy. Autokowariancje \( \gamma_F(h) \) fitowanego modelu powinny spełniać \[ \gamma_F(h) - \hat{\varphi}_1 \gamma_F(h-1) - \dots - \hat{\varphi}_p \gamma_F(h-p) = \left \{ {{\sigma^2, h = 0} \atop {0, h = 1,\dots, p}} \right. \] Każdej niesingularnej macierzy \( \Gamma_p \) odpowiada proces AR(p). Niestety nie możemy stwierdzić w ogólności tego samego dla procesu MA(q).

Generalnie (czyli teoretycznie) rząd p nie jest nam znany, gdy zaczynamy dopasowywać dane do modelu AR(p). Jeżeli założymy, że prawdziwym rzędem modelu jest rząd p a zamierzamy dopasować model rzędu m to powinniśmy oczekiwać, że oszacowany estymator \( \bar{\varphi}_m = \bar{\varphi}_{m1}, \bar{\varphi}_{m2}, \dots, \bar{\varphi}_{mm}) \) wykaże dla indeksów większych od p niskie wartości \( \bar{\varphi}_{mm}. \)

Algorytm Durbina - Levinsona

Wiemy jak wstępnie oszacować parametry metodą Yule-Walkera

\( X_t - \varphi_{m1} X_{t-1} - \dots - \varphi_{mp} X_{t-m} = Z_t, ~~Z_t \sim BS(0, \sigma^2). \)

z odpowiednimi

\( \hat{\varphi}_m = (\hat{\varphi}_{m1}, \dots, \hat{\varphi}_{mm}) = \hat{R}^{-1}_m \hat{\rho}_m \) - predyktory \( \varphi_i, \)
\( \hat{v}_m = \hat{\gamma}(0) [1 - \hat{\rho'}_p \hat{R}^{-1}_p \hat{\rho}_p]\) - predyktor \( \sigma^2. \)
Algorytm DL 
pozwala na sukcesywne obliczanie kolejnych rzędów procesu AR.

Jeżeli \( \hat{\gamma}(0) > 0 \) to dla m = 1, 2, ..., n-1 możemy rekursywnie dopasować model AR

\( \hat{\varphi}_{11} = \hat{\rho}(1),\ \)
\( \hat{v}_1 = \hat{\gamma}(0) [1 - \hat{\rho}^2(1)], \ \)
\( \hat{\varphi}_{mm} = [\hat{\gamma}(m) - \sum_{j=1}^{m-1} \hat{\varphi}_{m-1,j} \hat{\gamma}(m-j)] / \hat{v}_{m-1}, \)
\( \begin{bmatrix} \hat{\varphi}_{m1} \\ \vdots \\ \hat{\varphi}_{m,m-1}\end{bmatrix} = \hat{\bar{\varphi}}_{m-1} - \hat{\varphi}_{m,m} \begin{bmatrix} \hat{\varphi}_{m-1,m-1} \\ \vdots \\ \hat{\varphi}_{m-1,1}\end{bmatrix}, \)
\( \hat{v}_m = \hat{v}_{m-1} (1 - \hat{\varphi}^2_{mm}). \)
function [phi, v] = asc_durbin_levinson(x, p)
 
  if ( isempty (x) || (!isvector(x)) ) 
    error ("DL: pierwszy agrument musi byc niepustym wektorem");
    return;
  endif
 
  %dlugosc wektora
  lx = length(x);
 
  if ( !isnumeric(p) || p < 1)
    error ("DL: drugi argument musi byc liczba naturalna 0 < |h| <= dim(wektor)\n");
    return;
  endif
 
  %%%
  % algorytm Durbina - Levinsona
 
  fi = [];
  v  = [];
 
  % krok 0
  if (p == 1)
    p;
    phi = asc_kor(x,1);
    v   = asc_kow(x,0) * (1.0 - power(phi,2.0));
  else
    [fi, w] = asc_durbin_levinson(x, p - 1);
    p;
 
    suma = 0.0;
    for j=1:p-1
      suma += fi(p-1,j) * asc_kow(x,p-j);
    endfor
 
    fi(p, p) = (asc_kow(x,p) - suma) / w(p-1);
 
    for m=1:p-1
      fi(p,m) = fi(p-1,m) - fi(p,p)*fi(p-1,p-m);
    endfor
 
    w(p)     = w(p-1) * (1.0 - power(fi(p,p),2.0));
 
    phi = fi;
    v   = w;
  end
 
endfunction

Przy okazji, korzystając z powyższego algorytmu dostajemy funkcję autokorelacji częściowej próby \( \hat{\alpha}(m) = \hat{\varphi}_{mm} \). Wiemy, że dla modelu AR(p) dla wszystkich m > p mamy \( \alpha (m) = \varphi_{mm} = 0 \). Dodatkowo estymator \( \varphi_{mm} \) dla m > p ma z dobrym przybliżeniem rozkład normalny N(0,1/n), czyli - jeżeli model AR(p) jest dobrze dobrany to dla dostatecznie dużych m wartości \( \varphi_{mm} \) powinny się zgadzać z rozkładem normalnym N(0,1/n). W szczególności, jeżeli rząd AR jest równy p to \( \varphi_{mm} \) dla m > p powinno zawierać się w granicy 95% zgodności, czyli leżeć pomiędzy granicami \( \pm 1.96/\sqrt{n} \) z prawdopodobieństwem bliskim 0.95 (tylko 5% wartości może się nie zgadzać, czyli wypaść poza podane granice). Jeżeli tak jest w rzeczywistości to obliczony model AR(p) będzie dobrym oszacowaniem procesu losowego stojącego za danym szeregiem czasowym.

Przykład 
Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces AR(2), z \( \varphi_1 = 0.9, \varphi = -0.3 \) i wariancją \( \sigma^2 = 1 \). Następnie proces ten poddajemy działaniu algorytmu DL aż do p=5. Widzimy, że oszacowanie parametrów wielomianu \( \varphi \) dla pierwszych dwóch wartości różni się o kilka procent dla wszystkich p > 1, natomiast oszacowane wielkości \( \varphi_3, ..., \varphi_5\) są znikomo małe (maksymalnie 4% \( \varphi_1 \) lub 12% \( \varphi_2 \)) i dodanie ich do modelu nie zmieni w zasadzie niczego, dlatego można je odrzucić jako mało istotne. Wartość wariancji obliczona została na poziomie 99% wartości prawdziwej, \( \varphi_1 \) na poziomie 98% a \( \varphi_2 \) na poziomie mniejszym niż 1%, dając. Reasumując
  • oryginalny model
\( X_t - 0.9 X_{t-1} - 0.3 X_{t-2} = Z_t \ \)
  • dopasowany model [dla asc_durbin_levinson(x, 2)]
\( \hat{X}_t - 0.91710 \hat{X}_{t-1} - 0.30064 \hat{X}_{t-2} = \hat{Z}_t \ \)
octave:69> x = arma_rnd([0.9,-0.3], [0], 1, 10000, 10000);
octave:70> [phi, v] = asc_durbin_levinson(x, 5)
phi =
 
   0.70512   0.00000   0.00000   0.00000   0.00000
   0.91710  -0.30064   0.00000   0.00000   0.00000
   0.92346  -0.32003   0.02114   0.00000   0.00000
   0.92403  -0.32871   0.04618  -0.02712   0.00000
   0.92404  -0.32872   0.04625  -0.02732   0.00022
 
v =
 
   1.09071   0.99213   0.99169   0.99096   0.99096


MA

Dla przypadków, gdy q > 0 metoda zaprezentowana wcześniej nie do końca zdaje egzamin. W tym przypadku posługujemy się algorytmem innowacyjnym.

Tak samo, jak możemy dopasować modele AR do posiadanych szeregów stosując algorytm Durbina-Levinsona do sutokorelacji częściowych, w podobny sposób, możemy rekursywnie dopasowywać dane do procesów średniej kroczącej

\( X_t = Z_t + \hat{\theta_{m1}} Z_{t-1} + \dots + \hat{\theta_{mm}} Z_{t-m}, \{ Z_t \} = BS(0,\sigma^2), \,\)

dla m = 1,2,... używając algorytmu innowacyjnego.

Algorytm innowacyjny

Będziemy szacować wektor MA, czyli wektor \( \hat{\mathbf{\theta}}_m = (\hat{\theta}_{m1}, \dots, \hat{\theta}_{mm})', \,\) oraz wariancję procesu BS \( \hat{v}_m. \,\)

Algorytm 

Jeżeli \( \{ X_t \} \,\) ma średnią zerową oraz wartość oczekiwana korelatora \( E(X_iX_j) = \kappa(i,j) \) jest zdefiniowana przez niesingularną macierz kowariancji \([\kappa(i,j)]_{i,j=1}^n \,\) dla każdego n=1,2,... wtedy wartości \( \hat{X}_{n+1}, n \ge 0 \,\) oraz odpowiednie średnio-kwadratowe błędy \(v_n, n \ge 1 \,\) dane są poprzez równanie

\( \hat{X}_{n+1} = \left \{ {{0, n = 0} \atop {\sum_{j=0}^n \theta_{nj} (X_{n+1-j} - \hat{X}_{n+1-j}), n \ge 1}} \right. \)

a estymatory modelu liczymy rekurencyjnie z równań

\( \begin{align} v_0 &= \kappa(1,1), \\ \theta_{n,n-k} &= v_k^{-1} \Big( \kappa(n+1,k+1) - \sum_{j=0}^{k-1} \theta_{k,k-j} \theta_{n,n-j} v_j, ~~k=0,\dots,n-1\\ v_n &= \kappa(n+1,n+1) - \sum_{j=0}^{n-1} \theta^2_{n,n-j} v_j \end{align} \)

Poniżej prezentujemy skrypt Matlab / GNU Octave realizujący algorytm innowacyjny.

function [theta,v] = asc_innovation(x, qIn)
 
  if ( isempty (x) || (!isvector(x)) ) 
    error ("I: pierwszy agrument musi byc niepustym wektorem");
    return;
  endif
 
  %dlugosc wektora
  lx = length(x);
 
  if ( !isnumeric(qIn) || qIn < 1)
    error ("I: drugi argument musi byc liczba naturalna q > 0\n");
    return;
  endif
 
  %%%
  % algorytm innowacyjny
 
  %%%
  % pracujemy na wektorach
  w    = [];
  teta = [];
 
  %%%
  % wartości startowe
  % dla v(1) i theta(1,1)
  v_zero = asc_kow(x,0);
  w 	 = v_zero;
  teta   = asc_kor(x,1);
 
  %%%
  % właściwy algorytm innowacyjny
  for q = 1 : qIn   % dla rzedu = MA(1)...MA(q)
 
    %%%
    % kolejne wartości \theta_{q,q-k}
    for k=0:q-1
      suma = 0;
      for j=0:k-1
      	if k > j
	  suma += teta(q,q-j) * teta(k,k-j) * w(j+1);
      	endif
      endfor
      teta(q,q-k) = (asc_kow(x,q-k) - suma) / w(k+1);
 
      %%%
      % kolejne wartości v_q
      suma = 0;
      for j=0:q-1
      	if j == 0
	  fau = v_zero; 
	else
	  fau = w(j);
      	endif
        if q > j
	  suma += power(teta(q,q-j),2) * fau;
        endif
      endfor
      w(q) = asc_kow(x,0) - suma;
    endfor 
 
  endfor 
 
  theta = teta;
  v     = w';
 
endfunction
Przykład 

Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces MA(2), z \( \theta_1 = 0.5, \theta_2 = -0.3 \) i wariancją \( \sigma^2 = 0.3 \). Następnie proces ten poddajemy działaniu algorytmu innowacyjnego aż do q=5. Widzimy, że oszacowanie parametrów wielomianu \( \theta \) dla pierwszych dwóch wartości różni się o kilka procent dla wszystkich q > 1, natomiast oszacowane wielkości \( \theta_3, ..., \theta_5\) są znikomo małe (maksymalnie 3% \( \theta_1 \) lub 4% \( \theta_2 \)) i dodanie ich do modelu nie zmieni w zasadzie niczego, dlatego można je odrzucić jako mało istotne. Wartość wariancji obliczona została na poziomie 81% wartości prawdziwej, \( \theta_1 \) na poziomie 62% a \( \theta_2 \) na poziomie 81%, dając

  • oryginalny model
\( X_t = Z_t + 0.5 Z_{t-1} - 0.3 Z_{t-2}, \sigma^2 = 0.3 \ \)
  • dopasowany model [dla asc_innovation(x, 2)]
\( \hat{X}_t = \hat{Z}_t + 0.31128 \hat{Z}_{t-1} - 0.24571 \hat{Z}_{t-2}, \hat{\sigma}^2 = 0.36761 \ \)
octave:90> x = arma_rnd([0], [0.5,-0.3], 0.3, 10000, 10000);
octave:91> [theta, v] = asc_innovation(x,5)
theta =
 
   0.25308   0.00000   0.00000   0.00000   0.00000
   0.31128  -0.24571   0.00000   0.00000   0.00000
   0.32776  -0.25557   0.01019   0.00000   0.00000
   0.33206  -0.25853   0.01077  -0.00110   0.00000
   0.33087  -0.25614   0.00534   0.00319  -0.01660
 
v =
 
   0.37838   0.36761   0.36478   0.36405   0.36442

ARMA

Tak więc wiemy już jak szacować parametry procesów AR(p) i MA(q) w przypadkach gdy szeregi czasowe mogą być nimi opisane. Najbardziej jednak ogólną metodą szacowania parametrów modeli będzie znalezienie modelu ARMA(p,q) jako dopasowania do analizowanych danych. W przypadku gdy będziemy analizować np: dane AR(3) metodami dopasowywania do ARMA(p,q), powinniśmy z dobrym przybliżeniem dostać model ARMA(3,0).

Rekurencyjny algorytm dopasowania ARMA

W tym przypadku zakładamy, że mamy do czynienia z przyczynowym procesem ARMA(p,q)

\( X_t - \varphi_{1} X_{t-1} - \dots - \varphi_{p} X_{t-p} = Z_t + \hat{\theta_{1}} Z_{t-1} + \dots + \hat{\theta_{q}} Z_{t-q}, ~~\{ Z_t \} = BS(0,\sigma^2). \,\)

Przyczynowość zakłada, że

\( X_t = \sum_{j=0}^\infty \Psi_j Z_{t-j}, \,\)

czyli, że

\( \begin{align} \Psi_0 &= 1,\\ \Psi_j &= \theta_j + \sum_{i=1}^{\min(j,p)} \varphi_i \Psi_j-i, ~~~j \ne 0. \end{align} \)

Oczywiście dla \(j > q, \theta_j = 0\) oraz dla \( j>p, \varphi_j = 0 \). Aby obliczyć \(\Psi_j \) możemy użyć np: algorytmu innowacyjnego a następnie podstawić \(\Psi_i = \hat{\theta}_{mi}. , i=1,\dots,p+q\). Dostaniemy dzięki temu równanie

\( \hat{\theta}_{mj} = \theta_j + \sum_{i=1}^{\min(j,p)} \varphi_i \hat{\theta}_{mj-i}, ~~~j=1,\dots,p+q. \)

Dzięki tej transformacji znaleźliśmy wstępnie oszacowane parametry \( \hat{\bar{\varphi}} \) i \( \hat{\bar{\theta}} \) (wektory parametrów modeli AR i MA). Jeżeli z powyższego równania odrzucimy część związaną z losową częścią średniej kroczącej i zostawimy parametry dla j = q + 1, ..., q + p, to możemy łatwo zobaczyć, że spełnione będzie poniższe równanie na parametry wektora \( \hat{\bar{\varphi}} \)

\( \begin{bmatrix} \hat{\theta}_{m,q} & \hat{\theta}_{m,q-1} & \hat{\theta}_{m,q-2} & \cdots & \hat{\theta}_{m,q+1-p} \\ \hat{\theta}_{m,q+1} & \hat{\theta}_{m,q} & \hat{\theta}_{m,q-1} & \cdots & \hat{\theta}_{m,q+2-p} \\ \hat{\theta}_{m,q+2} & \hat{\theta}_{m,q+1} & \hat{\theta}_{m,q} & \cdots & \hat{\theta}_{m,q+3-p} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ \hat{\theta}_{m,q+p-1} & \hat{\theta}_{m,q+p-2} & \hat{\theta}_{m,q+p-3} & \cdots & \hat{\theta}_{m,q} \end{bmatrix} \begin{bmatrix} \hat{\varphi}_{1} \\ \hat{\varphi}_{2} \\ \hat{\varphi}_{3} \\ \vdots \\ \hat{\varphi}_{p}\end{bmatrix} = \begin{bmatrix} \hat{\theta}_{m,q+1} \\ \hat{\theta}_{m,q+2} \\ \hat{\theta}_{m,q+3} \\ \vdots \\ \hat{\theta}_{m,q+p}\end{bmatrix}. \)

Rozwiązując powyższe równanie macierzowe dostaniemy cały wektor \( \hat{\bar{\varphi}} \), który następnie użyjemy do obliczenia

\( \theta_j = \hat{\theta}_{mj} - \sum_{i=1}^{\min(j,p)} \varphi_i \hat{\theta}_{mj-i}, ~~~\mathbf{j=1,\dots,q}. \)

Na samym końcu znajdujemy oszacowanie wariancji procesu

\( \hat{\sigma}^2 = \hat{v}_m. \,\)

Jak zwykle prezentujemy program w języku MATLAB / GNU Octave implementujący powyższy algorytm. Poniższy algorytm odwołuje się do powyższej zaprezentowanego algorytmu innowacyjnego.

function [phi, theta, v] = asc_armafit(x, p, q)
 
  if ( isempty (x) || (!isvector(x)) ) 
    error ("armafit: pierwszy agrument musi byc niepustym wektorem");
    return;
  endif
 
  lx = length(x);
 
  if ( !isnumeric(p) || p < 0 || !isnumeric(p) || q < 0)
    error ("armafit: drugi i trzeci argument musi byc liczba naturalna p,q >= 0\n");
    return;
  endif
 
  disp("armafit(x,p,q)");
  p = p
  q = q
  disp("--------------");
 
  v     = [];
  phi   = [];
  theta = [];
 
  [preTheta, v] = asc_innovation(x,p+q);
 
  preTheta = preTheta(p+q,:);
 
  MpreTheta = [];
  for i=1:p
    for j=1:p
      index = q + j - i;
      if index < 1
	      localPreTheta = 0;
      else
	      localPreTheta = preTheta(index);
      endif
      MpreTheta(i,j) = localPreTheta;
    end
  end
 
  phi = inv(MpreTheta) * preTheta(q+1:q+p)';
 
  suma = [];
  for j = 1:q
    suma(j) = 0;
    for i = 1:min(j,p)
      suma(j) += phi(i) * preTheta(j-i+1);
    end
  end
  theta = preTheta(1:q) - suma;
 
  % oszacowanie
  phi   = phi;
  theta = theta';
  v     = v(p+q);
 
endfunction
Przykład 

Poniżej prezentujemy przykład użycia powyższego algorytmu do dopasowania sztucznych danych. Generujemy proces ARMA(2,1):

\( X_t - 0.2 X_{t-1} - 0.1 X_{t-2} = Z_t + 0.3 Z_{t-1}, ~~~\sigma^2 = 0.1. \ \)

Następnie proces ten poddajemy działaniu powyższego algorytmu armafit. Wartość wariancji obliczona została na poziomie 99% wartości prawdziwej, \( \theta_1 \) na poziomie 96%, \( \varphi_1 \) na poziomie 32% a \( \varphi_2 \)na poziomie 19% dając model

  • dopasowany model [dla asc_armafit(x, 2, 1)]
\( X_t - 0.33490 X_{t-1} - 0.28179 X_{t-2} = Z_t + 0.26164 Z_{t-1}, ~~~\sigma^2 = 0.10983. \ \)
octave:20> x = arma_rnd([0.2,0.1], [0.3], 0.1, 10000, 10000);
octave:21> [phi, theta, v] = asc_armafit(x, 2, 1)
armafit(x,p,q)
p =  2
q =  1
--------------
phi =
 
   0.33490
   0.28179
 
theta =  0.26164
v =  0.10983

Estymacja modelem maksimum wiarygodności

Zakładamy, że mamy do czynienia z przyczynowym procesem ARMA(p,q)

\( X_t - \varphi_{1} X_{t-1} - \dots - \varphi_{p} X_{t-p} = Z_t + \hat{\theta_{1}} Z_{t-1} + \dots + \hat{\theta_{q}} Z_{t-q}, ~~\{ Z_t \} = BS(0,\sigma^2), \theta_0 = 1. \,\)

Przyczynowość zakłada, że dla \( |u| \le 1 \) część równania związana z procesem AR będzie niezerowa (\( 1 + \varphi_{1} u - \dots - \varphi_{p} u^p \ne 0 \)). Podobnie zakładamy z częścią odpowiedzialną za losowość w układzie dla \( |u| < 1 \), \( 1 + \theta_{1} u - \dots - \theta_{q} u^q \ne 0 \) (czyli zakładamy zaszumienie układu).

Zadaniem naszym jest oszacować wektory \( \hat{\bar{\varphi}} \) i \( \hat{\bar{\theta}} \) oraz wariancję szumu metodą największej wiarygodności. Musimy zatem zmaksymalizować funkcję wiarygodności Gaussa daną poprzez

\( L(\hat{\bar{\varphi}}, \hat{\bar{\theta}}, \hat{\sigma}) = \frac{1}{\sqrt{(2 \pi \hat{\sigma}^2)^n r_0 \cdots r_{n-1}}} \exp \Big[ - \frac{\hat{\sigma}^2}{2} \sum_{j=1}^n \frac{(X_j - \hat{X}_j)^2}{r_{j-1}}\Big].\)

W powyższym wzorze

  • \( \hat{X}_i \) to jednokrokowe predyktory \( X_i \) obliczane po wstępnym szacowaniu parametrów modelu,
  • \( r_i \) - to ich odpowiednie średniokwadratowe błędy (szacowania).

Predyktory te obliczamy z wzorów rekurencyjnych (patrz program asc_one_step_predictors)

\( \hat{X}_1 = 0, \)
\( \hat{X}_i = \sum_{j=1}^i \theta_{ij} (X_{i-j} - \hat{X}_{i-j}) , ~~~2 \le i < \max(p,q)\)
\( \hat{X}_i = \sum_{j=1}^p\varphi_{j} X_{i-j} + \sum_{j=1}^q \theta_{ij} (X_{i-j} - \hat{X}_{i-j}) , ~~~i \ge \max(p,q)\)

Błędy r szacowane są z kolei za pomocą wzorów rekurencyjnych (pamiętając, że \(\theta_{kj} = 0\) dla j > q i danego k)

\( r_1 = 1, \)
\( r_k = 1 - \sum_{j=0}^{k-1} \theta^2_{k,k-j} r_j, k = 2, \dots, n.\)
Algorytm 
  1. Wstępnie szacujemy wektory \( \hat{\bar{\varphi}} \) i \( \hat{\bar{\theta}} \) oraz wariancję szumu dowolnym algorytmem (rekurencyjnym dla ARMA, czy innowacyjnym dla modelu losowego).
  2. Obliczamy predyktory jednokrokowe i ich błędy dla konkretnych wartości \( \hat{\bar{\varphi}}, \hat{\bar{\theta}}.\)
  3. Liczymy funkcję \( S = \sum_{j=1}^n \frac{(X_j - \hat{X}_j)^2}{r_{j-1}}. \) Jest ona podstawą szacowania maksimum wiarygodności. Możemy teraz postąpić dwojako
    1. Znajdujemy minimum funkcji kwadratów błędów S.
    2. Znajdujemy minimum zredukowanej funkcji wiarygodności \( l = \ln(S/n) + \sum_{j=1}^n \ln r_{j-1} / n. \)
  4. Mając parametry minimalizujące jedną z powyższych funkcji kończymy obliczając wariancję szumu z wzoru \( \hat{\sigma}^2 = S / n \) (dla minimalnej wartości danej statystyki.

Poniżej znajdziecie program obliczający predyktory jednokrokowe oraz realizujący powyższy algorytm znajdywania parametrów modelu w oparciu o minimalizację wybranej statystyki (l lub S).

function [phi, theta, v, stat] = asc_armafit_likelihood(x, P, Q, method='likeli')
 
    if ( isempty (x) || (!isvector(x)) ) 
    error ("armafit: pierwszy agrument musi byc niepustym wektorem");
    return;
  endif
 
  %dlugosc wektora
  lx = length(x);
 
  if ( !isnumeric(P) || P < 0 || !isnumeric(Q) || Q < 0)
    error ("armafit: drugi i trzeci argument musi byc liczba naturalna p,q >= 0\n");
    return;
  endif
 
  v     = [];
  phi   = [];
  theta = [];
 
  S_params = zeros(P * Q, P + Q);
  S        = zeros(P*Q,1);
  indexes  = zeros(P*Q,2);
  for p = 1 : P
    for q = 1 : Q
      i = (p - 1) * Q + q;
 
      indexes(i,1:2) = [p,q];
 
      [phi_tmp, theta_tmp, v_tmp] = asc_armafit(x, p, q);
      S_params(i, 1 : p + q) = [phi_tmp', theta_tmp'];
 
      [xbar, r] = asc_one_step_predictors(x, phi_tmp, theta_tmp);
      S(i) = sum(power(x(2:end)' - xbar(2:end),2)./r(1:end-1));      
    endfor
  endfor
 
  if method == "square"   
    stat = S;
  else
    stat = log(S / lx) + sum(log(r)) / lx;    
  endif
 
  [S_value, S_index] = min(stat);  
  v     = min(S) / lx;
  phi   = S_params(S_index, 1 : indexes(S_index, 1));
  theta = S_params(S_index, indexes(S_index,1) + 1 : indexes(S_index, 1) + indexes(S_index, 2));
 
endfunction
function [xbar, r] = asc_one_step_predictors(x, phi, theta)
 
    if ( isempty (x) || (!isvector(x)) ) 
    error ("OSP: pierwszy agrument musi byc niepustym wektorem");
    return;
  endif
 
  %dlugosc wektora
  lx = length(x);
  q  = length(theta);
  p  = length(phi);
 
  if ( !isvector(phi) || isempty(phi) || !isvector(theta) || isempty(theta))
    error ("OSP: drugi i trzeci argument musi byc niepustym wektorem\n");
    return;
  endif
 
  xbar = zeros(1, lx);
  r    = zeros(1, lx);
  %m    = q;
  m    = max(q,p); %TO DO & RETHINK!
 
  if q == m
    vec = theta;
  else
    vec = phi;
  endif
 
  % m pierwszych predyktorów
  for i = 2 : m
    suma = 0;
    for j = 1 : i
      suma += vec(j) * (x(i+1-j) - xbar(i+1-j));
    endfor
    xbar(i) = suma;
  endfor
 
  % lx - m - 1 kolejnych predyktorów
  for i = m + 1: lx
    suma_phi   = 0;
    for k = 1 : p
      suma_phi += phi(k) * x(i + 1 - k);
    endfor
    suma_theta = 0;
    for j = 1 : q
      suma_theta += theta(j) * (x(i+1-j) - xbar(i+1-j));
    endfor 
    xbar(i) = suma_phi + suma_theta;
  endfor
 
  % wektor błędów predyktorów
  r            = [];
  theta_r      = zeros(1, lx);
  theta_r(1:q) = theta;
 
  r(1) = 1;
  for n = 2 : lx
    suma_r = 0;
    for j = 1 : n - 1
      suma_r += power(theta_r(n-j),2) * r(j);
    endfor
    r(n) = 1 - suma_r;
  endfor
 
endfunction