Adaptacyjne filtry ortogonalne
Autorzy: Tomasz P. Zieliński
Pliki: rozdzial_08.zip
Przykład 8.1
W przykładzie 8.1 (plik przyklad_8_1.m)jest zaprezentowany program, w którym zaimplementowano przykładowy filtr FIR w postaci kratowej. Należy zwrócić uwagę, że błędy e+k [n] i e?k [n] oznaczono w nim jako eak[n] i ebk[n] (odpowiednio zmienne ea(k) i eb(k)), czyli znaki + i – zastąpiono literami a i b.% Przykład 8.1 % Autor: Tomasz Zieliński, tzielin@agh.edu.pl clear all; clf; % Podaj współczynniki transmitancji H(z)=A(z) filtra (UWAGA! a(1)=1, M<=N) a = [ 1 -0.9 0.64 -0.576 ]; N = length(a); aa = a(2:N); M=N-1; % odrzucamy pierwszy element równy 1 % Oblicz współczynniki "odbicia" gamma(i) filtra kratowego - tabela 8.1, % równania (8.21)(8.22) aij(M,1:M)=aa(1:M); for i=M:-1:1 gamma(i)=-aij(i,i); for j=1:i-1 aij(i-1,j) = (aij(i,j)+gamma(i)*aij(i,i-j))/(1-gamma(i)^2); end end gamma, pause % Odtwórz współczynniki {a} na podstawie wsp. {gamma} - tabela 8.1, (8.16),(8.17) aa = zeros(M,M); aa(1,1) = -gamma(1); for i=2:M aa(i,i) = -gamma(i); for j=1:i-1 aa(i,j) = aa(i-1,j) - gamma(i)*aa(i-1,i-j); end end aa = [ 1 aa(M,:) ], pause % Sygnał filtrowany Nx=100; n=0:Nx-1; x=sin(2*pi*n/12+pi/4); % Filtracja kratowa "tylko zera" (rys. 8.1b i 8.5a): % H1(z)=A(z)=[ 1 -0.9 0.64 -0.576 ]; y1 = filtrK_Z( x, gamma); plot(y1); title('Sygnał wyjściowy - filtr: tylko zera'); pause % Porównanie ze zwykła filtracją y1z = filter(a,1,x); plot(y1-y1z); title('Różnica z filter(a,1,x)'); %----------------------------------------------------------------------------------- % function y = filtrK_Z(x,gamma) % Filtr kratowy - tylko zera % Autor: Tomasz Zieliński, tzielin@agh.edu.pl % N=length(x); % M=length(gamma); % eb(1:M) = zeros(1,M); % for n = 1 : N % ea(1) = x(n); % kolejna próbka % for k = 1 : M % kolejne sekcje filtra (8.2) % ea(k+1) = ea(k) - gamma(k)*eb(k); % ebnext(k+1) = eb(k) - gamma(k)*ea(k); % end % eb = [ x(n) ebnext(2:M) ]; % y(n) = ea(k+1); % end
Przykład 8.2
W przykładzie 8.2 (plik przyklad_8_2.m) jest zaprezentowany program, w którym zaimplementowano w postaci kratowej przykładowy filtr IIR typu tylko-bieguny. Należy zwrócić uwagę, że błędy ek+[n] i ek-[n] oznaczono w nim jako eak[n] i ebk[n] (odpowiednio zmienne ea(k)i eb(k)), czyli + i – zastąpiono literami a i b.% Przykład 8.2 % Autor: Tomasz Zieliński, tzielin@agh.edu.pl clear all; clf; % Podaj współczynniki transmitancji H(z)=1/A(z) filtra (UWAGA! a(1)=1, M<=N) a = [ 1 -0.9 0.64 -0.576 ]; % Podaj współczynniki transmitancji H(z)=A(z) filtra (UWAGA! a(1)=1, M<=N) a = [ 1 -0.9 0.64 -0.576 ]; N = length(a); aa = a(2:N); M=N-1; % odrzucamy pierwszy element równy 1 % Oblicz współczynniki "odbicia" gamma(i) filtra kratowego - tabela 8.1, % równania (8.21)(8.22) aij(M,1:M)=aa(1:M); for i=M:-1:1 gamma(i)=-aij(i,i); for j=1:i-1 aij(i-1,j) = (aij(i,j)+gamma(i)*aij(i,i-j))/(1-gamma(i)^2); end end gamma, pause % Sygnał filtrowany Nx=100; n=0:Nx-1; x=sin(2*pi*n/12+pi/4); % Filtracja kratowa "tylko bieguny" (rys. 8.2b i 8.5b): % H2(z)=1/A(z)=1/[ 1 -0.9 0.64 -0.576 ]; y2 = filtrK_B( x, gamma); plot(y2); title('Sygnał wyjściowy - filtr: tylko bieguny'); pause % Porównanie ze zwykła filtracją y2z = filter(1,a,x); subplot(111); plot(y2-y2z); title('Różnica z filter(1,a,x)'); %----------------------------------------------------------------------------------- % function y = filtrK_B(x,gamma) % Filtr kratowy - tylko bieguny % N=length(x); % M=length(gamma); % eb(1:M) = zeros(1,M); % for n = 1 : N % ea(M+1) = x(n); % kolejna próbka % for k = M : -1 : 1 % kolejne sekcje filtra (8.27) % ea(k) = ea(k+1) + gamma(k)*eb(k); % eb(k+1) = eb(k) - gamma(k)*ea(k); % end % eb = [ ea(1) eb(2:M+1) ]; % y(n) = ea(1); % end
Przykład 8.3
W przykładzie 8.3 (plik przyklad_8_3.m) zaimplementowano filtr kratowy IIR typu zera-bieguny.% Przykład 8.3 % Autor: Tomasz Zieliński, tzielin@agh.edu.pl clear all; clf; % Podaj współczynniki transmitancji H(z)=B(z)/A(z) filtra (UWAGA! a(1)=1, M<=N) b = [ 1 3 3 1 ]; a = [ 1 -0.9 0.64 -0.576 ]; P=length(b); N=length(a); aa=a(2:N); M=N-1; % odrzucamy pierwszy element równy 1 % Oblicz współczynniki "odbicia" gamma(i) filtra kratowego - tabela 8.1 % równania (8.21)(8.22) aij(M,1:M)=aa(1:M); for i=M:-1:1 gamma(i)=-aij(i,i); for j=1:i-1 aij(i-1,j) = (aij(i,j)+gamma(i)*aij(i,i-j))/(1-gamma(i)^2); end end gamma, pause % Oblicz współczynniki c(i) filtra kratowego - równanie (8.40) for k = P:-1:1 s=0; for(j=k+1:P) s = s + c(j)*aij(j-1,j-k); end c(k) = b(k) - s; end c, pause % Sygnał filtrowany Nx=100; n=0:Nx-1; x=sin(2*pi*n/12+pi/4); % Filtracja "kratowa" % "zera i bieguny" (rys. 8.4e i 8.6b) : H3(z)= [ 1 3 3 1 ] / [1 -0.9 0.64 -0.576 ] y3 = filtrK_ZB( x, gamma, c); % Rysunki plot(y3); title('Sygnał wyjściowy - filtr: zera i bieguny'); pause % Porównanie ze zwykła filtracją y3z = filter(b,a,x); plot(y3-y3z); title('Różnica z filter(b,a,x)'); pause %----------------------------------------------------------------------------------- % function y = filtrK_ZB(x,gamma,c) % Filtr kratowy - zera i bieguny % N=length(x); % M=length(gamma); % eb(1:M) = zeros(1,M); % for n = 1 : N % ea(M+1) = x(n); % kolejna próbka % for k = M : -1 : 1 % kolejne sekcje filtra (8.27) % ea(k) = ea(k+1) + gamma(k)*eb(k); % eb(k+1) = eb(k) - gamma(k)*ea(k); % end % eb = [ ea(1) eb(2:M+1) ]; % y(n) = sum( c.*eb(1:M+1) ); % end
Przykład 8.4
W przykładzie 8.4 (plik corrx.m) przedstawiono programy w języku MATLAB, realizujące wszystkie obliczenia z projektowania kratowego filtra Wienera. Napisano je na podstawie programów w językach Fortran i C, zamieszczonych w literaturze [11]. W kolejności są to funkcie:przykład 8.4a = corrxy.m, przykład 8.4b = lev.m, przykład 8.4c = firw.m, przykład 8.4d = filtrLWF.m.
function [r] = corrxy(x,y,M) % Przykład 8.4a % Obliczanie M-próbek funkcji korelacji wzajemnej sygnałów x[n] i y[n] % Oblicz rxx lub rdx, w zależności od sygnałów wejściowych N = length(x); for k = 0 : M r(k+1) = sum( x(1+k:N) .* y(1:N-k) )/N; endlev.m
function [L,E] = lev(M,rxx) % Przykład 8.4b % Obliczanie współczynników filtrów predykcji liniowej rzędu od 1 do M % na podstawie wektora rxx autokorelacji sygnału x[n] % metodą Durbina-Levinsona - inny zapis niż w tabl. 8.2, taki jak w [11] % Autor implementacji w Matlabie: Tomasz Zieliński, tzielin@agh.edu.pl L(1,1)=1; L(2,2)=1; L(2,1)=-rxx(2)/rxx(1); E(1)=rxx(1); E(2)=E(1)*(1-L(2,1)^2); for k = 3:M+1 delta = sum( rxx(2:k) .* L(k-1,1:k-1) ); % równanie (8.58b) gamma = delta/E(k-1); % równanie (8.68) L(k,1) = - gamma; for i = 2:k-1 L(k,i) = L(k-1,i-1) - gamma*L(k-1,k-1-i+1); % równanie (8.69) end L(k,k)=1; E(k)=E(k-1)*(1-gamma^2); % równanie (8.70) endfirw.m
function [L,E,g,h] = firw(M,rdx,rxx) % Przykład 8.4c % Projektowanie współczynników filtra FIR Wienera na podstawie [11] % Autor implementacji w Matlabie: Tomasz Zieliński, tzielin@agh.edu.pl [L,E] = lev(M,rxx); % algorytm Levinsona for k=1:M+1 g(k) = sum( L(k,1:k) .* rdx(1:k) )/E(k); % g=Dinv*L*rdx, równanie (8.83) end for k=1:M+1 h(k) = sum( (L(k:M+1,k).') .* g(k:M+1) ); % h=L'*g, równanie (8.83) endfiltrLWF.m
function [y,e] = filtrLWF(M,g,gamma,d,x) % Przykład 8.4d % Nieadaptacyjny kratowy filtr Wienera (Lattice Wiener Filter), patrz rys. 8.7b % Na podstawie [11] % Autor implementacji w Matlabie: Tomasz Zieliński, tzielin@agh.edu.pl w = 0.000001*randn(1,M+1); % wektor roboczy, stany wewnętrzne każdej sekcji for n = 1 : length(x) ea(1) = x(n); % wejście do pierwszej sekcji filtra a priori eb(1) = x(n); % j.w. y(n) = g(1)*eb(1); % estymata y[n] bazująca na sekcji 1 e(n) = d(n) - y(n); % estymata e[n] bazująca na sekcji 1 for k = 2:M+1 % kolejne k-te sekcje filtra kratowego (8.2), rys.8.7b ea(k) = ea(k-1) - gamma(k)*w(k); % błąd ek+[n] eb(k) = w(k) - gamma(k)*ea(k-1); % błąd ek-[n] w(k) = eb(k-1); % stan wewnętrzny k-tej sekcji y(n) = y(n) + g(k)*eb(k); % estymata a posteriori xest[n] rzędu "k", równ. (8.84) e(n) = e(n) - g(k)*eb(k); % błąd a posteriori e[n] rzędu "k", równanie (8.86) end end
Przykład 8.5
W przykładzie 8.5 (plik filtrGLLPF.m) przedstawiono implementację adaptacji wag filtra kratowego typu FIR pracującego jako liniowy predyktor.function [y] = filtrGLLPF(M,x,lambda,beta) % Przykład 8.5 na podstawie [11] % Adaptacyjny gradientowy kratowy liniowy predyktor. % (Gradient Lattice Linear Prediction Filter) % Rys. 8.7b tylko z adaptacją wag gamma filtra % Autor implementacji w Matlabie: Tomasz Zieliński, tzielin@agh.edu w = 0.000001*randn(1,M+1); % wektor roboczy, stany wewnętrzne każdej sekcji gamma = w; da = w; for n = 1 : length(x) % dla kolejnych próbek sygnału x[n] ea(1) = x(n); % wejście do pierwszej sekcji filtra eb(1) = x(n); % wejście do pierwszej sekcji filtra for k = 2:M+1 % kolejne sekcje filtra ea(k) = ea(k-1) - gamma(k)*w(k); % równanie (8.2) eb(k) = - gamma(k)*ea(k-1) + w(k); % czyli "motylek" da(k) = lambda*da(k) + ea(k-1)*ea(k-1) + w(k)*w(k); % nowe d[k], (8.95)(8.96) gamma(k) = gamma(k) + beta*(ea(k)*w(k)+eb(k)*ea(k-1))/da(k); % nowe gamma[k], (8.97) w(k) = eb(k-1); % aktualizacja stanu wewnętrznego k-tej sekcji filtra kratowego end y(n) = ea(k); % sygnał wyjściowy y[n] end
Przykład 8.6
W przykładzie 8.6 (plik filtrGLWF.m) przedstawiono implementację adaptacyjnego gradientowego kratowego filtra Wienera typu FIR–LMS.function [y,e] = filtrGLWF(M,d,x,lambda,beta) % Przykład 8.6 % Adaptacyjny gradientowy filtr kratowy Wienera typu FIR-LMS % (Gradient Lattice Wiener Filter) % Rys. 8.7b tylko z adaptacją wag filtra (współczynnik gamma (k) i g(k)) % Na podstawie [11] % Autor implementacji w Matlabie: Tomasz Zieliński, tzielin@agh.edu.pl w = 0.000001*randn(1,M+1); % stany wewnętrzne każdej sekcji g = w; gamma = w; da = w; db = w; init = 0; for n = 1 : length(x) % dla kolejnych próbek sygnału x[n] ea(1) = x(n); % wejście do pierwszej sekcji filtra eb(1) = x(n); % wejście do pierwszej sekcji filtra y(n) = g(1)*eb(1); % estymata y[n] bazująca na sekcji 1 e(n) = d(n) - y(n); % estymata e[n] bazująca na sekcji 1 db(1) = lambda*db(1) + eb(1)*eb(1); % uaktualnienie db(1), równanie (8.116) g(1) = g(1) + beta*e(n)*eb(1)/db(1); % uaktualnienie g(1), równanie (8.115) for k = 2:M+1 % kolejne sekcje filtra ea(k) = ea(k-1) - gamma(k)*w(k); % równanie (8.2), czyli "motylek" eb(k) = - gamma(k)*ea(k-1) + w(k); % da(k) = lambda*da(k) + ea(k-1)*ea(k-1) + w(k)*w(k); % nowe d[k],(8.95)(8.96) gamma(k) = gamma(k) + beta*(ea(k)*w(k)+eb(k)*ea(k-1))/da(k); % nowe gamma[k],(8.97) y(n) = y(n) + g(k)*eb(k); % estymata x[n] rzędu "k", równ. (8.84) e(n) = e(n) - g(k)*eb(k); % bład e[n] estymaty rzędu "k", równanie (8.86) db(k) = lambda*db(k)+eb(k)*eb(k); % uaktualnienie dk [k] (8.116) if(k<=init) g(k) = g(k) + beta*e(n)*eb(k)/db(k); % uaktualnienie g[k] (8.115) end w(k) = eb(k-1); % aktualizacja stanu wewnętrznego k-tej sekcji filtra kratowego) end init = init+1; end
Przykład 8.7a
W przykładzie 8.7a (plik filtrFDAF_overlap_save.m) przedstawiono implementację w języku MATLAB filtra adaptacyjnego FDAF – overlap-save.function [y, e, Hest, H ] = filtrFDAF_overlap_save(M,d,x,nr,mi,alfa,delta,gamma) % Przykład 8.7a % Autor: Tomasz Zieliński, tzielin@agh.edu.pl lambda = 1-alfa; % współczynniki wykorzystywane podczas P = delta*ones(1,M); % nakładania ograniczenia na gradient funkcji kosztu bx = zeros(1,2*M); % inicjowanie bufora sygnału wejściowego x H = fft( [ones(1,M)/M zeros(1,M) ] ); % inicjowanie wag filtra y = []; e = []; Hest = []; % inicjowanie for k = 0 : length(x)/M-1 x1 = x(k*M+1:k*M+M); % pobierz kolejny blok próbek x[n] bx = [ bx(M+1:2*M) x1 ]; % włóż je do bufora X = fft(bx); % FFT by = real(ifft(X.*H)); % oblicz y[n] y = [ y by(M+1:2*M)]; % oddziel poprawny blok próbek y[n] e1 = d( k*M+1:k*M+M ) - y( k*M+1:k*M+M ); % oblicz blok próbek błędu e[n] e = [ e e1]; % zapamiętaj jako sygnał wyjściowy ee = [ zeros(1,M) e1 ]; % dodaj zera E = fft(ee); % FFT XE = conj(X) .* E; % iloczyn widm if(1) % korekta gradientu f. kosztu w czasie (z tym dokładniej, bez tego - szybciej) delta = ifft(XE ); % przejście z gradientem do dziedziny czasu if(1) delta = [ delta(1:M) zeros(1,M)]; end % OK if(0) delta = [ delta(1:M)/((x1*x1')+gamma) zeros(1,M)]; end % test if(0) P = lambda*P + alfa*abs(X(1:M)).^2; % test delta = [ delta(1:M)./(P) zeros(1,M)]; end XE = fft(delta); end % powrót z gradientem do dziedziny częstotliwości H = H + 2*mi*XE; % adaptacja wag filtra w dziedzinie częstotliwości Hest = [ Hest; H( nr ) ]; % zapamiętanie wybranych wag filtra end
Przykład 8.7b
W przykładzie 8.7b (plik filtrFDAF_overlap_add.m) przedstawiono implementację w języku MATLAB filtra adaptacyjnego FDAF – overlap-add.function [y, e, Hest, H ] = filtrFDAF_overlap_add(M,d,x,nr,mi,alfa,delta,gamma) % Przykład 8.7b % Autor: Tomasz Zieliński, tzielin@agh.edu.pl xx = zeros(1,2*M); % inicjowanie bufora sygnału wejściowego x[n] H = zeros(1,2*M); % inicjowanie wag filtra X2 = zeros(1,2*M); % inicjowanie wartości poprzedniego widma sygnału x[n] J = (-1).^(0:2*M-1); % macierz kompensacji czasowej poprzedniego widma sygnału x[n] lambda = 1-alfa; % alfa = 0.01; współczynniki wykorzystywane podczas P = delta*ones(1,M); % delta = 0.25 nakładania ograniczenia na gradient f. kosztu y = []; e = []; Hest = []; for k = 0 : length(x)/M-1 x1 = x(k*M+1:k*M+M); % pobranie kolejnego bloku próbek x[n] xx = [ x1 zeros(1,M) ]; % dodanie zer X1 = fft(xx); % FFT X = X1 + J.*X2; % suma widm FFT: obecnego (X1) i poprzedniego (X2) X2 = X1; % zapamiętanie obecnego widma yy = ifft(X.*H); % obliczenie y[n] y = [ y real(yy(1:M))]; % wydzielenie poprawnego bloku próbek y[n] i ich zapamiętanie e1 = d( k*M+1:k*M+M ) - y( k*M+1:k*M+M ); % obliczenie bloku próbek sygnału błędu e[n] e = [ e real(e1)]; % zapamiętanie go ee = [ e1 zeros(1,M) ]; % dodanie zer E = fft(ee); % FFT sygnału błędu e[n] delta = ifft( conj(X) .* E); % obliczenie gradientu funkcji kosztu, przejście do dz. czasu if(0) % # ograniczenie gradientu delta = [ delta(1:M)/((x1*x1')+gamma) zeros(1,M) ]; % # w dziedzinie czasu else % # P = lambda*P + alfa*abs(X(1:M)).^2; % # delta = [ delta(1:M)./P zeros(1,M)]; % # end % # Delta = fft(delta); % powrót z gradientem funkcji kosztu do dz. częstotliwości H = H + 2*mi*Delta; % adaptacja wag filtra w dziedzinie częstotliwości Hest = [ Hest; H( nr ) ]; % zapamiętanie wybranych wag filtra end
Przykład 8.7c
W przykładzie 8.7c (plik filtrFDAF_overlap_save_part.m) przedstawiono implementację w języku MATLAB filtra adaptacyjnego PBFDAF – overlap-save z podziałem odpowiedzi impulsowej na mniejsze fragmenty (Partitional Block FDAF).function [y,e,Hest,H] = filtrFDAF_overlap_save_part(Nh,M,d,x,nr,mi,alfa,delta,gamma) % Przykład 8.7c % Autor: Tomasz Zieliński, tzielin@agh.edu.pl Lb = length(x)/M; % liczba sekcji (bloków) próbek wejściowych Lh = Nh/M; % liczba sekcji (bloków) wag filtra lambda = 1-alfa; % alfa = 0.01; % współczynniki wykorzystywane podczas P = delta*ones(1,M); % delta = 0.25 % ogranicz. gradientu funkcji kosztu for k=1:Lh H(k,1:2*M) = fft( [ones(1,M)/M zeros(1,M)] ); % inicjowanie macierzy H wag filtr end y = []; e = []; Hest = []; % inicjowanie bx = zeros(1,2*M); % inicjowanie bufora bx na próbki x[n] X = zeros(Lh,2*M); % inicjowanie macierzy widm X for k = 0 : Lb-1 x1 = x(k*M+1:k*M+M); % pobranie kolejnej sekcji próbek wejściowych x[n] bx = [ bx(M+1:2*M) x1 ]; % zmodyfikowanie zawartości bufora tych próbek X = [ fft(bx); X(1:Lh-1,:) ]; % FFT bufora, aktualizacja macierzy widm sekcji sygnału x[n] XH = X.*H; % filtracja blokowa sygnału x[n] w dz. częstotliwości by = real(ifft(sum(XH))); % złożenie wyników filtracji (sum), powrót do dz. czasu y = [ y by(M+1:2*M) ]; % zapisanie sygnału wyjściowego y[n] e1 = d( k*M+1 :k*M+M ) - y( k*M+1 : k*M+M ); % obliczenie próbek błędu e[n] e = [ e real(e1)]; % zapamiętanie ich ee = [ zeros(1,M) e1 ]; % utworzenie wektora próbek błędu e[n] E = fft(ee); % przejście do dziedziny częstotliwości for k=1:Lh XE(k,:) = conj(X(k,:)) .* E; % obliczenie gradientu funkcji kosztu w dz. częstotliwości end if(1) % opcjonalne ograniczenie gradientu funkcji kosztu XE = XE.'; % transpozycja bez sprzężenia delta = ifft(XE ); % przejście z gradientem do dziedziny częstotliwości if(1) delta = [ delta(1:M,:); zeros(M,Lh)]; end % OK if(0) delta = [ delta(1:M,:)/((x1*x1')+gamma); zeros(M,Lh)]; end % test if(0) P = lambda*P + alfa*abs(X(1:M)).^2; delta = [ delta(1:M,:)./(P); % test zeros(M,Lh)]; end XE = fft(delta); % powrót z gradientem do dziedziny czasu XE = XE.'; % transpozycja bez sprzężenia end H = H + 2*mi*XE; % adaptacja wag filtra w dziedzinie częstotliwości Hest = [ Hest; H( nr ) ]; % zapamiętanie wybranych wag filtra end