Você está na página 1de 27

Introduccin a las Redes Neuronales: Parte 2

Red de Perceptrones
Dr. Ing. Marcelo Risk
Instituto Tecnolgico de Buenos Aires

ndice
1. Introduccin

2. El perceptrn a partir de un combinador lineal adaptativo

3. Implementacin de una red neuronal


3.0.1. Cdigo fuente de NEURAL3.H . . . . . . . . . . .
3.0.2. Cdigo fuente de NEURAL3.CPP . . . . . . . . . .
3.1. Ejemplo de identificacin de patrones con redes neuronales
3.1.1. OCHO.TXT . . . . . . . . . . . . . . . . . . . . . .
3.1.2. SEIS.TXT . . . . . . . . . . . . . . . . . . . . . . .
3.1.3. CINCO.TXT . . . . . . . . . . . . . . . . . . . . .
3.1.4. SEIS2.TXT . . . . . . . . . . . . . . . . . . . . . .
3.1.5. Cdigo fuente de NUMERO.CPP . . . . . . . . . .

1.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

8
8
11
23
23
23
24
24
24

Introduccin

Las redes neuronales (RN) se basan en la interconexin de neuronas artificiales,


y en el caso de las RN artificiales (RNA) en la interconexin de perceptrones, el
cual modeliza una neurona natural, en el presente trabajo utilizaremos el modelo de
neurona denominado clasificador no lineal [5, 4, 1].
Las RNA son mquinas o software que modelan la forma en la cual el cerebro
desarrola una tarea. Las RNA son una clase de mtodos estadsticos para el procesamiento de informacin, compuestas por una cantidad importante de unidades
simples de procesamiento, denominadas neuronas, las cuales interactuan entre s.
Las RN naturales estn presentes en el sistema nervioso de humanos, animales,
insectos, etc, tienen la habilidad de reconocer patrones, y desarrollar tareas complejas, en forma muy especializada [3, 2].
El cuadro 1 muestra comparaciones de performance, tales como velocidad de
procesamiento, cantidad de neuroras-compuertas, peso, consumo de energa y un
ejemplo de pasos necesarios para el procesamiento de la visin.

Cuadro 1: Comparaciones de performance y consumos entre el cerebro humano y


las computadoras.

Velocidad procesamiento
Neuronas-compuertas
Peso
Consumo
Procesamiento de la visin

Cerebro humano
103 ms (0.25 MHz)
109 con 103 conexiones c/u
1.5 kg
1016 Joule
100 pasos

Computadora
109 ms (2.5 GHz)
50 millones
kgs a tons
106 Joule
billones de pasos

Las RNA heredan la terminologa de las redes naturales, provenientes de la biologa, el cuadro 2 muestra las correspondencias entre dichos trminos y los correspondientes a la estadstica.
Cuadro 2: Correspondencia entre la terminologa de las RNA y la estadstica.
RNA
Estadstica
Nodos de entrada Variables independientes
Nodos de salida
Variables dependientes
Aprendizaje
Parametrizacin
Pesos
Parmetros

La figura 1 muestra en el panel izquierdo: neurona cerebral, gran cantidad de


dendritas (entradas de informacin), y axn (salida) simple; mientras en el panel
derecho: neurona motora, con menos dendritas, y salida mielinizada (aislada).
Ms all del alcance de este apunte, en muchos libros es posible encontrar el
paradigma de las redes neuronales, pero podemos decir que los atributos ms importantes de las redes neuronales es el aprendizaje y la generalizacin.
El aprendizaje es el proceso por el cual se le presenta a la red neuronal uno o
varios patrones con sus salidas deseadas (tantos como sea posible), determinndose un conjunto de entrenamiento, con dicho conjunto y mediante un algoritmo de
optimizacin se ajustan los coeficientes de la red.
Una vez entrenada la RNA, se puede probar la respuesta de la misma aplicndole
patrones distintos a los del entrenamiento, verificando si la respuesta fue correcta
en la mayora de los casos, entonces se puede decir que se obtuvo un entrenamiento
general.

Figura 1: Panel izquierdo: neurona cerebral, gran cantidad de dendritas (entradas


de informacin), y axn (salida) simple; panel derecho: neurona motora, con menos
dendritas, y salida mielinizada (aislada).

2.

El perceptrn a partir de un combinador lineal


adaptativo

Si a la salida del combinador lineal adaptativo se conecta un bloque de respuesta


alineal, denominado cuantificador, tal como la funcin signo, que responde a la
siguiente expresin 1.
(
y = +1 si x 0
(1)
y = 1 si x < 0
El sistema completo, formado por un combinador lineal adaptativo y un elemento
alineal a la salida de denomina adaline. En la figura 2 que sigue podemos apreciar
el diagrama en bloques del adaline.
Vector de
patrn de
entrada

x0k =+1

Xk

Pesos

Peso de
umbral

W1k

X1k

Entrada de corte

sk
W2k

X2k

X3k

yk

+1

W3k

-1

Salida
Lineal
Salida
Binaria
(+1,-1)

Dispositivo
de umbral
Wnk

Xnk

Wk
Xk

Error
Lineal
Algoritmo
LMS

ADALINE

dk
Entrada de
Respuesta Deseada
(seal de entrenamiento)

Figura 2: Diagrama en bloques del adaline.


Note en la figura 2 la entrada x0k , siempre alimentada con un valor constante
+1, con el propsito de controlar el umbral del cuantificador. Para el ajuste de los
coeficientes s puede utilizar el algoritmo de los cuadrados mnimos.
El adaline tiene la propiedad de separabilidad lineal, por ejemplo si analizamos
un adaline con dos entradas, como lo muestra la figura 3, podemos apreciar que se
4

determina una recta de separacin en el espacio de las combinaciones de entrada,


en este caso un plano.
X0 = +1

W0

X1

W1

W2

S(n)

+1

Y(n)
-1

X2

Figura 3: Diagrama en bloques del adaline de dos entradas.


La salida lineal S(n) tiene la siguiente expresin 2:
S(n) = W0 + X1 (n)W1 + X2 (n)W2

(2)

Si igualamos a cero la ecuacin 2, tenemos:


W1
W0
X1 (n)
(3)
W2
W2
La ecuacin 3 describe la recta que separa el plano de estados posibles de entrada,
1
en la misma se pueden reconocer la pendiente m = W
y la ordenada al origen
W2
W0
b = W2 . Las combinaciones de entrada por arriba de la recta de separacin generan
una salida de 1, y las combinaciones por debajo una salida de +1.
Entre las alternativas posibles para la eleccin del cuantificador, s encuentra la
funcin sigmoidea, la cual tiene la siguiente expresin 4:
X2 (n) =

1 e2S(n)
(4)
1 + e2S(n)
En una implementacin prctica de una neurona, es conveniente incluir todas
las alternativas posibles de cuantificacin y clculo error, de manera de poder implementar ms de un algoritmo de optimizacin.
Por ejemplo si se utiliza en lugar del error lineal instantneo, el error a la salida
del cuantificador, el algoritmo de optimizacin de coeficientes se denomina regla del
Perceptron, desarrollada por F. Rosenblatt.
La diferencia entre el error cuadrtico medio tomado de la salida lineal, con el
error tomado a la salida de la funcin sigmoidea es una respuesta ms abrupta por
parte del error sigmoideo.
Y (n) = SIG[S(n)] = tanh[S(n)] =

La eleccin por una u otra funcin de cuantificacin depende de muchos factores,


entre ellos como se implementan dichos cuantificadores. Por ejemplo si se construye
una red neuronal con hardware, es mucho ms fcil implementar la funcin signo
(simplemente con un comparador analgico).
Otra alternativa es utilizar la funcin sigmoidea durante el entrenamiento, porque
con ella es posible llegar a mejores optimizaciones, para luego durante la operacin
de la red utilizar la funcin signo. El diagrama en bloques completo de la neurona
se muestra en la figura 4.

X0 = +1

X1

X2

W1

W0

W2

W3

+1

S(n)

+1

Y1(n)
-1

Y2(n)
-1

X3
W4
X4

e(n)

d(n)

e1(n)

d1(n)

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 la
salida deseada.
Cuando se conectan ms de una neurona, se conforma una red neuronal, es
necesario en la mayora de las aplicaciones conectar varias neuronas, debido a que
aumenta notablemente la capacidad de reconocimiento de patrones.
Las redes neuronales se organizan en capas, formadas por una cantidad de neuronas cada una de ellas, generalmente son de dos o tres capas, denominndose las
capas 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 la
salida se denominan capas ocultas.
La figura 5 muestra un diagrama general de una red neuronal de tres capas, note
que el vector de entrada ingresa a todas las neuronas de la primera capa, la cual
genera un vector de salida de dicha capa, que sirve para alimentar las neuronas de
6

la capa oculta, y as sucesivamente las seales conforman el vector de salida.

Capa
de entrada

Capa
de salida

Vector
de entrada

Vector
de salida

Capa
oculta

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 mtodo de cuadrados mnimos, pero es necesario tener en cuenta
para la optimizacin 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 mtodos que se han desarrollado hasta el momento, se destaca
el mtodo de retropropagacin, debido al impacto que gener en la bibliografa
posterior.
El mtodo de retropropagacin busca propagar el error al valor deseado del vector
de salida, en sentido inverso al flujo de informacin a travs de la red neuronal; para
lograr esto el error llega a las capas anteriores multiplicado por el peso de las capas
posteriores.
Antes de comenzar el proceso de aprendizaje, generalmente se inicializan los
pesos de todas las neuronas con valores aleatorios pequeos, despus comienza el
aprendizaje, el cual puede durar una cantidad de iteraciones determinadas previamente, o bien buscar un error de salida mnimo, o ambos mtodos en caso de no
lograr el error mnimo.
La figura 6 muestra el diagrama de una red neuronal de dos capas, con el mtodo
de retropropagacin, los bloques denominados SIG desarrollan la funcin sigmoidea,
ecuacin 4, y el bloque denominado SIG desarrolla la ecuacin 5 dada a continuacin:
SIG0 [S(n)] =

{tanh[S(n)]}
= 1 {tanh[S(n)]}2 = 1 Y 2 (n)
{S(n)}

(5)

De esta forma la ecuacin que optimiza los pesos por el mtodo de los cuadrados
7

mnimos queda expresada de la siguiente forma:


Wk (n + 1) = Wk (n) 2ek (n)[1 Y 2 (n)]Xk (n)

3.

(6)

Implementacin de una red neuronal

Una red neuronal se forma a partir de la modelizacin de ua neurona, en el


listado que sigue se implement una neurona a travs de la clase CombinadorLinealAdaptativo, dentro de ella estn encapsuladas todas las propiedades necesarias para
el funcionamiento de un objeto que maneja un vector de datos Xk , un vector de pesos Wk , y otras variables tales como el error Ek , la cantidad de elementos Cantidad
y el valor del coeficiente de velocidad de optimizacin , adems de las funciones
necesarias para la carga de los vectores, el clculo de salida y la optimizacin de los
coeficientes del filtro.
Adems en dicho listado se encuentra la clase RedNeural, que conecta varias
neuronas para formar una red de dos capas, en la primera capa se encuentran 100
entradas a 5 neuronas, y en la segunda capa 3 neuronas. Para la optimizacin de la
red neuronal se implement el mtodo de retropropagacin.
3.0.1.

Cdigo fuente de NEURAL3.H

// NEURAL3.H
#include
#include
#include
#include

<math.h>
<stdlib.h>
<iostream.h>
<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

Figura 6: Diagrama general de una red neuronal de tres capas.

W210

W310

X2

X3

W312

W212

W112

W012

W311

W211

W111

W011

W110

W010

X1

X0

W410

W411

W412

Algoritmo
LMS

+1

Algoritmo
LMS

+1

Algoritmo
LMS

+1

SIG

S12

SIG

S11

SIG

S10

SIG

SIG

SIG

Y12

Y11

Y10

W221

W121

W021

W220

W120

W020
W420

W421

Algoritmo
LMS

+1

Algoritmo
LMS

+1

SIG

S21

SIG

S20

SIG

SIG

d1

Y1

d0

Y0

CombinadorLinealAdaptativo( int n);


~CombinadorLinealAdaptativo();
void
void
void
void
void
void
void
void

Calcula( void);
CantidadSynapsis( int n = 50);
LlenaPesos( float *Array, int cantidad);
LlenaEntradas( float *Array, int cantidad);
LlenaPesos( float *Array);
LlenaEntradas( float *Array);
LlenaSalidaDeseada( float Salida);
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 capa
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo

*C100;
*C101;
*C102;
*C103;
*C104;
*C105;
*C106;
*C107;
*C108;
*C109;
10

CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
// segunda capa
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo
CombinadorLinealAdaptativo

*C110;
*C111;
*C112;
*C113;
*C114;
*C115;
*C116;
*C117;
*C118;
*C119;
*C20;
*C21;
*C22;
*C23;

Red Neural();
Red Neural( int inputs);
~Red Neural();
void
void
void
void

LlenaEntradas( float *d);


LlenaEntradas2( float *d);
CalculaNuevoSet( float *d);
CalculaNuevoSet2( float *d);

float
float
float
float
};

3.0.2.

MuestraSalidaDigital1(
MuestraSalidaDigital2(
MuestraSalidaDigital3(
MuestraSalidaDigital4(

void);
void);
void);
void);

Cdigo 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 umbral
for( int j = 0; j < Cantidad; j++){
Suma += Wk[j] *Xk[j];
}
Sk = Suma;
// Sigmoidea
yk = (1.0-exp(-2.0*Sk)) / (1.0+exp(-2.0*Sk))
// Funcion signo
if( yk >= 0)
Yk = 1.0;
else
Yk = -1.0;
// Calcula error
Ek = 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(
return Sk;
}

void){

float CombinadorLinealAdaptativo::MuestraSalidaSigmoidea(
return yk;
}
float CombinadorLinealAdaptativo::MuestraSalidaDigital(
return Yk;
}

void){

float CombinadorLinealAdaptativo::MuestraErrorLineal(
return Ek;
}

void){

void){

float CombinadorLinealAdaptativo::MuestraErrorSigmoidea(
return Eks;
}
float CombinadorLinealAdaptativo::MuestraErrorDigital(
return Ekd;
}

void){

void){

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
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete

C101;
C102;
C103;
C104;
C105;
C106;
C107;
C108;
C109;
C110;
C111;
C112;
C113;
C114;
C115;
C116;
C117;
C118;
C119;

delete
delete
delete
delete
}

C20;
C21;
C22;
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(
C21->LlenaEntradas(
C22->LlenaEntradas(
C23->LlenaEntradas(
}

salida,
salida,
salida,
salida,

20);
20);
20);
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(
C114->LlenaEntradas(
C115->LlenaEntradas(
C116->LlenaEntradas(
C117->LlenaEntradas(
C118->LlenaEntradas(
C119->LlenaEntradas(

d,
d,
d,
d,
d,
d,
d,

NumberInputs);
NumberInputs);
NumberInputs);
NumberInputs);
NumberInputs);
NumberInputs);
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(
C21->LlenaEntradas(
C22->LlenaEntradas(
C23->LlenaEntradas(
}

salida,
salida,
salida,
salida,

20);
20);
20);
20);

void RedNeural::CalculaNuevoSet( float *d){


// optimizacion por el metodo LMS
float error[20];
float salida[20];
// La informacion se propaga a traves de la red
LlenaEntradas( d);
// Comienza la optimizacion
19

salida[0]
salida[1]
salida[2]
salida[3]

=
=
=
=

deseada[0]
deseada[1]
deseada[2]
deseada[3]

C20->MuestraSalidaSigmoidea();
C21->MuestraSalidaSigmoidea();
C22->MuestraSalidaSigmoidea();
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(
C101->CalculaNuevoSet(
C102->CalculaNuevoSet(
C103->CalculaNuevoSet(
C104->CalculaNuevoSet(
C105->CalculaNuevoSet(
C106->CalculaNuevoSet(
C107->CalculaNuevoSet(
C108->CalculaNuevoSet(
C109->CalculaNuevoSet(
C110->CalculaNuevoSet(
C111->CalculaNuevoSet(
C112->CalculaNuevoSet(
C113->CalculaNuevoSet(
C114->CalculaNuevoSet(
C115->CalculaNuevoSet(
C116->CalculaNuevoSet(
C117->CalculaNuevoSet(
C118->CalculaNuevoSet(
C119->CalculaNuevoSet(
}

error[0]);
error[1]);
error[2]);
error[3]);
error[4]);
error[5]);
error[6]);
error[7]);
error[8]);
error[9]);
error[10]);
error[11]);
error[12]);
error[13]);
error[14]);
error[15]);
error[16]);
error[17]);
error[18]);
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 identificacin de patrones con redes neuronales

En el ejemplo que sigue a continuacin se busca la identificacin de patrones por


parte de una redes neuronal R. Dicha red es de dos capas, con un vector de entrada
de 100 elementos, y con 5 neuronas en la primera capa y 3 en la segunda, formando
as un vector de salida de tres elementos.
La red R se entrena con tres patrones, que corresponden a los nmeros 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 continuacin se pueden apreciar las grillas correspondientes a los nmeros 8,
6, 5 y 6 con ruido.
3.1.1.

3.1.2.

OCHO.TXT
0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0 0 0 0
10 10 10 10
10 0 0 0
10 0 0 0
10 10 10 10
10 0 0 0
10 0 0 0
10 10 10 10
0 0 0 0
0 0 0 0

0
10
10
10
10
10
10
10
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0 0 0 0 0 0 0 0
10 0 0 0 0 0 0 0
10 0 0 0 0 0 0 0
10 0 0 0 0 0 0 0
10 10 10 10 10 0 0 0
10 0 0 0 10 0 0 0
10 0 0 0 10 0 0 0
10 10 10 10 10 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

SEIS.TXT

23

Por otro lado la red R2 se entrena con las grillas de los nmeros 5 y 6, buscando
las salidas deseadas (1,1,1) y (-1,-1,-1) respectivamente.
Las grillas se encuentran en archivos de texto, con los elementos de la misma
separados por tabulador y retorno de carro, como se muestra a continuacin:
3.1.3.

CINCO.TXT
0
0
0
0
0
0
0
0
0
0

3.1.4.

0
0
0
0
0
0
0
0
0
0

0 0 0 0
10 10 10 10
10 0 0 0
10 0 0 0
10 10 10 10
0 0 0 0
0 0 0 0
10 10 10 10
0 0 0 0
0 0 0 0

0
10
0
0
10
10
10
10
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

SEIS2.TXT
0 10 0 0 0 0 0 0 0 0
0 0 10 0 0 0 10 0 10 0
0 0 10 0 0 0 0 0 0 0
0 0 10 0 0 0 0 0 0 0
0 0 10 10 10 10 10 10 0 0
0 0 10 0 0 0 10 0 0 0
0 0 10 0 0 0 10 0 0 0
0 10 10 10 10 10 10 0 0 0
0 0 0 10 0 0 0 0 0 0
0 0 0 0 0 0 10 0 0 0

3.1.5.

Cdigo fuente de NUMERO.CPP

// NUMERO.CPP
#include
#include
#include
#include

"neural3.h"
<stdlib.h>
<iostream.h>
<fstream.h>

float numero[10][10];
24

float
float
float
float

*num1
*num2
*num3
*num4

=
=
=
=

new
new
new
new

float[100];
float[100];
float[100];
float[100];

void main( void){


RedNeural R(100); // 100 entradas, 10 x 10 pixels
int j, k, l:
// para entrenar la red, leemos dos numeros, 8 y 6
// Lee numero 8
ifstream 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 6
ifstream 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 5
numero2.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 ruido
numero2.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
delete
delete
delete
}

num1;
num2;
num3;
num4;

Referencias
[1] Ricardo Armentano, Javier Fochesatto, and Marcelo Risk. Anlisis de Seales
y Sistemas. Editorial Rocamora, 1996.
[2] Sid Deutsch and Alice Deutsch. Understanding the nervous system, an engineering point of view. IEEE Press, 1993.
[3] William T. Keeton. Biological science. W.W. Norton and company, third edition
edition, 1980.
[4] Ral Rojas. Neural networks: a systematic approach. Springer, 1996.
[5] Bernard Widrow and Michael Lehr. 30 years of adaptive neural networks: perceptron, madaline, and backpropagation. Proceedings of the IEEE, 78(9):14151442,
1990.

27

Você também pode gostar