DEPARTAMENTO DE INGENIERIA ELÉCTRICA COORDINACIÓN DE LA LICENCIATURA EN COMPUTACI~N

Texto completo

(1)

UNIVERSIDAD A U T ~ N O M A

METROPOLITANA

UNIDAD IZTAPALAPA

Casa abierta al tiempo I 1

DEPARTAMENTO DE INGENIERIA ELÉCTRICA

COORDINACIÓN DE LA LICENCIATURA EN

COMPUTACI~N

"

IMPLEMENTACIÓN DEL ALGORITMO DE RETROPOPAGACIÓN

PARA ENTRENAMIENTO DE REDES NEURONALES

"

ALUMNOS:

LICENCIATURA EN COMPUTACIóN:

GÓMEZ BLAS MARíA MAGNOLIA 91321250

LIC. EN ING. ELECTRóNICA EN COMPUTAC16N:

GUZMÁN MONTOYA EDUARDO 91320666

ASESOR:

LIC. ALMA

E.

MARTiNEZ LICONA

20901

(2)
(3)

UNIVERSIDAD A U T ~ N O M A

METROPOLITANA

UNIDAD IZTAPALAPA

Casa

abierta

al

tiempo

I I

(4)

UNIVERSIDAD A U T ~ N O M A

METROPOLITANA

UNIDAD IZTAPALAPA

(5)

Casa abierta al

tiempo

Aunque las redes neuronales pueden servir para comprender el funcionamiento del cerebro, los ingenieros están interesados en ellas para aplicarlas a la resolución de problemas. Las redes neuronales tienen una velocidad de procesamiento superior a la que tienen las técnicas de procesamiento comunes, gracias a su naturaleza de paralelismo

masivo y por ser intrínsecamente analógicas. Por su naturaleza adaptiva, las redes

neuronales pueden adecuarse a los cambios en los datos y aprender las características de las señales de entrada.

Gran parte de la tarea de desarrollar una aplicación con redes neuronales no es otra cosa que intentar de proveer al sistema con una "naturaleza" adecuada para el aprendizaje de una tarea determinada. Los diseñadores gastan mucho tiempo y esfuerzo decidiendo que estructura usar para la red, que datos de entrenamiento son apropiados, como inicializar

los

pesos de la red, etc (conceptos que más adelante explicaremos). El entrenamiento de la red corresponde al aprendizaje de toda una vida de un ser humano. Dado una ilimitada cantidad de tiempo de entrenamiento, una red puede resolver casi la mayoría de los problemas. Pero cuando se quiere que el entrenamiento sea eficiente y que este tome una mínima cantidad de tiempo el énfasis del desarrollo de una aplicación cambia del

aprendizaje de la red a su naturaleza. Mediante el uso de una red inherentemente más capaz en el problema, se puede reducir el entrenamiento a un mínimo.

Es por las grandes ventajas que proporciona hacer uso' de una Red Neuronal para la resolución de problemas (principalmente de clasificación) que nuestro objetivo es dar a

conocer una estructura para la creación de una Red Neuronal así como también el algoritmo de entrenamiento de la Red, anexando el código necesario (en

C++)

y explicando su funcionamiento para facilitar la tarea de decisión sobre que estructura usar y como implementarla.

Este documento esta dirigido a programadores con conocimientos previos en

Programación Orientada a Objetos y que conozcan algo sobre la terminología utilizada en Redes Neuronales, no obstante que explicamos, en este documento, algunos de esos

(6)

Casa abierta al tiempo

Retropropagacibn

El cerebro humano posee un promedio de 15,000,000,000 neuronas de varios tipos y cada una de ellas recibe señales a través de aproximadamente 10,000 sinapsis. Este fabuloso grado de interconexión convierte al cerebro humano en la pieza biológica más compleja existente sobre la tierra. Luego de muchos años de investigación llevada a cabo por neuroanatomistas y neurofisiólogos, el estudio del cerebro ha progresado lo suficiente como para comprender su organización fundamental, aunque todavía se ignoran muchos de los detalles de

los

mecanismos neuronales.

AI preguntarse como funciona el cerebro,

los

neurobiólogos y

los

psicólogos tomaron caminos de sentido opuesto: los primeros partieron del estudio de neuronas aisladas

investigando sus respuestas a los estímulos a los que eran sometidas; los segundos estudiaron las funciones del cerebro desde el punto de vista del comportamiento y el conocimiento. Así, gradualmente, se fue adquiriendo una idea cada vez más clara acerca del modo de trabajar del cerebro, aunque va a transcurrir mucho tiempo antes de que se adquiera un conocimiento sólido y completo sobre el tema.

Distintas áreas de la corteza cerebral están especializadas para procesar información de diferentes modalidades sensoriales, y otras se especializan en funciones motoras. Sin embargo, todas las áreas poseen una organización similar, y su estructura relativamente uniforme sugiere que aquella es capaz de aplicar un estilo de computación de propósito general que puede satisfacer el tratamiento de información sensorial o el razonamiento más abstracto. El procesamiento de la información y la memoria comparten el mismo circuito en el cerebro, en contraste con las computadoras digitales en las que la memoria y la unidad central de proceso están separadas físicamente.

La gran eficacia del cerebro como computadora biológica, indujo a pensar en la posibilidad de lograr capacidades similares en dispositivos artificiales basados en los mismos principios de diseño que los sistemas neuronales.

Hoy, la denominación “Red Neuronal” o -más adecuadamente- “Red Neuronal Artificial”, se refiere a cualquier arquitectura computacional que consista en interconexiones masivas y en paralelo de procesadores “neuronales”.

(7)

Proyecto: Algoritmo de

I

Retropropagacibn

I

Casa abierta al tiempo

L

QUÉ ES UNA RED NEURONAL ARTIFICIAL 3

Una Red Neuronal o también llamada Red Neuronal Artificial (ANN) es un sistema de

procesamiento de información o de señales compuesto por un gran número de elementos simples de procesamiento, llamados neumnas artificiales o simplemente nodos . Dichos

nodos están interconectados por uniones directas llamadas conexiones y cooperan para

realizar un procesamiento en paralelo (simulado) con el objetivo de resolver una tarea computacional dada. La capacidad de procesamiento de la red está almacenada en los

pesos, obtenidos por un proceso de adaptación o aprendizaje de una serie de algoritmos

(patrones) de entrenamiento.

Las redes neuronales intentan simular, al menos parcialmente, la estructura y funciones del cerebro y sistema nervioso de criaturas vivientes.

Las redes neuronales tambien tienen su analogía con la naturaleza. En una red neuronal, la naturaleza se refiere a Características como estructura física (o estructura física inicial en el caso de uno de los pocos modelos de red que modifican su estructura durante el entrenamiento), modelo de aprendizaje usado durante el entrenamiento, y el conjunto inicial de pesos de conexión. Una red neuronal con una naturaleza efectiva inherentemente facilita en gran medida la tarea de desarrollar un sistema que pueda resolver eficientemente un problema particular.

Una de las características atractivas de las ANNs es su capacidad para auto-adaptarse a

condiciones ambientales especiales cambiando sus fuerzas de conexión o pesos o

cambiando su estructura.

Las ANN’s son consideradas a veces como modelos grotescos del cerebro humano. Este

punto de vista es exagerado, debido a que el cerebro humano no es totalmente conocido y su comportamiento es muy complejo. Por esto, es más razonable comparar capacidades de ANN’s con sistemas nerviosos más simples de animales primitivos, tales como insectos,

que tienen la habilidad de auto-adaptarse a ambientes más complejos.

A continuación, explicaremos tanto el funcionamiento de las neuronas biológicas como el de las neuronas artificiales a fin de comprender mejor como se ha tratado de imitar el funcionamiento de las primeras con el de las neuronas artificiales enfatizando cuando sea necesario la similitud entre ambas.

(8)

Casa abierta

al

tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

MODELOS DE NEURONAS

Neurona Biolbgica.

Una neurona biológica en forma muy simplificada y esquemática consta de las siguientes partes fundamentales:

Dentritas

a) Cuerpo celular o soma: es el lugar en donde las funciones lógicas de la neurona son

realizadas.

b) Axón: es una fibra nerviosa conectada al soma, está altamente ramificado y cumple la función de salida de la neurona. Las señales son convertidas generalmente en secuencias de pulsos (espigas o spikes) las cuales son propagadas sin atenuación a lo largo del axón con otras neuronas.

c) Denfritas: Forman un árbol altamente ramificado de fibras nerviosas unido al soma, y

constituyen las entradas de las neuronas. Estas están conectadas a otras neuronas a través de conexiones llamadas sinapsis.

d) Sinapsis: son contactos especializados en una neurona, los cuales son puntos de

terminación de los axones de otras neuronas. Las sinapsis juegan el rol de interface

(9)

Casa abierta

al

tiempo

Proyecto: Algoritmo de

I

Retropropagación

I

El almacenamiento de la información en una neurona, se supone que se realiza en las conexiones sinápticas, o más precisamente en la fuerza de estas conexiones (pesos en el modelo de la neurona artificial).

De acuerdo al modelo simplificado de una neurona; el soma recibe entradas de otras neuronas a través de conexiones sinápticas ajustables, o adaptativas, a sus dentritas. La señal de salida (consistente en impulsos nerviosos) de la neurona es transmitida a lo largo del axón y este hace sinapsis con dentritas de otras neuronas.

Cuando una neurona es exitada, esta produce impulsos nerviosos (es decir un tren de impulsos) que son transmitidos a lo largo del axón hacia conexiones sinápticas de otras neuronas. La frecuencia de los pulsos de salida depende de la fuerza de la señal de entrada y de la fuerza (peso) de la conexión sináptica correspondiente. Las señales de entrada a una sinapsis exitatoria aumenta la frecuencia de los pulsos de salida, mientras que señales en una sinapsis inhibitoria disminuye dicha frecuencia.

Neurona Artificial.

Las neuronas artificiales o simplemente nodos, son elementos de procesamiento que intentan simular la estructura y función de neuronas biológicas. Sin embargo,

los

modelos de neuronas artificiales no están exactamente restringidos por las neuronas reales y están basados parcialmente en la biología. Esto sigue de los siguientes hechos:

a) No está completamente entendido el comportamiento del sistema nervioso, el cual es

b) Solamente parte del comportamiento de una neurona biológica es esencial a su

c) Desde el punto de vista de una implementación técnica, será probablemente imposible y

d) Las ANN’S están diseñadas para realizar problemas computacionales muy específicos; y

muy complejo.

capacidad de procesamiento de información.

también ineficiente simular el comportamiento real de una neurona biológica.

sus arquitecturas y características dependen del problema a resolver.

El comportamiento de una neurona artificial consiste en una implementación digital en la que se simula el efecto de cada señal de entrada de una neurona biológica siguiendo la fórmula que representa una función de activación llamada escal6n* , que consiste en ir

multiplicando la señal de entrada (vector de entrada o de patrones) por el peso, ya antes mencionado, de cada una de las neuronas, con ello se logra representar la fuerza de la sinapsis de una neurona biológica, posteriormente se hace una sumatoria de estas multiplicaciones y se comparan contra un umbral (más adelante se explica su importancia) produciendo así una salida como respuesta a esto. Toda esta funcionalidad esta capturada en un modelo llamado percepfrón.

* Además de esta función de activación existe otra llamada sigrnoide explicada en el aprtado de Redes de propagacidn hacia atrds

(10)

Casa abierta al tiempo

I

Proyecto: Algoritmo de

Retropropagacibn

I

X I

\

wl

- f

Xn => Multiplicacwn por el peso

Representación del funcionamiento del Perceptrón

donde x1,x2,...,xn son los valores del vector de entrada y wl, w2,

...

,wn son los pesos de las neuronas.

Las componentes del vector de entrada pueden ser valores continuos o binarios, los pesos son esencialmente continuos y pueden tomar valores positivos o negativos.

El entrenamiento se hace mediante un algoritmo adaptativo que ajusta automáticamente los pesos de forma tal que la salida este tan cerca como sea posible de la salida deseada.

En el siguiente apartado se estudiará el aprendizaje de las redes neuronales, donde se incluyen los perceptrones y las redes de propagación hacia atrás.

EL APRENDIZAJE EN LAS REDES NEURONALES

Perceptrones.

El perceptrón, inventado por Rosenblatt (1962), fue uno de los primeros modelos de redes

neuronales. Un perceptrón imita una neurona tomando la suma ponderada de sus entradas y enviando a la salida un 1 si la suma es más grande que algún valor umbral ajustable (si ocurre de otro modo, devuelve O).

Las entradas (x1,x2, ..., x,,) y los pesos de conexión (w,, w2, ... ,wn) son valores normalmente

reales que pueden ser positivos o negativos. Si la presencia de alguna característica xi

tiende a causar la activación del perceptrón, el peso wi será positivo; si la característica xi

inhibe al perceptrón, entonces el peso wi será negativo. El perceptrón en sí mismo se

compone de los pesos, el procesador de sumas y el procesador del umbral ajustable. El

aprendizaje es un proceso en el cual se modifican los valores de los pesos y del umbral. El perceptrón se dispara si la suma ponderada es mayor que cero.

(11)

Casa abierta al tiempo

U

Proyecto: Algoritmo de

Retropropagacibn

Un perceptrón calcula una función binaria de su entrada. Algunos perceptrones se pueden combinar para calcular funciones más complejas como aquellas en las que el perceptrón cuenta con muchas entradas y salidas.

En este caso, grupos de perceptrones se pueden entrenar mediante pares de entradakalida, hasta que aprendan a calcular la función correcta. Pero la propiedad que resulta verdaderamente interesante del aprendizaje del perceptrón es que cualquiera que sea el cálculo que un perceptrón pueda llevar a cabo ipuede aprender a calcularlo!. Se

demostrará dentro de un momento.

En primer lugar es necesario echar un vistazo al modo de calcular del perceptrón. Sea x un

vector de entrada (x1,x2, ..., x"). Adviertase que la función de suma ponderada g(x), y la

función de salida o(x) se pueden definir como:

g(x) =

2

w xi

Y=l

I

1 si g(x) >

o

I

o

si g(x)

o

o(x)

=

{

Ahora considérese el caso en que sólo se tienen dos entradas. Entonces:

Si g(x) es exactamente O, el perceptrón no podrá decidir si debe dispararse. Un ligero cambio en las entradas podría dar lugar a que el dispositivo se decida por uno de los dos caminos. Si se resuelve la ecuación g(x) = O se obtiene la ecuación de una recta:

La situación de la recta está completamente determinada por los pesos WO, w1 y w2.

Observese que w2 debe ser distinto de cero, de lo contrario X2 que es un valor del vector de entrada, nos estaría diciendo que toma un valor demasiado grande, es decir infinito, lo cual no tiene sentido. Ahora si un vector de entrada se sitúa hacia uno de los lados de la recta, el perceptrón da como salida I; si se desplaza hacia el otro lado dará salida O. Una

recta que separe correctamente dos casos de entrenamiento se corresponde con un perceptrón funcionando correctamente. Dicha recta se denomina superficie de decisidn.

Para perceptrones con muchas entradas, la superficie de decisión será un hiperplano en el espacio multidimensional de los posibles vectores de entrada. El problema del aprendizaje consiste en localizar una superficie de decisión apropiada.

Se puede utilizar una forma de búsqueda local conocida como descenso por el gradiente.

El gradiente es un vector que indica en qué dirección nos debemos mover en el espacio de pesos para reducir dicha superficie en el espacio de todos los posibles pesos.

(12)

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

El algoritmo de aprendizaje del perceptrón es un algoritmo de búsqueda. Comienza en un

estado inicial aleatorio y acaba encontrando un estado solución. El espacio de búsqueda simplemente consiste en todas las posibles asignaciones de valores reales a los pesos del perceptrón, y la estrategia de búsqueda es un descenso por el gradiente. Pero el objetivo último del aprendizaje es hacer que un sistema se coloque en una posición en la que pueda resolver mejor los problemas.

La introducción de los perceptrones a finales de la década de los cincuenta causó un gran entusiasmo. Suponía un dispositivo que se asemejaba mucho a una neurona y para el que había disponibles algoritmos de aprendizaje bien definidos. En realidad, el perceptrón es incapaz de resolver algunos problemas verdaderamente sencillos. Un ejemplo es el problema O-Exclusiva (XOR).

El perceptrón no puede aprender a crear una superficie lineal de decisión que separe estas diferentes salidas, porque dicha superficie de decisidn no existe. No hay una única recta que pueda separar las salidas 1 de las salidas O. Démonos cuenta que aquí la deficiencia no esta en el algoritmo de aprendizaje del perceptrón, sino en el modo en el que el

perceptrón representa el conocimiento.

Sin embargo el uso de perceptrones multicapa soluciona nuestros problemas de representación del conocimiento. Sin embargo, introduce un grave problema de aprendizaje ya que el problema de convergencia no es aplicable a los perceptrones multicapa. El algoritmo de aprendizaje del perceptrón puede ajustar correctamente

los

pesos entre las entradas y las salidas pero no puede ajustar los pesos entre

los

perceptrones.

A pesar de su identificación como "importante problema a investigar", las investigaciones

sobre el aprendizaje en el perceptrón multicapa sufrió una interrupción a finales de la década de los setenta. Se mostró muy poco interés en dicho campo hasta la década de los ochenta cuando se propusieron diferentes procedimientos de aprendizaje para perceptrones multicapa (también denominadas como redes multicapa). El siguiente apartado está dedicado a conocer uno de estos procedimientos de aprendizaje y que es en

el

que se basa este documento.

Redes de propagación hacia atrás (BPN).

La capacidad de entrenar redes multicapa es un paso importante de cara a la construcción de máquinas inteligentes con componentes similares a las neuronas. Por tanto ahora vamos a tender al estudio de redes multicapa mucho más complejas.

(13)

U

Proyecto: Algoritmo de

Retropropagación

Casa abierta al tiempo

El principal problema es el aprendizaje. El sistema para la representación del conocimiento empleado por las redes neuronales es bastante opaco, ya que las redes deben aprender. Los perceptrones tienen la curiosa propiedad de que cualquiera que sea lo que tenga que calcular pueden aprender a hacerlo. Esta propiedad se extiende a las redes multicapa. La propagación hacia atrás (backpropagafion) es un paso que nos lleva en esa dirección.

Resultará útil tratar en primer lugar con las diferentes subclases de redes multicapa, denominadas redes complefamenfe conectadas, laminadas y alimentadas hacia adelante. Un ejemplo de dichas redes es el que aparece a continuación:

n n A

1") UNIDADES DE SALIDA

Ti

aWii

UNIDADES OCULTAS

En esta figura xi, hi, oi representan las unidades de activación de las unidades de entrada, ocultas y de salida. Los pesos de las conexiones entre las capas de entrada y oculta se denotan aquí como wji, mientras que los pesos de las conexiones entre las capas salida y oculta se denotan como wkj. Esta red tiene tres capas aunque algunas veces pueda resultar útil el que tenga más. Cada unidad de una capa (neurona) se conecta hacia adelante en dirección a cualquier unidad de la siguiente capa. Las activaciones saltan desde la capa de entrada hacia la capa oculta y desde ésta hacia la capa de salida. Normalmente el conocimiento de la red está codificado en los pesos en las conexiones entre las unidades. Los niveles de activación en la capa de salida determinan la salida de la red.

La existencia de unidades ocultas permiten que la red pueda desarrollar complejos detectores de características o de representaciones internas.

En las redes de propagación hacia atrás, la unidad en una propagación hacia atrás requiere una función de activación ligeramente diferente que la del perceptrón. Todavía hay una unidad de propagación hacia atrás que suma sus entradas ponderadas pero, al contrario que el perceptrón, produce un valor entre O y 1 como salida, basada en una función sigmoide (en forma de S), que es continua y diferenciable, como requiere el algoritmo de propagación hacia atrás. Sea sum la suma ponderada de las entradas de una unidad. La ecuación de la salida viene dada por:

(14)

Casa abierta al tiemPo

n

Proyecto: Algoritmo de Retropropagaci6n

Obsérvese que si la suma es O, la salida es 0.5 (A diferencia que el perceptrón que tenia que ser O o 1). A medida que la suma aumenta, la salida se hace aproximadamente 1 y a medida que se hace más pequeña, la salida se aproxima a O.

AI igual que el perceptrón, una red de propagación hacia atrás normalmente empieza con un conjunto de pesos aleatorio. La red ajusta sus pesos cada vez que ve un par entradakalida. Cada par requiere dos etapas: Un paso hacia adelante y un paso hacia atrás. El paso hacia adelante, implica la presentación de un ejemplo de entrada hacia la red y permite que las activaciones continúen hasta que alcancen la capa de salida. Durante el paso hacia atrás, la salida que se tiene de la red en ese momento, se compara con la salida objetivo y se calcula el error estimado de las unidades de salida. Los pesos que están conectados a las unidades de salida, se pueden ajustar para reducir dichos errores. Entonces, se pueden utilizar las estimaciones del error de las unidades de salida para derivar el error estimado de las unidades de las capas ocultas. Por último, los errores se propagan hacia atrás a las conexiones procedentes de las unidades de entrada.

AI contrario que el algoritmo de aprendizaje del perceptrón, el algoritmo de propagación hacia atrás normalmente calcula sus pesos de un modo progresivo, después de observar cada par de entradahalida. Después de haber observado todos

los

pares de E/S (y ajustando los pesos cada vez) se puede decir que se ha completado una etapa (epoch). El entrenamiento de una red de propagación hacia atrás normalmente consta de mucha etapas.

Funcionamiento de la BPN.

Dado un conjunto de pares de vectores de EntradaSalida, se desea calcular un conjunto de pesos para una red, que haga corresponder las entradas con las correspondientes salidas.

Las entradas se consideran los estímulos de las neuronas de la primera capa de la red, estas se propagan a través de cada capa superior hasta que es generada una salida. Esta salida que proporciona la red es comparada con la salida deseada y se calcula un error

para cada neurona de salida.

Los errores son transmitidos hacia atrás desde la capa de salida a cada neurona de la capa oculta inmediatamente abajo. Este proceso se repite capa por capa hasta llegar a la primera capa oculta. Basándose en el error recibido, los pesos son actualizados para cada neurona, de este modo la red converge hacia un estado donde se permite que todos

los

(15)

m

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

Tipos de entrenamiento.

Existen 2 tipos de entrenamiento el supervisado y no supervisado. El entrenamiento supervisado es aquel en donde el usuario sabe de antemano la salida que desea y va observando y comparando las salidas arrojadas por la red, con las salidas esperadas. El

objetivo de este tipo de entrenamiento es el de tratar de minimizar el error que se genera de la comparación de las salidas, por lo que se debe siempre vigilar el proceso de entrenamiento de la red. El usuario decide en que momento suspender el entrenamiento de la red, según considere que el error es suficientemente pequeño o que las salidas arrojadas por

la

red son lo suficientemente parecidas a las esperadas. El entrenamiento supervisado es el que se utilizó para la implementación del algoritmo de entrenamiento de la red en este documento.

El entrenamiento no supervisado es aquel donde el usuario no sabe el resultado que obtendrá de la red, así que solo le da las entradas necesarias y esperará lo que esta le arroje como consecuencia, es decir, dado un conjunto de datos de entrada, a la red se le permite jugar con ellos para intentar descubrir regularidades y relaciones entre las diferentes partes de las entradas.

El aprendizaje se produce frecuentemente a través de alguna noción sobre qué

características del conjunto de entrada son importantes. Sin embargo, con frecuencia no conocemos de antemano que características son importantes, y pedir a un sistema de aprendizaje que lo alcance con datos de entrada puros, puede ser cara

(16)

Casa abierta al tiempo L I

A continuación se presentan los pasos que se deben de seguir durante el entrenamiento de la red, para un solo vector de entrada.

ProDagacion hacia adelante.

1. Posicionarse en la capa de entrada y aplicarle el vector de entrada xp =

(xpl,xp2, ..., xpN), es decir dar a cada neurona de entrada el valor xpi correspondiente.

2. Calcular

los

valores de entrada de la red para las neuronas de la capa oculta:

a) Posicionarse en la primera neurona a procesar en la capa inmediatamente

b) Poner a cero la entrada total.

c) Calcular el producto del peso de conexión de la primera entrada con el valor de entrada (en caso de la primera capa oculta) y con la salida transmitida ha esa neurona (en caso de que se trate de las capas ocultas subsecuentes). arriba de la que se encuentra actualmente.

d) Sumar este producto a la acumulación de la entrada. e) Repetir el paso c) y d) para cada conexión de entrada.

En caso de que se trate de la primera capa oculta usar:

n

En caso de que se trate de las capas ocultas subsecuentes usar: n

netopk =

C

wokj ipj

j= 1

(17)

Casa abierta al tiempo

9

Comenzar calculando el valor de salida de la neurona mencionada en el paso 1 para aplicarle la función sigmoidal siguiente f(x)

=

1 / ( 1

-

e-' )

donde x es la entrada total.

g) Repetir los pasos b) hasta

9

para cada neurona de esta capa.

En caso de que se trate de las salidas de la capa oculta usar:

En caso de que se llegue a la capa de salida usar:

En ambos casos, f es la función sigmoidal mencionada en el inciso

9.

Una vez que el valor de salida ha sido calculado para cada neurona en la red, los valores calculados para cada neurona en la capa de salida son comparados con la salida deseada elemento por elemento:

epk = (ypk

-

Opk) donde y es la k-ésima salida esperada y

o es la salida de la k-ésima neurona de la capa de salida

En cada neurona de salida, un valor de error es calculado como consecuencia de lo

anterior. Estos términos de error son los que alimentan el regreso (segunda parte del algoritmo) para todas las demás neuronas en la estructura de la red

Propagación hacia atrás.

1. Calcular los términos de error para las neuronas:

Localizar la primera neurona a procesar en la capa inmediatamente abajo de la capa de salida.

Poner a cero el error total.

Calcular el producto del peso de la primera conexión de salida con el error que proviene de la neurona en la capa superior (epk).

Sumar este producto a la acumulación del error. Repetir los pasos c) y d) para cada conexión de salida.

Multiplicar el error acumulado por o(1 - o), donde o es el valor de salida de la neurona de la capa oculta producida durante la operación de la propaga ción hacia adelante.

Repetir los pasos b) hasta

9

para cada unidad en esta capa. Repetir

los

pasos a) hasta g) para cada capa.

En caso de que se trate de calcular los términos de error de las neuronas de salida usar:

6'pk

=

(epk)[Opk(l

-

Opk)]( net'pk)

(18)

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagación

I

En caso de que se trate de calcular

los

términos de error de las neuronas ocultas usar:

Note que

los

términos de error en las neuronas de la capa oculta son calculados antes que la conexión de los pesos de la capa de salida hayan sido actualizados.

2. Actualización de los pesos:

Localizar la primera neurona a procesar en la capa inmediatamente arriba de la capa de entrada.

Calcular el valor del peso modificado para la primera conexión de entrada a esta neurona, multiplicando una fracción (q) del error acumulado en

esta neurona por el valor de entrada de esta misma neurona.

Modificar este peso sumando un término de momento igual a una fracción del peso modificado en la iteración anterior.

Guardar tanto el nuevo peso como el viejo peso para esta conexión. Cambiar la conexión del peso sumando la nueva conexión del peso modificado a la conexión del peso viejo.

Repetir pasos b) hasta e) para cada conexión de entrada a esta neurona. Repetir

los

pasos b) hasta

9

para cada neurona en esta capa.

Repetir los pasos b) hasta g) para cada capa en la red.

En caso de que se trate de la actualización de pesos en la capa de salida usar:

En caso de que se trate de la actualización de pesos en la capa oculta usar:

El orden de la actualización de los pesos en una capa individual no es importante.

El factor q es conocido como coeficiente de aprendizaje.

3. Calcular el término del error total: M

Ep = (I/2) 62pk

k=l

Dado que esta cantidad es la que mide que también va

el

aprendizaje de la red. Entonces, este debe ser aceptablemente pequeño para cada vector de entrada.

En el algoritmo, el momento es usado para aumentar la velocidad del aprendizaje. Si el valor del momento está en torno a 0.9, la velocidad de aprendizaje aumenta.

(19)

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

La propagación hacia atrás necesita de la función de activación sigmoidal porque la regla de derivación de

los

pesos impone que la función de activación sea continua y

diferenciable.

La regla de derivación de los pesos es más compleja que la derivación de la regla del incremento fijo del perceptrón, pero la idea sigue siendo la misma. Existe una función de error que define una superficie en el espacio de pesos, y los pesos se modifican en la dirección que marca el gradiente de esta superficie. La superficie de error para las redes multicapa es más compleja que la superficie de error de los perceptrones. Una diferencia notable la establece la existencia de mínimos locales.

Existen varios métodos de superar el problema de los mínimos locales. El factor de impulso

o momento, que tiende a mantener los cambios de

los

pesos en la misma dirección, es uno

de ellos, y permite que el algoritmo escape de los mínimos pequeños.

Afortunadamente, las redes de propagación hacia atrás normalmente no tropiezan con mínimos locales. Especialmente en el caso de redes más grandes, resulta que un espacio de pesos con muchas dimensiones proporciona muchos grados de libertad para el algoritmo. En la práctica, la falta de un teorema de convergencia no es un problema. Sin embargo, esta agradable característica de las redes de propagación hacia atrás no se ha descubierto hasta fechas muy recientes, cuando las computadoras digitales se han hecho lo suficientemente rápidas como para simular las redes neuronales a gran escala. El

algoritmo de propagación hacia atrás se derivó de forma independiente por varios investigadores, pero fue descartado muchas veces por su problema con

los

mínimos

locales. En la etapa anterior a la aparición de las computadoras digitales rápidas, los investigadores sólo podían verificar sus ideas demostrando teoremas sobre ellas.

(20)

Retropropagación

Casa abierta al tiempo I I

La BPN es una herramienta versátil que es fácilmente aplicada a un diverso número de problemas. Generalmente, esta versatilidad es debido a la naturaleza general de

los

procesos de aprendizaje de la red.

La generalidad ofrecida por

los

procesos comunes permiten arreglos y conectividad de neuronas individuales dentro de la red que pueden ser variadas drásticamente. Similarmente, debido a la variedad de estructuras de la red que pueden ser creadas y entrenadas con éxito usando algoritmos de retropropagación, esta técnica de aprendizaje de la red puede ser aplicada a muchas clases diferentes de problemas. En el resto de esta sección, describiremos ciertas aplicaciones seleccionadas para ilustrar la diversidad de la arquitectura de la red BPN.

COMPRESIóN DE DATOS.

Como primer ejemplo, podemos considerar el problema común de compresión de datos. Específicamente, probarlo para encontrar una manera de comprimir los datos necesarios para codificar y reproducir correctamente una imagen de video de alta resolución, así que podríamos transmitir estas imágenes a través de un equipo de comunicación con ancho de banda bajo o medio. Aunque hay muchos algoritmos que cumplen con esta tarea de compresión de datos, la mayoría de estos son designados para tratar con datos estáticos, tales como el código ASCII o con la muestra de imágenes que son medianamente consistentes, tales como los gráficos por computadora. Porque los datos de video rara vez contienen formas regulares bien definidas (y aún menos frecuente contiene espacio desocupado), la compresión de datos de video es un problema difícil desde el punto de vista algorítmico.

Una red neuronal, como la descrita anteriormente, es la ideal para la compresión o

reducción de datos de video, porque una BPN puede ser entrenada fácilmente para trazar un mapa de patrones de un espacio n-dimensional a otro m-dimensions/. Entonces

cualquier imagen de video puede ser pensada como una matriz de pixeles, esto

(21)

Casa abierta al tiempo

Arquitectura de la Red para la Compresi6n de Datos.

El primer paso en la solución de este problema es tratar de encontrar una manera de

representar la estructura de nuestra red, para que así llevemos a cabo la compresión de datos deseada. Nos gustaría seleccionar la arquitectura de la red de manera que nos de un factor razonable de reducción de datos (es decir, 4 a 1) y que nos facilite una recuperación aproximada de la imagen original de la codificada. La figura siguiente satisface estos

requerimientos:

NIDADES DE SALIDA

UNIDADES OCUL

UNIDADES DE .TAS

E NTR ADA

La estrategia implicada para la arquitectura de la red se hace evidente, puesto que hay menos neuronas ocultas que neuronas de entrada, la capa oculta representa la forma de compresión de los datos.

Para proveer un vector imagen como el patrón de estimulación de entrada, la red propaga las entradas a través de las neuronas ocultas a la salida. Dado que la capa oculta contiene solo un cuarto de número de neuronas de procesamiento, los valores de salida producidos por las neuronas de la capa oculta pueden ser pensados como la forma codificada de la entrada. Además, para propagar la salida de las neuronas de la capa oculta hacia la capa de salida, hemos implementado un mecanismo para reconstruir la imagen original de la

codificada.

Durante el entrenamiento, la red mostrará ejemplos de vectores tomados para representar las imágenes de video. Cada vector podrá ser usado como la entrada a la red. Usando el proceso de retropropagación, la red desarrollará la codificación interna de los pesos de modo que la imagen sea comprimida en un cuarto del tamaño de la original en las salidas de las neuronas ocultas. Si leemos los valores de salida producidos por las neuronas de la capa oculta en nuestra red y transmitimos estos valores a la estación de recepción,

(22)

Casa abierta ai tiempo

Retropropagación

En este ejemplo, la actividad del patrón de salida de la segunda capa es transferido a una estación de recepción, donde esta es ampliada como la salida de otra capa que forma parte de la mitad superior del árbol de la red. La red de recepción, reconstruye la imagen transmitida, usando la función de mapeado inverso contenida en la conexión de pesos de la mitad superior de la red.

Clasificación del tamaño de la red.

Hay 2 problemas que faltan ser resueltos por esta aplicación: el primero es la clasificación del tamaño de la red y el segundo es la generación de los conjuntos de datos muestra que se necesitan para entrenar la red. Dirijámonos al primer aspecto.

Es irreal esperar crear una red que contenga una neurona de entrada por cada pixel de una imagen de video. Aun cuando nos restrinjamos a una resolución baja nuestra red tendría que tener 336,000 neuronas de entrada

(525

líneas x 640 pixeles). Además, toda la

red debería contener aproximadamente 750,000 neuronas de proceso (336,000 + 336,000 / 4 + 336,000) y 50 billones de conexiones. Así que la simulación de una red que contenga

un gran número de neuronas y un vasto número de conexiones es demasiado costoso en tiempo como para llevarse a la práctica.

Nuestra estrategia de clasificación es por lo tanto un poco menos ambiciosa; restringiremos el tamaño de

los

espacios de entrada y salida a 64 pixeles. Así, la capa oculta contendrá 16 neuronas.

(23)

Proyecto: Algoritmo de

I

Retropropagación

I

Casa abierta al tiempo Entrenamiento de la red.

Si consideramos la naturaleza de la aplicación de la red entonces esta debería ser entrenada para conseguir un mapa de espacio n, es decir que el número de permutaciones

posibles del patrón de entrada es significativamente más pequeño en 64 dimensiones que en 336,000 dimensiones. Esto facilita la generación de imágenes para entrenar la red usando 64 entradas, porque una imagen de video completa puede ser subdividida en alrededor de 5000 matrices de 8 x 8, cada una de las cuales puede ser usada para entrenar la red.

PROBLEMAS DE CLASIFICACI~N.

La existencia de neuronas ocultas en la red permiten que esta pueda desarrollar complejos detectores de características o de representaciones internas. La figura muestra la aplicación de una red de tres capas para el problema de reconocimiento de dígitos.

o 1 2 3 4 5 6 7 8 9

ENTWDA

Uso de una red multicapa para aprender a clasificar dígitos escritos a mano

La parrilla de dos dimensiones que contiene el número “7” forma la capa de entrada. Una única neurona oculta podría activarse fuertemente por una línea horizontal de la entrada o

(24)

Casa abierta al

tiempo

quizá por una línea diagonal. Lo más importante es advertir que el comportamiento de estas neuronas ocultas se aprende automáticamente y no es consciente de esta estructura de dos dimensiones. Precisamente porque esta estructura puede ser muy importante, la mayoría de las redes permiten que sus unidades ocultas mantengan solamente conexiones locales con la red de entrada (una subparrilla diferente de 4 x 4 para cada neurona oculta).

Se espera que para abordar problemas como el de reconocimiento de caracteres escritos a mano, la red neuronal no sólo aprenda a clasificar las entradas para las que está entrenada, sino que generalice y sea capaz de explicar las entradas que todavía no haya visto. En este punto surge una pregunta razonable, que es: “si todas las redes neuronales parecen ser capaces de hacer esta clasificación”. De hecho, manejar la mayoría de los

problemas de clasificación es para lo que están mejor preparadas las redes neuronales.

Si se muestran todas las posibles entradas y salidas a una red de propagación hacia atrás, la red probablemente encontrará un conjunto de pesos que haga corresponder las entradas con las salidas. Considere el reconocimiento de rostros y de caracteres. Existe un número infinito de orientaciones y expresiones de un rostro, y un número infinito de fuentes y tamaños para un carácter, y los humanos aprenden a clasificar estos objetos fácilmente a partir de unos pocos ejemplos. Nosotros desearíamos que estas redes hicieran lo mismo. De hecho, la propagación hacia atrás parece un mecanismo de generalización prometedor. Si se trabaja en un dominio (como los dominios de clasificación que se acaban de explicar) donde a entradas similares le corresponden salidas similares, la propagación hacia atrás se puede interpolar cuando se producen entradas que nunca antes se habían dado. Por ejemplo, después de aprender a distinguir entre unas pocas Aes de diferente tamaño y otras pocas Bes de diferente tamaño, una red podría distinguir entre cualquierA y cualquier B.

Sin embargo, hay algunos peligros. Durante la primera parte del entrenamiento, el rendimiento con el conjunto de entrenamiento mejora conforme la red ajusta sus pesos a lo largo de la propagación hacia atrás. El rendimiento sobre el conjunto de prueba (ejemplos con los que no se permite que aprenda la red) también mejora, aunque no tanto como el ejemplo de entrenamiento. AI poco tiempo, el rendimiento de la red alcanza una meseta conforme los pesos cambian mucho buscando un camino para una mejora posterior. Pero el rendimiento del conjunto de prueba es peor. ¿Por qué? La red comenzó memorizando

los pares de entrada-salida concretos en lugar de establecer los pesos que describen de forma general la correspondencia para todos los casos. Con miles de pesos de valor real a su disposición, la propagación hacia atrás es capaz teóricamente de almacenar conjuntos de entrenamiento complejos; con suficientes neuronas ocultas, el algoritmo podría aprender a asignar una neurona oculta a cada patrón de entrada distinto del conjunto de entrenamiento. Es un testimonio de la potencia de la propagación hacia atrás que realmente se da en la práctica.

(25)

Casa abierta al tiempo

suficiente para impedir la memorización, pero no debería ser tan grande como para confundir al clasificador, creando un cuello de botella entre las capas de entrada y salida. AI enfrentarse a un cuello de botella, la red sale con representaciones internas compactas de sus entradas.

(26)

Casa abierta

al tiempo

CONSIDERACIONES PRACTICAS.

Para la implementación del algoritmo de retropropagación hubo que considerar algunos puntos:

1.

2.

3.

4.

5.

6.

Normalizar el vector de entrada, es decir cambiar cada valor del vector de

entrada a valores que van desde un rango de 0.1 hasta 0.9 para que las salidas obtenidas de la red se asemejen más considerablemente a las salidas esperadas.

Limitar el argumento de la exponecial en caso de este llegue a un valor menor a (-40) darle el valor de 40, para que no se produzcan errores de desbordamiento de memoria (oveflow) durante la corrida del programa.

La asignación de los valores para los pesos se hace de manera aleatoria en un rango que va de -0.5 hasta 0.5.

La asignación de momentos también se hace de manera aleatoria en el mismo rango que los pesos.

La red se alimentará con vectores de entrada contenidos en un archivo

La(s) salida(s) esperada(s) también estarán contenida(s) en este archivo.

CóDIGO DE IMPLEMENTACIÓN.

A continuación se presenta el código de implementación del algoritmo de retropropagación ya muchas veces mencionado:

Archivo BPN.CPP

(27)

n

Proyecto: Algoritmo de

Retropropagación

Casa abierta al tiempo

Librerias de cabecera

#include <c:\red\bpn-glob.cpp> #include <c:\red\bpnclass.cpp> #include <conio.h>

#include <stdlib.h> #include <math.h> #include 4ostream. h> #include <fstream.h> #include <string.h> #include <stdio.h>

Prototipos de las funciones

void BPNfunction(); void GetNetParamO; void Netlnit(Layer&,Net&);

void GetlnputVec(doub1e *,double *,char *,long *);

double Normaliza(double,int); int GetFileLine(char *);

void OutputsFile(Layer& CS);

void OutputCalc(doub1e *,Layer& ,Net&); void ErrorCalc (double *,Layer& ,Net&); void Updating (double *,Layer& ,Net&); void TotError(Layer& CS);

double Max (double , double );

double Min (double , double );

Proarama orinciRa1

void main ()

{

BPNfunction(); //CONSTRUIR LA RED Y ENTRENARLA

cout << "\n\n\t\t\" Programa Terminado Y' I' <<endl;

1

Cuerpo de las funciones

(28)

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagacibn

I

void BPNfunction()

{

clrscr();

cout << "\n\n\t\" Dimensiones de la red : \"\n\n";

GetNetParamO; I/ Obtiene los datos de entrada para construir la red

//Creación de los registros de datos ocupados en el entrenamiento: double *Input = new double [NumEnt];

double *Expected = new double [NumSal];

I/ Asignación de memoria al arreglo global utilizado para la normalización. I/ Este arreglo se llena (inicializa) en la función GetFileLineO;

N = new NORMA [NumEnt]; // Vector para normalizar

. . .

/I Elementos que constituyen la red, inicialización.

//""""""""""""""""""""""""""""""""- """""""""""""""""""""""""""""""~"

/I CONSTRUCCIóN DE LA RED:

cout << "\n\t\t Construyendo la red ... \n\n";

I/ Capas de Salida < CS > : Arreglo de neuronas para la salida.

Layer CS(NumSa1,TamNeu);

I/ Capas Ocultas < CO > : Arreglo de capas de neuronas

Net CO(NumCapas,NeuxCapa,TamNeu);

I/ INICIALIZA LA RED

Netlnit(CS,CO);

I/ Obtiene el número de líneas a analizar del archivo de entradas y N obtiene el vector para la normalización de los vectores de entrada

int NumDatos=GetFileLine(FileName);

int DatoActual; I/ Último vector que se proceso

long Posicion = O; /I Posición en el archivo de datos de entrenamiento.

cout << "\n\t El entrenamiento de la red ha comenzado\n";

for(DatoActual=O;DatoActual<NumDatos;DatoActual++)

{

/I COMIENZA ENTRENAMIENTO CON EL NUEVO VECTOR DE ENTRADA

/////// Algoritmo BPN ///////

GetlnputVec(lnput,Expected,FileName,&Posicion);

(29)

Casa abierta al tiempo

Proyecto: Algoritmo de

I

Retropropagación

I

CalcErr = 100; // lnicializa el error calculado con un valor grande para poder

int i = O;

while( (TotErr CalcErr) && !kbhit() ) // entrenar la red.

{

OutputCalc(lnput,CS,CO); // Propagación hacia adelante(de ent.).

ErrorCalc(Expected,CS,CO); // Propagación hacia atrás (error).

Updating(lnput,CS,CO); // Modificación de errores.

TotError(CS); // Cálculo del error de salida.

i++; // Número de iteraciones efectuadas.

1

// Muestra el desarrollo del programa.

clrscr();

cout <<"\n\t\tNúmero de datos para entrenar:"<< NumDatos<<endl<<endl; cout <<"\n\t\tSalidas Para el Dato :"<< (DatoActual+l)<<endl;

cout << "\t\tNúmero de iteraciones :" << i <<end¡<< endl;

cout << "\t\t Error"<<" :"<<CalcErr<<endl;

/I Imprime el vector esperado.

cout << "\n\tVector de Salida Esperado :\n\t\ (";

for (i=O;i<NumSal;i++)

cout << "}\n";

cout << Expected[¡] <<I' ;

// Imprime el vector de salida calculado.

cout << "\n\tVector de Salida Calculado : \n\tf';

for (i=O;i<NumSal;i++)

cout << CS.GetSalida(i) <<I' 'I ;

cout <<

"}\n";

cout << "\n\t\t\t< ENTRENANDO ... >'I;

/I Guarda en un archivo las salidas de la red y el error total

OutputsFile(CS);

} //TERMINA EL for , REGRESA PARA OBTENER OTRO VECTOR Y VOLVER

// A ENTRENAR LA RED.

delete Input; delete Expected; delete N;

(30)

Casa abierta

al

tiempo

I

Proyecto: Algoritmo de

Retropropagación

I

{

tout << "\tNúmero de entradas: ;

cin >r NumEnt;

cout << "\n\tNúmero de salidas: 'I ;

cin >> NumSal;

cout << "\n\tNúmero de neuronas por capa: I' ;

cin >> NeuxCapa;

cout << "\n\tNúmero de capas: ;

cin >> NumCapas;

if (NumEntzNeuxCapa) TamNeu

=

NumEnt; else TamNeu = NeuxCapa;

/// Abre el archivo que contiene las entradas y las salidas esperadas para la red

cout << "\n\tNOMBRE Y RUTA DEL ARCHIVO DE ENTRADAS\n\t\t";

cin >> FileName;

eta

=

0.15;

alpha

=

0.2;

TotErr

=

0.0005;

CalcErr = 100;

Tolerancia

=

O. 1 ; // Diez % de tolerancia para valores mayores o

// menores que el rango obtenido en los datos // de entrenamiento para la normalización.

1

// Inicializa la red con pesos y momentos aleatorios.

void Netlnit(Layer& CS,Net& CO)

{

int i,j,k;

// Inicializa capa de salida

cout << "\t\tinicializando la red ... \n\n";

randomize();

for (j=O;j<NumSal;j++) //para todas las neuronas de salida. for (i=O;i<TamNeu;i++)//para todos

los

pesos.

{

double w,m,r; r = random(l0);

// # entre O y 0.5 * Signo

+

o

-

w = OS*(l/(r+l) ) pow(-l~andom(2)); // peso aleatorio

r = random(l0);

m = OS*(l/(r+l) ) * pow(-I ~andom(2)); // momento aleatorio

(31)

Casa abierta

al

tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

CS.SetWeight(j,i,w); CS.SetMom(j,i,m);

1

// Inicializa la red

for (k=O; k<NumCapas; k++) //para todas las capas

for (j=O;j<NeuxCapa;j++) //para todas las neuronas de la capa. for(i=O;i<TamNeu;i++) //para todos los pesos y momentos.

{

double w,m,r;

r = random(l0);

// # entre O y 0.5 * Signo + o -

w = 0.5*(l/(r+I))* pow(-I ,random(2)); // peso aleatorio

r

=

random(l0);

m = 0.5*(l/(r+l))* pow(-l~andom(2)); // momento aleatorio

CO.SetWeight(k,j,i,w); CO.SetMom(k,j,i,m);

1

1

void OutputCalc(doub1e *Input,Layer& CS,Net& CO)

{

int i,j,k; double net;

// Validación de rango para el número de capas.

if (NumCapas <= O)

{

tout << " Error: El número de capas debe estar entre 1 y 10. \n" ;

cout << " AI presionar una tecla el programa terminara. \n" ;

getch0;

-

exit(1);

1

. . .

// Cálculo de la salida para la primera capa interna. Se calcula aparte debido a que // el número de entradas puede ser diferente al de neuronas por capa y además la // entrada viene de un registro y no de una capa de neuronas.

(32)

Casa abierta al tiempo

I

Proyecto: Algoritmo de Retropropagación

I

for (j=O; j<NeuxCapa ; j++) // Cálculo de todas las salidas de la capa l . {

net

=

O;

/I Cálculo de la entrada total a la neurona.

for

(¡=O;

i<NumEnt ; y++) /I Calcula la suma de todas las entradas a la

/I neurona.

{

net = net + ( CO.GetWeight(O,j,i)*Input[i] );//wt-i x Sal-¡

net = (net<-40)? 40:net;// avoid overf1ow;sal min

-=

lA-18

1

I/ Cálculo de la salida para la neurona j

CO.SetSalida(0, j, (l/(l+exp(-net))) );

1

. . .

I! Cálculo de la salida para cada neurona en las capas subsiguientes a la primera N capa oculta y hasta la última.

if (NumCapas > 1) {

for (k=l;k<NumCapas;k++) /I Para todas las capas restantes (k+l)

for (j=O; j<NeuxCapa ; j++) I/ Para todas las neuronas

{

{

net = O;

I/ Cálculo de la entrada total a la neurona j (net).

for

(¡=O;

i<NeuxCapa ; y++)

{

net = net+( CO.GetWeight(k,j,i)*CO.GetSalida(k-1 ,i) );//wt-i x Sal-i

net = (net<-40)? 40:net;// avoid overf1ow;sal min -= lA-18

1

/I Cálculo de la salida para la neurona j

CO.SetSalida(k, j, (l/(l+exp(-net))) );

1

1

1

. . .

// Cálculo de la salida para cada neurona en la capa de salida.

/I Se debe calcular a parte debido a su tamaño particular.

(33)

A

A

Casa

abierta al

tiempo

Proyedo: Algoritmo de

I

Retropropagacidn

I

{

net

=

O;

// Cálculo de la entrada total a la neurona j (net). for

(¡=O;

i<NeuxCapa ; y++)

{

net

=

net + ( CS.GetWeight(j,i)*CO.GetSalida((NumCapas-I),¡) ) ; N wt-i x Sal-¡ net

=

(net<-40)? 40:net;// avoid overflow;sal min

-=

IA-18

}

// Cálculo de la salida para la neurona j CS.SetSalida( j, (l/(l+exp(-net))) );

1

1;

void ErrorCalc(doub1e *Expected,Layer& CS,Net& CO)

int i,j,k;

double sal,sigma;

// Cálculo del error para la capa de salida.

for (j=O; j<NumSal ; j++) // Calcula el error de salida para todas las neuronas.

{

sal

=

CS.GetSalida(j);

CS.SetError( j, (Expected[j]-sal)*saI*(1-~al) );

// Cálculo del error para la última capa oculta.

// i es la neurona en la capa de salida. j la de la última capa oculta. for (j=O; jeNeuxCapa; j++)// Para todas las neuronas en la última capa. {

sigma =O;

for

(¡=O;

i<NumSal ; y++) // Calcula el factor de error para la la neurona j. sigma

=

sigma + CS.GetError(i)’CS.GetWeight(i,j); /M-¡ Err-¡

sal

=

CO.GetSalida(NumCapas-1 ,j);

CO.SetError(NumCapas-1

,

j, sigma*sal*(l-sal) );//Calc. error para neu. j

1

// Cálculo del error para las demas capas ocultas.

// i es la neurona en la capa oculta anterior a k. j la de la capa oculta k.

if (NumCapas > 1)

t

for (k=NumCapas-2;k >= 0;k- )

(34)

Casa

abierta al

tiempo c I {

for (j=O; j<NeuxCapa; j++) // Para todas las neuronas en la capa k.

sigma =O;

for

(¡=O;

i<NeuxCapa ; y++) // Factor de error para la la neurona j.

sigma

=

sigma

+

CO.GetError(k+l ,i)*CO.GetWeight(k+l ,i,j); //wt-i * Err-¡

sal

=

CO.GetSalida(k,j);

CO.SetError(k, j, sigma*sal*(l-sal) );//Calc. error para neu. j

}; //End of ErrorCalc();

void Updating(doub1e *Input,Layer& CS,Net& CO)

// Modificación de pesos para la capa de salida. int i,j,k;

double NewMom;// Nuevo peso.

for

(j=o;

jeNumSal; j++) // Para todas las neuronas de salida.

for

(¡=O;

i<NeuxCapa; y++) // Para todos

los

pesos en la neurona j.

NewMom

=

eta * CS.GetError(j)

*

CO.GetSalida(NumCapas-I ,i);

CS.SetWeight(j,i,(CS.GetWeight(j,i)+NewMom+alpha*CS.GetMom(j,i) ) ); CS.SetMom(j,i,NewMom);

1

// Modificación de pesos para la primera capa oculta.

for (j=O; j<NeuxCapa; j++)// Para todas las neuronas en la capa.

for

(¡=O;

i<NumEnt; y++) // Para todos los pesos en la neurona j. {

NewMom

=

eta CO.GetError(O,j) * Input[¡];

CO.SetWeight(O,j,i,(CO.GetWeight(O,j,i)+NewMom+alpha*CO.GetMom(O,j,i) ) );

CO.SetMom(O,j,i,NewMom);

1

N Modificación de pesos para la primera capa oculta.

if (NumCapas > 1)

c

for(k=l; keNumCapas; k++)

(35)

m

Casa abierta al

tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

for(i=O; i<NeuxCapa; y++) // Para todos los pesos en la neurona j.

{

NewMom

=

eta * CO.GetError(k,j) CO.GetSalida(k-1 j);

~~.~~~~eight(k,j,i,(CO.GetWeight(k,j,i)+Ne~om+alpha*C~.GetMom(kl~li)) );

CO.SetMom(k,j,i,NewMom);

1

}; // Fin de la Función.

// Cálculo del error total para la salida de la red

void TotError(Layer& CS)

int j;

double SumaError=O;

for (j=O; j<NumSal; j++)

SumaError

=

SumaError

+

pow(CS.GetErrorCj),2);

CalcErr

=

0.5 * SumaError;

1;

// Obtiene los vectores de Entradas y de Salidas Esperadas // del archivo especificado y las normaliza

void GetlnputVec(doub1e *Input,double *Expected,char *FileName,long *Pos) {

double d; int y;

ifstream InputFile(FileName);

if (IlnputFile) // Verifica si el archivo es valido

a u t << I' No se puede abrir el archivo"; exit(1);

{

1

Inputfile. seekg(*Pos,ios::beg); // File PTR Position for (i=O;i<NumEnt;i++)

{

lnputFile >> d; I/ Obtiene las entradas

Inpuqi]

=

Normaliza(d,i); // Las Normaliza

1

(36)

Proyecto: Algoritmo de

I

Retropropagacidn

I

Casa

abierta al tiempo

for (i=O;i<NumSal;i++)

InputFile ?> Expected[¡]; // Obtiene las salidas

InputFile >> ws;

*Pos

=

InputFile.tellg();

InputFile.close(); //Cierra el archivo.

1

// Normaliza la entrada i de valor Val

double Normaliza(doub1e Val,int i)

{

double Valstandar,

ValAbs

=

Val- N[i].Min;

return ( (ValAbs*(l-(2*Tolerancia)))/N[i].ValMax) + Tolerancia;

1;

// Guarda en un archivo las salidas de la red y el error total

void OutputsFile(Layer& CS)

{

static int band-arch=O; // bandera que nos indica

con

O si debemos crear el archivo if (band-arch==O)

{

// y 1 si debemos escribir al final

ofstream output-file("salidas.dat",ios::out);

if (!output-file)

t

cout << "hNo se puede abrir el archivo"; exit(1);

if (output-file) {

for (int i=O;i<NumSal;i++)

{

output-file << CS.GetSalida(i); output-file << 'I 'I;

1

output-file << CalcErr << "h";

1

(37)

Casa abierta

al

Bempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

band-arch=l ;

1

else

{

//abrir un archivo ya existente

ofstream output-file("salidas.dat",ios::app);

//verifica la incidencia de errores al abrir el archivo

if (!output-file)

{

1

tout << "hNo se puede abrir el archivo"; exit(1);

if (output-file)

{

for (int i=O;i<NumSal;i++) {

output-file << CS.GetSalida(i); output-file << 'I 'I;

1

output-file << CalcErr << "h";

1

1

// Obtiene el número de líneas del archivo de entradas así como el // vector para la normalización.

int GetFileLine(char FileName[80])

double d,sal;

int NumLineas=O,i;

// Inicializa vector de normalización. for (i=O;i<NumEnt;i++)

N[i].Min

=

100000;

N[i].Max = -100000;

N[i].ValMax

=

0.0; ifstream InputFile(FileName); if (IlnputFile)

{

1

1

tout << I* No se puede abrir el archivo"; return 1;

(38)

Casa abierta

al tiempo

Proyecto: Algoritmo de

I

Retropmpagacibn

I

cout << "h\t Calculando vector para la normalización"; cout << "h\t de los vectores de entrada ...hh";

while (!lnputFile..eof()) // Encuentra el vector para normalizar

{

for (i=O;i<NumEnt;i++)

InputFile >> d; I/ Obtiene las entradas N[i].Min

=

Min(N[i].Min,d);

N[i].Max

=

Max(N[i].Max,d);

1

for(i=O;i<NumSal;i++)

InputFile >> sal; // Obtiene las salidas

InputFile >> ws; NumLineas++;

1

for (i=O;i<NumEnt;i++)

N[i].ValMax

=

N[i].Max

-

N[i].Min;

InputFile.close(); retum(NumLineas);

1

// Retoma el valor máximo

double Max(double valuel

,

double value2) {

1

return ( (valuel > value2) '? valuel : value2);

// Retorna el valor minimo

double Min(double valuel

,

double value2)

{

1

return ( (valuel < value2) ? valuel : value2);

(39)

Casa ablerta al tiempo

Proyecto: Algoritmo de

I

Retropropagaci6n

I

#if !defined( JOSTREAM-H )

#include <iostream.h> #endif I1 JOSTREAM-H

#if !defined( -CONIO-H )

#include <conio.h> #endif /I -CONIO-H

Definicidn de clases

// Definición de la clase neurona

class Neuron

{

double *wt-arr; 11 arreglo de pesos double *mom-arr; 11 arreglo de momentos

double length; 11 longitud

double error; 11 error

double salida; 11 salida

public:

Neuron();

Neuron(int size);

-Neuron(){delete wt-arr;delete mom-arr;}; void Show (void);

int GetLength(){retum length;}; double GetWeight(int i);

void SetWeight(int ¡,double value); double GetMom(int i);

void SetMom(int ¡,double value); double GetError(){retum error;};

void SetError(doub1e value){error

=

value;}; double GetSalidaO{retum salida;);

void SetSalida(doub1e value){salida

=

value;}; void Init(int size);

1;

Neuron::NeuronO {

length

=

O;

wt-arr

=

NULL;

(40)

A

A

Casa

abierta al

tiempo

Retropropagaci6n

mom-arr

=

NULL; error

=

1;

salida

=

0.5;

1;

Neuron::Neuron(int size)

{

int i;

length

=

size;

wt-arr

=

new double [length]; mom-arr

=

new double [length];

for (i=O;i<length;i++)

wt-anji]

=

0.5;

mom-anji]

=

0.5; {

1

error

=

I;

salida

=

0.5;

1;

void Neuron::Show(void)

{

int i;

if (length==O) {

tout << "\tNeuron object empty

or

initiated to 'O'.\n" ;

cout << "\tlf empty call Object.Init(value) function.\n" ;

1

else {

(41)

Casa abierta

al

tiempo

double Neuron::GetWeight(int i)

void Neuron::SetWeight(int ¡,double value)

1

1;

wt-arr[i]

=

value;

double Neuron::GetMom(int i)

{

1;

return mom-arr[i];

void Neuron::SetMom(int ¡,double value)

{

1;

mom-arr[i]

=

value;

void Neuron::lnit(int size)

int i;

length

=

size;

wt-arr

=

new double [length]; mom-arr

=

new double [length];

for (i=O;i<length;i++)

wt-arr[i]

=

0.5;

mom-arr[i]

=

0.5;

// Clase Capa

class Layer

{

Figure

Actualización...

Referencias

Actualización...