Sei sulla pagina 1di 36

Introducción a las Redes Neuronales: Parte 1 Procesamiento Adaptativo

Dr. Ing. Marcelo Risk Instituto Tecnológico de Buenos Aires

Índice

1. Introducción

2

2. Filtrado adaptativo

2

2.1. Estructura general de los filtros adaptativos

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

2

2.2. Identificación de los parámetros

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

3

2.3. Corrección adaptativa de señales

 

.

.

.

.

.

.

.

3

2.4. Técnicas de estimación óptima .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

4

2.5. Método de resolución directa

 

.

.

.

.

.

.

.

6

2.6. Métodos iterativos

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

7

2.6.1. Algoritmo de gradiente mediante el método de Newton

 

7

2.6.2. Método de gradiente buscado por descenso escalonado

8

2.6.3. Algoritmo LMS de Widrow

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

8

3. Aplicaciones del filtrado adaptativo

 

9

3.1. Modelización adaptativa en la síntesis de filtros FIR

 

9

3.1.1. Cancelación adaptativa de ruido

 

9

3.1.2. Modelización adaptativa en la síntesis de filtros IIR .

.

.

.

.

.

10

3.2. Implementación de filtros adaptativos

 

10

3.2.1.

Estructura básica de un filtro adaptativo

 

10

3.3. Implementación del combinador lineal adaptativo

 

.

.

.

.

.

.

.

.

.

.

.

14

3.3.1. Código fuente de FILTADAPT.H

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

16

3.3.2. Código fuente de FILTADAPT.CPP

.

.

.

.

.

.

.

.

.

.

.

.

.

.

16

3.3.3. Código fuente de FiltroAdaptativo.py

.

.

.

.

.

.

.

.

.

.

.

.

.

.

19

4. Ejemplos de aplicaciones del filtrado adaptativo

 

20

4.1. Ejemplo de identificación de un sistema

 

20

4.1.1. Código fuente de FILTRO.CPP

21

4.1.2. Código fuente de IdentificacionSistema.py

 

.

.

.

.

.

.

.

.

.

.

.

26

4.2. Ejemplo de cancelación de interferencias

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

28

4.2.1. Código fuente de FILTRO2.CPP

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

29

4.2.2. Código fuente de CancelacionRuido.py

.

.

.

.

.

.

.

.

.

.

.

.

.

34

1

1. Introducción

En el presente apunte se puede apreciar una breve introducción al procesamiento adaptativo de señales, y su relación con las redes neuronales (RN), es especial con las arquitecturas de RN basadas el modelo de neurona denominado perceptrón. La segunda sección de este documento describe los fundamentos del filtrado adaptativo, y luego una implementación de los mismos a partir de un combinador lineal adaptativo. Finalmente se estudiarán dos aplicaciones, uno a la identificación de un sistema y otro para la cancelación de interferencias. La parte 2 muestra una introducción a las redes neuronales, a partir de la modeli- zación de una neurona con un combinador lineal modificado. Al final de dicha sección se presenta una implementación completa de una RN, y un ejemplo de aplicación de la misma.

2. Filtrado adaptativo

Los filtros adaptativos son aquellos filtros autoprogramables cuya respuesta en frecuencia o función transferencia está alterada o adaptada para dejar pasar sin degradación las componentes deseadas y atenuar las señales no deseadas, o que generan interferencias, o reducir cualquier distorsión de se`nal de entrada. Los primeros filtros adaptativos o de autoaprendizaje fueron descriptos por Lucky [3], quien los utilizó en el diseño de un ecualizador para compensar la distorsión en sistemas de transmisión de datos. Como generalmente no existe información disponible a priori, los filtros adaptati- vos requieren un período inicial de aprendizaje, también denominado de adaptación. Los algoritmos utiizados en el procesamiento digital de señales han tenido su precedente en la teoría de los sistemas adaptativos de control, si bien existen con respecto de éstos ciertas diferencias.

2.1. Estructura general de los filtros adaptativos

Un filtro adaptativo está compuesto principalmente por tres partes:

a) El índice de performance, el cual debe ser optimizado.

b) El algoritmo que recalcula los parámetros del filtro.

c) La estructura del filtro, que realiza las operaciones requeridas sobre la señal.

El índice de performance depende de la aplicación, es decir, está determinado por el tipo de trabajo del sistema adaptativo. En general se toma como evaluador la minimización del error cuadrático medio e el cual generalmente es satisfactoria, como lo muestra la ecuación 9, donde y es la salida del sistema, y modelo es la salida del modelo.

e = (y y modelo ) 2

2

(1)

El algoritmo de optimización es el mecanismo mediante el cual los parámetros, optimizando el criterio, son calculados. Existen dos tipos de algoritmos, el primero es no recursivo, y requiere la colección de todos los datos en una ventana temporal, para luego resolver un sistema de ecuaciones. El segundo tipo de algoritmo es el algoritmo del gradiente, el cual requiere la solución de un conjunto de ecuaciones lineales por inversión de una matriz y de esta forma los resultados no estarán disponibles en tiempo real. En rigor los algoritmos más utilizados desde el punto de vista del procesamiento digital son del tipo recursivo, el cual se actualiza a partir de cada entrada de la señal de entrada o con un pequeño grupo de muestras. Los resultados están disponibles inmediatamente y es posible el seguimiento de señales no estacionarias. Un ejemplo de ello es el algoritmo LMS (least mean squa- re). Como es obvio la estructura del filtro depende tanto del algoritmo como de la aplicación.

2.2. Identificación de los parámetros

La identificación de parámetros de un sistema es un procedimiento muy utilizado para el análisis en sistemas de control. Para controlar el comportamiento óptimo de un sistema es necesario conocer su conducta dinámica. Esta está usualmente dada por ecuaciones diferenciales que relacionan la entrada y la salida del sistema. Si sólo se reconoce la estructura de las ecuaciones, pero no los parámetros, algún tipo de algoritmo de computación podría ser aplicado para estimarlos. La figura 1 muestra el diagrama en bloques de un sistema de identificación adap- tativo. Las entradas y salidas ruidosas son medidas tanto durante la aplicación normal o durante la prueba de especificaciones. Estas son ingresadas a un filtro con coeficientes variables, los cuales están ajustados por un algoritmo optimizador. Luego de la adaptación, el filtro representa el mejor modelo para el sistema, y sus coeficientes son los parámetros identificados del sistema.

2.3. Corrección adaptativa de señales

Si para una entrada del sistema innaccesible se debe actuar sobre la señal de salida de forma tal de realizar algún tipo de corrección de la señal, como por ejemplo la eliminación de interferencia en la señal de electrocardiograma (ECG), o para la separación del ECG materno del fetal, entonces en este caso la información de la señal y de la corrección 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 predicción lineal, es aquel que provee a su salida las salidas futuras del proceso. La misión específica de un filtro de predicción lineal es la de estimar la salida futura del proceso como una combinación lineal de las salidas presente y pasada.

3

+
+

ruido

Sistema

Sistema
Sistema
Sistema

e(t)

+ ruido Sistema e(t) ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1:
ruido +
ruido
+

s(t)

+ ruido Sistema e(t) ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1:
+ ruido Sistema e(t) ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1:
+ ruido Sistema e(t) ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1:

Criterio

de Error

Modelo

+ ruido Sistema e(t) ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1:

Ajuste del

Modelo

ruido + s(t) Criterio de Error Modelo Ajuste del Modelo Figura 1: Diagrama en bloques de

Figura 1: Diagrama en bloques de un sistema de identificación adaptativo.

Originariamente los filtros de predicción se utilizaron para predecir las trayecto- rias de un blanco en movimiento en aplicaciones militares, y hoy en día se utilizan para predecir la evolución de procesos muy diversos. La figura 3 muestra el dDia- grama en bloques de un filtro de prediccion lineal. La señal de entrada s, y versión retardada de la misma son enviadas al procesador adaptativo, el cual debe intentar predecir la entrada para hacer que con y y d se calcule el error, buscando que este último se minimize. Los filtros de predicción se utilizan además en decodificación de señales y reducción de ruido.

2.4. Técnicas de estimación óptima

Como se dijo anteriormente el error es la resta (según la aplicación) entre la salida del sistema y la del modelo:

e = y y modelo

En el caso de señales discretas este será:

e n = y n w n

(2)

(3)

si para simplificar la nomenclatura hacemos y modelo = w:

e n = y n w n

4

(4)

Señal a ser corregida

Σ
Σ

Ruido

Filtro Adaptativo w Algoritmo Adaptativo Conocimiento apriori de señal y ruido
Filtro
Adaptativo
w
Algoritmo
Adaptativo
Conocimiento
apriori de
señal y ruido

Criterio

Señal corregida

Figura 2: Diagrama en bloques de un sistema de correccion adaptativa de señales.

s d + y Procesador Delay Σ Adaptativo - error
s
d
+
y
Procesador
Delay
Σ
Adaptativo
-
error

Figura 3: Diagrama en bloques de un filtro de prediccion lineal.

5

si tomamos para identificar un modelo tipo ARMA:

de donde:

W(z)

X(z) =

w n =

p

i=1

α

m j=0 β j

z j

1 p

i=0

α i z j

i w ni +

m

j=0

β j x nj

(5)

(6)

Entonces para el error entre la salida del sistema físico y modelo se utiliza la ecuación 3, luego:

e n =

y n =

p

i=1

α i y ni +

p

i=1

(α i α

i )y ni +

m

j=0

m

j=0

β j x nj

(β j β j )x nj

(7)

(8)

El error cuadrático medio (ECM ) es una magnitud se calcual como:

(9)

La expresión anterior representa en el espacio generado por los coeficientes α i y β j un hiperparaboloide de dimensiones p + m + 1, que posee un mínimo absoluto en el punto dado por:

ξ

2

= E(e n )

α j = α j β j = β j

1 i p 0 j m

(10)

El problema de estimar los coeficientes se reduce a calcular los coeficientes α i y β j que minimizan el error cuadrático ξ (ver ecuación 9).

2.5. Método de resolución directa

Los métodos de resolución directa consisten en calcular el punto en que se anulan todas las derivadas del error cuadrático medio, para las siguientes condiciones:

δξ

δα i

δξ

δβ j

= 0

1 i p

= 0

0 j m

(11)

Dado que la función ξ no posee máximos para los valores finitos de α i y β j la solución de las ecuaciones conducen al mínimo deseado.

6

Si se trata de un proceso cuasiestacionario, debe emplearse la esperanza mate- mática de ECM como la suma temporal dentro del período de estacionareidad del proceso, luego el cálculo debe repetirse periódicamente, de manera de cubrir todo el tiempo en estudio.

2.6. Métodos iterativos

Estos métodos involucran un menor número de operaciones matemáticas y pro- veen además una estimación de α i y β j adaptable a las fluctuaciones de los coe- ficientes verdaderos α i y β j . De los diversos métodos iterativos sólo estudiaremos el algoritmo del gradiente mediante el método de Newton-Raphson, el método del gradiente buscado por descenso escalonado, y el algoritmo LMS de Widrow.

2.6.1. Algoritmo de gradiente mediante el método de Newton

Este método consiste en descender sobre el hiperparaboloide de ECM siguiendo la dirección impuesta por el método de Newton-Raphson para la determinación de una raíz y por ende con una sencilla transformación, el mínimo de:

 

f

entonces:

 

x

luego:

(x 0 ) = f(x 0 x 1

)

x 0

1

= x 0

f(x 0 ) f (x 0

)

x k+1 = x k

f(x k ) ) f (x k

k = 0, 1,

(12)

(13)

(14)

La convergencia depende del valor inicial y de la naturaleza de f (x). Si ahora tomamos:

f(x) = ξ (x)

(15)

en vez de un cero se tendrá un mínimo, entonces:

α

β

k+1

i

k+1

i

=

=

α

β

k

i

k

i

µ

µ

ξ

(x)

ξ

(x)

ξ

(x)

ξ

(x)

1 i p

0 j m

(16)

El coeficiente µ es una constante que determina la dimensión del peso, y gobierna la velocidad de convergencia, es decir un valor de µ demasiado pequeño requiere un elevado número de iteraciones para alcanzar el mínimo.

7

2.6.2. Método de gradiente buscado por descenso escalonado

En este caso los coeficientes o pesos son ajustados según el gradiente en cada paso, lo cual simplifica notablemente el cálculo. Este método está gobernado por las ecuaciones en la cual µ es una constante que regula el tamaño del paso. Al igual que el m ´ todo anterior, un valor demasiado pequeño de µ requerirá un elevado número de iteraciones para alcanzar un mínimo, 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 estimación inicial descen- diendo sobre la superficie de ECM en la dirección del gradiente (perpendicular a las curvas de nivel) hasta alcanzar un mínimo. La diferencia entre este método y el de Newton-Raphson radica en la practicidad del algoritmo puesto que en el primero es necesario resolver una matriz inversa. El cálculo de los coeficientes en este método se realiza con las siguientes ecuacio- nes:

α

β

k+1

i

k+1

i

=

=

α

k

i

β

k

i

δξ

µ

δα i δξ µ δβ j

1 i p

0 j m

(17)

Donde el supraíndice indica el orden de iteración.

2.6.3. Algoritmo LMS de Widrow

En el algoritmo anterior se requiere la determinación del gradiente del ECM en cada iteración, es decir se estimo el gradiente de ξ. Bernard Widrow analizó las condiciones de estabilidad, la constante de tiempo de convergencia, y el error de estimación del algoritmo anterior, reemplazando el valor del gradiente por una estimación del mismo empleando una sola muestra [7]. Es decir, aproximando la esperanza matemática del ECM por el mismo pero en cada iteración. En otras palabras se toma a e k 2 como una estimación directa de ξ, entonces:

α

β

k+1

i

k+1

i

=

=

α

β

k

i

k

i

µ δ(e 2 )

δα i µ δ(e 2

)

k

k

δβ j

1

0

i p

j m

(18)

Si tomamos la definición del ECM y elevamos al cuadrado ambos miembros, calculamos la derivadas parciales y reemplazamos en la ecuación anterior se obtiene:

α

k+1

i

β

k+1

i

=

=

α

k

i

β

k

i

+

2µe k y k1

(19)

+

2µe k x k1

(20)

8

3. Aplicaciones del filtrado adaptativo

3.1. Modelización adaptativa en la síntesis de filtros FIR

La idea básica es asociar a un pseudofiltro las especificaciones ideales de un filtro que generalmente no será físicamente realizable. El pseudofiltro es únicamente conceptual; el esquema utilizado puede verse en la figura 4.

~ f 1 f ~ 2 Pseudofiltro ~ f n d + x y Σ
~
f
1
f
~
2
Pseudofiltro
~
f
n
d
+
x
y
Σ
Filtro
Σ
Adaptativo
-
error
Figura 4: Diagrama en bloques de un sistema de filtrado adaptativo a través de un
pseudofiltro.

3.1.1. Cancelación adaptativa de ruido

La situación básica de cancelación de ruido está ilustrada en la siguiente figura

5.

Una señal es transmitida de un canal a un sensor que recibe la señal más ruido no correlacionado n0. Esta combinación aditiva forma la primera entrada. Un segundo sensor recibe ruido n1 el cual no está correlacionado con la señal pero sí lo está de alguna manera con el ruido n0. Esta constituye la entrada de referencia al cancelador. el ruido n1 es filtrado de forma tal de obtener una réplica n0. La salida se resta de la entrada primaria para producir una salida del sistema igual a s + n0 + y. Ejemplo de ello son la cancelación de ruido en señales de audio (n1 es la in- terferencia), cancelación de la interferencia en el ECG del corazón transplantado y

9

Primaria Entrada

Primaria Entrada de Fuente señal de Fuente ruido s+nO + Σ nO - y Adaptativo Filtro

de Fuente señal

de Fuente ruido

s+nO + Σ nO - y Adaptativo Filtro n1 error
s+nO
+
Σ
nO
-
y
Adaptativo Filtro
n1
error

Salida

Referencia Entrada

- y Adaptativo Filtro n1 error Salida Referencia Entrada Cancelador Adaptativo de Ruido Figura 5: Diagrama

Cancelador Adaptativo de Ruido

Figura 5: Diagrama en bloques de un sistema de cancelación de ruido con filtrado adaptativo.

separación del ECG materno del fetal como así también la cancelación de ecos en circuitos telefónicos de larga distancia.

3.1.2. Modelización adaptativa en la síntesis de filtros IIR

Como se ha visto anteriormente la transferencia de un filtro de respuesta infinita al impulso (IIR) a sintetizar será:

H(z) =

A(z)

1 B(z)

(21)

El diagrama en bloques de tal filtro se puede apreciar en la figura 6.

3.2. Implementación de filtros adaptativos

3.2.1. Estructura básica de un filtro adaptativo

Los filtros adaptativos se pueden implementar tanto como filtros de respuesta finita al impulso (FIR) o de respuesta infinita al impulso (IIR), pero en general se prefiere el esquema FIR debido a una mayor simplicidad y estabilidad, teniendo en cuenta que el algoritmo de adaptación es el encargado de calcular los coeficientes del filtro, por lo cual un esquema FIR asegura la estabilidad del filtro a pesar de las combinaciones de coeficientes calculadas. La estructura de un filtro FIR se puede desarrollar con un combinador lineal, cuyo diagrama se muestra en la figura 7.

10

y

+ A(z) B(z)
+
A(z)
B(z)

x

y + A(z) B(z) x Figura 6: Diagrama en bloques de un filtro adaptativo IIR. W

Figura 6: Diagrama en bloques de un filtro adaptativo IIR.

W 0 X 0 W 1 X 1 Σ W 2 X 2 W 3
W
0
X
0
W
1
X
1
Σ
W
2
X
2
W
3
X
3

Y

Figura 7: Diagrama en bloques de un combinador lineal.

11

La expresión del combinador es:

Y =

N1

k=0

W k X k

(22)

donde N es la cantidad de coeficientes u orden del filtro, X es el vector de entrada, W es el vector de pesos, e Y es la salida. La figura anterior muestra el combinador lineal en la forma de entrada paralelo, pero en la mayoría de las aplicaciones es necesario ingresar los datos (muestras) en forma serie, especialmente cuando el filtro se implementa en tiempo real y por lo tanto las muestras van llegando una a una, en este caso se debe utilizar la forma serie del combinador lineal, como lo muestra la figura 7.

X(n) T X(n-1) T X(n-2) T X(n-3)
X(n)
T
X(n-1)
T
X(n-2)
T
X(n-3)
W 0 W 1 Σ W 2 W 3
W
0
W
1
Σ
W
2
W
3

Y(n)

Figura 8: Diagrama en bloques de un combinador lineal serie.

En el combinador lineal con entrada serie podemos apreciar cómo se forma el vector de entrada X con la muestra actual X(n) y las muestras anteriores X(n 1) a X(n 3), para lograr el retardo entre dichas muestras se intercala un bloque de retardo T . La expresión del combinador lineal con entrada serie es la siguiente:

Y (n) =

N1

k=0

W k X k (n k)

(23)

Como se describió en la introducción, los sistemas de lazo cerrado utilizan la diferencia entre la salida deseada d(n) y salida actual Y (n) para calcular en error:

e(n) = d(n) Y (n)

12

(24)

por lo tanto:

e(n) = d(n)

N1

k=0

W k X k (n k)

(25)

Elevando el error al cuadrado obtenemos el denominado error cuadrático instan- táneo:

e 2 (n) = d 2 (n) 2

N1

k=0

W k X k (n k) + N1 W k X k (n k) 2

k=0

(26)

Por otro lado se define a error cuadrático medio como:

quedando:

ξ =

M1

m=0

ξ = E e 2 (n) =

M1

m=0

e 2 (n)

d 2 (n) 2

N1

n=0

W k r dx (n) +

N1 N1

n=0

l=0

W k W l r xx (n l)

(27)

(28)

donde las ecuaciones r dx y r xx las correlaciones cruzadas entre la salida deseada y la entrada y la autocorrelación da la entrada respectivamente. El error cuadrático 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 también apreciamos los pesos óptimos W 1 y W 2 que corresponden al mínimo de ξ de la superficie de performance. El proceso de adaptación busca minimizar el error cuadrático medio, para lograr este objetivo se propone el método de descenso a pasos a través de la superficie de performance. Con el método de descenso a pasos es posible recalcular cada peso teniendo información 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 ecuación 29.

W k (n + 1) = W k (n) + µ( k )

En el método de adaptación basado en el error cuadrático medio, el gradiente se define como:

(29)

k

= δ e 2 (n)

δW k (n)

(30)

entonces sustituyendo la ecuación 30 en la 29:

W k (n + 1) = W k (n) µ δ δW e 2 k (n) (n)

13

(31)

Se utiliza el error instantáneo porque está disponible muestra a muestra du- rante la optimización de los pesos del filtro. Entonces desarrolando la derivada y reemplazando por la definición de la ecuación 25, tenemos:

W k (n + 1) = W k (n) 2µe(n)

δ e(n)

δW k (n)

y reemplazando con 25, quedando:

W k (n + 1) = W k (n) 2µe(n) δ d(n) N1

k=0

W k X k (n k)

δW k (n)

(32)

(33)

Note que d(n) y X k (n) son independientes de W k , por lo tanto:

(34)

La ecuación 34 es la expresión final del algoritmo del método de los cuadrados mínimos. El coeficiente de velocidad de convergencia µ debe elegirse de forma tal de llegar al valor óptimo lo suficientemente rápido, pero sin perder estabilidad, por lo tanto los valores recomendados para µ deben estar en el rango descripto en la ecuación ??:

W k (n + 1) = W k (n) 2µe(n)X k (n)

1

(35)

20NP x donde N es la cantidad de coeficientes del filtro, y P x es la potencia de los datos durante el proceso de optimización:

0 < µ <

P x =

1

M + 1

M1

n=0

X 2 (n)

(36)

En la ecuación 36 M es la cantidad de muestras durante la optimización de los pesos. El combinador lineal cuando utiliza el método de los cuadrados mínimos se puede describir con el diagrama en bloques de la figura 9, de esta forma se denomina combinador lineal adaptativo.

3.3. Implementación del combinador lineal adaptativo

El combinador lineal adaptativo se puede implementar como una clase, en len- guaje C++ [4], y en Python [5, 2]. Dentro de la clase FiltroAdaptativo están encap- suladas 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 optimización Alfa, demás de las funciones necesarias para la carga de los vectores, el cálculo de la salida y la optimización de los coeficientes del filtro.

14

W0 X(n) T W1 X(n-1) T Σ W2 X(n-2) T W3 - Σ + X(n-3)
W0
X(n)
T
W1
X(n-1)
T
Σ
W2
X(n-2)
T
W3
-
Σ
+
X(n-3)
e(n)
cuadrados Algoritmo mínimos de
Figura 9: Diagrama en bloques de un combinador lineal serie adaptativo.

15

Y(n)

d(n)

3.3.1. Código fuente de FILTADAPT.H

// FILTADAPT.H

#include <math.h> #include <stdlib.h> #include <iostream.h> #include <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. Código fuente de FILTADAPT.CPP

// FILTADAPT.CPP:

#include "filtadapt.h" #include <stdlib.h>

FiltroAdaptativo::FiltroAdaptativo( int n)

{

16

Alfa = 1.0 / (100.0*double(n)); Ek = 1.0; Sk = 0.0; Cantidad = n; Xk = new double[Cantidad];

Wk = new double[Cantidad]; for( int j = 0; j < Cantidad; j++)

{

Xk[j] = 0.0; Wk[j] = 0.0;

}

}

FiltroAdaptativo::~FiltroAdaptativo()

{

delete Xk;

delete Wk;

}

void FiltroAdaptativo::LlenaPesos( double *Array, int cantidad)

{

for( int j = 0; j < cantidad; j++) Wk[j] = Array[j];

}

void FiltroAdaptativo::LlenaPesos( double *Array)

{

for( int j = 0; j < Cantidad; j++) Wk[j] = Array[j];

}

void FiltroAdaptativo::CalculaNuevoSet( double e)

{

Ek = e;

for( int j = 0; j < Cantidad; j++)

{

Wk[j] = Wk[j] + Alfa*Ek*Xk[j];

}

}

void FiltroAdaptativo::MuestraSet( void)

{

cout << endl;

for( int j = 0; j < Cantidad; j++) cout << Wk[j] << ", ";

}

17

double FiltroAdaptativo::Calcula( void)

{

double Suma = 0.0;

for( int j= 0; j < Cantidad; j++) Suma += Wk[j] * Xk[j]; Sk = Suma; return Sk;

}

double FiltroAdaptativo::put( double d)

{

for( int j = Cantidad-1; j > 0; j--) Xk[j] = Xk[j-1]; Xk[0] = d; return Calcula(); }

void FiltroAdaptativo::LlenaEntradas( double *Array, int cantidad)

{

for( int j = 0; j < Cantidad; j++) Xk[j] = Array[j]; Calcula();

}

void FiltroAdaptativo::LlenaEntradas( double *Array)

{

for( int j = 0; j < Cantidad; j++) Xk[j] = Array[j]; Calcula();

}

double FiltroAdaptativo::MuestraSalida( void)

{

return Sk;

}

int FiltroAdaptativo::GuardaPesos( char *name)

{

ofstream A; A.open(name); if( !A) return -1; A << Cantidad << endl; for( int j = 0; j < Cantidad; j++) A << Wk[j] << endl;

18

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.

Código fuente de FiltroAdaptativo.py

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. Ejemplos de aplicaciones del filtrado adaptativo

4.1. Ejemplo de identificación de un sistema

Los filtros adaptativos son capaces de identificar un sistema desconocido, en otras palabras de desarrollar una modelización, el objetivo es encontrar un filtro FIR que modelice el sistema desconocido [1]. El diagrama en bloques del proceso de modelización se muestra en la figura 3b. En los párrafos siguientes se describirá una implementación en C++ para la identificación de un sistema, en este ejemplo el sistema desconocido es un filtro IIR con la siguiente ecuación de recurrencia:

(37)

donde a y b son los coeficientes del filtro, cuya condición de estabilidad es que la suma de los coeficientes sea menor o igual a uno.

y(n) = ax(n) + by(n 1)

20

A continuación se describen los pasos a seguir para lograr dicho proceso:

1) Ambos sistemas, el filtro y el sistema desconocido, deben ser excitados por un generador de ruido aleatorio de valor medio nulo.

2) El filtro adaptativo comienza un proceso de optimización, comenzando los pesos con valores iniciales aleatorios pequeños; utilizando el método de los cuadrados mínimos se optimizan los pesos (coeficientes del filtro) minimizando el error.

3) La cantidad de iteraciones necesarias para la optimización se pueden calcular buscando un error mínimo y una cantidad máxima de iteraciones, en caso de no lograr el error mínimo.

En el ejemplo presentado el sistema desconocido (filtro IIR) y el filtro tienen una respuesta al impulso y al escalón como lo muestran las figuras 10 y 11, respectiva- mente, mientras que la figura 12 muestra el error 2 para las 1000 primeras iteraciones de la adaptación.

2 para las 1000 primeras iteraciones de la adaptación. Figura 10: Respuesta del filtro IIR y
2 para las 1000 primeras iteraciones de la adaptación. Figura 10: Respuesta del filtro IIR y

Figura 10: Respuesta del filtro IIR y del filtro adaptativo a un impulso.

4.1.1. Código fuente de FILTRO.CPP

// FILTRO.CPP: Identificacion de un sistema con un filtro

21

Figura 11: Respuesta del filtro IIR y del filtro adaptativo a un escalón. 22
Figura 11: Respuesta del filtro IIR y del filtro adaptativo a un escalón. 22

Figura 11: Respuesta del filtro IIR y del filtro adaptativo a un escalón.

22

Figura 12: error 2 para las 1000 primeras iteraciones de la adaptación.
Figura 12: error 2 para las 1000 primeras iteraciones de la adaptación.

23

// adaptativo

#include <iostream.h> #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 = 5000;

ofstream Salida; Salida.open( c:\neural\\filtro.txt);

int j; double Px = 0.0; double Mean = 0.0; double *noise; noise = new double[Number]; // Calcula ruido blnco sin valor medio for( j = 0; j < Number; j++){

noise[j] = double(random(1000))/1000.0; 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, e; // coeficientes del sistema a identificar double a = 0.3; double b = 0.7; cout << "Coeficientes del sistema a identificar: " << endl; cout << "y[n] = a*x[n] + b*y[n-1]" << endl; cout << "a = ";

24

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 for( j = 0; j < Number; j++){

x

= noise[j];

d

= a*x + b*dAnt;

y

= F(x);

e

= d - y;

" << endl;

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 Salida << "x\td\ty" << endl; for( j = 0; j < 50; j++){

<< endl;

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 Salida << "x\td\ty" << endl; for( j = 0; j < 50; j++){

<< endl;

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.

Código fuente de IdentificacionSistema.py

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. Ejemplo de cancelación de interferencias

En muchas ocasiones una señal de gran ancho de banda w(n) se encuentra inter- ferida por la suma de ruido de ancho de banda estrecho s(n), conformando la señal suma x(n); las dos señales que forman x(n) no están correlacionadas:

x(n) = w(n) + s(n)

La solución a este problema es diseñar un filtro de ancho de banda estrecho (notch), pero en ciertas ocasiones la banda de ruido no es conocida o varía lentamente en el tiempo, para lo cual los filtros adaptativos pueden utiizarse, pues en cualquiera de las dos situaciones son capaces de optimizar su funcionamiento [6]. El filtro adaptativo debe ser capaz de sustraer s(n) de x(n), teniendo en cuenta que debe predecir la componente en cada muestra a través de las muestras anteriores, dicha predicción se logra gracias al ancho de banda estrecho de s(n), y debido a que como el ancho de banda de s(n) es mucho menor que el de w(n), las muestras de s(n) tienen tienen una alta correlación; por otro lado las muestras de w(n) tienen una muy baja correlación. En la figura 13 podemos apreciar el diagrama en bloques del sistema de can- celación de interferencias, donde el decorrelacionador introduce un retardo de T muestras, con el propósito de decorrelacionar las componentes s(n) de la señal x(n).

(38)

28

x(n) + salida Σ - s’(n) retardo T Adaptativo Filtro decorrelacionador e(n) = x(n) -
x(n)
+
salida
Σ
-
s’(n)
retardo
T
Adaptativo Filtro
decorrelacionador
e(n) = x(n)
- s’(n)

Figura 13: Diagrama en bloques de un filtro adaptativo para cancelación de interfe- rencias.

La salida del filtro adaptativo tiene la siguiente expresión:

s (n) =

N1

k=0

W k (n)x(n k T )

(39)

La señal de error e(n) se utiliza en el proceso de optimización del filtro adaptativo, con el método de los cuadrados mínimos. En dicho proceso de optimización x(n) es la suma de una secuencia aleatoria de valor medio nulo, sobre la cual se suma el ruido de ancho de banda estrecha, por ejemplo un tono senoidal, o bien una suma de dos o tres tonos puros. El retardo del decorrelacionador en la mayoría de los casos es suficiente con una muestra de retardo. Una vez adaptado el filtro, la señal a filtrar debe ser ingresada directamente al filtro; eventualmente el filtro, puede reoptimizarse para seguir las variaciones de señal interferente. El ejemplo presentado trata de suprimir una interferencia producida por un tono puro sobre una señal de electrocardiograma (ECG). El programa perteneciente a este ejemplo es FILTRO2.CPP. y la figura iguiente muestra los resultados del filtrado sobre una porción de la señal de ECG. La figura 14 muestra el error 2 para las primeras 500 iteraciones durante la adap- tación del filtro, mientras que la figura 15 muestra en la señal superior el ECG original sin ruido ni interferencias, en la señal central el mismo ECG pero con la interferencia sumada, y finalmente en la señal 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ó.

4.2.1. Código fuente de FILTRO2.CPP

// FILTRO2.CPP: cancelacion de interferencias con un filtro adaptativo.

#include <iostream.h>

29

Figura 14: error 2 para las primeras 500 iteraciones durante la adaptación del filtro.
Figura 14: error 2 para las primeras 500 iteraciones durante la adaptación del filtro.

30

Figura 15: La señal superior el ECG original sin ruido ni interferencias, en la señal

Figura 15: La señal superior el ECG original sin ruido ni interferencias, en la señal central el mismo ECG pero con la interferencia sumada, y finalmente en la señal 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 can’t 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 dAnt = 0.0; dAnt2 = 0.0; for( j = 0; j < Number; j++){

" << endl;

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 Salida << "ecg\tx\ty" << endl; dAnt = 0.0;

<< endl;

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.

Código fuente de CancelacionRuido.py

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)/flo 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. Análisis de Señales 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:547–588, 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: percep- tron, madaline, and backpropagation. Proceedings of the IEEE, 78(9):1415–1442,

1990.

36