Ćwiczenia 5: Różnice pomiędzy wersjami
m (cofnięcie testu) |
|||
(Nie pokazano 25 wersji utworzonych przez 2 użytkowników) | |||
Linia 1: | Linia 1: | ||
− | == | + | [[Analiza_sygnałów_-_ćwiczenia]]/AR_2 |
− | === | + | |
+ | = Notebook= | ||
+ | Proszę pobrać i zapisać lkoalnie notebook: | ||
+ | [https://drive.google.com/file/d/0BzwQ_Lscn8yDOG1icFRTeGMyRTQ/view?usp=sharing Ipython notebook z ćwiczeniami z modeli AR ] | ||
+ | |||
+ | |||
+ | następnie w terminalu, w katalogu zawierającym notebook piszemy: | ||
+ | > jupyter notebook | ||
+ | |||
+ | gdzie notebook to nazwa pobranego właśnie pliku | ||
+ | |||
+ | ==Procesy AR== | ||
+ | Dla przypomnienia: | ||
+ | proces AR generowany jest tak, że kolejna próbka jest ważoną sumą <math>p</math> poprzednich próbek i niezależnej zmiennej losowej o średniej 0 i wariancji <math>\sigma^2</math>: | ||
+ | ::<math>x_n = \sum_{k=1}^p a_k * x_{n-k} +\varepsilon_n</math> | ||
+ | ::i <math>\varepsilon_n \sim N(0,\sigma^2)</math> | ||
+ | |||
+ | |||
+ | Proces AR można zatem scharakteryzować podając: | ||
+ | * współczynniki <math>a</math> oraz | ||
+ | * <math>\sigma^2</math>. | ||
+ | |||
+ | |||
+ | |||
+ | ===Zadanie: ilustracja realizacji procesu === | ||
+ | Poniższy kod po uzupełnieniu będzie ilustrował jak mogą wyglądać pojedyncze realizacje procesu opisywanego przez współczynniki a=[0.9, -0.7] i wariancję 1. | ||
+ | <source lang = python> | ||
+ | ...# stosowne importy | ||
+ | |||
+ | def realizacjaAR(a,sigma, N): | ||
+ | x = np.zeros(N) | ||
+ | for i in range(2,N): #kolejno tworzymy próbki w każdej realizacji | ||
+ | x[i]=a[0]*x[i-1]+a[1]*x[i-2]+ ... | ||
+ | return x | ||
+ | |||
+ | a = np.array([0.9, -0.7]) | ||
+ | sigma = 1 | ||
+ | N_realizacji = 5 # liczba realizacji | ||
+ | N=500 #liczba punktów w realizacji | ||
+ | |||
+ | realizacja = np.zeros((N_realizacji, N)); # macierz na wszystkie realizacje | ||
+ | for r in range(0,N_realizacji): #generujemy realizacje procesu | ||
+ | realizacja[r,:] = ... | ||
+ | |||
+ | for r in range(0,N_realizacji): #rysujemy realizacje procesu | ||
+ | py.subplot(5,1,r+1) | ||
+ | py.plot( ...) | ||
+ | py.title('realizacja'+str(r)) | ||
+ | py.show() | ||
+ | </source> | ||
+ | |||
+ | ===Zadanie: ilustracja funkcji autokorelacji procesu === | ||
+ | Dla współczynników <math>a</math>, dla których proces ten jest stacjonarny, charakteryzuje się też pewną konkretną funkcją autokorelacji. | ||
+ | Poniższe ćwiczenie powinno nam uświadomić: | ||
+ | * jak może wyglądać estymowana funkcja autokorelacji dla realizacji procesu AR | ||
+ | * jak estymata funkcji autokorelacji zależy od długości realizacji (czyli od ilości dostępnych informacji). Co dzieje się z funkcją autokorelacji dla poszczególnych realizacji, gdy zwiększamy liczbę punktów w realizacji '''N''' od 50 do 5000? | ||
+ | Poniższy kod powinien stanowić kontynuację poprzedniego. | ||
+ | <source lang = python> | ||
+ | for r in range(0,N_realizacji): #rysujemy funkcję autokorelacji poszczególnych realizacji | ||
+ | f_corr =... | ||
+ | tau = np.arange(-N+1,N,1) | ||
+ | ind = range(...-10,...+10) # tu szykujemy indeksy, dzięki którym będziemy mogli pobrać wycinek +/- 10 próbek wokół przesunięcia 0 | ||
+ | py.plot(tau[ind],f_corr[ind]) | ||
+ | py.title(fragment funkcji autokorelacji) | ||
+ | py.show() | ||
+ | </source> | ||
+ | <!-- | ||
Proces autoregresyjny rzędu <math>p</math> jest zdefiniowany jako: | Proces autoregresyjny rzędu <math>p</math> jest zdefiniowany jako: | ||
::<math>x_t = \sum _{i=1}^p a_i x_{t-i} +\epsilon _t</math> | ::<math>x_t = \sum _{i=1}^p a_i x_{t-i} +\epsilon _t</math> | ||
Linia 25: | Linia 91: | ||
py.show() | py.show() | ||
</source> | </source> | ||
+ | --> | ||
+ | |||
+ | ==Model AR== | ||
+ | Rozważania na temat procesów AR są o tyle interesujące, że wiele sygnałów, które chcielibyśmy badać całkiem nieźle daje się opisać jako procesy AR . | ||
+ | Wyobrażamy sobie wówczas, że rejestrowane sygnały są generowane przez pewien model AR (trochę tak jak funkcja realizacjaAR wytwarzała pojedyncze realizacje procesu). Pojawia się w tym momencie pytanie: jak możemy poznać wartości parametrów <math>a</math> i <math>\sigma^2</math>, które ''pasują'' do badanych sygnałów? | ||
===Estymacja parametrów=== | ===Estymacja parametrów=== | ||
− | |||
Algorytmów służących do estymacji parametrów modelu AR jest kilka. Tu przedstawimy algorytm Yule-Walker'a: | Algorytmów służących do estymacji parametrów modelu AR jest kilka. Tu przedstawimy algorytm Yule-Walker'a: | ||
* mnożymy stronami równania opisujące proces dla póbki <math>t</math> i <math>t-m</math> | * mnożymy stronami równania opisujące proces dla póbki <math>t</math> i <math>t-m</math> | ||
Linia 60: | Linia 130: | ||
* Wygeneruj 2000 próbek sygnału z modelu AR o parametrach a = {0.9, -0.6}, epsilon=2 | * Wygeneruj 2000 próbek sygnału z modelu AR o parametrach a = {0.9, -0.6}, epsilon=2 | ||
* Oblicz funkcję autokorelacji tego sygnału: <tt>ak = np.correlate(x,x,mode='full')</tt> | * Oblicz funkcję autokorelacji tego sygnału: <tt>ak = np.correlate(x,x,mode='full')</tt> | ||
− | * Znormalizuj tą funkcję dzieląc ją przez | + | * Znormalizuj tą funkcję dzieląc ją przez liczbę pokrywających się próbek dla każdego przesunięcia <math>\tau</math> |
− | * Oblicz parametry zgodnie ze wzorami z poprzedniego paragrafu dla modelu rzędu 2. (wypisz konkretną postać wzorów | + | * Oblicz parametry zgodnie ze wzorami z poprzedniego paragrafu dla modelu rzędu 2. (wypisz konkretną postać wzorów analitycznych a następnie zaimplementuj je) |
− | |||
* Wypisz parametry prawdziwe i estymowane. | * Wypisz parametry prawdziwe i estymowane. | ||
* Sprawdź jak wpływa długość sygnału na dokładność estymaty (uruchom program kilka razy dla każdej z badanych długości sygnału) | * Sprawdź jak wpływa długość sygnału na dokładność estymaty (uruchom program kilka razy dla każdej z badanych długości sygnału) | ||
− | + | wskazówka: <tt>R[0]=ak[N-1]</tt> | |
<!-- | <!-- | ||
<source lang = python> | <source lang = python> | ||
Linia 114: | Linia 183: | ||
--> | --> | ||
+ | <source lang = python> | ||
+ | #wspolczynniki modelu AR | ||
+ | a = np.array([0.9, -0.6]) | ||
+ | sigma = 2 | ||
+ | N = 200 | ||
+ | x = np.zeros(N); | ||
+ | |||
+ | #generujemy realizacje procesu | ||
+ | for i in range(2,N): | ||
+ | x[i] = a[0]*x[i-1] + a[1]*x[i-...] + ... | ||
+ | |||
+ | py.subplot(2,1,1) | ||
+ | py.plot(x) | ||
+ | py.xlabel('numer próbki') | ||
+ | py.title('wygenerowany sygnal') | ||
+ | |||
+ | py.subplot(2,1,2) | ||
+ | ak = np.correlate(x,x,mode='full') | ||
+ | # ak nieobciążona: | ||
+ | norm_ak = ... | ||
+ | ak /= norm_ak | ||
+ | m = ... # przesunięcia | ||
+ | py.plot(m, ak) | ||
+ | py.xlabel('przesunięcie m') | ||
+ | py.title('funkcja autokorelacij sygnalu x') | ||
+ | |||
+ | R=ak[N-1:] | ||
+ | r0=R[0] | ||
+ | r1=R[1] | ||
+ | r2=R[2] | ||
+ | |||
+ | # estymujemy wspolczynniki modelu na podstawie funkncji autokorelacji | ||
+ | |||
+ | a2 = ... | ||
+ | a1 = ... | ||
+ | s_2 = ... | ||
+ | |||
+ | print('prawdziwe wspolczynniki') | ||
+ | print( a[0], a[1], sigma) | ||
+ | print('estymowane wspolczynniki') | ||
+ | print( '%.3f, %.3f, %.3f'%(a1, a2, s_2**0.5)) | ||
+ | |||
+ | py.show() | ||
+ | </source> | ||
+ | ===Estymacja parametrów dla modelu rzędu p === | ||
W przypadku modelu rzędu <math>p</math> estymację parametrów metodą Y-W można zaimplementować np. tak: | W przypadku modelu rzędu <math>p</math> estymację parametrów metodą Y-W można zaimplementować np. tak: | ||
<source lang = python> | <source lang = python> | ||
Linia 129: | Linia 243: | ||
N = len(x) | N = len(x) | ||
ak = np.correlate(x,x,mode='full') | ak = np.correlate(x,x,mode='full') | ||
− | ak=ak/ | + | norm_ak = np.hstack((np.arange(1,N+1,1),np.arange(N-1,0,-1))) |
+ | ak=ak/norm_ak | ||
R=ak[N-1:] | R=ak[N-1:] | ||
RL = R[1:1+p] | RL = R[1:1+p] | ||
Linia 137: | Linia 252: | ||
RP[i,:] = aa | RP[i,:] = aa | ||
a=np.linalg.solve(RP,RL) | a=np.linalg.solve(RP,RL) | ||
− | + | sigma = (ak[N-1] - np.sum(a*ak[N:N+p]))**0.5 | |
− | return a, | + | return a, sigma |
</source> | </source> | ||
Linia 147: | Linia 262: | ||
::<math>\mathrm{AIC}(p)= \frac{2p}{N} +\ln(V) </math> | ::<math>\mathrm{AIC}(p)= \frac{2p}{N} +\ln(V) </math> | ||
− | <math>p</math> - | + | <math>p</math> - liczba parametrów modelu, |
− | <math>N</math> - | + | <math>N</math> - liczba próbek sygnału, |
<math>V</math> - wariancja szumu. | <math>V</math> - wariancja szumu. | ||
Linia 163: | Linia 278: | ||
AIC = np.zeros(len(zakres_rzedow)) | AIC = np.zeros(len(zakres_rzedow)) | ||
for p in zakres_rzedow: | for p in zakres_rzedow: | ||
− | a, | + | a,sigma = parametryAR(x,p) |
− | AIC[p-1] = (2.0*p)/N + np.log(np.sqrt( | + | AIC[p-1] = (2.0*p)/N + np.log(np.sqrt(sigma)) |
− | print 'p:', p, ' a:',a,' | + | print 'p:', p, ' a:',a,' sigma: ',sigma |
return AIC | return AIC | ||
</source> | </source> | ||
− | Zobaczmy jak działa to na przykładowym | + | Zobaczmy jak działa to na przykładowym sygnale AR: |
<source lang = python> | <source lang = python> | ||
import numpy as np | import numpy as np | ||
Linia 282: | Linia 397: | ||
===Widmo procesu=== | ===Widmo procesu=== | ||
− | Najpierw rozważmy konkretny przykład. Niech model będzie rzędu ''p=2'' i ma współczynniki <math>a_1 = 0.9, a_2 = -0.6</math> i <math>\varepsilon = 2</math>. Wyliczamy wartości funkcji <math>A(z) = a_1 z^{-1}+a_2 z^{-2}</math> dla <math>z = e^{i \omega}</math>: | + | Najpierw rozważmy konkretny przykład. Niech model będzie rzędu ''p=2'' i ma współczynniki <math>a_1 = 0.9, a_2 = -0.6</math> i <math>\sigma_{\varepsilon} = 2</math>. Wyliczamy wartości funkcji <math>A(z) = a_1 z^{-1}+a_2 z^{-2}</math> dla <math>z = e^{i \omega}</math>: |
<source lang = python> | <source lang = python> | ||
a=[0.9, -0.6] | a=[0.9, -0.6] | ||
− | + | sigma_eps = 2 | |
w=np.arange(-np.pi,np.pi,0.1) | w=np.arange(-np.pi,np.pi,0.1) | ||
z=np.exp(1j*w) | z=np.exp(1j*w) | ||
Linia 298: | Linia 413: | ||
i obliczamy widmo: | i obliczamy widmo: | ||
<source lang = python> | <source lang = python> | ||
− | Sp=H*H.conj()* | + | Sp=H*H.conj()* sigma_eps**2 |
Sp = Sp.real | Sp = Sp.real | ||
</source> | </source> | ||
Linia 315: | Linia 430: | ||
A += parametry_a[i]*z**(-(i+1)) | A += parametry_a[i]*z**(-(i+1)) | ||
H = 1./A | H = 1./A | ||
− | Sp = H*H.conj()* | + | Sp = H*H.conj()* sigma_eps**2 # widmo |
Sp = Sp.real | Sp = Sp.real | ||
return Sp, w | return Sp, w | ||
Linia 322: | Linia 437: | ||
==== Ćwiczenie ==== | ==== Ćwiczenie ==== | ||
Proszę: | Proszę: | ||
− | * Wygenerować realizację modelu AR <math>a = \{0.6, -0.7, 0.3, -0.25\}, \quad \varepsilon = 2</math> | + | * Wygenerować realizację modelu AR <math>a = \{0.6, -0.7, 0.3, -0.25\}, \quad \sigma_{\varepsilon} = 2</math> |
<source lang = python> | <source lang = python> | ||
− | def generujAR(a, | + | def generujAR(a, sigma_eps, N): |
x=np.zeros(N) | x=np.zeros(N) | ||
rzad = len(a) | rzad = len(a) | ||
Linia 330: | Linia 445: | ||
for p in range(len(a)): | for p in range(len(a)): | ||
x[i] += a[p]*x[i-(p+1)] | x[i] += a[p]*x[i-(p+1)] | ||
− | x[i] += | + | x[i] += sigma_eps*np.random.randn() |
return x | return x | ||
</source> | </source> | ||
Linia 345: | Linia 460: | ||
from numpy.fft import fft, fftshift | from numpy.fft import fft, fftshift | ||
− | def generujAR(a, | + | def generujAR(a, sigma_eps, N): |
x=np.zeros(N) | x=np.zeros(N) | ||
rzad = len(a) | rzad = len(a) | ||
Linia 351: | Linia 466: | ||
for p in range(len(a)): | for p in range(len(a)): | ||
x[i] += a[p]*x[i-(p+1)] | x[i] += a[p]*x[i-(p+1)] | ||
− | x[i] += | + | x[i] += sigma_eps*np.random.randn() |
return x | return x | ||
Linia 379: | Linia 494: | ||
return a,epsilon | return a,epsilon | ||
− | def widmoAR(parametry_a, | + | def widmoAR(parametry_a, sigma_eps, N_punktow): |
w = np.linspace(-np.pi,np.pi,N_punktow) | w = np.linspace(-np.pi,np.pi,N_punktow) | ||
z = np.exp(1j*w) | z = np.exp(1j*w) | ||
Linia 386: | Linia 501: | ||
A += parametry_a[i]*z**(-(i+1)) | A += parametry_a[i]*z**(-(i+1)) | ||
H = 1./A | H = 1./A | ||
− | Sp = H*H.conj()* | + | Sp = H*H.conj()* sigma_eps**2 # widmo |
Sp = Sp.real | Sp = Sp.real | ||
return Sp, w | return Sp, w | ||
Linia 394: | Linia 509: | ||
epsilon = 2 | epsilon = 2 | ||
# obliczanie widma z modelu | # obliczanie widma z modelu | ||
− | Sp, w = widmoAR(a, | + | Sp, w = widmoAR(a, sigma_eps,200) |
#generujemy realizacje procesu | #generujemy realizacje procesu | ||
N=600 | N=600 | ||
− | x = generujAR(a, | + | x = generujAR(a, sigma_eps, N) |
# estymujemy wspolczynniki modelu metodą Ypula-Walkera | # estymujemy wspolczynniki modelu metodą Ypula-Walkera | ||
# obliczamy widmo dla estymowanego modelu | # obliczamy widmo dla estymowanego modelu | ||
for p in range(3,7): | for p in range(3,7): | ||
− | a_est, | + | a_est, sigma_eps_est = parametryAR(x,p) |
− | Sp_est, w = widmoAR(a_est, | + | Sp_est, w = widmoAR(a_est, sigma_eps_est,200) |
py.plot(w,Sp_est ) | py.plot(w,Sp_est ) | ||
py.plot(w,Sp) | py.plot(w,Sp) | ||
Linia 541: | Linia 656: | ||
</source> | </source> | ||
− | + | == Co z tego musimy zapamiętać:== | |
− | + | * widmo sygnału stochastycznego estymujemy, a nie obliczamy | |
+ | * są dwie klasy technik: | ||
+ | ** nieparametryczne - '''widmo estymujemy''' bezpośrednio dla sygnału np. metodą periodogram, Welcha, wielookienkową | ||
+ | ** parametryczne: najpierw '''estymujemy model''' opisujący dane, a nstępnie '''dla modelu obliczamy widmo''' | ||
+ | ===Ogólny schemat === | ||
W praktyce musimy najczęściej estymować widmo mając dany tylko sygnał. Wówczas powinniśmy pwstąpić według następującego algorytmu: | W praktyce musimy najczęściej estymować widmo mając dany tylko sygnał. Wówczas powinniśmy pwstąpić według następującego algorytmu: | ||
* oszacować rząd modelu np. przy pomocy kryterium Akaikego | * oszacować rząd modelu np. przy pomocy kryterium Akaikego | ||
* wyestymować parametry modelu | * wyestymować parametry modelu | ||
* obliczyć widmo dla estymowanego modelu | * obliczyć widmo dla estymowanego modelu | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Aktualna wersja na dzień 08:51, 30 sty 2017
Analiza_sygnałów_-_ćwiczenia/AR_2
Spis treści
Notebook
Proszę pobrać i zapisać lkoalnie notebook: Ipython notebook z ćwiczeniami z modeli AR
następnie w terminalu, w katalogu zawierającym notebook piszemy:
> jupyter notebook
gdzie notebook to nazwa pobranego właśnie pliku
Procesy AR
Dla przypomnienia: proces AR generowany jest tak, że kolejna próbka jest ważoną sumą [math]p[/math] poprzednich próbek i niezależnej zmiennej losowej o średniej 0 i wariancji [math]\sigma^2[/math]:
- [math]x_n = \sum_{k=1}^p a_k * x_{n-k} +\varepsilon_n[/math]
- i [math]\varepsilon_n \sim N(0,\sigma^2)[/math]
Proces AR można zatem scharakteryzować podając:
- współczynniki [math]a[/math] oraz
- [math]\sigma^2[/math].
Zadanie: ilustracja realizacji procesu
Poniższy kod po uzupełnieniu będzie ilustrował jak mogą wyglądać pojedyncze realizacje procesu opisywanego przez współczynniki a=[0.9, -0.7] i wariancję 1.
...# stosowne importy
def realizacjaAR(a,sigma, N):
x = np.zeros(N)
for i in range(2,N): #kolejno tworzymy próbki w każdej realizacji
x[i]=a[0]*x[i-1]+a[1]*x[i-2]+ ...
return x
a = np.array([0.9, -0.7])
sigma = 1
N_realizacji = 5 # liczba realizacji
N=500 #liczba punktów w realizacji
realizacja = np.zeros((N_realizacji, N)); # macierz na wszystkie realizacje
for r in range(0,N_realizacji): #generujemy realizacje procesu
realizacja[r,:] = ...
for r in range(0,N_realizacji): #rysujemy realizacje procesu
py.subplot(5,1,r+1)
py.plot( ...)
py.title('realizacja'+str(r))
py.show()
Zadanie: ilustracja funkcji autokorelacji procesu
Dla współczynników [math]a[/math], dla których proces ten jest stacjonarny, charakteryzuje się też pewną konkretną funkcją autokorelacji. Poniższe ćwiczenie powinno nam uświadomić:
- jak może wyglądać estymowana funkcja autokorelacji dla realizacji procesu AR
- jak estymata funkcji autokorelacji zależy od długości realizacji (czyli od ilości dostępnych informacji). Co dzieje się z funkcją autokorelacji dla poszczególnych realizacji, gdy zwiększamy liczbę punktów w realizacji N od 50 do 5000?
Poniższy kod powinien stanowić kontynuację poprzedniego.
for r in range(0,N_realizacji): #rysujemy funkcję autokorelacji poszczególnych realizacji
f_corr =...
tau = np.arange(-N+1,N,1)
ind = range(...-10,...+10) # tu szykujemy indeksy, dzięki którym będziemy mogli pobrać wycinek +/- 10 próbek wokół przesunięcia 0
py.plot(tau[ind],f_corr[ind])
py.title(fragment funkcji autokorelacji)
py.show()
Model AR
Rozważania na temat procesów AR są o tyle interesujące, że wiele sygnałów, które chcielibyśmy badać całkiem nieźle daje się opisać jako procesy AR . Wyobrażamy sobie wówczas, że rejestrowane sygnały są generowane przez pewien model AR (trochę tak jak funkcja realizacjaAR wytwarzała pojedyncze realizacje procesu). Pojawia się w tym momencie pytanie: jak możemy poznać wartości parametrów [math]a[/math] i [math]\sigma^2[/math], które pasują do badanych sygnałów?
Estymacja parametrów
Algorytmów służących do estymacji parametrów modelu AR jest kilka. Tu przedstawimy algorytm Yule-Walker'a:
- mnożymy stronami równania opisujące proces dla póbki [math]t[/math] i [math]t-m[/math]
- [math]x_t x_{t-m} = \sum _{i=1}^p a_i x_{t-i} x_{t-m} +\epsilon _t x_{t-m} [/math]
- bierzemy wartość oczekiwaną lewej i prawej strony. Wartości oczekiwane [math]E\lbrace x_t x_{t-m}\rbrace [/math] to funkcja autokorelacji [math]R(m)[/math] więc:
- [math]R(m) = \sum _{i=1}^p a_i R(m-i)+ \sigma _\epsilon ^2 \delta (m)[/math]
gdzie [math]m=0,\dots ,p.[/math]
- Dla [math]m\gt 0[/math] możemy zapisać stąd układ równań:
- [math]\left[\begin{array}{c} R(1)\\ R(2)\\ \vdots \\ R(p) \end{array}\right]= \left[\begin{array}{cccc} R(0)& R(-1) &\dots &\\ R(1)& R(0) &R(-1) \dots &\\ \vdots & & &\\ R(p-1) & &\dots &R(0) \end{array}\right] \left[\begin{array}{c} a_1\\ a_2\\ \vdots \\ a_p \end{array} \right] [/math]
- stąd wyliczamy współczynniki [math]a[/math],
dla [math]m=0[/math] mamy
- [math]R(0) = \sum _{k=1}^p a_k R(-k) + \sigma _\epsilon ^2[/math]
- można stąd wyliczyć [math]\sigma _\epsilon ^2 [/math]
Ćwiczenie: estymacja parametrów procesu AR
- Wygeneruj 2000 próbek sygnału z modelu AR o parametrach a = {0.9, -0.6}, epsilon=2
- Oblicz funkcję autokorelacji tego sygnału: ak = np.correlate(x,x,mode='full')
- Znormalizuj tą funkcję dzieląc ją przez liczbę pokrywających się próbek dla każdego przesunięcia [math]\tau[/math]
- Oblicz parametry zgodnie ze wzorami z poprzedniego paragrafu dla modelu rzędu 2. (wypisz konkretną postać wzorów analitycznych a następnie zaimplementuj je)
- Wypisz parametry prawdziwe i estymowane.
- Sprawdź jak wpływa długość sygnału na dokładność estymaty (uruchom program kilka razy dla każdej z badanych długości sygnału)
wskazówka: R[0]=ak[N-1]
#wspolczynniki modelu AR
a = np.array([0.9, -0.6])
sigma = 2
N = 200
x = np.zeros(N);
#generujemy realizacje procesu
for i in range(2,N):
x[i] = a[0]*x[i-1] + a[1]*x[i-...] + ...
py.subplot(2,1,1)
py.plot(x)
py.xlabel('numer próbki')
py.title('wygenerowany sygnal')
py.subplot(2,1,2)
ak = np.correlate(x,x,mode='full')
# ak nieobciążona:
norm_ak = ...
ak /= norm_ak
m = ... # przesunięcia
py.plot(m, ak)
py.xlabel('przesunięcie m')
py.title('funkcja autokorelacij sygnalu x')
R=ak[N-1:]
r0=R[0]
r1=R[1]
r2=R[2]
# estymujemy wspolczynniki modelu na podstawie funkncji autokorelacji
a2 = ...
a1 = ...
s_2 = ...
print('prawdziwe wspolczynniki')
print( a[0], a[1], sigma)
print('estymowane wspolczynniki')
print( '%.3f, %.3f, %.3f'%(a1, a2, s_2**0.5))
py.show()
Estymacja parametrów dla modelu rzędu p
W przypadku modelu rzędu [math]p[/math] estymację parametrów metodą Y-W można zaimplementować np. tak:
def parametryAR(x,p):
'''funkcja estymująca parametry modelu AR
argumenty:
x- sygnał
p - rząd modelu
f. zwraca:
a - wektor współczynników modelu
epsilon - estymowana wariancja szumu
funkcja wymaga zaimportowania modułu numpy as np
'''
N = len(x)
ak = np.correlate(x,x,mode='full')
norm_ak = np.hstack((np.arange(1,N+1,1),np.arange(N-1,0,-1)))
ak=ak/norm_ak
R=ak[N-1:]
RL = R[1:1+p]
RP = np.zeros((p,p))
for i in range(p):
aa = ak[N-1-i:N-1-i+p]
RP[i,:] = aa
a=np.linalg.solve(RP,RL)
sigma = (ak[N-1] - np.sum(a*ak[N:N+p]))**0.5
return a, sigma
Jak znaleźć rząd modelu?
Kryterium Akaike (AIC):
- [math]\mathrm{AIC}(p)= \frac{2p}{N} +\ln(V) [/math]
[math]p[/math] - liczba parametrów modelu,
[math]N[/math] - liczba próbek sygnału,
[math]V[/math] - wariancja szumu.
Kryterium to karze za zwiększanie ilości parametrów i nagradza za zmniejszanie niewytłumaczonej wariancji.
Poniższy kod jest przykładową implementacją kryterium AIC:
def kryterium_AIC(x,maxymalnyRzad):
zakres_rzedow = range(1,maxymalnyRzad)
N = len(x)
AIC = np.zeros(len(zakres_rzedow))
for p in zakres_rzedow:
a,sigma = parametryAR(x,p)
AIC[p-1] = (2.0*p)/N + np.log(np.sqrt(sigma))
print 'p:', p, ' a:',a,' sigma: ',sigma
return AIC
Zobaczmy jak działa to na przykładowym sygnale AR:
import numpy as np
import pylab as py
from numpy.fft import fft, fftshift
def parametryAR(x,p):
'''funkcja estymująca parametry modelu AR
argumenty:
x- sygnał
p - rząd modelu
f. zwraca:
a - wektor współczynników modelu
epsilon - estymowana wariancja szumu
funkcja wymaga zaimportowania modułu numpy as np
'''
N = len(x)
ak = np.correlate(x,x,mode='full')
ak=ak/N
R=ak[N-1:]
RL = R[1:1+p]
RP = np.zeros((p,p))
for i in range(p):
aa = ak[N-1-i:N-1-i+p]
RP[i,:] = aa
a=np.linalg.solve(RP,RL)
epsilon = (ak[N-1] - np.sum(a*ak[N:N+p]))**0.5
return a,epsilon
def kryterium_AIC(x,maxymalnyRzad):
zakres_rzedow = range(1,maxymalnyRzad)
AIC = np.zeros(len(zakres_rzedow))
for p in zakres_rzedow:
a,epsilon = parametryAR(x,p)
AIC[p-1] = (2.0*p)/N + np.log(np.sqrt(epsilon))
print 'p:', p, ' a:',a,' epsilon: ',epsilon
return AIC
#wspolczynniki modelu AR
a = np.array([0.9, -0.7])
epsilon=2
N=600
x=np.zeros(N);
#generujemy realizacje procesu
for i in range(2,N):
x[i]=a[0]*x[i-1]+a[1]*x[i-2] +epsilon*np.random.randn()
py.subplot(2,1,1)
py.plot(x)
py.title('wygenerowany sygnal')
py.subplot(2,1,2)
AIC = kryterium_AIC(x,6)
py.plot(range(1,len(AIC)+1),AIC)
py.title('Kryterium AIC')
py.show()
Widmo modelu AR
Widmo modelu można wyliczyć analitycznie znając jego współczynniki: Przepisujemy równanie modelu:
- [math]x_t = \sum _{i=1}^p a_i x_{t-i} +\epsilon _t[/math]
- [math]\sum _{i=0}^p a_i x_{t-i} =\epsilon _t[/math]
biorąc transformaty [math]Z[/math] obu stron mamy równanie algebraiczne:
- [math]A(f)X(f) =E(f)[/math]
- [math]X(f)=A^{-1}(f) E(f)=H(f) E(f)[/math]
Stąd widmo:
- [math]S(f) = X(f)X^*(f)=H(f)VH^*(f)[/math]
Jak znaleźć A — transformata Z
Transformata Z jest dyskretnym odpowiednikiem transformaty Laplace'a:
- [math]X(z) = Z\lbrace x[n]\rbrace = \sum _{n=0}^\infty {x[n]z^{-n}}[/math]
gdzie [math]z=Ae^{i \phi }[/math] jest liczbą zespoloną. Szczególnym przypadkiem tej transformaty jest dyskretna transformata Fouriera - wystarczy podstawić [math]A=1/N[/math] i [math]\phi = - 2 \pi k/ N [/math] porównaj.
Własności transformaty Z
Transformata ta jest liniowa tzn.
- [math]\mathrm{Z}\lbrace a_1x_1[n] +a_2x_2[n]\rbrace =a_1X_1(z)+a_2X_2(z)[/math]
jak ją policzyć od sygnału przesuniętego w czasie to:
- [math]\mathrm{Z}\lbrace x[n-k]\rbrace = z^{-k}X(z)[/math]
dla impulsu:
- [math]\mathrm{Z}\lbrace \delta [n]\rbrace =1[/math]
więc
- [math]\mathrm{Z}\lbrace \delta [n-n0]\rbrace = z^{-n0} [/math]
Stosując tą transfomatę do procesu AR dostajemy:
- [math]\mathrm{Z}\lbrace x[n] + a_1 x[n-1] + \dots + a_p x[n-p]\rbrace = (1 + a_1 z^{-1} + \dots + a_p z^{-p})X(z)[/math]
- [math]=A(z)X(z)[/math]
Widmo procesu
Najpierw rozważmy konkretny przykład. Niech model będzie rzędu p=2 i ma współczynniki [math]a_1 = 0.9, a_2 = -0.6[/math] i [math]\sigma_{\varepsilon} = 2[/math]. Wyliczamy wartości funkcji [math]A(z) = a_1 z^{-1}+a_2 z^{-2}[/math] dla [math]z = e^{i \omega}[/math]:
a=[0.9, -0.6]
sigma_eps = 2
w=np.arange(-np.pi,np.pi,0.1)
z=np.exp(1j*w)
# dla zadanego modelu
A=-1+a[0]*z**(-1)+a[1]*z**(-2);
Następnie obliczamy odwrotność A :
H=1./A
i obliczamy widmo:
Sp=H*H.conj()* sigma_eps**2
Sp = Sp.real
Możemy je wykreślić w funkcji częstości [math]\omega[/math].
py.plot(w,Sp )
Operacje te możemy uogólnić i zaimplementować jako funkcję do obliczania widma modelu zadanego przez parametry:
def widmoAR(parametry_a, epsilon, N_punktow):
w = np.linspace(-np.pi,np.pi,N_punktow)
z = np.exp(1j*w)
A = -1 * np.ones(N_punktow) + 1j*np.zeros(N_punktow)
for i in range(len(parametry_a)):
A += parametry_a[i]*z**(-(i+1))
H = 1./A
Sp = H*H.conj()* sigma_eps**2 # widmo
Sp = Sp.real
return Sp, w
Ćwiczenie
Proszę:
- Wygenerować realizację modelu AR [math]a = \{0.6, -0.7, 0.3, -0.25\}, \quad \sigma_{\varepsilon} = 2[/math]
def generujAR(a, sigma_eps, N):
x=np.zeros(N)
rzad = len(a)
for i in range(rzad,N):
for p in range(len(a)):
x[i] += a[p]*x[i-(p+1)]
x[i] += sigma_eps*np.random.randn()
return x
- Obliczyć widmo dla tego modelu
- Wyestymować parametry modelu na podstawie sygału, zakładając, że rząd jest p = 3,4,5,6
- Obliczyć widmo dla wyestymowanego modelu
- Wykreślić widma prawdziwego modelu i modeli estymowanych
*
Ćwiczenie
Dla modelu z poprzedniego ćwiczenia proszę wygenerować realizację sygnału długości 1000 punktów. Proszę porównać widma:
- prawdziwe, obliczone z prawdziwych parametrów modelu
- obliczone z estymowanego modelu
- obliczone przez periodogram
- obliczone metodą Welcha
- obliczone metodą wielookienkową Thomsona
import numpy as np
import pylab as py
from numpy.fft import fft, fftshift,fftfreq
import gendpss as dpss
def generujAR(a, epsilon, N):
x=np.zeros(N)
r = len(a)
for i in range(r,N):
for p in range(len(a)):
x[i] += a[p]*x[i-(p+1)]
x[i] += epsilon*np.random.randn()
return x
def parametryAR(x,p):
N = len(x)
ak = np.correlate(x,x,mode='full')
ak = ak/N
R = ak[N-1:]
RL = R[1:1+p]
RP = np.zeros((p,p))
for i in range(p):
aa = ak[N-1-i:N-1-i+p]
RP[i,:] = aa
a = np.linalg.solve(RP,RL)
epsilon = (ak[N-1] - np.sum(a*ak[N:N+p]))**0.5
return a,epsilon
def widmoAR(parametry_a, epsilon, N_punktow):
w = np.linspace(-np.pi,np.pi,N_punktow)
z = np.exp(1j*w)
A = -1 * np.ones(N_punktow) + 1j*np.zeros(N_punktow)
for i in range(len(parametry_a)):
A += parametry_a[i]*z**(-(i+1))
H = 1./A
Sp = H*H.conj()*epsilon**2 # widmo
Sp = Sp.real
return Sp, w
def periodogram(s, okno , Fs):
s = s*okno
N_fft = len(s)
S = fft(s,N_fft)#/np.sqrt(N_fft)
P = S*S.conj()/np.sum(okno**2)
P = P.real # P i tak ma zerowe wartośći urojone, ale trzeba ykonać konwersję typów
F = fftfreq(N_fft, 1/Fs)
return (fftshift(P),fftshift(F))
def pwelch(s,okno, przesuniencie, Fs):
N = len(s)
N_s = len(okno)
start_fragmentow = np.arange(0,N-N_s+1,przesuniencie)
ile_fragmentow = len(start_fragmentow)
ile_przekrycia = N_s*ile_fragmentow/float(N)
print ile_przekrycia, ile_fragmentow
P_sredni = np.zeros(N_s)
for i in range(ile_fragmentow):
s_fragment = s[start_fragmentow[i]:start_fragmentow[i]+N_s]
(P, F) = periodogram(s_fragment,okno,Fs)
P_sredni += P
return (P_sredni/ile_przekrycia,F)#(P_sredni/ile_przekrycia,F)
def mtm(s, NW = 3, Fs = 128):
K = int(2*NW-1)
N = len(s)
w = dpss.gendpss(N,NW,K)
S=np.zeros(N)
for i in range(K):
Si = np.abs(fft(s*w.dpssarray[i]))**2
S[:] += Si.real
S = S/K
F = fftfreq(N,1.0/Fs)
return (fftshift(S),fftshift(F))
#wspolczynniki modelu AR
a = np.array([0.3, 0.2, 0.5, -0.25 ,-0.3])
epsilon = 2
N=256
# obliczanie widma z modelu
Sp, w = widmoAR(a,epsilon,N)
#generujemy realizacje procesu
x = generujAR(a, epsilon, N)
# estymujemy wspolczynniki modelu metodą Yula-Walkera
# obliczamy widmo dla estymowanego modelu
a_est,epsilon_est = parametryAR(x,5)
Sp_est, w = widmoAR(a_est,epsilon_est,N)
okno = np.blackman(N)
Fs = 2*np.pi
P_periodogram,F_periodogram = periodogram(x, okno , Fs=Fs)
okno = np.blackman(N/4)
P_welch, F_welch = pwelch(x,okno, len(okno)/2, Fs=Fs)
P_mtm, F_mtm = mtm(x, NW = 4.5, Fs =Fs)
py.plot(w,Sp)
py.plot(w,Sp_est)
py.plot(F_periodogram,P_periodogram)
py.plot(F_welch, P_welch/(len(P_periodogram)/len(P_welch)))#uwaga Welch ma inne df
py.plot(F_mtm, P_mtm)
#py.legend(('prawdziwy','estymowany z AR','periodogram','Welch','mtm'))
print 'enenrgia sygnału: ', np.sum(x**2)
print 'enenrgia spektrum AR',np.sum(Sp)
print 'enenrgia est',np.sum(Sp_est)
print 'enenrgia mtm',np.sum(P_mtm)
print 'enenrgia welch',np.sum(P_welch)
print 'enenrgia period',np.sum(P_periodogram)
py.show()
Co z tego musimy zapamiętać:
- widmo sygnału stochastycznego estymujemy, a nie obliczamy
- są dwie klasy technik:
- nieparametryczne - widmo estymujemy bezpośrednio dla sygnału np. metodą periodogram, Welcha, wielookienkową
- parametryczne: najpierw estymujemy model opisujący dane, a nstępnie dla modelu obliczamy widmo
Ogólny schemat
W praktyce musimy najczęściej estymować widmo mając dany tylko sygnał. Wówczas powinniśmy pwstąpić według następującego algorytmu:
- oszacować rząd modelu np. przy pomocy kryterium Akaikego
- wyestymować parametry modelu
- obliczyć widmo dla estymowanego modelu