Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Procesamiento Adaptativo
Dr. Ing. Marcelo Risk
Instituto Tecnolgico de Buenos Aires
ndice
1. Introduccin
2. Filtrado adaptativo
2.1. Estructura general de los filtros adaptativos . . . . . . . . . .
2.2. Identificacin de los parmetros . . . . . . . . . . . . . . . . .
2.3. Correccin adaptativa de seales . . . . . . . . . . . . . . . . .
2.4. Tcnicas de estimacin ptima . . . . . . . . . . . . . . . . . .
2.5. Mtodo de resolucin directa . . . . . . . . . . . . . . . . . . .
2.6. Mtodos iterativos . . . . . . . . . . . . . . . . . . . . . . . .
2.6.1. Algoritmo de gradiente mediante el mtodo de Newton
2.6.2. Mtodo de gradiente buscado por descenso escalonado .
2.6.3. Algoritmo LMS de Widrow . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
3
3
4
6
7
7
8
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
9
10
10
10
14
16
16
19
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
20
21
26
28
29
34
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1.
Introduccin
2.
Filtrado adaptativo
2.1.
2.2.
2.3.
Si para una entrada del sistema innaccesible se debe actuar sobre la seal de
salida de forma tal de realizar algn tipo de correccin de la seal, como por ejemplo
la eliminacin de interferencia en la seal de electrocardiograma (ECG), o para la
separacin del ECG materno del fetal, entonces en este caso la informacin de la
seal y de la correccin requerida es de extrema importancia. Un diagrama de este
tipo de filtro correctivo se ve en la figura 2.
Otro tipo de ejemplo muy utilizado de filtro adaptativo que se conoce como filtro
de prediccin lineal, es aquel que provee a su salida las salidas futuras del proceso.
La misin especfica de un filtro de prediccin lineal es la de estimar la salida
futura del proceso como una combinacin lineal de las salidas presente y pasada.
ruido
e(t)
ruido
s(t)
Sistema
+
Criterio
de Error
Modelo
Ajuste del
Modelo
2.4.
(2)
(3)
(4)
Ruido
Seal corregida
Filtro
Adaptativo
Algoritmo
Adaptativo
Conocimiento
apriori de
seal y ruido
Criterio
+
Procesador
Adaptativo
Delay
error
(5)
de donde:
wn =
p
X
i wni +
i=1
m
X
j xnj
(6)
j=0
Entonces para el error entre la salida del sistema fsico y modelo se utiliza la
ecuacin 3, luego:
yn =
p
X
i yni +
i=1
m
X
j xnj
(7)
j=0
p
m
X
X
0
0
en =
(j j )xnj
(i i )yni +
(8)
j=0
i=1
(9)
j = j
0
j = j
1ip
0jm
(10)
2.5.
=0
i
=0
j
1ip
(11)
0jm
Si se trata de un proceso cuasiestacionario, debe emplearse la esperanza matemtica de ECM como la suma temporal dentro del perodo de estacionareidad del
proceso, luego el clculo debe repetirse peridicamente, de manera de cubrir todo el
tiempo en estudio.
2.6.
Mtodos iterativos
f (x0 ) =
f (x0 )
x 0 x1
(12)
f (x0 )
f 0 (x0 )
(13)
entonces:
x1 = x0
luego:
xk+1 = xk
f (xk )
f 0 (xk )
k = 0, 1, ...
(14)
f (x) = (x)
(15)
(x)
00
=
(x)
0
(x)
ik+1 = ik 00
(x)
ik+1
ik
1ip
(16)
0jm
2.6.2.
En este caso los coeficientes o pesos son ajustados segn el gradiente en cada
paso, lo cual simplifica notablemente el clculo.
Este mtodo est gobernado por las ecuaciones en la cual es una constante
que regula el tamao del paso. Al igual que el mtodo anterior, un valor demasiado
pequeo de requerir un elevado nmero de iteraciones para alcanzar un mnimo,
y un valor excesivo puede ocasionar inestabilidades en el algoritmo.
Tanto en este caso como en el anterior se parte utilizando todo el conocimiento
previo sobre los valores a estimar y luego es desplazada la estimacin inicial descendiendo sobre la superficie de ECM en la direccin del gradiente (perpendicular a las
curvas de nivel) hasta alcanzar un mnimo.
La diferencia entre este mtodo y el de Newton-Raphson radica en la practicidad
del algoritmo puesto que en el primero es necesario resolver una matriz inversa.
El clculo de los coeficientes en este mtodo se realiza con las siguientes ecuaciones:
= ik
j
ik+1 = ik
1ip
ik+1
0jm
(17)
ik+1 = ik
ik+1
1ip
(18)
0jm
(19)
(20)
3.
3.1.
f1
f2
fn
~
~
~
Pseudofiltro
x
Filtro
Adaptativo
-
error
3.1.1.
Entrada
Primaria
s+nO
Fuente
de seal
Salida
nO
y
Entrada
Referencia
Fuente
de ruido
Filtro
Adaptativo
n1
error
A(z)
1 B(z)
(21)
3.2.
3.2.1.
10
A(z)
B(z)
X0
X1
W0
W1
W2
X2
W3
X3
11
N
1
X
Wk Xk
(22)
k=0
W0
X(n)
T
W1
X(n-1)
T
W2
Y(n)
X(n-2)
T
W3
X(n-3)
N
1
X
Wk Xk (n k)
(23)
k=0
12
(24)
por lo tanto:
e(n) = d(n)
N
1
X
Wk Xk (n k)
(25)
k=0
N
1
X
Wk Xk (n k) +
k=0
N
1
X
!2
Wk Xk (n k)
(26)
k=0
(27)
m=0
quedando:
=
M
1
X
m=0
d (n) 2
N
1
X
Wk rdx (n) +
n=0
N
1 N
1
X
X
Wk Wl rxx (n l)
(28)
n=0 l=0
donde las ecuaciones rdx y rxx las correlaciones cruzadas entre la salida deseada
y la entrada y la autocorrelacin da la entrada respectivamente.
El error cuadrtico medio describe una superficie de performance, cuando se
lo grafica con respecto a los pesos W , en la figura siguiente podemos observar una
superficie de performance para el caso de dos pesos, donde tambin apreciamos
los pesos ptimos W1 y W2 que corresponden al mnimo de de la superficie de
performance.
El proceso de adaptacin busca minimizar el error cuadrtico medio, para lograr
este objetivo se propone el mtodo de descenso a pasos a travs de la superficie de
performance.
Con el mtodo de descenso a pasos es posible recalcular cada peso teniendo
informacin acerca del peso anterior y del gradiente en el punto de peso anterior
sobre la superficie de performance, multiplicado por un coeficiente de velocidad de
convergencia, como lo indica la ecuacin 29.
Wk (n + 1) = Wk (n) + (5k )
(29)
(31)
Se utiliza el error instantneo porque est disponible muestra a muestra durante la optimizacin de los pesos del filtro. Entonces desarrolando la derivada y
reemplazando por la definicin de la ecuacin 25, tenemos:
e(n)
(32)
Wk (n + 1) = Wk (n) 2e(n)
Wk (n)
y reemplazando con 25, quedando:
P 1
d(n) N
W
X
(n
k)
k
k
k=0
Wk (n + 1) = Wk (n) 2e(n)
Wk (n)
(33)
(34)
M
1
X
1
Px =
X 2 (n)
M + 1 n=0
(36)
3.3.
El combinador lineal adaptativo se puede implementar como una clase, en lenguaje C++ [4], y en Python [5, 2]. Dentro de la clase FiltroAdaptativo estn encapsuladas todas las propiedades necesarias para el funcionamiento de un objeto que
maneja un vector de datos Xk, un vector de pesos Wk, y otras variables tales el
error Ek, la cantidad de elementos Cantidad y el valor de coeficiente de velocidad de
optimizacin Alfa, dems de las funciones necesarias para la carga de los vectores,
el clculo de la salida y la optimizacin de los coeficientes del filtro.
14
W0
X(n)
T
W1
X(n-1)
T
W2
Y(n)
X(n-2)
T
W3
X(n-3)
e(n)
Algoritmo de
cuadrados mnimos
15
d(n)
3.3.1.
// FILTADAPT.H
#include
#include
#include
#include
<math.h>
<stdlib.h>
<iostream.h>
<fstream.h>
class FiltroAdaptativo {
double *Xk;
double *Wk;
double Ek;
double Sk;
int Cantidad;
public:
double Alfa; // en Alfa a mu por 2
FiltroAdaptativo( int n = 20);
~FiltroAdaptativo();
double Calcula( void);
void LlenaPesos( double *Array, int cantidad);
void LlenaEntradas( double *Array, int cantidad);
void LlenaPesos( double *Array);
void LlenaEntradas( double *Array);
double MuestraSalida( void); void MuestraSet( void);
void CalculaNuevoSet( double e);
double put ( double d); double operator ()( double d)
{
return put (d);
}
int GuardaPesos( char *name); int LeePesos( char *name);
};
3.3.2.
// FILTADAPT.CPP:
#include "filtadapt.h"
#include <stdlib.h>
FiltroAdaptativo::FiltroAdaptativo( int n)
{
16
FiltroAdaptativo::MuestraSet( void)
<< endl;
int j = 0; j < Cantidad; j++)
<< Wk[j] << ", ";
17
A.close();
return 0;
}
int FiltroAdaptativo::LeePesos( char *name)
{
ifstream A;
A.open(name);
if( !A)
return -1;
int j;
A >> j;
if( j != Cantidad)
return -2;
for( int j = 0; j < Cantidad; j++)
A >> Wk[j];
A.close();
return 0;
}
3.3.3.
import sys
import math
from random import *
from pylab import *
class FiltroAdaptativo:
def __init__(self,n):
self.Ek = 1
self.Sk = 0
self.Cantidad = n
self.Alfa = 1.0 / (100.0*float(self.Cantidad)) # en Alfa va mu por 2
self.Xk = zeros(self.Cantidad)
self.Wk = zeros(self.Cantidad)
def Calcula(self):
Suma = 0.0
for j in range(self.Cantidad):
Suma += self.Wk[j] * self.Xk[j]
self.Sk = Suma
def LlenaPesos(self,Array):
19
for j in range(self.Cantidad):
self.Wk[j] = Array[j]
def LlenaEntradas(self,Array):
for j in range(self.Cantidad):
self.Xk[j] = Array[j]
def MuestraSalida(self):
print "Sk = " + self.Sk
def MuestraSet(self):
print self.Wk
def MuestraEntradas(self):
print self.Xk
def CalculaNuevoSet(self,ee):
self.Ek = ee
for j in range(self.Cantidad):
self.Wk[j] = self.Wk[j] + self.Alfa*self.Ek*self.Xk[j]
def put(self,dd):
for j in range(1,self.Cantidad):
self.Xk[self.Cantidad-j] = self.Xk[self.Cantidad-1-j]
self.Xk[0] = dd
self.Calcula()
return self.Sk
4.
4.1.
(37)
donde a y b son los coeficientes del filtro, cuya condicin de estabilidad es que la
suma de los coeficientes sea menor o igual a uno.
20
Figura 10: Respuesta del filtro IIR y del filtro adaptativo a un impulso.
4.1.1.
Figura 11: Respuesta del filtro IIR y del filtro adaptativo a un escaln.
22
23
// adaptativo
#include
#include
#include
#include
<iostream.h>
<fstream.h>
<math.h>
"filtadapt.h"
cin >> a;
cout << "b = ";
cin >> b;
dAnt = 0.0;
// ajuste valor Alfa (coeficiente de velocidad de
convergencia)
// del algoritmo LMS
F.Alfa = 1.0 / (20.0*double(CantidadCoeficientes)*Px);
cout << "Busca la solucion optima por el metodo LMS ..." << endl;
for( j = 0; j < Number; j++){
x = noise[j];
d = a*x + b*dAnt;
y = F(x);
e = d - y;
F.CalculaNuevoSet( e);
dAnt = d;
if( j == 0)
cout << "Error inicial = " << e << endl;
}
cout << "Error final = " << e << endl;
F.GuardaPesos( "c:\\neural\\pesos.txt");
// Respuesta al impulso de ambos filtros
Salida << "Respuesta al impulso" << endl;
cout << "Respuesta al impulso..." << endl;
Salida << "x\td\ty" << endl;
for( j = 0; j < 50; j++){
x = 0.0;
if( j == 25)
x = 1.0;
d = a*x + b*dAnt;
y = F(x);
Salida << x << "\t" << d << "\t" << y << endl;
dAnt = d;
}
Salida << endl;
Salida << "Respuesta al escalon" << endl;
cout << "Respuesta al escalon..." << endl;
Salida << "x\td\ty" << endl;
for( j = 0; j < 50; j++){
x = 0.0;
if( j == 25)
25
x = 1.0;
d = a*x + b*dAnt;
y = F(x);
Salida << x << "\t" << d << "\t" << y << endl;
dAnt = d;
}
delete noise;
cout << endl << "FIN";
}
4.1.2.
import sys
sys.path.append(....) # poner el path de FiltroAdaptativo.py
import math
from random import *
from pylab import *
from FiltroAdaptativo import *
F = FiltroAdaptativo(20)
Number = 5000
Px = 0.0
Mean = 0.0
noise = zeros(Number)
seed()
for j in range(Number):
noise[j] = normalvariate(0.0,1.0)
Px += noise[j] * noise[j]
Px /= float(Number+1)
x = 0.0
y = 0.0
dAnt = 0.0
e = 0.0
a = 0.3
b = 0.7
F.MuestraSet()
F.Alfa = 1.0 / (20.0*float(F.Cantidad)*Px)
26
print F.Alfa
for j in range(Number):
x = noise[j]
d = a*x + b*dAnt
y = F.put(x)
e = d - y
F.CalculaNuevoSet(e)
dAnt = d
F.MuestraSet()
N = 100
xx = arange(N)
yy = zeros(N)
zz = zeros(N)
yy[N/2] = 1.0
F.LlenaEntradas(zeros(20))
for j in range(1,N):
zz[j] = F.put(yy[j])
yy[j] = a*yy[j] + b*yy[j-1]
subplot(211)
plot(xx,yy,b)
ylim(-0.1,1.1)
title(Filtrado con $y(n)=ax(n)+by(n-1)$)
subplot(212)
plot(xx,zz,g)
ylim(-0.1,1.1)
title(Filtrado con $FiltroAdaptativo$)
savefig("EjercicioIdentificacionSistemaRespImpulso.eps")
close()
yy = zeros(N)
zz = zeros(N)
for j in range(N/2,N):
yy[j] = 1.0
27
F.LlenaEntradas(zeros(20))
for j in range(1,N):
zz[j] = F.put(yy[j])
yy[j] = a*yy[j] + b*yy[j-1]
subplot(211)
plot(xx,yy,b)
ylim(-0.1,1.1)
title(Filtrado con $y(n)=ax(n)+by(n-1)$)
subplot(212)
plot(xx,zz,g)
ylim(-0.1,1.1)
title(Filtrado con $FiltroAdaptativo$)
savefig("EjercicioIdentificacionSistemaRespEscalon.eps")
close()
4.2.
En muchas ocasiones una seal de gran ancho de banda w(n) se encuentra interferida por la suma de ruido de ancho de banda estrecho s(n), conformando la seal
suma x(n); las dos seales que forman x(n) no estn correlacionadas:
x(n) = w(n) + s(n)
(38)
28
x(n)
salida
s(n)
Filtro
Adaptativo
retardo
T
decorrelacionador
e(n) = x(n)
- s(n)
s (n) =
N
1
X
Wk (n)x(n k T )
(39)
k=0
Figura 14: error2 para las primeras 500 iteraciones durante la adaptacin del filtro.
30
Figura 15: La seal superior el ECG original sin ruido ni interferencias, en la seal
central el mismo ECG pero con la interferencia sumada, y finalmente en la seal
inferior la salida del filtro adaptativo, note en esta ltima el comportamiento para
las primeras 20 muestras, en las cuales el filtro adaptativo todavia no se enganch.
31
#include <fstream.h>
#include <math.h>
#include "filtadapt.h"
void main( void) {
int CantidadCoeficientes = 20;
cout << "Orden del filtro adaptativo = ";
cin >> CantidadCoeficientes;
FiltroAdaptativo F(CantidadCoeficientes);
int Number = 4000;
ofstream Salida;
Salida.open("filtro2.txt");
int j;
double Px = 0.0;
double Mean = 0.0;
noise = new double[Number];
double *ecg;
ecg = new double[Number];
double *ecgl;
ecg1 = new double[Number];
double Pi = 3.14;
// Calcula ruido blanco sin valor medio mas ruido
// de senoidal
for( j = 0; j < Number; j++){
noise[j] = double(random(1000))/10000.0;
noise[j] += sin( 1000.0*2.0*Pi*double(j)/double(number));
Mean += noise[j];
}
Mean /= double(Number);
for( j = 0; j < Number; j++){
noise[j] -= Mean;
Px += noise[j]*noise[j]);
}
// Calcula potencia del ruido
Px /= double(Number+1);
double x, y, d, dAnt, dAnt2, e;
char NameInput[80] = "apb.txt";
32
ifstream In;
In.open( NameInput);
if( !In){
cout << "I cant open the file !!!!!";
return
}
double data;
for( j = 0; j < Number; j++){
In >> data;
data /= 10.0;
ecg[j] = data;
ecg[j] += sin(
1000.0*2.0*Pi*double(j)/double(Number));
ecg1[j] = data;
In >> data;
}
// ajuste valor Alfa (coeficiente de velocidad de
convergencia)
// del algoritmo LMS
F.Alfa = 1.0 / (20.0*double(CantidadCoeficientes)*Px);
cout << "Alfa = " << F.Alfa << endl;
// Busca la solucion optima por el metodo LMS
cout << "Busca la solucion optima por el metodo LMS ..." << endl;
dAnt = 0.0;
dAnt2 = 0.0;
for( j = 0; j < Number; j++){
x = noise[j];
y = F(dAnt2);
dAnt = x;
dAnt2 = dAnt;
e = x - y;
// cout << e << endl;
F.CalculaNuevoSet( e);
if( j == 0)
cout << "Error inicial = " << e << endl;
}
cout << "Error final = " << e << endl;
Salida << endl;
Salida << "Filtrado de ruido" << endl;
cout << "Filtrado de ruido..." << endl;
Salida << "ecg\tx\ty" << endl;
dAnt = 0.0;
33
dAnt2 = 0.0;
for( j = 0; j < Number; j++){
x = ecg[j];
y = F(dAnt2);
dAnt = x;
dAnt2 = dAnt;
d = x - y;
Salida << ecgl[j] << "\t" << x << "\t" << d << endl;
dAnt = d;
}
delete noise;
delete ecg;
delete ecgl;
cout << endl << "FIN";
}
4.2.2.
import sys
sys.path.append(...)
import math
from random import *
from pylab import *
from FiltroAdaptativo import *
F = FiltroAdaptativo(20)
Number = 4000
ecg = zeros(Number)
ecgOrig = zeros(Number)
ecg1 = zeros(Number)
noise = zeros(Number)
Px = 0.0
Mean = 0.0
# calcula ruido blanco + senoidal
for j in range(Number):
noise[j] = normalvariate(0.0,1.0)/10
noise[j] += math.sin(1000.0*2.0*math.pi*float(j)/float(Number))
Mean += noise[j]
Mean /= float(Number)
34
for j in range(Number):
noise -= Mean
Px += noise[j]*noise[j]
Px /= float(Number+1)
fh = open(apb.txt)
for j in range(Number):
linea = fh.readline()
w = linea.split()
ecgOrig[j] = (float(w[0])-128.0)/10.0
ecg[j] = (float(w[0])-128.0)/10.0 + math.sin(1000.0*2.0*math.pi*float(j)/floa
ecg1[j] = (float(w[1])-128.0)/10.0
x = zeros(Number)
y = zeros(Number)
d = zeros(Number)
dAnt = 0.0
dAnt2 = 0.0
e = zeros(Number)
F.Alfa = 1.0 / (20.0*float(F.Cantidad)*Px)
# adaptacion del filtro adaptativo
for j in range(Number):
x[j] = noise[j]
y[j] = F.put(dAnt2)
dAnt = x[j]
dAnt2 = dAnt
e[j] = x[j] - y[j]
F.CalculaNuevoSet(e[j])
# filtrado del ECG
dAnt = 0.0
dAnt2 = 0.0
for j in range(Number):
x[j] = ecg[j]
y[j] = F.put(dAnt2)
dAnt = x[j]
dAnt2 = dAnt
d[j] = x[j] - y[j]
dAnt = d[j];
plot(ecgOrig[:250]+20,g)
plot(x[:250]+10,b)
35
plot(d[:250],r)
savefig("EjercicioCancelacionRuidoECG.eps")
close()
e2 = e*e
plot(e2[:500])
xlabel(iteraciones)
ylabel($error^2$)
savefig("ErrorCancelacionRuidoECG.eps")
close()
Referencias
[1] Ricardo Armentano, Javier Fochesatto, and Marcelo Risk. Anlisis de Seales
y Sistemas. Editorial Rocamora, 1996.
[2] Perry Greenfield and Robert Jedrzejewski. Using Python for interactive data
analysis. Association of Universities for Research in Astronomy, 2007.
[3] R. W. Lucky. Automatic equalization for digital communication. Bell Systems
Technology Journal, 44:547588, 1965.
[4] Al Stevens and Clayton Walnut. Standard C++ Bible. IDG Books, 2000.
[5] Guido van Rossum and Fred L. Drake. Python tutorial, Release 2.5. Python
Software Foundation, docs@python.org, 2006.
[6] Bernard Widrow, John Glover, John MacCool, John Kaunitz, Charles Williams,
Robert Hearn, James Zeidler, Eugene Dong, and Robert Goodlin. Adaptive noise
cancelling: principles and applications. Proceedings of the IEEE, 63(12):1692
1716, 1975.
[7] Bernard Widrow and Michael Lehr. 30 years of adaptive neural networks: perceptron, madaline, and backpropagation. Proceedings of the IEEE, 78(9):14151442,
1990.
36