Introducción a las Redes Neuronales: Parte 2 Red de ...
Transcript of Introducción a las Redes Neuronales: Parte 2 Red de ...
Introducción a las Redes Neuronales: Parte 2Red de Perceptrones
Dr. Ing. Marcelo RiskInstituto Tecnológico de Buenos Aires
Índice1. Introducción 1
2. El perceptrón a partir de un combinador lineal adaptativo 4
3. Implementación de una red neuronal 83.0.1. Código fuente de NEURAL3.H . . . . . . . . . . . . . . . . . 83.0.2. Código fuente de NEURAL3.CPP . . . . . . . . . . . . . . . . 11
3.1. Ejemplo de identificación de patrones con redes neuronales . . . . . . 233.1.1. OCHO.TXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.1.2. SEIS.TXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.1.3. CINCO.TXT . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.1.4. SEIS2.TXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.1.5. Código fuente de NUMERO.CPP . . . . . . . . . . . . . . . . 24
1. IntroducciónLas redes neuronales (RN) se basan en la interconexión de neuronas artificiales,
y en el caso de las RN artificiales (RNA) en la interconexión de perceptrones, elcual modeliza una neurona natural, en el presente trabajo utilizaremos el modelo deneurona denominado clasificador no lineal [5, 4, 1].
Las RNA son máquinas o software que modelan la forma en la cual el cerebrodesarrola una tarea. Las RNA son una clase de métodos estadísticos para el pro-cesamiento de información, compuestas por una cantidad importante de unidadessimples de procesamiento, denominadas neuronas, las cuales interactuan entre sí.
Las RN naturales están presentes en el sistema nervioso de humanos, animales,insectos, etc, tienen la habilidad de reconocer patrones, y desarrollar tareas comple-jas, en forma muy especializada [3, 2].
El cuadro 1 muestra comparaciones de performance, tales como velocidad deprocesamiento, cantidad de neuroras-compuertas, peso, consumo de energía y unejemplo de pasos necesarios para el procesamiento de la visión.
1
Cuadro 1: Comparaciones de performance y consumos entre el cerebro humano ylas computadoras.
Cerebro humano ComputadoraVelocidad procesamiento 10−3ms (0.25 MHz) 10−9ms (2.5 GHz)Neuronas-compuertas 109 con 103 conexiones c/u 50 millonesPeso 1.5 kg kgs a tonsConsumo 10−16 Joule 10−6 JouleProcesamiento de la visión 100 pasos billones de pasos
Las RNA heredan la terminología de las redes naturales, provenientes de la bio-logía, el cuadro 2 muestra las correspondencias entre dichos términos y los corres-pondientes a la estadística.
Cuadro 2: Correspondencia entre la terminología de las RNA y la estadística.
RNA EstadísticaNodos de entrada Variables independientesNodos de salida Variables dependientesAprendizaje ParametrizaciónPesos Parámetros
La figura 1 muestra en el panel izquierdo: neurona cerebral, gran cantidad dedendritas (entradas de información), y axón (salida) simple; mientras en el panelderecho: neurona motora, con menos dendritas, y salida mielinizada (aislada).
Más allá del alcance de este apunte, en muchos libros es posible encontrar elparadigma de las redes neuronales, pero podemos decir que los atributos más im-portantes de las redes neuronales es el aprendizaje y la generalización.
El aprendizaje es el proceso por el cual se le presenta a la red neuronal uno ovarios patrones con sus salidas deseadas (tantos como sea posible), determinándo-se un conjunto de entrenamiento, con dicho conjunto y mediante un algoritmo deoptimización se ajustan los coeficientes de la red.
Una vez entrenada la RNA, se puede probar la respuesta de la misma aplicándolepatrones distintos a los del entrenamiento, verificando si la respuesta fue correctaen la mayoría de los casos, entonces se puede decir que se obtuvo un entrenamientogeneral.
2
Figura 1: Panel izquierdo: neurona cerebral, gran cantidad de dendritas (entradasde información), y axón (salida) simple; panel derecho: neurona motora, con menosdendritas, y salida mielinizada (aislada).
3
2. El perceptrón a partir de un combinador linealadaptativo
Si a la salida del combinador lineal adaptativo se conecta un bloque de respuestaalineal, denominado cuantificador, tal como la función signo, que responde a lasiguiente expresión 1. {
y = +1 si x ≥ 0
y = −1 si x < 0(1)
El sistema completo, formado por un combinador lineal adaptativo y un elementoalineal a la salida de denomina adaline. En la figura 2 que sigue podemos apreciarel diagrama en bloques del adaline.
Pesos
Vector depatrón deentrada
Xk
X2k
X3k
Xnk
Xk
Wnk
W3k
W2k
W1k
ΔWk
X1k
Σ
Σ
SalidaLineal
SalidaBinaria(+1,-1)
2μ
Entrada deRespuesta Deseada
(señal de entrenamiento)
ErrorLineal
dk
sk
x0k
yk
εk
+
-Algoritmo
LMS
-1
+1
Dispositivode umbral
Peso deumbral
=+1 Entrada de corte
ADALINE
Figura 2: Diagrama en bloques del adaline.
Note en la figura 2 la entrada x0k, siempre alimentada con un valor constante+1, con el propósito de controlar el umbral del cuantificador. Para el ajuste de loscoeficientes s puede utilizar el algoritmo de los cuadrados mínimos.
El adaline tiene la propiedad de separabilidad lineal, por ejemplo si analizamosun adaline con dos entradas, como lo muestra la figura 3, podemos apreciar que se
4
determina una recta de separación en el espacio de las combinaciones de entrada,en este caso un plano.
Σ
X0 = +1
X1
X2
W0
W1
S(n)
W2
+1
-1
Y(n)
Figura 3: Diagrama en bloques del adaline de dos entradas.
La salida lineal S(n) tiene la siguiente expresión 2:
S(n) = W0 +X1(n)W1 +X2(n)W2 (2)
Si igualamos a cero la ecuación 2, tenemos:
X2(n) = −W1
W2
X1(n)−W0
W2
(3)
La ecuación 3 describe la recta que separa el plano de estados posibles de entrada,en la misma se pueden reconocer la pendiente m = −W1
W2y la ordenada al origen
b = −W0
W2. Las combinaciones de entrada por arriba de la recta de separación generan
una salida de −1, y las combinaciones por debajo una salida de +1.Entre las alternativas posibles para la elección del cuantificador, s encuentra la
función sigmoidea, la cual tiene la siguiente expresión 4:
Y (n) = SIG[S(n)] = tanh[S(n)] =1− e−2S(n)
1 + e−2S(n)(4)
En una implementación práctica de una neurona, es conveniente incluir todaslas alternativas posibles de cuantificación y cálculo error, de manera de poder im-plementar más de un algoritmo de optimización.
Por ejemplo si se utiliza en lugar del error lineal instantáneo, el error a la salidadel cuantificador, el algoritmo de optimización de coeficientes se denomina regla delPerceptron, desarrollada por F. Rosenblatt.
La diferencia entre el error cuadrático medio tomado de la salida lineal, con elerror tomado a la salida de la función sigmoidea es una respuesta más abrupta porparte del error sigmoideo.
5
La elección por una u otra función de cuantificación depende de muchos factores,entre ellos como se implementan dichos cuantificadores. Por ejemplo si se construyeuna red neuronal con hardware, es mucho más fácil implementar la función signo(simplemente con un comparador analógico).
Otra alternativa es utilizar la función sigmoidea durante el entrenamiento, porquecon ella es posible llegar a mejores optimizaciones, para luego durante la operaciónde la red utilizar la función signo. El diagrama en bloques completo de la neuronase muestra en la figura 4.
Σ
Σ
X1
X0 = +1
X2
X3
X4
W1W0
W2
e(n)
d(n)
S(n)
W3
W4- +
+1
-1
Σe1(n)
d1(n)
Y1(n) Y2(n)
- +
+1
-1
Σe2(n)
d2(n)
- +
Figura 4: Diagrama en bloques del adaline completo, con salidas y errores lineales,sigmoideos y signo.
En dicha figura 4 podemos apreciar que para cada error debe suministrarse lasalida deseada.
Cuando se conectan más de una neurona, se conforma una red neuronal, esnecesario en la mayoría de las aplicaciones conectar varias neuronas, debido a queaumenta notablemente la capacidad de reconocimiento de patrones.
Las redes neuronales se organizan en capas, formadas por una cantidad de neu-ronas cada una de ellas, generalmente son de dos o tres capas, denominándose lascapas en las cuales entra el vector de entrada y donde se genera el vector de salida,capas de entrada y salida, respectivamente; las capas restantes entre la entrada y lasalida se denominan capas ocultas.
La figura 5 muestra un diagrama general de una red neuronal de tres capas, noteque el vector de entrada ingresa a todas las neuronas de la primera capa, la cualgenera un vector de salida de dicha capa, que sirve para alimentar las neuronas de
6
la capa oculta, y así sucesivamente las señales conforman el vector de salida.
Vectorde entrada
Capade entrada
Capade salida
Capaoculta
Vectorde salida
Figura 5: Diagrama general de una red neuronal de tres capas.
Para el aprendizaje de una red neuronal, al igual que para una neurona simple,se puede utilizar el método de cuadrados mínimos, pero es necesario tener en cuentapara la optimización de todos los pesos de todas las neuronas que conforman la red,el error producido a una salida deseada en el vector de salida.
Entre todos los métodos que se han desarrollado hasta el momento, se destacael método de retropropagación, debido al impacto que generó en la bibliografíaposterior.
El método de retropropagación busca propagar el error al valor deseado del vectorde salida, en sentido inverso al flujo de información a través de la red neuronal; paralograr esto el error llega a las capas anteriores multiplicado por el peso de las capasposteriores.
Antes de comenzar el proceso de aprendizaje, generalmente se inicializan lospesos de todas las neuronas con valores aleatorios pequeños, después comienza elaprendizaje, el cual puede durar una cantidad de iteraciones determinadas previa-mente, o bien buscar un error de salida mínimo, o ambos métodos en caso de nolograr el error mínimo.
La figura 6 muestra el diagrama de una red neuronal de dos capas, con el métodode retropropagación, los bloques denominados SIG desarrollan la función sigmoidea,ecuación 4, y el bloque denominado SIG’ desarrolla la ecuación 5 dada a continua-ción:
SIG′[S(n)] =δ{tanh[S(n)]}
δ{S(n)}= 1− {tanh[S(n)]}2 = 1− Y 2(n) (5)
De esta forma la ecuación que optimiza los pesos por el método de los cuadrados
7
mínimos queda expresada de la siguiente forma:
Wk(n+ 1) = Wk(n)− 2µek(n)[1− Y 2(n)]Xk(n) (6)
3. Implementación de una red neuronalUna red neuronal se forma a partir de la modelización de ua neurona, en el
listado que sigue se implementó una neurona a través de la clase CombinadorLinea-lAdaptativo, dentro de ella están encapsuladas todas las propiedades necesarias parael funcionamiento de un objeto que maneja un vector de datos Xk, un vector de pe-sos Wk, y otras variables tales como el error Ek, la cantidad de elementos Cantidady el valor del coeficiente de velocidad de optimización α, además de las funcionesnecesarias para la carga de los vectores, el cálculo de salida y la optimización de loscoeficientes del filtro.
Además en dicho listado se encuentra la clase RedNeural, que conecta variasneuronas para formar una red de dos capas, en la primera capa se encuentran 100entradas a 5 neuronas, y en la segunda capa 3 neuronas. Para la optimización de lared neuronal se implementó el método de retropropagación.
3.0.1. Código fuente de NEURAL3.H
// NEURAL3.H
#include <math.h>#include <stdlib.h>#include <iostream.h>#include <fstream.h>
class CombinadorLinealAdaptativo{public:
float *Xk;float *Wk;float Sk;float Ek;float Eks;float Ekd;float Dk;float Yk;float yk;float Alfa;int Cantidad;
CombinadorLinealAdaptativo();
8
Σ
X
+1
W0
10W
410
W110
W210
W310
S10
Alg
orit
mo
LM
S
SIG
’
SIG
+
Σ
X
+1
W0
11W
411
W111
W211
W311
S11
Alg
orit
mo
LM
S
SIG
’
SIG
+
Σ
X
+1
W0
12W
412
W112
W212
W312
S12
Y10 Y11
Σ
X
+1
W0
20W
420
W120
W220
S20
Alg
orit
mo
LM
S
SIG
’
SIG
+-
+
-
+
Σ
X
+1
W0
21W
421
W121
W221
S21
Alg
orit
mo
LM
S
SIG
’
SIG
+
Y1
Y0 d
1
d0
Y12
Alg
orit
mo
LM
S
SIG
’
SIG
+
X0 X1
X2 X3
Figura 6: Diagrama general de una red neuronal de tres capas.
9
CombinadorLinealAdaptativo( int n);~CombinadorLinealAdaptativo();
void Calcula( void);void CantidadSynapsis( int n = 50);void LlenaPesos( float *Array, int cantidad);void LlenaEntradas( float *Array, int cantidad);void LlenaPesos( float *Array);void LlenaEntradas( float *Array);void LlenaSalidaDeseada( float Salida);void LlenaAlfa( float a);
float MuestraSalidaLineal( void);float MuestraSalidaDigital( void);float MuestraSalidaSigmoidea( void);float MuestraErrorLineal( void);float MuestraErrorSigmoidea( void);float MuestraErrorDigital( void);void MuestraSet( void);
void CalculaNuevoSet( void);void CalculaNuevoSet( float ek);int GuardaPesos( char *name);int LeePesos( char *name);};
// Red Neuronal de dos capas
class Red Neural{public:
int NumberInputs;float deseada[4]; valores deseados
// Primera capaCombinadorLinealAdaptativo *C100;CombinadorLinealAdaptativo *C101;CombinadorLinealAdaptativo *C102;CombinadorLinealAdaptativo *C103;CombinadorLinealAdaptativo *C104;CombinadorLinealAdaptativo *C105;CombinadorLinealAdaptativo *C106;CombinadorLinealAdaptativo *C107;CombinadorLinealAdaptativo *C108;CombinadorLinealAdaptativo *C109;
10
CombinadorLinealAdaptativo *C110;CombinadorLinealAdaptativo *C111;CombinadorLinealAdaptativo *C112;CombinadorLinealAdaptativo *C113;CombinadorLinealAdaptativo *C114;CombinadorLinealAdaptativo *C115;CombinadorLinealAdaptativo *C116;CombinadorLinealAdaptativo *C117;CombinadorLinealAdaptativo *C118;CombinadorLinealAdaptativo *C119;// segunda capaCombinadorLinealAdaptativo *C20;CombinadorLinealAdaptativo *C21;CombinadorLinealAdaptativo *C22;CombinadorLinealAdaptativo *C23;
Red Neural();Red Neural( int inputs);~Red Neural();
void LlenaEntradas( float *d);void LlenaEntradas2( float *d);void CalculaNuevoSet( float *d);void CalculaNuevoSet2( float *d);
float MuestraSalidaDigital1( void);float MuestraSalidaDigital2( void);float MuestraSalidaDigital3( void);float MuestraSalidaDigital4( void);};
3.0.2. Código fuente de NEURAL3.CPP
// NEURAL3.CPP
#include "neural3.h"#include <stdlib.h>
#define ALFAINICIAL 1e-3
CombinadorLinealAdaptativo::CombinadorLinealAdaptativo( int n){Alfa = ALFAINICIAL;Ek = 1.0;Dk = 1.0;
11
Eks = 1.0;Ekd = 1.0;Cantidad = n + 1;Xk = new float[Cantidad];Wk = new float[Cantidad];for( int j = 0; j < Cantidad; j++){
Xk[j] = 0.0;Wk[j] = float(random(1000))/10000.0;}
}
CombinadorLinealAdaptativo::CombinadorLinealAdaptativo(){Alfa = ALFAINICIAL;Ek = 1.0;Dk = 1.0;Eks = 1.0;Ekd = 1.0;}
void CombinadorLinealAdaptativo::CantidadSynapsis( int n){Cantidad = n + 1;Xk = new float[Cantidad];Wk = new float[Cantidad];for( int j = 0; j < Cantidad; j++){
Xk[j] = 0.0;Wk[j] = float(random(1000))/1000000.0;}
}
CombinadorLinealAdaptativo::CombinadorLinealAdaptativo(){delete Xk;delete Wk;}
void CombinadorLinealAdaptativo::LlenaPesos( float *Array, int Cantidad){for( int j = 0; j < Cantidad; j++)
Wk[j] = Array[j];}
void CombinadorLinealAdaptativo::LlenaPesos( float *Array){for( int j = 0; j < Cantidad; j++)
Wk[j] = Array[j];}
void CombinadorLinealAdaptativo::CalculaNuevoSet( void){
12
for( int j = 0; j < Cantidad; j++){Wk[j] = Wk[j] + Alfa*ek*Xk[j];}
}
void CombinadorLinealAdaptativo::CalculaNuevoSet( float ek){for( int j = 0; j < Cantidad; j++){
Wk[j] = Wk[j] + Alfa*ek*Xk[j];}
}
void CombinadorLinealAdaptativo::MuestraSet( void){cout << endl;for( int j = 0; j < Cantidad; j++){
cout << Wk[j] << ", ";}
}
void CombinadorLinealAdaptativo::Calcula( void){float Suma = 0.0;Xk[Cantidad-1] = 1.0; // entrada constante para controlar el umbralfor( int j = 0; j < Cantidad; j++){
Suma += Wk[j] *Xk[j];}
Sk = Suma;// Sigmoideayk = (1.0-exp(-2.0*Sk)) / (1.0+exp(-2.0*Sk))// Funcion signoif( yk >= 0)
Yk = 1.0;else
Yk = -1.0;// Calcula errorEk = Dk - Sk;Eks = Dk - yk;Ekd = Dk - Yk;}
void CombinadorLinealAdaptativo::LlenaEntradas( float *Array, int Cantidad){int j;for( j = 0; j < Cantidad; j++){
Xk[j] = Array[j];}
Calcula();}
13
void CombinadorLinealAdaptativo::LlenaEntradas( float *Array){int j;for( j = 0; j < Cantidad; j++){
Xk[j] = Array[j];}
Calcula();}
void CombinadorLinealAdaptativo::LlenaSalidaDeseada( float Salida){Dk = Salida;}
void CombinadorLinealAdaptativo::LlenaAlfa( float a){if( a >= le-12 && a < 0.1)
Alfa = a;else
Alfa = le-12;}
float CombinadorLinealAdaptativo::MuestraSalidaLineal( void){return Sk;}
float CombinadorLinealAdaptativo::MuestraSalidaSigmoidea( void){return yk;}
float CombinadorLinealAdaptativo::MuestraSalidaDigital( void){return Yk;}
float CombinadorLinealAdaptativo::MuestraErrorLineal( void){return Ek;}
float CombinadorLinealAdaptativo::MuestraErrorSigmoidea( void){return Eks;}
float CombinadorLinealAdaptativo::MuestraErrorDigital( void){return Ekd;}
int CombinadorLinealAdaptativo::GuardaPesos( char *name){
14
ofstream A;A.open( name);if( !A)
return -1;A << Cantidad << endl;for( int j = 0; j < Cantidad; j++){
A << Wk[j] << endl;}
A.close();return 0;}
int CombinadorLinealAdaptativo::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;}
RedNeural::RedNeural(){NumberInputs = 50;C100 = new CombinadorLinealAdaptativo(NumberInputs);C101 = new CombinadorLinealAdaptativo(NumberInputs);C102 = new CombinadorLinealAdaptativo(NumberInputs);C103 = new CombinadorLinealAdaptativo(NumberInputs);C104 = new CombinadorLinealAdaptativo(NumberInputs);C105 = new CombinadorLinealAdaptativo(NumberInputs);C106 = new CombinadorLinealAdaptativo(NumberInputs);C107 = new CombinadorLinealAdaptativo(NumberInputs);C108 = new CombinadorLinealAdaptativo(NumberInputs);C109 = new CombinadorLinealAdaptativo(NumberInputs);C110 = new CombinadorLinealAdaptativo(NumberInputs);C111 = new CombinadorLinealAdaptativo(NumberInputs);C112 = new CombinadorLinealAdaptativo(NumberInputs);C113 = new CombinadorLinealAdaptativo(NumberInputs);C114 = new CombinadorLinealAdaptativo(NumberInputs);
15
C115 = new CombinadorLinealAdaptativo(NumberInputs);C116 = new CombinadorLinealAdaptativo(NumberInputs);C117 = new CombinadorLinealAdaptativo(NumberInputs);C118 = new CombinadorLinealAdaptativo(NumberInputs);C119 = new CombinadorLinealAdaptativo(NumberInputs);//C20 = new CombinadorLinealAdaptativo(20);C21 = new CombinadorLinealAdaptativo(20);C22 = new CombinadorLinealAdaptativo(20);C23 = new CombinadorLinealAdaptativo(20);}
// Red Neuronal de dos capas
RedNeural::RedNeural( int inputs){NumberInputs = NumberInputs;C100 = new CombinadorLinealAdaptativo(NumberInputs);C101 = new CombinadorLinealAdaptativo(NumberInputs);C102 = new CombinadorLinealAdaptativo(NumberInputs);C103 = new CombinadorLinealAdaptativo(NumberInputs);C104 = new CombinadorLinealAdaptativo(NumberInputs);C105 = new CombinadorLinealAdaptativo(NumberInputs);C106 = new CombinadorLinealAdaptativo(NumberInputs);C107 = new CombinadorLinealAdaptativo(NumberInputs);C108 = new CombinadorLinealAdaptativo(NumberInputs);C109 = new CombinadorLinealAdaptativo(NumberInputs);C110 = new CombinadorLinealAdaptativo(NumberInputs);C111 = new CombinadorLinealAdaptativo(NumberInputs);C112 = new CombinadorLinealAdaptativo(NumberInputs);C113 = new CombinadorLinealAdaptativo(NumberInputs);C114 = new CombinadorLinealAdaptativo(NumberInputs);C115 = new CombinadorLinealAdaptativo(NumberInputs);C116 = new CombinadorLinealAdaptativo(NumberInputs);C117 = new CombinadorLinealAdaptativo(NumberInputs);C118 = new CombinadorLinealAdaptativo(NumberInputs);C119 = new CombinadorLinealAdaptativo(NumberInputs);//C20 = new CombinadorLinealAdaptativo(20);C21 = new CombinadorLinealAdaptativo(20);C22 = new CombinadorLinealAdaptativo(20);C23 = new CombinadorLinealAdaptativo(20);}
RedNeural::~RedNeural(){delete C100;
16
delete C101;delete C102;delete C103;delete C104;delete C105;delete C106;delete C107;delete C108;delete C109;delete C110;delete C111;delete C112;delete C113;delete C114;delete C115;delete C116;delete C117;delete C118;delete C119;
delete C20;delete C21;delete C22;delete C23;}
void RedNeural::~RedNeural( float *d){C100->LlenaEntradas( d, NumberInputs);C101->LlenaEntradas( d, NumberInputs);C102->LlenaEntradas( d, NumberInputs);C103->LlenaEntradas( d, NumberInputs);C104->LlenaEntradas( d, NumberInputs);C105->LlenaEntradas( d, NumberInputs);C106->LlenaEntradas( d, NumberInputs);C107->LlenaEntradas( d, NumberInputs);C108->LlenaEntradas( d, NumberInputs);C109->LlenaEntradas( d, NumberInputs);C110->LlenaEntradas( d, NumberInputs);C111->LlenaEntradas( d, NumberInputs);C112->LlenaEntradas( d, NumberInputs);C113->LlenaEntradas( d, NumberInputs);C114->LlenaEntradas( d, NumberInputs);C115->LlenaEntradas( d, NumberInputs);C116->LlenaEntradas( d, NumberInputs);C117->LlenaEntradas( d, NumberInputs);
17
C118->LlenaEntradas( d, NumberInputs);C119->LlenaEntradas( d, NumberInputs);
float salida[20];salida[0] = C100->MuestraSalidaSigmoidea();salida[1] = C101->MuestraSalidaSigmoidea();salida[2] = C102->MuestraSalidaSigmoidea();salida[3] = C103->MuestraSalidaSigmoidea();salida[4] = C104->MuestraSalidaSigmoidea();salida[5] = C105->MuestraSalidaSigmoidea();salida[6] = C106->MuestraSalidaSigmoidea();salida[7] = C107->MuestraSalidaSigmoidea();salida[8] = C108->MuestraSalidaSigmoidea();salida[9] = C108->MuestraSalidaSigmoidea();salida[10] = C110->MuestraSalidaSigmoidea();salida[11] = C111->MuestraSalidaSigmoidea();salida[12] = C112->MuestraSalidaSigmoidea();salida[13] = C113->MuestraSalidaSigmoidea();salida[14] = C114->MuestraSalidaSigmoidea();salida[15] = C115->MuestraSalidaSigmoidea();salida[16] = C116->MuestraSalidaSigmoidea();salida[17] = C117->MuestraSalidaSigmoidea();salida[18] = C118->MuestraSalidaSigmoidea();salida[19] = C119->MuestraSalidaSigmoidea();
C20->LlenaEntradas( salida, 20);C21->LlenaEntradas( salida, 20);C22->LlenaEntradas( salida, 20);C23->LlenaEntradas( salida, 20);}
void RedNeural::LlenaEntradas2( float *d){C100->LlenaEntradas( d, NumberInputs);C101->LlenaEntradas( d, NumberInputs);C102->LlenaEntradas( d, NumberInputs);C103->LlenaEntradas( d, NumberInputs);C104->LlenaEntradas( d, NumberInputs);C105->LlenaEntradas( d, NumberInputs);C106->LlenaEntradas( d, NumberInputs);C107->LlenaEntradas( d, NumberInputs);C108->LlenaEntradas( d, NumberInputs);C109->LlenaEntradas( d, NumberInputs);C110->LlenaEntradas( d, NumberInputs);C111->LlenaEntradas( d, NumberInputs);C112->LlenaEntradas( d, NumberInputs);
18
C113->LlenaEntradas( d, NumberInputs);C114->LlenaEntradas( d, NumberInputs);C115->LlenaEntradas( d, NumberInputs);C116->LlenaEntradas( d, NumberInputs);C117->LlenaEntradas( d, NumberInputs);C118->LlenaEntradas( d, NumberInputs);C119->LlenaEntradas( d, NumberInputs);
float salida[20];salida[0] = C100->MuestraSalidaDigital();salida[1] = C101->MuestraSalidaDigital();salida[2] = C102->MuestraSalidaDigital();salida[3] = C103->MuestraSalidaDigital();salida[4] = C104->MuestraSalidaDigital();salida[5] = C105->MuestraSalidaDigital();salida[6] = C106->MuestraSalidaDigital();salida[7] = C107->MuestraSalidaDigital();salida[8] = C108->MuestraSalidaDigital();salida[9] = C108->MuestraSalidaDigital();salida[10] = C110->MuestraSalidaDigital();salida[11] = C111->MuestraSalidaDigital();salida[12] = C112->MuestraSalidaDigital();salida[13] = C113->MuestraSalidaDigital();salida[14] = C114->MuestraSalidaDigital();salida[15] = C115->MuestraSalidaDigital();salida[16] = C116->MuestraSalidaDigital();salida[17] = C117->MuestraSalidaDigital();salida[18] = C118->MuestraSalidaDigital();salida[19] = C119->MuestraSalidaDigital();
C20->LlenaEntradas( salida, 20);C21->LlenaEntradas( salida, 20);C22->LlenaEntradas( salida, 20);C23->LlenaEntradas( salida, 20);}
void RedNeural::CalculaNuevoSet( float *d){// optimizacion por el metodo LMSfloat error[20];float salida[20];
// La informacion se propaga a traves de la redLlenaEntradas( d);
// Comienza la optimizacion
19
salida[0] = deseada[0] - C20->MuestraSalidaSigmoidea();salida[1] = deseada[1] - C21->MuestraSalidaSigmoidea();salida[2] = deseada[2] - C22->MuestraSalidaSigmoidea();salida[3] = deseada[3] - C23->MuestraSalidaSigmoidea();
salida[0] = salida[0]*(1.0- (C20->MuestraSalidaSigmoidea();*C20->>MuestraSalidaSigmoidea()));
salida[1] = salida[0]*(1.0- (C21->MuestraSalidaSigmoidea();*C21->>MuestraSalidaSigmoidea()));
salida[2] = salida[0]*(1.0- (C22->MuestraSalidaSigmoidea();*C22->>MuestraSalidaSigmoidea()));
salida[3] = salida[0]*(1.0- (C23->MuestraSalidaSigmoidea();*C23->>MuestraSalidaSigmoidea()));
C20->CalculaNuevoSet( salida[0]);C21->CalculaNuevoSet( salida[0]);C22->CalculaNuevoSet( salida[0]);C23->CalculaNuevoSet( salida[0]);
error[0] = salida[0]*C20->Wk[0] + salida[1]*C21->Wk[0]+ salida[2]*C22->Wk[0] + salida[3]*C23->Wk[0];
error[1] = salida[0]*C20->Wk[1] + salida[1]*C21->Wk[1]+ salida[2]*C22->Wk[1] + salida[3]*C23->Wk[1];
error[2] = salida[0]*C20->Wk[2] + salida[1]*C21->Wk[2]+ salida[2]*C22->Wk[2] + salida[3]*C23->Wk[2];
error[3] = salida[0]*C20->Wk[3] + salida[1]*C21->Wk[3]+ salida[2]*C22->Wk[3] + salida[3]*C23->Wk[3];
error[4] = salida[0]*C20->Wk[4] + salida[1]*C21->Wk[4]+ salida[2]*C22->Wk[4] + salida[3]*C23->Wk[4];
error[5] = salida[0]*C20->Wk[5] + salida[1]*C21->Wk[5]+ salida[2]*C22->Wk[5] + salida[3]*C23->Wk[5];
error[6] = salida[0]*C20->Wk[6] + salida[1]*C21->Wk[6]+ salida[2]*C22->Wk[6] + salida[3]*C23->Wk[6];
error[7] = salida[0]*C20->Wk[7] + salida[1]*C21->Wk[7]+ salida[2]*C22->Wk[7] + salida[3]*C23->Wk[7];
error[8] = salida[0]*C20->Wk[8] + salida[1]*C21->Wk[8]+ salida[2]*C22->Wk[8] + salida[3]*C23->Wk[8];
error[9] = salida[0]*C20->Wk[9] + salida[1]*C21->Wk[9]+ salida[2]*C22->Wk[9] + salida[3]*C23->Wk[9];
error[10] = salida[0]*C20->Wk[10] + salida[1]*C21->Wk[10]+ salida[2]*C22->Wk[10] + salida[3]*C23->Wk[10];
error[11] = salida[0]*C20->Wk[11] + salida[1]*C21->Wk[11]+ salida[2]*C22->Wk[11] + salida[3]*C23->Wk[11];
error[12] = salida[0]*C20->Wk[12] + salida[1]*C21->Wk[12]+ salida[2]*C22->Wk[12] + salida[3]*C23->Wk[12];
error[13] = salida[0]*C20->Wk[13] + salida[1]*C21->Wk[13]
20
+ salida[2]*C22->Wk[13] + salida[3]*C23->Wk[13];error[14] = salida[0]*C20->Wk[14] + salida[1]*C21->Wk[14]
+ salida[2]*C22->Wk[14] + salida[3]*C23->Wk[14];error[15] = salida[0]*C20->Wk[15] + salida[1]*C21->Wk[15]
+ salida[2]*C22->Wk[15] + salida[3]*C23->Wk[15];error[16] = salida[0]*C20->Wk[16] + salida[1]*C21->Wk[16]
+ salida[2]*C22->Wk[16] + salida[3]*C23->Wk[16];error[17] = salida[0]*C20->Wk[17] + salida[1]*C21->Wk[17]
+ salida[2]*C22->Wk[17] + salida[3]*C23->Wk[17];error[18] = salida[0]*C20->Wk[18] + salida[1]*C21->Wk[18]
+ salida[2]*C22->Wk[18] + salida[3]*C23->Wk[18];error[19] = salida[0]*C20->Wk[19] + salida[1]*C21->Wk[19]
+ salida[2]*C22->Wk[19] + salida[3]*C23->Wk[19];
error[0] = error[0]*(1.0- (C100->MuestraSalidaSigmoidea()*C100->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C101->MuestraSalidaSigmoidea()*C101->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C102->MuestraSalidaSigmoidea()*C102->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C103->MuestraSalidaSigmoidea()*C103->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C104->MuestraSalidaSigmoidea()*C104->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C105->MuestraSalidaSigmoidea()*C105->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C106->MuestraSalidaSigmoidea()*C106->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C107->MuestraSalidaSigmoidea()*C107->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C108->MuestraSalidaSigmoidea()*C108->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C109->MuestraSalidaSigmoidea()*C109->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C110->MuestraSalidaSigmoidea()*C110->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C111->MuestraSalidaSigmoidea()*C111->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C112->MuestraSalidaSigmoidea()*C112->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C113->MuestraSalidaSigmoidea()*C113->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C114->MuestraSalidaSigmoidea()*C114->MuestraSalidaSigmoidea()));
error[0] = error[0]*(1.0- (C115->MuestraSalidaSigmoidea()
21
*C115->MuestraSalidaSigmoidea()));error[0] = error[0]*(1.0- (C116->MuestraSalidaSigmoidea()
*C116->MuestraSalidaSigmoidea()));error[0] = error[0]*(1.0- (C117->MuestraSalidaSigmoidea()
*C117->MuestraSalidaSigmoidea()));error[0] = error[0]*(1.0- (C118->MuestraSalidaSigmoidea()
*C118->MuestraSalidaSigmoidea()));error[0] = error[0]*(1.0- (C119->MuestraSalidaSigmoidea()
*C119->MuestraSalidaSigmoidea()));
C100->CalculaNuevoSet( error[0]);C101->CalculaNuevoSet( error[1]);C102->CalculaNuevoSet( error[2]);C103->CalculaNuevoSet( error[3]);C104->CalculaNuevoSet( error[4]);C105->CalculaNuevoSet( error[5]);C106->CalculaNuevoSet( error[6]);C107->CalculaNuevoSet( error[7]);C108->CalculaNuevoSet( error[8]);C109->CalculaNuevoSet( error[9]);C110->CalculaNuevoSet( error[10]);C111->CalculaNuevoSet( error[11]);C112->CalculaNuevoSet( error[12]);C113->CalculaNuevoSet( error[13]);C114->CalculaNuevoSet( error[14]);C115->CalculaNuevoSet( error[15]);C116->CalculaNuevoSet( error[16]);C117->CalculaNuevoSet( error[17]);C118->CalculaNuevoSet( error[18]);C119->CalculaNuevoSet( error[19]);}
float RedNeural::MuestraSalidaDigital1( void){return C20->MuestraSalidaDigital();}
float RedNeural::MuestraSalidaDigital2( void){return C21->MuestraSalidaDigital();}
float RedNeural::MuestraSalidaDigital3( void){return C22->MuestraSalidaDigital();}
float RedNeural::MuestraSalidaDigital4( void){
22
return C23->MuestraSalidaDigital();}
3.1. Ejemplo de identificación de patrones con redes neuro-nales
En el ejemplo que sigue a continuación se busca la identificación de patrones porparte de una redes neuronal R. Dicha red es de dos capas, con un vector de entradade 100 elementos, y con 5 neuronas en la primera capa y 3 en la segunda, formandoasí un vector de salida de tres elementos.
La red R se entrena con tres patrones, que corresponden a los números 6, 8 y 5,los cuales forman una grilla de 10 por 10 elementos, buscando las salidas deseadas[-1,1,1,-1], [1,1,-1,-1] y [1,-1,1,-1], respectivamente.
A continuación se pueden apreciar las grillas correspondientes a los números 8,6, 5 y 6 con ruido.
3.1.1. OCHO.TXT
0 0 0 0 0 0 0 0 0 00 0 10 10 10 10 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 10 10 10 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 10 10 10 10 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0
3.1.2. SEIS.TXT
0 0 0 0 0 0 0 0 0 00 0 10 0 0 0 0 0 0 00 0 10 0 0 0 0 0 0 00 0 10 0 0 0 0 0 0 00 0 10 10 10 10 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 0 0 0 10 0 0 00 0 10 10 10 10 10 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0
23
Por otro lado la red R2 se entrena con las grillas de los números 5 y 6, buscandolas salidas deseadas (1,1,1) y (-1,-1,-1) respectivamente.
Las grillas se encuentran en archivos de texto, con los elementos de la mismaseparados por tabulador y retorno de carro, como se muestra a continuación:
3.1.3. CINCO.TXT
0 0 0 0 0 0 0 0 0 00 0 10 10 10 10 10 0 0 00 0 10 0 0 0 0 0 0 00 0 10 0 0 0 0 0 0 00 0 10 10 10 10 10 0 0 00 0 0 0 0 0 10 0 0 00 0 0 0 0 0 10 0 0 00 0 10 10 10 10 10 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0
3.1.4. SEIS2.TXT
0 10 0 0 0 0 0 0 0 00 0 10 0 0 0 10 0 10 00 0 10 0 0 0 0 0 0 00 0 10 0 0 0 0 0 0 00 0 10 10 10 10 10 10 0 00 0 10 0 0 0 10 0 0 00 0 10 0 0 0 10 0 0 00 10 10 10 10 10 10 0 0 00 0 0 10 0 0 0 0 0 00 0 0 0 0 0 10 0 0 0
3.1.5. Código fuente de NUMERO.CPP
// NUMERO.CPP
#include "neural3.h"#include <stdlib.h>#include <iostream.h>#include <fstream.h>
float numero[10][10];
24
float *num1 = new float[100];float *num2 = new float[100];float *num3 = new float[100];float *num4 = new float[100];
void main( void){
RedNeural R(100); // 100 entradas, 10 x 10 pixelsint j, k, l:
// para entrenar la red, leemos dos numeros, 8 y 6// Lee numero 8ifstream numero1;numero1.open("OCHO.TXT");l = 0;for( j = 0; j < 10; j++){
for( k = 0; k < 10; k++){numero1 >> numero[j][k];cout << numero[j][k] << "\t"num1[l++] = numero[j][k];}
cout << endl;}
// Lee numero 6ifstream numero2;numero2.open( "SEIS.TXT");l = 0;for( j = 0; j < 10; j++){
for( k = 0; k < 10; k++){numero2 >> numero[j][k];cout << numero[j][k] << "\t";num2[l++] = numero[j][k];}
cout << endl;}
// Lee numero 5numero2.close();numero2.open( "CINCO.TXT");l = 0;for( j = 0; j < 10; j++){
for( k = 0; k < 10; k++){numero2 >> numero[j][k];cout << numero[j][k] << "\t";
25
num3[l++] = numero[j][k];}
cout << endl;}
// Lee numero 6 con ruidonumero2.close();numero2.open("SEIS2.TXT");l = 0;for( j = 0; j < 10; j++){
for( k = 0; k < 10; k++){numero2 >> numero[j][k];cout << numero[j][k] << "\t";num4[l++] = numero[j][k];}
cout << endl;}
float error, error1, error2;int pasada = 1;cout << "Comienza entrenamiento ..." << endl << endl;for( j = 0; j < 3000; j++){
R.deseada[0] = -1.0;R.deseada[1] = 1.0;R.deseada[2] = 1.0;R.deseada[3] = -1.0;R.CalculaNuevoSet( num2); // seis
R.deseada[0] = 1.0;R.deseada[1] = 1.0;R.deseada[2] = -1.0;R.deseada[3] = -1.0;R.CalculaNuevoSet( num1); // ocho
R.deseada[0] = 1.0;R.deseada[1] = -1.0;R.deseada[2] = 1.0;R.deseada[3] = -1.0;R.CalculaNuevoSet( num3); // cinco}
cout << "Fin entrenamiento ..." << endl << endl;
R.LlenaEntradas( num2);cout << "Muestra numero 6 (-1,1,1,-1): ";cout << R.MuestraSalidaDigital1() << " " << R.MuestraSalidaDigital2();
26
cout << " " << R.MuestraSalidaDigital3() << " "<< R.MuestraSalidaDigital4() << endl;
R.LlenaEntradas( num1);cout << "Muestra numero 8 (1,1,-1,-1): ";cout << R.MuestraSalidaDigital1() << " " << R.MuestraSalidaDigital2();cout << " " << R.MuestraSalidaDigital3() << " "<< R.MuestraSalidaDigital4() << endl;
R.LlenaEntradas( num3);cout << "Muestra numero 5 (1,-1,1,-1): ";cout << R.MuestraSalidaDigital1() << " " << R.MuestraSalidaDigital2();cout << " " << R.MuestraSalidaDigital3() << " "<< R.MuestraSalidaDigital4() << endl;
R.LlenaEntradas( num4);cout << "Muestra numero 6 con ruido (?,?,?,?): ";cout << R.MuestraSalidaDigital1() << " " <<R.MuestraSalidaDigital2();cout << " " << R.MuestraSalidaDigital3() << " "<< R.MuestraSalidaDigital4() << endl;
delete num1;delete num2;delete num3;delete num4;}
Referencias[1] Ricardo Armentano, Javier Fochesatto, and Marcelo Risk. Análisis de Señales
y Sistemas. Editorial Rocamora, 1996.
[2] Sid Deutsch and Alice Deutsch. Understanding the nervous system, an enginee-ring point of view. IEEE Press, 1993.
[3] William T. Keeton. Biological science. W.W. Norton and company, third editionedition, 1980.
[4] Raúl Rojas. Neural networks: a systematic approach. Springer, 1996.
[5] 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.
27